gen*_*ive 15 java generics netbeans
我已经学习并试验了Java Generics一段时间,但我遇到了一些我无法解释的问题.以下面的代码为例:
public class Question {
public <T> Sub<T> getSub(Class<T> c) {
return new Sub<T>(c);
}
public class Sub<S> {
private Class<S> c;
public Sub(Class<S> c) {
this.c = c;
}
public void add(S s) {
}
}
}
Run Code Online (Sandbox Code Playgroud)
和测试代码:
import generics.Question.Sub;
public class Answer {
public static void main(String [] args) {
Question q = new Question();
Sub<String> s = q.getSub(String.class);
s.add("");
}
}
Run Code Online (Sandbox Code Playgroud)
当它运行时,它会给出一个非常神秘的错误消息:
C:\Answer.java:8: incompatible types
found : generics.Question.Sub<java.lang.String>
required: generics.Question.Sub<java.lang.String>
Sub<String> s = q.getSub(String.class);
1 error
Run Code Online (Sandbox Code Playgroud)
现在,通过一些实验,我已经找到了如何防止编译器错误.我可以使Sub类成为静态内部类,或者我需要将Sub类称为Question.Sub <String>.我不能做的是解释为什么我需要这样做.
我已经完成了关于泛型的Java文档的一些阅读,但没有一个涵盖这个特殊情况.
任何人都可以解释为什么代码是当前形式的不兼容类型?
-编辑-
仔细观察,我可以看到我在Netbeans之外得到了同样的行为.如果我有以下结构中的代码:
generics\
generics\Question.java
generics\Answer.java
Run Code Online (Sandbox Code Playgroud)
当我一起编译文件时,我没有收到错误:
C:\>javac generics\Question.java generics\Answer.java
C:\>
Run Code Online (Sandbox Code Playgroud)
但是,当我首先编译问题然后回答,我得到错误:
C:\>javac generics\Question.java
C:\>javac generics\Answer.java
generics\Answer.java:8: incompatible types
found : generics.Question.Sub<java.lang.String>
required: generics.Question.Sub<java.lang.String>
Sub<String> s = q.getSub(String.class);
^
1 error
Run Code Online (Sandbox Code Playgroud)
我听过有关类型擦除的提及.在这种情况下是这种情况吗?
类型擦除是目前 Java 中泛型实现方式的一个属性。这意味着变量的类型仅在编译时已知,而在运行时未知。因此,例如,在以下内容中:
Map<String,String> map = new HashMap<String,String>();
Run Code Online (Sandbox Code Playgroud)
那么编译器就知道要检查以字符串/字符串为基础放入的项目。但是,编译后的代码对 String,String 一无所知 - 您仍然可以插入错误类型的对象,例如:
Map other = (Map)map;
other.put(new Integer(3), new Double( 4.5 );
Run Code Online (Sandbox Code Playgroud)
问题在于,编译后的代码在传入时不会检查参数类型,运行时也不会检查(因为类型信息已被删除,因此类型被删除)。
我怀疑类型擦除在这里是一个问题 - 因为在编译时,您拥有完整的类型信息 - 但它可能是一个错误。泛型(来自实现)存在相当多的棘手问题,并且 JavaC 和 Eclipse 使用不同的编译器,因此可能会出现不同的错误。在某些情况下,Eclipse 编译器比 Sun 编译器更忠实于规范(因此 Eclipse 会产生错误,而 Sun 不会),这主要是由于类型系统工作方式的复杂性。
所以这很可能是 1.5.0_14 编译器中泛型的一个(或多个)错误......