2016-04-08 8 views
2

Ich habe versucht, das nächste zu verstehen. Dieser Codeblock wird gedruckt nächstGenerische Besetzung mit Klammern

[email protected] 
[email protected] 

So nehme ich an, dass Guss erfolgreich abgeschlossen war, aber ich erwarte, dass Classcast für die zweite Objekt in der Liste.

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. Auch ich sah ein Problem, dass generische Typumwandlung (mit (T) -Objekt) null zurückgibt, anstatt die Ausnahme ClassCastExceptiong zu werfen, aber ich kann es nicht reproduzieren. Wenn jemand darüber Bescheid wissen, hier einen Kommentar, bitte

+1

Sie könnten nachschlagen, was "Typ löschen" ist und wie es in Java funktioniert. – Tom

+0

Ich wette, dass Sie dort eine unkontrollierte Cast-Warnung haben. –

+0

@Tom, danke, ich habe gelernt, dass JVM generische wie Objekttyp in Runtime (oder nächsten Typ, wenn es "existiert") – Gcinbax

Antwort

-2

ich gelernt habe, dass JVM wie Objekttyp generic sieht in Runtime (oder nächstem Typ, wenn es „existiert“ hat)

Nicht unbedingt Object. Dies ist der Fall für unbegrenzte Generics, wie in Ihrem Code. Wenn es eine Grenze hat, wie <T extends ParentClass>, dann wäre der Laufzeittyp ParentClass. Da Ihr Code keine Grenze hat, wird es Object sein und dies würde während einer Besetzung kein Problem verursachen.

Nun zu Ihrem Typ Kontrollen zu verbessern und die richtigen Compiler-Fehler zu erhalten, werden Sie einen generischen Typen zu Container hinzufügen müssen:

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

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

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

und aktualisieren Generic mit einer rohen Container Klasse zu vermeiden:

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); 
     } 
    } 
} 

Jetzt ein diamond operator in Ihrer Haupt-Methode hinzufügen:

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

Und Sie werden dann haben:

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

Und ein Compiler Fehler, der besagt, dass Lists.newArrayList(new One(), new Two()) nicht, ob der gewünschte Typ One ist erlaubt.


Btw: Sie können immer noch diese Compilerprüfung umgehen, indem sie entweder mit rohen Arten oder Object als gattungs und dies wird noch nicht eine Laufzeitausnahme verursachen, da beide Container und Generic Klassen keine Grenzen haben.

+0

Wenn jemand sich über den Downvote fragt: [Tim Biegeleisen] (https://stackoverflow.com/users/1863229/tim-biegeleisen) benutzte es als eines seiner Ziele für seine Rache-Downvotes. – Tom