2014-09-02 15 views
0

我最近完成了在AP计算机科学(Java)的在线课程,并在最后的考试中,是去是这样一个问题:的Java未定义泛型支架使用

Which of these needs a String cast to use String methods on it:
I. ArrayList a = new ArrayList();
II. ArrayList<Object> b = new ArrayList<Object>();
III. ArrayList<String> c = new ArrayList<String>();

一下这让我感到困惑:可以选项I甚至可以被铸造?它没有通用的定义,所以除非Java编译器拒绝ArrayList<Object>,那么什么类的是E呢?


这是(需要在抑制评论,因为这是一个“未登记”操作)我的测试代码:

ArrayList a = new ArrayList(); 

@SuppressWarnings("unchecked") 
a.add(new Object()); 

@SuppressWarnings("unchecked") 
a.add(new String("test")); 

@SuppressWarnings("unchecked") 
a.add(null); 

System.out.println((String)(a.get(0))); 

不管是在参数为add()方法,它总是给编译器错误:

test.java:14: error: <identifier> expected 
     a.add(new Object()); 
      ^

如果我尝试添加该代码的任何地方的标识符(如:a<Object>.add(new Object())),它会给出确切的同样的错误了。

问题是没有参数传递给泛型参数时实际发生的事情,并且可以首先将任何东西添加到此列表中,更不用说将其转换为另一个对象了?提前致谢!

+0

“标识符预期”表示“语法错误”。我认为这与泛型没有任何关系。然而,我没有看到你的代码有任何问题。请仔细检查一下,我会在一秒之内启动IDE。 – markspace 2014-09-02 23:58:26

+0

@markspace我再次检查它。我猜测它想要一个E类型的对象(或者至少是E的一个子类),但它没有找到它。 – portablesounds 2014-09-03 00:02:45

回答

1

您有一个简单的语法错误。 @SuppressWarnings不能用于像a.add(x)这样的任何语句,只能用于类声明,方法声明和变量声明。这就是为什么它要求一个标识符,@SuppressWarnings期望看到这三个中的一个,而不是一个简单的陈述。

public static void main(String[] args) { 
     ArrayList a = new ArrayList(); 
     a.add(new Object()); 
     a.add(new String("test"); 
     a.add(null); 
     System.out.println((String) (a.get(0))); 
    } 

这段代码编译得很好。

那么当你使用原始类型时会发生什么?没有。没有类型检查完成。上面的代码在println语句上产生一个java.lang.ClassCastException error。当你打算放置一个String时,并没有发现你将Object放入了,并且直到运行时才知道你在println上的投射会变差。

+0

谢谢!就是这样!猜猜他们是对的:/ – portablesounds 2014-09-03 00:16:38

0

未指定时,默认为泛型的边界,如果没有指定,则默认为object。

这意味着:

List lst = new ArrayList(); 

完全等同于:

List<Object> lst = new ArrayList<Object>(); 

在这样的列表,一切都可以添加或检索,因为一切都在Java的扩展对象,除原语(但然后自动装箱进场)。

所以,你可以写正确:

lst.add("String"); 
lst.add(new Date()); 
lst.add(new Integer(1)); 
lst.add(1); // It is converted to an Integer by auto-boxing 

而且你可以写正确:

String str = (String)lst.get(0); 

但是你要知道能够在运行转换异常:

String str2 = (String)lst.get(1); // Will give error, cause element 1 is a date. 

如果你有一个定义泛型边界的特定ArrayList子类,例如:

public class MyList<E extends MyClass> extends ArrayList<E> { 

的,你仍然可以使用它没有泛型:

MyList lst = new MyList(); 

但它只会接受的MyClass MyClass的或子类:

lst.add(new MyClass()); 
lst.add(new MySubClass()); 
MyClass a = lst.get(0); 
MyClass b = lst.get(1); 
MySubClass c = (MySubClass)lst.get(1); 

,但没有别的:

lst.add("String"); // Will give compile time error 
+0

嗯然后为什么不编译代码,即使我找不到语法错误的东西?此外,如果这是真的,那么我不应该抑制“未检查​​”的错误。 – portablesounds 2014-09-03 00:08:48

+0

@markspace回答了为什么它不编译时,我正在编写完整的解释:) – 2014-09-03 00:10:10

+0

未检查不是一个错误,只是编译器给你的警告,让你知道你正在使用参数化的类,而不使用泛型参数。 – 2014-09-03 00:32:08