Java - 泛型类的类成员的行为

标签 java generics

如果您在 Java 中将泛型类的实例声明为原始类型,编译器是否假定参数化类型为 Object对于所有类成员方法?这是否甚至扩展到那些返回具体参数化类型的某种形式(例如 Collection )的方法?

我错误地声明了一个没有参数化类型的泛型类的实例,这导致了非常有趣的下游影响。我提供了一个产生“不兼容类型”编译错误的场景的简化示例。我的基本问题:为什么 javac 会产生“不兼容类型”错误,并提示下面指示的行?

import java.util.*;

public class Main {
    public static void main(String[] args) {
       final Test<String> t1 = new Test<String>(); 
       final Test t2 = new Test<String>();

       for (final Integer i : t1.getInts()) {
           System.out.println(i);
       }
       for (final Integer i : t2.getInts()) { //<-- compile-time error
           System.out.println(i);
       }
    }

    public static class Test<T> {
        public Test() {
        }

        public Set<Integer> getInts() {
            final Set<Integer> outSet = new HashSet<Integer>();
            outSet.add(new Integer(1));
            outSet.add(new Integer(2));
            outSet.add(new Integer(3));
            return outSet;
        }
    }
}

一个有趣的注意事项是,如果 t2使用通配符类型 ( Test<?> t2…) 声明代码按预期编译和运行。

使用 for-each 循环调用 next()getInts() 返回的集合上的迭代器上(它返回从正在迭代的 Iterable 中收集的泛型类型)。 The documentation here提到如果 Iterable 是原始的,Object用作返回类型。为什么编译器似乎也更改了 Test.getInts() 的返回类型来自 Set<Integer>Set<Object>

最佳答案

因为你使用了原始的 Test , Test 中的所有泛型类被有效地类型删除,甚至是不相关的泛型,如返回 Set<Integer> ,所以 Set<Integer>getInts 返回变成原始的 Set .这就解释了为什么你会得到不兼容的类型,因为原始的 Set将返回 Object s,不是 Integer

Section 4.8 of the JLS涵盖原始类型:

The type of a constructor (§8.8), instance method (§8.4, §9.4), or non-static field (§8.3) M of a raw type C that is not inherited from its superclasses or superinterfaces is the raw type that corresponds to the erasure of its type in the generic declaration corresponding to C.

The use of raw types is allowed only as a concession to compatibility of legacy code. The use of raw types in code written after the introduction of generics into the Java programming language is strongly discouraged. It is possible that future versions of the Java programming language will disallow the use of raw types.

(强调我的)

此行为的原因是为了与前泛型 Java 代码向后兼容,因为内置 Java 类的前泛型版本与泛型内置类的原始类型版本相同。也就是说,一个预泛型 Set与原始 Set 相同(删除了泛型)。

关于Java - 泛型类的类成员的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23225728/

相关文章:

c# - 不能使用二级派生类作为通用基类类型的参数

c# - 在 C# 中使用 Type.GetType() 返回的类型

c# - 使用泛型类型 'System.Collections.Generic.List<T>' 需要 '1' 类型参数

java - 使用 Spring Boot 和 Jackson ObjectMapper 时 OffsetDateTime 属性的 JSON 序列化差异

java - RSocket 适用于生成的数据,但不适用于 Spring Reactive MongoDB

java - 一个简单Java的棘手问题: variable scope

c# - 通用 IList<T> 的 "type"是什么?

java - 在selenium中使用gecko时出现错误

java - GWT Java URL validator

generics - 有没有办法解决 Java 无法将泛型参数转发给非泛型类型的问题?