2012-03-29 100 views
1

(使用Java)我正在實現一個泛型類,它是一個B樹。當用戶運行程序時,他們可以提供一些參數來確定樹的類型(整數,字符,雙精度或字符串)。創建泛型類的對象

在我的主要方法,我有這樣的代碼:

// 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>(); 

但是,如果我有if語句,編譯器會抱怨。如果我刪除它們然後編譯並運行良好:/我該如何解決這個問題?這樣用戶可以提供類型,樹會根據提供的類型創建嗎?謝謝。

下面是一些編譯器輸出的:

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 

..有更多的卻是相似的,重複每種類型

+2

你能提供編譯器日誌嗎? – mishadoff 2012-03-29 08:08:55

+0

我已將它編輯到問題:) – Tim 2012-03-29 08:14:47

+0

問題標題說:'創建一個抽象類的對象',但實際上你問的東西不同。 – anubhava 2012-03-29 08:16:04

回答

1

每個if語句中的變量t僅在if的上下文中定義,在它們之外編譯器將不會識別它們。
if語句之前定義變量t

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

酷謝謝:)這也適用.. – Tim 2012-03-29 08:17:04

+0

@Tim你應該養成爲每個if語句插入括號的習慣,即使對於單行 – jb10210 2012-03-29 08:35:49

0

插入大括號:

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>(); 
} 

或在聲明前宣佈你的樹:

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

這會讓它編譯,但稍後以共享的方式使用't'將會很困難。根本問題是每個't'都是不同的類型。 – 2012-03-29 08:12:49

+0

哇這個作品!感謝它非常簡單... – Tim 2012-03-29 08:16:19

+0

@JeffFoster每個't'不是一個不同的類型,它們在運行時都是相同的類型。 – jb10210 2012-03-29 08:21:56

1

BTree<T>類應該是抽象的,因爲你似乎想實例化相同的功能爲各種類型T的。

如果您需要爲不同類型的T特定的功能,你需要或者實施

class CharacterBTree extends BTree<Character> 

或做對飛象

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

也;聲明您BTree<T> t變量,如果公司的外面,所以你的代碼變得

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

我會使用一個案例switch語句(也許這不是你所需要的解決方案,因爲mishandoff說,看到日誌可以幫助一點點更)只是從邏輯上來看:

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

如果你試圖像

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(); 

這是行不通的。首先,因爲t變量只在它們的if語句的範圍內,其次,因爲不能使變量沿着不同的代碼路徑有不同的靜態類型。

你可以做類似

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

但你不能做任何事情與存儲在t的項目有用後來因爲後面不知道是什麼樹的代碼。這更多的是一個基本的設計問題,而不是語法問題。

您可以創建一個界面 - 我們稱之爲ValueHolder - 並使用它來定義您需要對樹中的值執行的任何操作。然後定義諸如DoubleHolderCharacterHolder等的類,這些類實現了ValueHolder接口。然後,你可以這樣寫:

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

和之後,你可以從樹中的項目,他們會ValueHolder型的,所以你可以調用任何由該接口提供的方法。