Wie überprüfe ich das (generische (generisches Argument))?
Dies ist eine Frage abgeleitet vonErstellen Sie einen generischen Baum mit Vererbung . Ich öffne diese Frage als separate Frage, da dies nicht nur mit einem Tree-Problem zusammenhängt. Dies ist eher ein generisches und ein Klassenproblem.
FrageZur besseren Veranschaulichung durch Codes haben wir aTree
Klasse aSubTree
Klasse und aWrongSubTree
Klasse:
class Tree<TREE extends Tree<?,?>, DATA> {
}
class SubTree<STREE extends SubTree<?,?>, DATA> extends Tree<STREE, DATA> {
}
class WrongSubTree<WSTREE extends Tree<?,?>, DATA> extends Tree<WSTREE, DATA> {
}
Bei der Objekterstellung möchten wir überprüfen, ob das generische Argument der Klasse des Objekts selbst entspricht:
Tree<Tree<?,?>, String> tree01 = new Tree<Tree<?,?>, String>(); // equals : OK
Tree<SubTree<?,?>, String> tree02 = new Tree<SubTree<?,?>, String>(); // (!) not equals
SubTree<SubTree<?,?>, String> tree03 = new SubTree<SubTree<?,?>, String>(); // equals : OK
WrongSubTree<Tree<?,?>, String> tree04 = new WrongSubTree<Tree<?,?>, String>(); // (!) not equals
(Beachten Sie, dass die 4 obigen Zeilen vorerst keine Kompilierungsfehler und keine Laufzeitausnahmen enthalten.)
Mein VersuchDazu versuchen wir aClass<>
Parameter in den Konstruktoren:
class Tree<TREE extends Tree<?,?>, DATA> {
public Tree(Class<TREE> clazz) {
System.out.println(this.getClass());
System.out.println(clazz);
System.out.println();
if (this.getClass() != clazz)
throw new RuntimeException();
}
}
class SubTree<STREE extends SubTree<?,?>, DATA> extends Tree<STREE, DATA> {
public SubTree(Class<STREE> clazz) {
super(clazz);
}
}
class WrongSubTree<WSTREE extends Tree<?,?>, DATA> extends Tree<WSTREE, DATA> {
public WrongSubTree(Class<WSTREE> clazz) {
super(clazz);
}
}
(Die obigen Klassendefinitionen sind gültige Java-Codes.)
ProblemAber ich weiß nicht, wie ich diesen Konstruktor nennen soll:
Tree<Tree<?,?>, String> tree01a = new Tree<Tree<?,?>, String>(Tree.class);
// The constructor Tree<Tree<?,?>,String>(Class<Tree>) is undefined
Tree<Tree<?,?>, String> tree01b = new Tree<Tree<?,?>, String>(Tree<?,?>.class);
// Syntax error, insert "Dimensions" to complete ArrayType
Die beiden obigen Zeilen verursachen Kompilierungsfehler.
Ich denke, es liegt am Konstruktorpublic Tree(Class<TREE> clazz) {}
erwartetClass<Tree<?,?>>
, aber nichtClass<Tree>
. Das können wir jedoch nichtTree<?,?>.class
.
Der Grund ist, ich habe versucht, die Klasse zu ändern:
class Tree<TREE extends Tree<?,?>, DATA> {
public Tree(Class<Tree> clazz) { // changed
System.out.println(this.getClass());
System.out.println(clazz);
System.out.println();
if (this.getClass() != clazz)
throw new RuntimeException();
}
}
Tree<Tree<?,?>, String> tree01a = new Tree<Tree<?,?>, String>(Tree.class);
Es liegt kein Kompilierungsfehler vor.
Das Folgende verursacht jedoch denselben Kompilierungsfehler:
class Tree<TREE extends Tree<?,?>, DATA> {
public Tree(Class<Tree<?,?>> clazz) { // changed
System.out.println(this.getClass());
System.out.println(clazz);
System.out.println();
if (this.getClass() != clazz)
throw new RuntimeException();
}
}
Tree<Tree<?,?>, String> tree01a = new Tree<Tree<?,?>, String>(Tree.class);
// The constructor Tree<Tree<?,?>,String>(Class<Tree>) is undefined
Bearbeiten Sie # 1Beyogen aufmein Kommentar Unten habe ich es versucht. Hoffe, es hilft für einige Inspirationen.
static class SimpleClass<T> {
private SimpleClass(Object dummy) {
// dummy constructor, avoid recursive call of the default constructor
}
SimpleClass() {
SimpleClass<T> myself = new SimpleClass<T>(new Object()) {};
System.out.println(((ParameterizedType) myself.getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
// prints "T"
TypeReference<SimpleClass<T>> typeRef = new TypeReference<SimpleClass<T>>() {};
System.out.println(typeRef.getType());
// prints "Main.Main$SimpleClass<T>"
}
void func() {
SimpleClass<T> myself = new SimpleClass<T>(new Object()) {};
System.out.println(((ParameterizedType) myself.getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
// prints "T"
TypeReference<SimpleClass<T>> typeRef = new TypeReference<SimpleClass<T>>() {};
System.out.println(typeRef.getType());
// prints "Main.Main$SimpleClass<T>"
}
}
public static void main(String[] args) {
SimpleClass<String> simpleObj = new SimpleClass<String>();
simpleObj.func();
SimpleClass<String> outsideSimpleClass = new SimpleClass<String>(){};
System.out.println(((ParameterizedType) outsideSimpleClass.getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
// prints "class java.lang.String"
}
Beachten wir nochkann nicht get "class java.lang.String"Innerhalb SimpleClass
.
Noch wichtiger ist, wenn wir das Type-Argument verwenden<T>
ein Objekt aus instanziiereneine andere Klasse, wir können immer noch nicht den Typparameter davon bekommen:
static class AnotherClass<T> {
private AnotherClass(Object dummy) {}
}
static class SimpleClass<T> {
SimpleClass() {
AnotherClass<T> another = new AnotherClass<T>(new Object()) {};
System.out.println(((ParameterizedType) another.getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
// prints "T"
TypeReference<AnotherClass<T>> anotherTypeRef = new TypeReference<AnotherClass<T>>() {};
System.out.println(anotherTypeRef.getType());
// prints "Main.Main$AnotherClass<T>"
}
void func() {
AnotherClass<T> another = new AnotherClass<T>(new Object()) {};
System.out.println(((ParameterizedType) another.getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
// prints "T"
TypeReference<AnotherClass<T>> anotherTypeRef = new TypeReference<AnotherClass<T>>() {};
System.out.println(anotherTypeRef.getType());
// prints "Main.Main$AnotherClass<T>"
}
}
Beachten Sie, dass dies das Type-Argument von bedeutetAnotherClass
kann nicht in enthüllt werdenSimpleClass
, wo es ein Ort außerhalb der Klasse selbst ist!
Nach meinem Verständnis können wir nur die anonyme Unterklasse & verwenden.getGenericSuperclass()
trick an einem ort wo es eigentlich schon die antwort kennt. Wie inmain()
Hier ist der Ort, an demclass java.lang.String
ist wirklich als das Typargument definiert.
(IMO, wenn die Fähigkeit dieses Tricks so eingeschränkt ist, ist es überhaupt nicht wirklich nützlich.)