2015-10-16 3 views
7

Вот код:Дженерик типа стирания в Java

public class Main { 
    public static void main(String[] args) { 
     Gen<Integer> g = new Gen<Integer>(5); 

     System.out.println(g.getClass()); 
     System.out.println(g.ob.getClass()); 
    } 
} 

class Gen<T> { 
    T ob; 

    public Gen(T x) { 
     ob = x; 
    } 
} 

А вот выходного

class Gen    // This I understand 
class java.lang.Integer // But if type erasure is happening, shouldn't this be java.lang.Object? 

Я понял, что параметр Типа T стирается во время выполнения, но тогда почему параметр типа ob выживает во время выполнения?

+3

Вам нужно будет начать различать переменные, ссылки и объекты, –

+2

Если 'Car c = new Mercedes();' как вы думаете, должен быть результат 'c.getClass()' и почему? – Pshemo

+0

спасибо всем за ответ, я получаю это сейчас – Ramanlfc

ответ

0

Поскольку мое первое знакомство с дженериками было с C#, потребовалось время, чтобы удержать стирание стилей в java.

Но после лучшего понимания java generics я понял, что в своем вопросе я смешиваю 2 отдельные темы: Generics and Reflection.

Главный вопрос был, почему второй вызов здесь

System.out.println(g.getClass()); 
System.out.println(g.ob.getClass()); 

вернулся java.lang.Integer вместо java.lang.Object.

Глядя на документах для getClass(), ответ становится очевидным

Возвращает выполнения класса этого объекта.

так, getClass() не возвращает тип ссылки, но фактический объект, на который ссылается ссылка.

напр:

Object o = "abc"; 
System.out.println(o.getClass()); 

Выходной сигнал не был бы тип ссылки java.lang.Object, а тип объекта java.lang.Stringфактическое.

2

Type erasure происходит. Generics - это система проверки типа времени компиляции. Во время выполнения вы все равно получаете класс (это информация типа времени выполнения). Связанная документация по стиранию типа написана (частично)

На языке Java были введены обобщения для обеспечения более точных проверок типов во время компиляции и поддержки общего программирования. Для реализации дженериков компилятор Java применяет стирание стилей к:

Замените все параметры типа в общих типах своими границами или объектом, если параметры типа являются неограниченными. Таким образом, полученный байт-код содержит только обычные классы, интерфейсы и методы.

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

+0

Это не отвечает на вопрос OP о том, почему тип времени выполнения содержащегося объекта не «стирается». – Random832

+0

Но это (в бат-коде), он смущен rtti с информацией времени компиляции. –

4

Nope!

Рассмотрим это:

Object x = new Integer(1); 
System.out.println(x.toString()); 

Вы получите 1.

Но не должен ли я получить Object.toString()?

В то время как номер x является ссылкой типа Object, фактический референтом является Integer, поэтому во время выполнения, то Integer реализация toString называется.

То же самое для getClass.

2

Независимо от того, какой тип имеет переменная, возвращаемое значение getClass() зависит от значения переменной . Итак, поскольку у вас в основном есть переменная Object ob, которая содержит Integer (ваш int был преобразован в нее в то время, когда вы указали ее как параметр этого конструктора), выход ob.getClass() равен class java.lang.Integer.

Кроме того, о вашем вопросе о том, почему getClass() запоминает аргумент типа: это не так. Все это определяет класс контента. Например:

class Foo { 
    public Foo() {} 
} 

class Bar extends Foo { 
    public Bar() {} 
} 

class Baz<T> { 
    public T object; 

    public Baz(T object) { this.object = object; } 
} 

Если теперь запустить следующий фрагмент кода ...

public static void main(String... args) { 
    Baz<Foo> obj = new Baz(new Bar()); 
    System.out.println(obj.object.getClass()); 
} 

Вы заметите, что выход не class Foo, это class Bar.

2

Поскольку при компиляции класс Gen имеет Object ob; Дженерики исчезают из конечного продукта. Угловые скобки играют роль только во время компиляции во время проверки статического типа. Это то, что компилятор может сделать для вас, чтобы дать вам лучшее спокойствие, заверить вас, что вы правильно используете коллекции и другие параметризованные типы.

Фактический объект, назначенный ob во время выполнения, является экземпляром класса Integer, а ob.getClass() служит для поиска фактического класса объекта, на который ссылается указатель -> следовательно, вы увидите java. lang.Integer напечатан.

Помните, что получается эффективно класс Gen {Object ob; ...}

+0

Это не разъясняет, почему 'getClass()' возвращает 'Integer'. –

+0

Фактический объект, назначенный ob во время выполнения, является экземпляром класса Integer. И вот как вы узнаете ... –

+0

Это должно быть в ответе, затем –

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