Скажем, у нас есть метод «общедоступный метод», который использует частный «subMethod1» и частный «subMethod2» в его вычислении. Эти subMethods не служат никакой другой цели, кроме как разбить «метод» на более читаемые инкапсулированные части и избежать дублирования кода внутри метода.Обмен примитивными данными между методами?
Нам нужен каждый из этих вспомогательных методов для работы с двумя или более примитивными типами данных, которые являются локальными переменными, определенными в верхней части метода. Мы не можем передавать их в вспомогательные методы по ссылке, так как java не позволяет передавать примитивы по ссылке.
Итак, наше решение состоит в том, чтобы реорганизовать и изменить локальные переменные, определенные в верхней части метода, на переменные-члены, которые, конечно же, могут быть прочитаны и записаны как методом, так и его под-методами. Проблема в том, что теперь у нас есть переменные-члены, которые на самом деле не существуют для хранения состояния объекта, но существуют только эффективно, во время выполнения метода. Конечно, на самом деле они существуют на протяжении всего жизненного цикла объекта, но они используются только во время выполнения метода, и они могут исчезать в другое время, не затрагивая поведения объекта вообще (имейте в виду, что метод инициализирует члены к значениям по умолчанию в начале своего тела метода).
Ну, вы говорите, просто оберните примитивы в объекты, сохраните их локально внутри метода, затем попросите «метод» передать эти объекты в свои подтемы, где они смогут изменить свое значение, поскольку оно передано по ссылке как все объекты. Проблема в том, что «метод» используется внутри цикла моделирования, где он будет выполняться миллионы раз. Обертки объектов замедляют замедление, и здесь важна производительность.
Так что мой вопрос: есть ли какое-либо решение, которое даст мне такое же представление, как мои уродливые «использовать члены для совместного использования примитивных данных между методами», но также будет иметь хороший дизайн OO? Будет ли подходящим внутренний класс, обертывающий метод, под-методы и примитивные данные?
Благодаря, Ионы
EDIT: Вот это приготовленный образец кода, единственной целью которого является продемонстрировать замедление, вызванное использованием объектов обертки, как описано выше:
public class TestSharedMembers {
protected int m17Multiples;
protected int m23Multiples;
public int methodPrimitive(int i) {
m17Multiples = 0;
m23Multiples = 0;
calc17Primitive(i);
calc23Primitive(i);
return m17Multiples + m23Multiples;
}
private void calc17Primitive(int i) {
if (i % 17 == 0)
m17Multiples++;
}
private void calc23Primitive(int i) {
if (i % 23 == 0)
m23Multiples++;
}
/// using object wrappers
class IntWrapper {
private int mInt;
public IntWrapper(int i) {
mInt = i;
}
public int getInt() {
return mInt;
}
public void increment() {
mInt++;
}
}
public int methodObject(int i) {
IntWrapper o17 = new IntWrapper(0);
IntWrapper o23 = new IntWrapper(0);
calc17Object(i, o17);
calc23Object(i, o23);
return o17.getInt() + o23.getInt();
}
private void calc17Object(int i, IntWrapper o) {
if (i % 17 == 0)
o.increment();
}
private void calc23Object(int i, IntWrapper o) {
if (i % 23 == 0)
o.increment();
}
public static void main(String[] args) {
TestSharedMembers t = new TestSharedMembers();
final int NUM_ITERS = 20000000;
double start = System.currentTimeMillis();
int total = 0;
for (int i=0; i<NUM_ITERS; i++) {
total += t.methodPrimitive(i);
}
double stop = System.currentTimeMillis();
System.out.println(total);
System.out.println(stop - start);
start = System.currentTimeMillis();
total = 0;
for (int i=0; i<NUM_ITERS; i++) {
total += t.methodObject(i);
}
stop = System.currentTimeMillis();
System.out.println(total);
System.out.println(stop - start);
}
}
EDIT 2: Еще один пример чтобы проверить теорию Джона.
public class TestSharedMembers {
protected int m17Multiples;
protected int m23Multiples;
public int methodPrimitive(int i) {
m17Multiples = 0;
m23Multiples = 0;
calc17Primitive(i);
calc23Primitive(i);
return m17Multiples + m23Multiples;
}
private void calc17Primitive(int i) {
if (i % 17 == 0)
m17Multiples++;
if (i % 19 == 0)
m17Multiples++;
if (i % 5 == 0)
m17Multiples++;
if (i % 43 == 0)
m17Multiples++;
if (i % 41 == 0)
m17Multiples++;
if (i % 91 == 0)
m17Multiples++;
}
private void calc23Primitive(int i) {
if (i % 23 == 0)
m23Multiples++;
if (i % 17 == 0)
m23Multiples++;
if (i % 19 == 0)
m23Multiples++;
if (i % 5 == 0)
m23Multiples++;
if (i % 43 == 0)
m23Multiples++;
if (i % 41 == 0)
m23Multiples++;
if (i % 91 == 0)
m23Multiples++;
}
/// using object wrappers
class IntWrapper {
private int mInt1;
private int mInt2;
public IntWrapper(int i1, int i2) {
mInt1 = i1;
mInt2 = i2;
}
public int getInt1() {
return mInt1;
}
public int getInt2() {
return mInt2;
}
public void increment1() {
mInt1++;
}
public void increment2() {
mInt2++;
}
}
public int methodObject(int i) {
IntWrapper o = new IntWrapper(0,0);
calc17Object(i, o);
calc23Object(i, o);
return o.getInt1() + o.getInt2();
}
private void calc17Object(int i, IntWrapper o) {
if (i % 17 == 0)
o.increment1();
if (i % 19 == 0)
o.increment1();
if (i % 5 == 0)
o.increment1();
if (i % 43 == 0)
o.increment1();
if (i % 41 == 0)
o.increment1();
if (i % 91 == 0)
o.increment1();
}
private void calc23Object(int i, IntWrapper o) {
if (i % 23 == 0)
o.increment2();
if (i % 17 == 0)
o.increment1();
if (i % 19 == 0)
o.increment1();
if (i % 5 == 0)
o.increment1();
if (i % 43 == 0)
o.increment1();
if (i % 41 == 0)
o.increment1();
if (i % 91 == 0)
o.increment1();
}
public static void main(String[] args) {
TestSharedMembers t = new TestSharedMembers();
final int NUM_ITERS = 20000000;
double start = System.currentTimeMillis();
int total = 0;
for (int i=0; i<NUM_ITERS; i++) {
total += t.methodPrimitive(i);
}
double stop = System.currentTimeMillis();
System.out.println(total);
System.out.println(stop - start);
start = System.currentTimeMillis();
total = 0;
for (int i=0; i<NUM_ITERS; i++) {
total += t.methodObject(i);
}
stop = System.currentTimeMillis();
System.out.println(total);
System.out.println(stop - start);
}
}
Почему решение оберточного объекта было бы медленнее, чем решение переменной-члена? – irreputable
Я думаю, что это из-за создания и уничтожения объектов. Я знаю, что это медленнее, хотя, потому что я его протестировал. – Jonah