创建泛型类的对象

时间:2012-03-29 08:06:41

标签: java generics if-statement

(使用Java)我正在实现一个B-Tree的泛型类。当用户运行程序时,他们可以提供一些参数来确定树的类型(整数,字符,双精度或字符串)。

在我的主要方法中,我有这段代码:

// 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

..还有更多,但它类似,并为每种类型重复

5 个答案:

答案 0 :(得分:1)

每个t语句中的变量if仅在if的上下文中定义,在它们之外,编译器将无法识别它们。
t语句之前定义变量if

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'

答案 1 :(得分:1)

您的BTree<T>类不应该是抽象的,因为您似乎想要为所有类型T实现相同的功能。

如果您需要针对不同类型T的特定功能,则需要实施

class CharacterBTree extends BTree<Character>

或者像

一样动起来
 BTree<Character> t = new BTree<Character>() {
    ...
 };

也;在if之外声明您的BTree<T> t变量,因此您的代码变为

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

答案 2 :(得分: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>();

答案 3 :(得分:0)

我会使用case-switch语句(也许它不是你需要的解决方案,因为错误的操作说,看到日志可以帮助更多一点)从逻辑的角度来看:

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

答案 4 :(得分: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,因此您可以调用该界面提供的任何方法。