2013-11-21 2 views
0

Я пытаюсь представить эту программу для манипулирования звука, но я получаю эту ошибку:Почему мой код глубокой копии Java говорит мне, что «Задание требует глубокой, а не мелкой копии»?

Assignment requires a deep, not shallow copy. Are you just copying pointers, or copying the contents of the array?...

Я думаю, что я делаю неполную копию на моем общедоступном ничтожном наборе (double[] mySamples), но я новичок в Java и действительно не знаю, что делать.

public class Sound 
{ 
    private double[] temp; 
    private double[] samples; 

    public Sound() { 
     samples = null; 
    } 

    public Sound(Sound s) { 
     int j = 0; 
     double[] source = s.samples; 
     double temp[] = new double[source.length]; 
     for(int i = 0; i < source.length; i++) { 
      temp[j] = source[i]; 
     } 
     samples = temp; 
    } 

    public double[] get() { 
     return samples; 
    } 

    public void set(double[] mySamples) { 
     if (mySamples == null) { 
      throw new IllegalArgumentException("samples cannot be null"); 
     } else { 
      samples = mySamples; 
     } 
    } 


    public void increaseVol(double percent) { 
     double [] result = new double[samples.length]; 
     for (int i = 0; i < samples.length; i++) { 
      double reduce = samples[i] * percent; 
      result[i] = samples[i] + reduce; 
     } 
     samples = result; 
    } 

    public void wavSave(java.lang.String fileName) { 
     WavIO.write(fileName, samples); 
    } 
} 
+4

Пожалуйста, отредактируйте свой код так, чтобы он показывал разумные углубления. Укажите, какая строка показывает ошибку. –

+0

Это мой первый раз на этом веб-сайте, действительно не знаю, что вы подразумеваете под разумным отступом. Все равно, спасибо за помощь. – user3079090

+1

Вы добавляете пробелы в строки кода, которые должны быть отступом, например, код внутри блоков. Это не имеет никакого отношения к этому сайту и относится к базовому форматированию кода Java. Это важно, потому что чем проще читать код, тем легче вам помочь. Опять же, какая строка показывает вашу ошибку? –

ответ

1

Я думаю, что вам нужно сделать два изменения -
Ваш конструктор делает что-то странное с этими образцами (и может быть причиной вашей ошибки сам по себе) - я не уверен, что вы пытаетесь делать, но я думаю, вам нужно просто отложить установку.

public Sound(Sound s) { 
    int j = 0; 
    set(s.samples); 
} 

Просто скопируйте массив образцов в наборе, и хранить его.

public void set(double[] mySamples) { 
    if (mySamples == null) { 
    throw new IllegalArgumentException(
     "samples cannot be null"); 
    } else { 
    samples = new double[mySamples.length]; 
    for (int i = 0; i < mySamples.length; i++) { 
     samples[i] = mySamples[i]; 
    } 
    } 
} 
+0

Спасибо большое! Это решило мою проблему ... – user3079090

0

Да, вы делаете «мелкие» копии. Массивы в Java похожи на указатели, в том случае, если вы вернетесь или установите массив, это всего лишь указатель (действительно, ссылка) на этот массив. С вашим текущим кодом для разных объектов Sound довольно легко ссылаться на один и тот же базовый массив, который, вероятно, не тот, который вы хотите.

В методе set вам нужно скопировать содержимое массива, а не просто копировать ссылку на этот массив.

Вы правильно копируете содержимое массива в конструкторе Sound(Sound s). Однако вам не нужно вручную выделять новый массив и записывать for-loop для копирования значений. Просто позвоните java.util.Arrays.copyOf(), чтобы скопировать его. Вы можете использовать подобный метод в методе set.

Метод get также имеет проблему, когда он возвращает ссылку на массив из вашего объекта Sound. Теперь вызывающий абонент ссылается на внутреннее состояние объекта Sound и может манипулировать им. Это может быть или не быть тем, чего вы хотите.

0

Примитивные массивы и массивы автобоксированных ссылочных типов (из примитивов) являются окончательными и неизменяемыми. Поэтому они являются идеальными кандидатами для метода clone().

Вы можете редактировать этот код:

public void set(double[] mySamples) { 
    if (mySamples == null) { 
     throw new IllegalArgumentException(
      "samples cannot be null"); 
    } else { 
     samples = new double[mySamples.length]; 
     for (int i = 0; i < mySamples.length; i++) { 
      samples[i] = mySamples[i]; 
     } 
    } 
} 

в это с той же функциональностью и высокой производительностью:

public void set(double[] mySamples) { 
    if (mySamples == null || mySamples.length < 1) { 
     throw new IllegalArgumentException(
      "samples cannot be null or empty"); 
    } 
    samples = mySamples.clone(); 
} 

Это работает безопасно, потому что double s неизменны и примитивные и поэтому мелкая копия так же как и глубокая копия в этом случае. Это также безопасно, потому что double не может быть подклассифицирован, и поэтому без clone().

Кроме того, производительность clone() на массивах намного, намного быстрее, чем итерация по массиву в коде и копирование элемента по элементу.

TL; DR: Создание копии массива примитивов (или массива соответствующих автобоксированных ссылочных типов, соответствующих примитиву) вполне возможно является единственным случаем, когда он идеален для использования метода clone().

Смежные вопросы