2012-03-29 23 views
1

(Mit Java) Ich implementiere eine generische Klasse, die eine B-Struktur ist. Wenn der Benutzer das Programm ausführt, kann er einige Argumente angeben, die den Typ des Baumes bestimmen (Integer, Character, Double oder String).Erstelle ein Objekt einer generischen Klasse

In meinem Haupt-Methode habe ich diesen Code:

// Get user input and split it into tokens 
// Tokens[1] = the type specified by the user 

if(tokens[1].equals("DOUBLE")) 
    BTree<Double> t = new BTree<Double>(); 

else if(tokens[1].equals("CHARACTER")) 
    BTree<Character> t = new BTree<Character>(); 

else if(tokens[1].equals("INTEGER")) 
    BTree<Integer> t = new BTree<Integer>(); 

else if(tokens[1].equals("STRING")) 
    BTree<String> t = new BTree<String>(); 

Aber der Compiler beschwert sich, wenn ich die if-Anweisungen haben. Wenn ich sie entferne, kompiliert sie und läuft gut:/wie kann ich das beheben? Damit der Benutzer den Typ liefern kann und der Baum je nach Typ erstellt wird? Vielen Dank.

Hier einige der Compiler Ausgabe:

C:\Users\User\Desktop>javac *.java 
Main.java:42: error: cannot find symbol 
BTree<Double> t = new BTree<Double>(); 
symbol: variable BTree 
location: class Main 

Main.java:42: error: cannot find symbol 
BTree<Double> t = new BTree<Double>(); 
symbol: variable Double 
location: class Main 

Main.java:42: error: cannot find symbol 
BTree<Double> t = new BTree<Double>(); 
symbol: variable t 
location: class Main 

.. Es gibt mehr, aber es ist ähnlich und

für jeden der Typen wiederholt
+2

Können Sie Compiler-Protokoll bereitstellen? – mishadoff

+0

Ich habe es in die Frage bearbeitet :) – Tim

+0

Frage Titel sagt: 'Erstellen Sie ein Objekt einer abstrakten Klasse ', aber eigentlich fragen Sie etwas anderes. – anubhava

Antwort

1

Die Variable t in jeder der if Anweisungen ist nur im if Kontext definiert, außerhalb davon erkennt der Compiler sie nicht.
Definieren Sie Ihre Variable t vor den if Anweisungen.

BTree<?> t = null; 
if(tokens[1].equals("DOUBLE")) { 
    t = new BTree<Double>(); 
} 
else if(tokens[1].equals("CHARACTER")) { 
    t = new BTree<Character>(); 
} 
else if(tokens[1].equals("INTEGER")) { 
    t = new BTree<Integer>(); 
} 
else if(tokens[1].equals("STRING")) { 
    t = new BTree<String>(); 
} 
// now you can use your 't' 
+0

cool danke :) das funktioniert auch .. – Tim

+0

@Tim sollte man sich auch angewöhnen Klammern für jede 'if' Anweisung einzufügen, auch für Einzeiler – jb10210

0

Insert geschweiften Klammern:

if(tokens[1].equals("DOUBLE")){ 
    BTree<Double> t = new BTree<Double>(); 
} 
else if(tokens[1].equals("CHARACTER")){ 
    BTree<Character> t = new BTree<Character>(); 
} 
else if(tokens[1].equals("INTEGER")){ 
    BTree<Integer> t = new BTree<Integer>(); 
} 
else if(tokens[1].equals("STRING")){ 
    BTree<String> t = new BTree<String>(); 
} 

Oder deklarieren Sie Ihren Baum vor der Bestätigung:

BTree<? extends Object> t = null; 
if(tokens[1].equals("DOUBLE")) 
    t = new BTree<Double>(); 
else if(tokens[1].equals("CHARACTER")) 
    t = new BTree<Character>(); 
else if(tokens[1].equals("INTEGER")) 
    t = new BTree<Integer>(); 
else if(tokens[1].equals("STRING")) 
    t = new BTree<String>(); 
+2

Dies wird es zu kompilieren, aber 't' später in einer gemeinsamen Art wird schwierig sein. Das grundlegende Problem ist, dass jedes "t" ein anderer Typ ist. –

+0

wow das funktioniert! Danke, es war so einfach ... – Tim

+0

@JeffFoster jedes 't' ist kein anderer Typ, sie alle sind zur Laufzeit identisch. – jb10210

1

Ihre BTree<T> Klasse sollte nicht abstrakt sein, da Sie T die gleiche Funktionalität für alle Arten von der Art zu wollen, scheinen instanziieren.

Wenn Sie für verschiedene Arten von T spezifische Funktionalität benötigen, müssen Sie entweder implementieren

class CharacterBTree extends BTree<Character> 

oder tun es im Fluge wie

BTree<Character> t = new BTree<Character>() { 
    ... 
}; 

auch; deklariert Ihren BTree<T> t Variable außerhalb des, wenn das, so dass Ihr Code wird

BTree<?> t = null; 
if ("char".equals(whatever)) { 
    t = new BTree<Character>(); 
} else if { 
    ... 
} 
0

i eine Fall-switch-Anweisung verwenden würde (vielleicht ist es nicht die Lösung, die Sie benötigen, wie mishandoff sagte, könnte das Protokoll zu sehen, ein wenig helfen mehr) gerade von einem logischen Standpunkt aus:

switch(tokens[1]) { 
    case "DOUBLE" : BTree<Double> t = new BTree<Double>(); break; 
    .... 
    .... 
} 
0

Wenn Sie so etwas wie

if (tokens[1].equals("DOUBLE")) 
    BTree<Double> t = new BTree<Double>(); 
else if (tokens[1].equals("CHARACTER")) 
    BTree<Character> t = new BTree<Character>(); 
// etc. 

t.doStuff(); 

, die nicht funktionieren versuchen. Erstens, weil die t Variablen nur in ihrem Bereich innerhalb ihrer if-Anweisungen sind, und zweitens, weil Sie eine Variable nicht verschiedene statische Typen entlang unterschiedlicher Code-Pfade haben können.

Sie so etwas wie

BTree<?> t; 
if (tokens[1].equals("DOUBLE")) 
    t = new BTree<Double>(); 
else if (tokens[1].equals("CHARACTER")) 
    t = new BTree<Character>(); 
// etc. 

tun konnte, aber dann kann man nichts Nützliches mit den Einzelteilen in t später, weil der Code gespeichert tun, die wissen, folgt nicht, was es ist ein Baum. Dies ist eher ein grundlegendes Designproblem, kein Syntaxproblem.

Sie könnten eine Schnittstelle erstellen - nennen wir sie ValueHolder - und definieren, welche Operationen Sie für die Werte in der Struktur ausführen müssen. Definieren Sie dann Klassen wie DoubleHolder, CharacterHolder usw., die die Schnittstelle ValueHolder implementieren. Dann können Sie schreiben:

BTree<? extends ValueHolder> t; 
if (tokens[1].equals("DOUBLE")) 
    t = new BTree<DoubleHolder>(); 
else if (tokens[1].equals("CHARACTER")) 
    t = new BTree<CharacterHolder>(); 
// etc. 

und danach können Sie Elemente aus dem Baum abrufen und sie werden von Typ sein ValueHolder so können Sie eine der Methoden, die von dieser Schnittstelle aufrufen.

Verwandte Themen