2016-04-06 4 views
1

zu verwenden Ich habe vor kurzem in ein bisschen Mühe beim Versuch, eine meiner bukkit Plugins Version durch Reflektion zu machen. Die Sache ist, ich weiß, wie man eine Instanz einer Klasse unter Verwendung ihres Namens erstellt, aber ich weiß nicht, wie man den Klassennamen als Typ für eine Methode oder einen Konstruktorparameter verwendet. Mit anderen Worten, ich möchte diese zu transformieren:Wie Klassenname als Typ für Methode Argument

public class Foo{ 
private Goat goat; 

public Foo(Goat goat){ 
    this.goat=goat; 
} 

in so etwas wie folgt aus:

public class Foo{ 
private Class.forName("mypackage.Goat") goat; 
public Foo(Class.forName("mypackage.Goat") goat){ 
    this.goat=goat; 
} 

Ehrlich gesagt weiß ich nicht, ob es überhaupt möglich ist, aber es würde eine Menge bei der Herstellung meiner Entwicklung helfen schneller.

EDIT:

Meine Situation ist ein wenig komplizierter als das, was ich vor vorgestellt. Das ist der Grund, warum ich keine Generika verwenden kann. Der oben abgebildete "Ziegen" -Typ I ist eigentlich eine Klasse in einem mir unbekannten Paket, daher kenne ich nur den Klassennamen. Daher muss ich die Class.forName-Methode zusammen mit einem kleinen Algorithmus verwenden, der die aktuelle bukkit-Version erkennt und an den Paketnamen anfügt, den ich bereits kenne, so dass net.minecraft.server zu net.minecraft.server.v1_8_R1 wird Mit anderen Worten, ich kenne nur den Klassennamen zur Laufzeit. Ich weiß, ich sauge zu erklären ...

+1

einen Blick auf Generika nehmen: https://docs.oracle.com/javase/tutorial/java/generics/ – user987339

Antwort

1

Aktualisiert Antwort:

Sie haben in den Kommentaren geklärt, dass Sie nur die Typnamen zur Laufzeit kennen.

Der Typ des Feldes (und Konstruktorparameter) goat ist auf Kompilierzeit festgelegt. Die einzige Möglichkeit, Runtime-Informationen zum Erstellen einer Foo-Klasse zu verwenden, besteht darin, genau das zu tun: Generiere es zur Laufzeit. Es gibt keinen Mechanismus zum Deklarieren eines Platzhalters, der später von einer Zeichenfolge ausgefüllt wird.

Wenn Sie das unbedingt tun müssen, wäre Tomcat (das JSPs on-the-fly kompiliert) und Vert.x (das Klassen on-the-fly generiert), einige Stand der Technik, die Sie aufrufen könnten. Es wird nicht trivial sein (es sei denn, du schaust natürlich nur auf javac, natürlich).

Original-Antwort:

Sie können dies mit generics:

public class Foo<T> { 
    private T goat; 
    public Foo(T goat){ 
     this.goat=goat; 
    } 
} 

Verbrauch:

Foo<Goat> f = new Foo<>(); // Or new Foo<Goat>() (earlier Java versions didn't support the <> form) 

Nun f erwartet goat ein Goat zu sein.

Es ist wie wenn man etwas aus der Sammlung Framework verwenden:

List<String> strings = new List<String>(); 
List<Date> dates = new List<Date>(); 
// ... 
+0

Dank Für die netten Infos und Erklärungen zu Generika, aber leider passen sie nicht zu meinem Fall.Wie Sie bereits gesagt haben, muss der Typ beim Erstellen eines neuen Foo-Objekts noch angegeben werden, und ich kann das nicht tun, da ich in meinem gesamten Programm nur die Klassennamen der Typen kenne, die ich möchte Verwenden Sie, da die Pakete jedes Update ändern (ich weiß, es ist mies, aber das ist die Art, wie Mojang es wollte) – dadus33

+0

@ dadus33: Ich bin nicht ganz gefolgt, sagst du nur den Namen ** zur Laufzeit **? –

+0

Yup, genau. Ich hasse auch die Stackoverflow-15-Zeichen-Regel. – dadus33