2015-12-24 2 views
7

Я получаю ошибку ClassCastException, когда я запускаю ее из-за неявного приведения d к двойному при запуске кода. Однако, если я изменяю ссылку на d in на Object[], то это не может быть параметром функции set. Если я изменю функцию set, чтобы принять Object[], тогда все будет работать нормально, но тогда класс будет терпеть неудачу во время выполнения, если кто-либо вызовет set на объект, который не имеет тип N.Возвращение массива из общего класса

Мне нужно решение, которое может get() старый массив (или его клон), и который может set() данных в новый массив.

public class Foo<N> { 

    public static void main(String[] args) { 
     Foo<Double> foo = new Foo<Double>(); 
     Double[] d = foo.get(); 

     // do stuff to d ... 

     foo.set(d); 
    } 

    N[] data; 

    public Foo() { 
     data = (N[]) new Object[2]; 
    } 

    public N[] get() { 
     return (N[]) data; 
    } 

    public void set(N[] data) { 
     this.data = data; 
    } 

} 
+1

Возможный дубликат [Как создать общий массив в Java?] (Http://stackoverflow.com/questions/529085/how-to-create-a-generic-array-in-java) – Julien

+0

Это не дубликат этого q. – avisnacks

+0

вы можете использовать этот http: // stackoverflow.com/a/3403976/2513573 для извлечения типа и Array.newInstance для создания массива – AdamSkywalker

ответ

1

Для создания массива с правильным типом выполнения требуется некоторое представление времени выполнения этого типа. Общий класс, такой как Foo<N>, не имеет представления времени исполнения N.

Есть два решения:

  1. Используйте List<N> вместо этого. Это лучше, если это возможно!
  2. Вручную добавьте представление времени исполнения N, перейдя в Class<N> в Foo, для создания массива используйте java.lang.reflect.Array.newInstance.

Код для второго решения:

public Foo(Class<N> newDataClass) { 
    data = (N[]) Array.newInstance(newDataClass, 2); 
} 

Foo<Double> foo = new Foo<>(Double.class); 

EDIT:

Если то, что вы хотите сделать, это вместо того, чтобы получить копию существующего Double массива вы можете сделать это с (N[]) data.clone(). Установка этого не будет проблемой.

1

Есть трюк.

class Foo<N> { 

    // Deliberately no parameters. 
    N[] myArray = makeArray(); 

    private N[] makeArray(N... ns) { 
     return ns; 
    } 

    public N[] get() { 
     return myArray; 
    } 
} 

Это может выглядеть как нет литья (что хорошо), но на самом деле есть, это просто делается с помощью системы varargs.

+0

Возможно, я был неясен в вопросе, но в моем случае массив уже создан, и мне нужно внести в него изменения. Поэтому мне нужно, чтобы это от foo что-то с этим делало. И сбросьте его. У меня не может быть решения, которое создаст его в конструкторе. – avisnacks

+2

@avisnacks: В вашем примере вы создаете массив в конструкторе 'Foo'. Разве это не так, как должно работать? Можете ли вы обновить вопрос, чтобы сделать это более ясным? – Lii

+0

@OldCurmudgeon: Это не работает. Вы всегда будете получать массив 'Object' в' myArray'. Когда инициализатор называет 'makeArray', нет следа' N' слева, он был удален. Общий метод vararg всегда создает массивы Object. Создание массивов общего типа вообще невозможно. Это описано, например, в [Учебном пособии по Java] (https://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#createArrays). – Lii

1

Удобный (но подробный) способ сделать это - изменить конструктор, чтобы принять фиктивный аргумент с типом массива, так как вы знаете, что он двойным по вашему основному методу.

public class Foo<N> { 
     N[] data; 

     public Foo(N inType) { 
      data = (N[]) Array.newInstance(inType.getClass(), 2) ; 
     } 

     public N[] get() { 
      return (N[]) data; 
     } 

     public void set(N[] data) { 
      this.data = data; 
     } 

     public static void main(String[] args) { 
      Foo<Double> foo = new Foo<Double>(new Double(0)); 
      Double[] d = foo.get(); 
      // do stuff to d ... 
      foo.set(d); 
     } 

    } 
0

Проблема с общим заключается в том, что во время выполнения он не имеет определенного типа. Это всего лишь класс Object, что означает, что создание такого объекта совершенно бессмысленно, потому что вы фактически создали бы объект типа Object.

Однако вы можете создавать такие объекты извне класса, поскольку здесь известен реальный тип объекта (Double). Поэтому я бы предложил использовать какой-то List, который может быть динамическим, чтобы сохранить значения.

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