2009-07-30 3 views
7

Если у меня есть Stack классJava Raw Тип и дженерики взаимодействие

class Stack<E> {} 

теперь, если я:

1) Stack<Integer> s = new Stack()

2) Stack s = new Stack<Integer>()

3) Stack s = new Stack()

может кто-нибудь объяснить мне, что это за взаимодействия (gener ic < -> сырьевые) причины?

В основном я сомневаюсь в точке 1. На самом деле, если я делаю это назначение, это небезопасно, потому что этот стек может хранить типы, отличные от Integer. Да, но если у меня есть метод push и попытайтесь сохранить значение othern чем Integer, то компилятор остановит меня ... поэтому, когда у меня будет эта небезопасная операция?

+0

Я не понимаю - вы хотите иметь стек, где вы можете нажимать другие вещи, а затем целые (например, целые числа и парные разряды), или вы хотите использовать стек только с одним типом (Integer), и пусть компилятор помочь тебе? –

+1

Нет. Я хочу стек с одним типом и хочу знать, что произойдет, если я сделаю эти назначения. – xdevel2000

ответ

6

Все они небезопасны, потому что Java-дженерики в силу type erasure - это просто синтаксический сахар. Например, это полностью действительный код Java:

Stack<Integer> s = new Stack<Integer>(); 
Stack<Double> s2 = (Stack<Double>)s; 
s2.push(3.3d); 

Точка Java-дженериков заключается в том, что вы должны быть явно о том, как отличать объекты. Вот и все. Они ничего не делают (кроме генерации компилятора и предупреждений IDE).

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

+0

не является случаем OP # 2, где компилятор достаточно умен, чтобы вывести аргументы общего типа для s? –

+0

Да, но в пункте 1 компилятор советует мне, если я попытаюсь поставить (с помощью операции push) объект, отличный от Integer. Таким образом, может быть, что дженерики - это не только «синтаксический сахар», но и пункт 1 также изменяет поведение компилятора (семантику). Поэтому снова я не понимаю, где это небезопасно ... Должен ли, пожалуйста, дать мне более аналитическое объяснение? – xdevel2000

7

Все три являются совершенно законными, так как фактическая разница во времени между Stack и Stack<Integer>, но все три будут приводить к предупреждениям компилятора.

Stack<Integer> s = new Stack() 

Это приведет к «бесконтрольно преобразованию» предупреждение, потому что это не безопасно в целом для преобразования исходного типа в параметризованный тип. Однако в этом случае это совершенно безопасно: нажатие Integer значений не вызывает никаких ошибок; нажатие значений не Integer приведет к ошибке типа.

Stack s = new Stack<Integer>() 

Это законное преобразование из параметризованного типа в необработанный тип. Вы сможете нажать значение любого типа. Однако любая такая операция приведет к предупреждению «непроверенного вызова».

Stack s = new Stack() 

Опять же, это законно, без какого-либо неявного преобразования. Вы сможете нажать значение любого типа. Однако любая такая операция приведет к предупреждению «непроверенного вызова».

Вы также можете получить предупреждение «необработанного типа» в любое время, когда вы обратитесь к типу Stack.

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