Java中的通用类型内部类

时间:2010-03-02 21:10:38

标签: 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) {
        }
    }
}

测试代码:

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

当它运行时,它会给出一个非常神秘的错误消息:

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

现在,通过一些实验,我已经找到了如何防止编译器错误。我可以使Sub类成为静态内部类,或者我需要将Sub类称为Question.Sub&lt; String&gt;。我不能做的是解释为什么我需要这样做。

我已经完成了关于泛型的Java文档的一些阅读,但没有涉及这个特殊情况。

有人可以解释为什么代码是当前形式的不兼容类型吗?

- 编辑 -

仔细观察,我可以看到我在Netbeans之外得到了同样的行为。如果我有以下结构中的代码:

generics\
generics\Question.java
generics\Answer.java

当我一起编译文件时,我没有收到错误:

C:\>javac generics\Question.java generics\Answer.java

C:\>

然而,当我首先编译问题然后回答,我得到错误:

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

我听过有关类型擦除的提及。在这种情况下是这种情况吗?

1 个答案:

答案 0 :(得分:1)

类型擦除是当前在Java中实现泛型的方式的属性。这意味着变量的类型只在编译时知道,而不是在运行时。因此,例如,在以下内容中:

Map<String,String> map = new HashMap<String,String>();

然后编译器知道检查以字符串/字符串为基础的项目。但是,编译后的代码对String,String一无所知 - 您仍然可以使用错误的类型插入对象,例如:

Map other = (Map)map;
other.put(new Integer(3), new Double( 4.5 );

问题是编译后的代码在传入时不会检查参数类型,也不会检查运行时(因为类型信息已被删除,因此,类型擦除)。

我怀疑类型擦除是一个问题 - 因为在编译时,你有完整的类型信息 - 但它可能是一个错误。泛型(从实现中)有很多毛茸茸的问题,并且有不同的编译器在使用JavaC和Eclipse,因此可能会出现不同的错误。在某些情况下,Eclipse编译器比Sun编译器更忠实于规范(因此Eclipse会创建错误,而Sun则不会),而这主要是由于类型系统工作方式的复杂性。

所以很可能在1.5.0_14编译器中有一个(或多个)泛型错误......