2011-03-25 2 views
1

У меня простой общий класс, как показано ниже:Инстанцирование вспомогательный класс универсального типа класса

public class Test<T extends Number> { 

    public void doSomething() { 
     Test t = new Test(); 
     t.getNumber(); 

    } 

    public T getNumber() { 
     T d = new Double("1.5"); // I get an compiler error here! 
     return d; 
    } 
} 

Метод getNumber возвращает T (который расширяет Number) и в его реализации инстанцирует в два раза. Компилятор бросает вверх ошибку на линии:

T d = new Double("1.5"); // I get an compiler error here! 

ошибка:

Incompatible types: 
[ERROR] found : java.lang.Double 
[ERROR] required: T 

Поскольку T расширяет Number, я ожидал бы эту работу. Я что-то упускаю?

ответ

3

T расширяет номер, но это не означает, что он расширяет Double. Double - это только один из известных подклассов Number.

+0

Я понимаю, что вы имеете в виду. Хотя, это немного запутанно. Благодаря! –

1

Неправильно использовать общие параметры слева и конкретную реализацию справа.

0
T d = (T)new Double("1.5"); 

Вы должны набрать букву T. Даже при том, что она решает вашу проблему, я с подозрением отношусь к тому, что вы делаете.

1
  1. Вы должны получить предупреждение о компиляторе при создании экземпляра теста.
  2. Представьте, что вы создаете экземпляр Test<Integer>. Затем линия в методе getNumber становится:

    Целое число d = новое Двойное ("1,5");

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

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

public class Test { 
    public Number getNumber() { 
     Number d = Double.valueOf("1.5"); // No compiler error 
     return d; 
    } 
} 

Другим решением было бы выразить условие, что вы можете использовать любой суперкласс Double в качестве аргумента типа, т.е. :

public class Test<T super Double> { 
    public T getNumber() { 
     T d = Double.valueOf("1.5"); // No compiler error 
     return d; 
    } 
} 

несколько общих советов:

  • не боксировать примитивные типы без хорошего причина.
  • Не используйте new для создания экземпляров примитивов в штучной упаковке, вместо этого используйте статические методы фабрики в классах бокса.
  • Не используйте общие типы без уважительной причины. И когда вы переходите к проблеме определения общего типа, не создавайте экземпляр без параметра типа.
0

Родовое определение типа class Test<T extends Number> означает, что тот, кто хочет создать объект вашего Test класса может выбрать, какой параметр типа для использования. Пользователь выбирает, а не как разработчик класса.

Это означает, что вы не можете быть уверены, какой тип будет, и, таким образом, ваш метод getNumber() может только безопасно

  • возвращает объект, который каким-то образом пришел в качестве T объекта
  • возвращение null
  • возвращает объект, возвращаемый каким-либо другим способом T.
    • возвращает объект, созданный из возвращения Class<T> (или Class<? extends T>)
    • объект из Collection<T> (или Collection<? extends T>)
    • нечто подобное
Смежные вопросы