java - 如果实例没有分配泛型类型,则每个循环问题中的泛型

标签 java generics

<分区>

有人可以向我解释为什么明确需要为 ForEachLoop 实例分配泛型类型吗?

为什么编译器会提示:类型不匹配:无法从元素类型 Object 转换为 String

JDK 1.5.0_09

import java.util.ArrayList;
import java.util.Collection;

public class ForEachLoop<T> {

public static void main(String[] args) {

    // Non functional version
    ForEachLoop f = new ForEachLoop(); 

    // Functional version
    //ForEachLoop<Integer> f = new ForEachLoop();

            // Type mismatch: cannot convert from element type Object to String
    for(String a : f.getStrings()) {
        System.out.println(a);
    }
}

public Collection<String> getStrings() {
    Collection<String> strings = new ArrayList<String>();
    strings.add("Hello");
    return strings;
}

} 

最佳答案

这是一个相当常见的错误:

ForEachLoop f = new ForEachLoop(); 

应该是

ForEachLoop<Something> f = new ForEachLoop<Something>();

如果您使用原始类型(您不应该这样做),编译器将清除该实例的所有通用信息,即使它不是类型参数 T,以使其与 1.5 之前的代码兼容。

只有在为 Java 1.4 或更低版本编写代码时才使用原始类型,在这种情况下,您不应该有任何泛型。在字节码级别,该方法在类型删除后返回 Collection (raw)。通常,如果实例设置了泛型类型,当您尝试对集合执行 get 时,编译器将使用泛型信息来决定它应该返回一个 String,然后在字节码级别它会自动将从 Collection 接收到的 Object 转换为 String(因为它保证是 String)。但是,如果您使用原始类型,编译器将忽略所有通用信息,并且不会再自动为您转换对象。

编辑:在原始类型部分有这些东西:

Another implication of the rules above is that a generic inner class of a raw type can itself only be used as a raw type:

class Outer<T>{
  class Inner<S> {
    S s;
  }
}

it is not possible to access Inner as partially raw type (a "rare" type)

Outer.Inner<Double> x = null; // illegal
Double d = x.s;

because Outer itself is raw, so are all its inner classes, including Inner, and so it is not possible to pass any type parameters to it.

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 genericity 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.

It is a compile-time error to attempt to use a type member of a parameterized type as a raw type.

This means that the ban on "rare" types extends to the case where the qualifying type is parameterized, but we attempt to use the inner class as a raw type:

Outer<Integer>.Inner x = null; // illegal

This is the opposite of the case we discussed above. There is no practical justification for this half baked type. In legacy code, no type parameters are used. In non-legacy code, we should use the generic types correctly and pass all the required actual type parameters.

请注意,内部类具有独立于外部类之一的自己的类型参数,并且它仍然会被删除。基本上他们不希望我们在同一个实例上混合原始类型和通用类型,因为它在任何版本中都没有意义(在 1.5 之前,通用部分将是一个错误,在 1.5+ 中不鼓励使用原始类型,并且甚至可能会从 future 的版本中删除)

然后还有这个:

The type of a constructor (§8.8), instance method (§8.8, §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 erasure of its type in the generic declaration corresponding to C. The type of a static member of a raw type C is the same as its type in the generic declaration corresponding to C.

It is a compile-time error to pass actual type parameters to a non-static type member of a raw type that is not inherited from its superclasses or superinterfaces.

表示构造函数、实例方法和非静态字段在原始实例中将被视为原始。无论如何,静态成员将被视为通用成员,因为它们不需要访问实例。

关于java - 如果实例没有分配泛型类型,则每个循环问题中的泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3316095/

相关文章:

java - 输入表单的 RequestDispatcher

java - 编译器为什么以及如何区别对待这两个条件?

c# - 使用派生类类型作为基类泛型操作的参数

带有集合的 Java 正则表达式 [x, a-b-c, z, b-c, e, f]

java - 我无法获得 ImageReaderByFormatName ("jpeg-lossless")

swift - 为什么我的简单协议(protocol)只能用作通用约束?

swift - 如何使用泛型推断类型?

c# - 在接口(interface)中使用泛型方法根据文件输入返回变量类型列表

java - 从一个 Java Web 应用程序运行多个站点

java - Eclipse 自动完成显示 'Problems During Content Assist' 弹出窗口