当在类中声明类型参数时,Java Generics Type会丢失常量类型

时间:2015-12-01 05:51:53

标签: java generics

我使用的是Oracle JDK 7u79。我不知道为什么下面的代码会产生编译错误:

package generics;

import java.util.Collection;
import java.util.Collections;

class SomeClass {
    public Collection<String> getStringCollection() {
        return Collections.singleton("hello");
    }
}

class SomeTypedClass<T> {
    public Collection<String> getStringCollection() {
        return Collections.singleton("hello");
    }
}

public class SomeTest {
    public static void main(String[] args) {
        final int length1 = new SomeClass()     .getStringCollection().iterator().next().length();
        final int length2 = new SomeTypedClass().getStringCollection().iterator().next().length(); // compilation error
    }
}

错误:

Error:(21, 89) java: cannot find symbol
  symbol:   method length()
  location: class java.lang.Object

我已将常量泛型类型Collection<String>指定为getStringCollection()的方法参数,因此我认为SomeClassSomeTypedClass都应该编译而不会出错。

为什么会这样?什么是正确的解决方案,即在不进行投射的情况下不断输入Collection

1 个答案:

答案 0 :(得分:2)

实际上,由于您的SomeTypedClass<T>期望传入的类型为T,即使它未使用该类型,您也需要在SomeTest中执行此操作:

public class SomeTest {
    public static void main(String[] args) {
        final int length1 = new SomeClass()     .getStringCollection().iterator().next().length();
        final int length2 = new SomeTypedClass<String>().getStringCollection().iterator().next().length(); // no more compilation error
    }
}

我使用的是String,但您可以使用Object,因为T实际上并未使用{/ p>}。

根据您的真实场景,可能值得考虑使用SomeTypedClass课程做更多类似的事情:

class SomeTypedClass<T> {
    public Collection<T> getTypedCollection(T object) {
        return Collections.singleton(object);
    }
}

然后你可以这样做:

final int length2 = new SomeTypedClass<String>().getTypedCollection("hello").iterator().next().length();

如果您只对源自String的课程感兴趣,您也可以这样做:

class SomeTypedClass<T extends String> {
    public Collection<T> getStringCollection(T object) {
        return Collections.singleton(object);
    }
}

然后你可以这样做:

final int length2 = new SomeTypedClass<String>().getStringCollection("hello").iterator().next().length();