Сопротивление ссылки и передача переменного числа массивов - PullRequest
0 голосов
/ 18 ноября 2011

Ниже я написал простой код, который воссоздает проблемы, возникающие по мере роста моего приложения.

Формулировка проблемы:
У меня есть класс, который должен бытьиспользуется для создания полиморфных объектов, для каждого из которых требуется переменное количество массивов в качестве входных данных.Таким образом, у меня может быть два-пять экземпляров этих объектов во время работы моего приложения.И между ними эти объекты могут иметь 15 массивов.Более того, некоторые из этих массивов должны быть модифицируемыми из множества других, других объектов после их создания, а не только теми объектами, которые создали или «разместили» их.

Три вопроса:
1.) Какой самый устойчивый / рекомендуемый способ передачи нескольких различных массивов в класс?Я использовал подход varargs ниже, но не уверен, что это лучший способ.
2.) Как избежать проблем из-за статического ключевого слова?Вы увидите, что код в Main.java ниже выдает ошибки, связанные со статическим ключевым словом.Я не решаюсь разрешить всем экземплярам класса совместно использовать одну копию массива.Весь этот код находится во внутреннем фрейме в графическом интерфейсе, и позже я могу разрешить пользователю создавать несколько внутренних фреймов, каждый со своими собственными экземплярами всего этого кода для совершенно разных наборов данных.
3.) Как я могу разрешить различным другим объектам редактировать и иным образом манипулировать этими массивами после их создания?Ниже вы можете видеть, что я передаю массивы в Another.java, который затем присваивает эти массивы локальным переменным класса перед редактированием массива.Является ли локальный массив тем же объектом, который был передан в Another.java, или я допустил ошибку, создав дублирующиеся массивы?

Примеры кода:
Примеры кода ниже для иллюстрациичто я должен сделать.

Может кто-нибудь показать мне переписанную версию кода ниже, которая исправляет эти проблемы?

Кроме того, я был бы очень признателен за любые ссылки, которые вы можете отправить на статьи о том, как лучше всего решить эти проблемы.

Main.java

public class Main {
int arrayLength = 10;
double[] array1 = new double[arrayLength];
double[] array2 = new double[arrayLength];
double[] array3 = new double[arrayLength];
double[] array4 = new double[arrayLength];
double[] array5 = new double[arrayLength];

static void makeHandleArrays(){// how do I avoid static errors thrown here?
    HandleArrays firstHandleArrays = new HandleArrays();
    firstHandleArrays.arrayLength(array1);

    HandleArrays secondHandleArrays = new HandleArrays();
    secondHandleArrays.arrayLength(array1,array2,array3); //varargs approach
}

public static void main(String[] args){//how do I avoid static errors thrown here?
    makeHandleArrays();
    Another myOtherClass = new Another(array1,array2);
}}

HandleArrays.java

public class HandleArrays {//Is this varargs approach the best way to handle a variable number of arrays as inputs?
double[][] dataArrays;
int numArrays;
void arrayLength(double[] ...ds){
    dataArrays = new double[ds.length][];
    numArrays = ds.length;
    for(int i = 0;i<ds.length;i++){
        dataArrays[i]=ds[i];
    }
}
}  

EditArrays.java

public class EditArrays {
      double[] thisHereArray=new double[10];
EditArrays(double[] arrayToEdit){  
                thisHereArray=arrayToEdit;
    thisHereArray[6]=4.678;//does this edit the same object that was passed into the class?  Or did I make an error with the name change?  
}
}

Another.java

public class Another {
double[] localArray1;
double[] localArray2;

Another(double[] anArray){
    localArray1=anArray;
    EditArrays myEditArrays = new EditArrays(localArray1);// does the name change mean that this line is NOT editing the same anArray?
}
Another(double[] anArray, double[] anotherArray){
    localArray1=anArray;
    localArray2=anotherArray;
    EditArrays myEditArrays = new EditArrays(localArray1);// does the name change mean that this line is NOT editing the same anArray?
    EditArrays anotherEditArrays = new EditArrays(localArray2);// does the name change mean that this line is NOT editing the same anotherArray?
}
}  

1 Ответ

1 голос
/ 18 ноября 2011

Кажется, здесь происходит ряд разных проблем, поэтому я постараюсь их решить.

  • 1) Подход Varags

На самом деле вы не используете varags - вы используете overloading. Вместо того, чтобы иметь несколько методов с увеличивающимся числом переменных, вы можете просто объявить:

void methodName(dataType...variableName) {
    // method code here
}

Который даст вам массив типа входных данных (так что в этом случае вы получите массив массивов). Часто на varags ссылаются в цикле foreach. Единственным условием их использования является то, что они должны быть объявлены как последний параметр; также важно помнить, что их фактическое предоставление не является обязательным.

  • 2) static проблемы с ключевыми словами

Проблема, с которой вы сталкиваетесь при использовании ключевого слова static, заключается в том, что вы пытаетесь получить доступ к экземплярам переменных внутри метода static (на уровне класса). Методы static могут обращаться только к static переменным и переменным, которые были предоставлены как часть входных параметров. Чтобы обойти «статические ошибки», вам нужно будет передать либо экземпляр класса (через ссылку this), либо определенный массив, либо изменить ссылку на массив, чтобы она была статической:

Статические ссылки:

public class Main {
    static double[] arr = new double[10];

    public static void main(String...args) {
        arr[0] = 5;
    }
}

Передача в экземпляре ссылки:

public class Main {
    double[] arr = new double[10];

    static void modifyArray(double[] modArr) {
        modArr[0] = 3;
    }

    public static void main(String...args) {
        Main inst = new Main();
        modifyArray(inst.arr);
    }
}
  • 3) Внешнее редактирование массивов

Похоже, у вас возникла путаница по поводу того, как java обрабатывает входные параметры.
Java обрабатывает все входные параметры как передачу по значению, иногда называемую передачей копии. Это подробно описано в других разделах этого сайта, поэтому я не буду подробно останавливаться на этом.
Что это значит для вашего кода, это:

EditArrays(double[] arrayToEdit) {
    thisHereArray = arrayToEdit;
    thisHereArray[6] = 4.678;
}

фактически изменяет один массив - на который есть три (или более) ссылок. То есть thisHereArray и arrayToEdit, а также любая ссылка (скажем, localArray1 из Another) была передана, все указывают на точно такой же массив в памяти. Этот код производит эквивалентный эффект:

EditArrays(double[] arrayToEdit) {
    thisHereArray = arrayToEdit;
    arrayToEdit[6] = 4.678;
}

Все, что вы сделали, это продублировали ссылки, не фактический массив. В зависимости от ваших требований, это может быть хорошо или плохо. В многопоточной среде это вызовет огромное количество (почти не поддающихся отслеживанию / воспроизводимых) ошибок. В однопоточной среде вы, вероятно, в порядке.

  • Предоставление дополнительной обратной связи

Не зная ваших точных требований, немного сложно дать дополнительную обратную связь. Я могу дать некоторые общие рекомендации:

  1. Используйте массивы только для коллекций с определенным или постоянным размером. В противном случае используйте члены Collections framework.
  2. Не создавайте и не называйте переменные в формате variableSameTypeSameName1, variableSameTypeSameName2. У вас либо есть коллекция одних и тех же вещей (как вы, кажется, здесь), и все они должны быть помещены в коллекцию (массив), или они все представляют разных вещей и должны быть названы как таковые (peopleToInvite, peopleToExclude, peopleToKill).
  3. Do NOT выполняет редактирование внешних (передаваемых как параметр) объектов внутри конструктора. Вы можете передать ссылку на редактируемый объект, а затем вызвать метод для его редактирования.
  4. Не используйте System.out.println() внутри «обычных» или производственных методов (если вы не создаете консольное приложение, в чем я сомневаюсь). Это хорошо для отладки / разного тестирования, когда вы проверяете вещи.
  5. Вы упоминаете, что этот код работает в an internal frame in the GUI, хотя вы не предоставляете никакого кода Swing / AWT. Никогда не смешивать любой код пользовательского интерфейса с «бэкендом» или кодом модели напрямую (трудно сказать, что вы пытаетесь сделать, поэтому это не может быть проблемой) - следует избегать головной боли, которую он вызывает.
...