2016-03-20 5 views
1

Можно ли объявить массив чего-то, что расширяет класс?Array of <? extends T> в Java

я могу сделать:

Map[] foo; 
T[] foo;  //(in generic class) 
Map... foo; //(as argument declaration for "implicit" array) 
T... foo; //(as argument declaration in generic class for "implicit" array) 

Но мне нужно что-то вроде:

<? extends Map>[] foo; 
<? extends T>[] foo;  //(in generic class) 
<? extends Map>... foo; //(as argument declaration for "implicit" array) 
<? extends T>... foo; //(as argument declaration in generic class for "implicit" array) 

Он может быть использован какой-то List<? extends T>, но вместо этого он не совсем массив. Для примера, если вы хотите использовать его в так:

public class MyClass<T> { 
    public void foo(int someOtherStuff, <? extends T>... optionalArray){ 
     //some code 
    } 
} 

Может быть, «неявное» массив не является правильным, пожалуйста, скажите мне, как они называются правильно.

+0

Umm, все ссылки в Java уже могут содержать подтипы, поэтому что-то вроде 'Number [] foo = {new Integer (0), new Double (1), new Long (2), ...};' уже отлично. Это то, что вы хотите? – Radiodef

ответ

1

Кстати ..Я нашел ответ на первоначальный вопрос, может быть, кто-то нуждается в один день:

public class MyClass<T> { 
    public <R extends T> void foo(int someOtherStuff, R... optionalArray){ 
     //some code 
    } 
} 

Нашли его по ошибке, посмотрев на реализацию Arrays.asList(T[] a). В знал, что я видел, что синтаксис где-то просто не помнил, где.

+0

Ах, не знал этого. Где точное преимущество по сравнению с массивом 'T ...? –

+0

В приведенном выше примере, возможно, нет пользы, но это может быть полезно, если у вас есть: 'public void foo (Список )) {/ ** /}' Тогда этот метод будет принимать списки массивов всего, что расширяет Т. Но я никогда не нуждался в этом ... возможно, в будущем, когда я знаю, что он существует :) – afx

4

Объекты в Java являются полиморфными: вы можете просто объявить массив общего базового типа и иметь в нем объекты всех видов производных классов.

Ехать с примером Radiodef, это действует код:

Number[] foo = {new Integer(0), new Double(1), new Long(2), ...}; 

Что Java не является механизм, который определяет массив ограничен одной конкретных производного типа некоторых известного базового класса, где особенно производном тип известен только во время выполнения.

Итак, если вы имеете в виду public void foo(int someOtherStuff, <? extends T>... optionalArray), чтобы проверить, все ли объекты в optionalArray имеют одинаковый производный тип, тогда ответ заключается в том, что это невозможно сделать автоматически. Однако вы можете использовать

public void foo(int someOtherStuff, T... optionalArray) 

, чтобы получить гарантию того, что все объекты в массиве являются производными одного и того же класса T. Однако они могут иметь разные производные типы.

+1

Кроме того, даже массивы являются ковариантными. 'Number [] foo = new Integer [1];' также отлично действует, даже если он имеет оговорки, а именно: «ArrayStoreException». – Radiodef

+0

Извините, Феликс, нашел точный ответ на мой первоначальный вопрос и отметил, что он принят ;-) – afx

0

Вы совершенно правы Radiodef и Феликс
Большое спасибо за развернутый объяснений!

Я просто подумал, что должен объявить это так, потому что что-то не сработало, и я подумал, что это проблема. Но что-то другое было действительно проблемой. Сразу хочу оговориться, это быстро:

У меня следующий общий класс: (? Или нет)

public class MyClass<T> { 
    public void foo1(List<Object> someList){ //wrong 
     //some code 
    } 
    public void foo1(Object... someArray){ 
     //some code 
    } 
    public void foo2(List<? extends T> someList){ 
     foo1(someList); 
     //some code 
    } 
} 

Я хотел, что foo2 будет вызывать foo1(List<Object> someList), но вместо этого он вызывается foo1(Object... someArray), даже если T всегда будет распространяться объект

Однако, чтобы сделать эту работу, foo1(List<Object> someList) должен быть объявлен как это:

public void foo1(List<? extends Object> someList){ //correct 
     //some code 
    } 

тогда foo2 будет ссылаться на это, а не foo1(Object... someArray).

+0

Эх ... это, безусловно, о чем-то думать :) Кажется, что в Java кажется более удобным рассматривать список '? расширяет T' как массив базовых объектов, а не рассматривает его как список базовых объектов. Почему это так, я не знаю. Это хороший вопрос, просто спросите еще раз! –