it-swarm.com.de

Java generics, Klasse <T> des generischen Parameters abrufen

Ich habe eine abstrakte Klasse:

public abstract class RootProcessor<T> {
    Class<T> clazz;
}

Ich muss ClassT clazz; mit den Kindern von RootProcessor - jedes Kind hat sein eigenes T

Ich habe nur eine Lösung gefunden, aber sie benötigt das Compiler-Argument -Xlint:unchecked

public RootProcessor(){
    this.clazz = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}

Ist das die beste Lösung? Können wir das auch ohne -Xlint:unchecked?

40
Victor Mezrin

Die typsichere, aber kesselspezifische Methode hierfür ist die Übergabe des Class<T> Token "wo der Compiler es sehen kann":

public abstract class RootProcessor<T> {
    Class<T> clazz;

    protected RootProcessor<T>(Class<T> clazz) {
        this.clazz = clazz;
    }
}

public class FooProcessor extends RootProcessor<Foo> {
    public FooProcessor() {
        super(Foo.class);
    }
}

Wenn Sie eine ungeprüfte Besetzung machen, aber "wissen, was Sie tun" und möchten, dass der Compiler aufhört, sich zu beschweren, wäre der richtige Ansatz, die nicht typensicheren, aber Sie wissen, dass sie funktionieren und zu lokalisieren mit @SuppressWarnings:

public abstract class RootProcessor<T> {
    Class<T> clazz;
    { initClazz(); }

    @SuppressWarnings("unchecked")
    private void initClazz() {
        // the usual verbiage you already have in your question
        this.clazz = this.getClass().getGenericSuperclass().yadda().blah();
    }
}

(Ich werde das nicht gegen dich halten: P)

34
millimoose

Es gibt einen Beitrag zum selben Thema: Reflecting generics

Und eine Klasse, die es implementiert: TypeArgumentsUtils.Java

Ein Beispiel ist im Unit-Test.

Also, wenn Sie diese Klasse haben:

public class BarProcessor extends RootProcessor<Bar> {
    public BarProcessor() {
    }
}

als würden Sie den ersten Parameter mit erhalten:

Class barClass = TypeArgumentsUtils.getFirstTypeArgument(
        RootProcessor.class, BarProcessor.class);
3
Basilios Raptis