2016-04-08 3 views
2

Я попытался понять следующее. Этот блок кода напечатает следующийОбщий вид с использованием скобок

[email protected] 
[email protected] 

Так что я полагаю, что бросок был успешно завершен, но я ожидаю ClassCastException для второго объекта в списке.

public class TestGenerics 
{ 
    public static void main(String[] args) 
    { 
     Generic<One> integerGeneric = new Generic<One>(new Container(Lists.<Object>newArrayList(new One(), new Two()))); 
     integerGeneric.checkContainer(); 
    } 

    static class Generic<T> 
    { 
     private Container container; 

     public Generic(Container container) 
     { 
      this.container = container; 
     } 

     public void checkContainer() 
     { 
      for (Object key : container.getObjects()) 
      { 
       final T genericKey = (T)key; 
       System.out.println(genericKey); 
      } 
     } 
    } 

    static class Container 
    { 
     Iterable<Object> objects; 

     public Container(Iterable<Object> objects) 
     { 
      this.objects = objects; 
     } 

     public Iterable<Object> getObjects() 
     { 
      return objects; 
     } 
    } 

    static class One 
    { 

    } 

    static class Two 
    { 

    } 
} 

P.S. Также у меня возникла проблема, связанная с тем, что родовой тип cast (с использованием объекта (T)) возвращает null вместо исключения исключения ClassCastExceptiong, но я не могу его воспроизвести. Если кто-нибудь знает об этом, комментарий здесь, пожалуйста

+1

Возможно, вам захочется посмотреть, что такое «стирание типа» и как оно работает на Java. – Tom

+0

Я собираюсь поспорить, что у вас есть предупреждение о немедленном предупреждении. –

+0

@Tom, спасибо, я узнал, что JVM видит общий тип объекта во время выполнения (или ближайший тип, если он существует) – Gcinbax

ответ

-2

Я узнал, что JVM см родовое как тип объекта во время выполнения (или ближайшего типа, если она «существует»)

Не обязательно Object. Это относится к неограниченным генерикам, как в вашем коде. Если у него есть привязка, например <T extends ParentClass>, тогда тип времени выполнения будет ParentClass. Поскольку ваш код не имеет ограничений, он будет Object, и это не вызовет никаких проблем во время трансляции.

Теперь, чтобы улучшить ваши проверки типов и получить соответствующие ошибки компилятора, вам нужно добавить общий тип для Container:

static class Container<T> { 
    Iterable<T> objects; 

    public Container(Iterable<T> objects) { 
     this.objects = objects; 
    } 

    public Iterable<T> getObjects() { 
     return objects; 
    } 
} 

и обновить Generic, чтобы избежать использования сырого Container класса:

static class Generic<T> { 
    private Container<T> container; 

    public Generic(Container<T> container) { 
     this.container = container; 
    } 

    public void checkContainer() { 
     for (T key : container.getObjects()) { 
      final T genericKey = key; 
      System.out.println(genericKey); 
     } 
    } 
} 

Теперь добавьте diamond operator в основной метод:

Generic<One> integerGeneric = new Generic<One>(new Container(Lists.<Object>newArrayList(new One(), new Two()))); 

И тогда вы будете иметь:

Generic<One> integerGeneric = new Generic<>(new Container<>(Lists.newArrayList(new One(), new Two()))); 

И ошибка компилятора о том, что Lists.newArrayList(new One(), new Two()) не допускается, если требуемый тип One.


Btw: вы можете обойти эту проверку компилятора либо с использованием исходных типов или Object в качестве универсального типа, и это еще не будет вызывать исключение во время выполнения, так как Container и Generic классы не имеют границ.

+0

Если кто-то задается вопросом о нижнем горизонте: [Tim Biegeleisen] (https://stackoverflow.com)/users/1863229/tim-biegeleisen) использовал его в качестве одной из своих целей для мести вниз. – Tom

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