2017-12-30 9 views
-2

Es gibt einen Trick in Java Generics inter-Klasse zirkulären Verweis zu machen:Instantiate Kreisgenerische Klassen verwies

public static class GenA<A extends GenA<A, B>, B extends GenB<A, B>> { 
    public B objB; 
} 
public static class GenB<A extends GenA<A, B>, B extends GenB<A, B>> { 
    public A objA; 
} 

Wenn ich versuche reales Objekt zu instanziieren:

GenA<GenA, GenB> genA = new GenA<>(); 

I Kompilierungsfehlern erhalten:

CircularRef.java:7: error: type argument GenA is not within bounds of type-variable A 
     GenA<GenA, GenB> genA = new GenA<>(); 
    where A,B are type-variables: 
    A extends GenA<A,B> declared in class GenA 
    B extends GenB<A,B> declared in class GenA 
CircularRef.java:7: warning: [rawtypes] found raw type: GenA 
     GenA<GenA, GenB> genA = new GenA<>(); 
    missing type arguments for generic class GenA<A,B> 
    where A,B are type-variables: 
    A extends GenA<A,B> declared in class GenA 
    B extends GenB<A,B> declared in class GenA 
CircularRef.java:7: warning: [rawtypes] found raw type: GenB 
     GenA<GenA, GenB> genA = new GenA<>(); 
    missing type arguments for generic class GenB<A,B> 
    where A,B are type-variables: 
    A extends GenA<A,B> declared in class GenB 
    B extends GenB<A,B> declared in class GenB 
CircularRef.java:7: warning: [unchecked] unchecked method invocation: constructor <init> in class GenA is applied to given types 
     GenA<GenA, GenB> genA = new GenA<>(); 
    required: no arguments 
    found: no arguments 
CircularRef.java:7: warning: [unchecked] unchecked conversion 
     GenA<GenA, GenB> genA = new GenA<>(); 
    required: GenA<GenA,GenB> 
    found: GenA 

ich weiß Abhilfe:

public static class AdapterA extends GenA<AdapterA, AdapterB> { } 
public static class AdapterB extends GenB<AdapterA, AdapterB> { } 

, die funktioniert wie:

AdapterA adA = new AdapterA(); 
AdapterB adB = new AdapterB(); 
adA.objB = adB; 
adB.objA = adA; 

Wie kann ich instanziiert GenA/GenB Klassen direkt?

Sie sind nicht abstract. Ich mag -Xlint:all sagt keine Warnung zu.

EXTRA Ich schrieb Frage Defining typed hierarchy with Java generics and type self-referencing das oben beschriebene Problem in einer Menge Code und langweilig Benutzer versteckt enthält wie es schließen))

Einige Hinweise über generische Kreis Referenzierung Erklärung deklarieren sind bei:

UPDATE zusätzliche Referenz Mit Zugabe:

public static class GenA<A extends GenA<A, B, C>, B extends GenB<A, B, C>, C extends GenC<A, B, C>> { 
    public B objB; 
    public C objC; 
} 
public static class GenB<A extends GenA<A, B, C>, B extends GenB<A, B, C>, C extends GenC<A, B, C>> { 
    public A objA; 
    public C objC; 
} 
public static class GenC<A extends GenA<A, B, C>, B extends GenB<A, B, C>, C extends GenC<A, B, C>> { 
    public A objA; 
    public B objB; 
} 

Problem das gleiche für:

GenA<GenA, GenB, GenC> genA = new GenA<>(); 

und kann wie gewohnt gelöst werden:

public static class AdapterA extends GenA<AdapterA, AdapterB, AdapterC> { } 
public static class AdapterB extends GenB<AdapterA, AdapterB, AdapterC> { } 
public static class AdapterC extends GenC<AdapterA, AdapterB, AdapterC> { } 

UPDATE 2 Das Problem lem ist nicht mit Instanziierung aber mit der Erklärung der Art nach nicht:

GenA<GenA, GenB> genA; 
+0

Sie möglicherweise keine zu: 'Gena Gena = new Gena <>();' 'sollte Gena , GenB <...>>, GenB , GenB <...> >> Gena = new Gena <>() sein ; ', was am Ende unendlich lang sein kann. –

+0

** @ MadPhysicist ** Ich dachte darüber nach, aber war mir nicht sicher, da ich keine Erfahrung mit Java Generic spec ... – gavenkoa

+0

Was passiert, wenn Sie nur noch eine weitere Ebene von verschachtelten Generika hinzufügen? Wird es den Rohtypfehler loswerden? Es ist besser als eine Adapterklasse, wenn es funktioniert. –

Antwort

2

Sie in einem Verfahren mit seinem eigenen Typ Variablen instanziiert können:

<A extends GenA<A, B>, B extends GenB<A, B>> GenA<A, B> thing() { 
    return new GenA<>(); 
} 

Natürlich sind dies nur ist stochert die Frage, "wie instanziiere ich es" zu "wie rufe ich diese Methode auf". Und die Antwort darauf ist, sie in einer Methode mit eigenen Typvariablen aufzurufen (oder verwenden Sie GenA<?, ?> als den Typ, der den Wert erhält).

+0

Ja, beide 'GenA a = Sache <>();' und 'GenA a = Sache <>();' produziert Fehler ... Auch 'AdapterA xA = Ding ();' produziert Fehler – gavenkoa

+0

Wahrscheinlich weil 'Thing <>()' ist keine gültige Syntax. Geben Sie zum einen Hinweise für Methoden ein, die vor dem Methodennamen stehen. Zum anderen gilt der Diamantenbetreiber nur für den neuen Betreiber. –