简体   繁体   English

Java泛型在Eclipse中编译,但不在javac中编译

[英]Java generics compile in Eclipse, but not in javac

I had to discover I have Java code in my project, which compiles and runs fine in Eclipse, but throws a compilation error in javac. 我必须发现我的项目中有Java代码,它在Eclipse中编译并运行良好,但在javac中抛出了编译错误。

A self-contained snippet: 一个独立的片段:

import java.util.HashSet;
import java.util.Set;

public class Main {

    public static void main(String[] args) {
    Set<Integer> setOfInts = new HashSet<Integer>();
    Set<Object> setOfObjects = covariantSet(setOfInts);
    }

    public static <S, T extends S> Set<S> covariantSet(Set<T> set) {
    return new HashSet<S>(set);
    }

}

Compilation in javac returns: 在javac中编译返回:

Main.java:10: incompatible types
found   : java.util.Set<java.lang.Integer>
required: java.util.Set<java.lang.Object>
    Set<Object> setOfObjects = covariantSet(setOfInts);
                                           ^

This error now prevents building the project in Maven. 此错误现在阻止在Maven中构建项目。 As the Eclipse compiler is built to be more tolerant, I now have to assume the definition and usage of snippets as above static method is no valid Java? 由于Eclipse编译器构建得更宽容,我现在必须假设片段的定义和用法如上所述,静态方法是无效的Java?

It seems that Sun's 1.6 JDK can't infer the correct type. 看来Sun的1.6 JDK无法推断出正确的类型。 The following seems to work on my machine: 以下似乎适用于我的机器:

Set<Object> setOfObjects = Main.<Object, Integer>covariantSet(setOfInts);

Note that you must invoke the static method prefixed with the class name 请注意,您必须调用前缀为类名的静态方法

You are right. 你是对的。 This problem indeed exists. 这个问题确实存在。 Eclipse does not use javac . Eclipse不使用javac It uses its own compiler. 它使用自己的编译器。

Actually javac is "right". 实际上javac是“正确的”。 Generics are erasures. 泛型是擦除。 Type S is not included into your byte code, so jvm does not have enough information about the return type at runtime. 类型S未包含在字节代码中,因此jvm在运行时没有足够的有关返回类型的信息。 To solve the problem change the method prototype as following: 要解决此问题,请将方法原型更改为:

public static <S, T extends S> Set<S> covariantSet(Set<T> set, Class<S> returnType)

Now the return type is passed to the method at runtime and compiler should not complain. 现在返回类型在运行时传递给方法,编译器不应该抱怨。

In your Maven build skript you have set the compiler version. 在你的Maven构建skript中,你已经设置了编译器版本。

In Ant it lookes like this: 在Ant中,它看起来像这样:

<property name="source.version" value="1.5" />

search for 1.3 or 1.4, or compile to find that value in the maven skripts 搜索1.3或1.4,或编译以在maven skripts中找到该值

With value 1.5 the compiler will accept the generics (see your error messages) 值为1.5时,编译器将接受泛型(请参阅错误消息)

I know it's old question, but I want to mention, the function could be written as: 我知道这是一个老问题,但我想提一下,这个函数可以写成:

import java.util.HashSet;
import java.util.Set;

public class Main {

public static void main(String[] args) {
        Set<Integer> setOfInts = new HashSet<Integer>();
        Set<Object> setOfObjects = covariantSet(setOfInts);
    }

    public static <S> Set<S> covariantSet(Set<? extends S> set) {
        return new HashSet<S>(set);
    }

}

It's a little bit cleaner and you can use the function exactly how you intented to(with implicit generic typing). 它有点干净,您可以完全按照您的意图使用该功能(使用隐式泛型键入)。

Add the next plugin to your pom.xml: 将下一个插件添加到pom.xml:

<plugin>
     <artifactId>maven-compiler-plugin</artifactId>
     <version>2.3.2</version>
     <configuration>
          <source>1.6</source>
          <target>1.6</target>
     </configuration>
</plugin>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM