我很难理解为什么以下代码在Java 8/9中不编译,但是如果我从Eclipse IDE内部进行"运行",则可以正常运行,这很好。
package de.playground.test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class InferenceTest {
class InferenceObject<T> implements Comparable<InferenceObject<T>> {
@Override
public int compareTo(InferenceObject<T> o) {
return 0;
}
}
public static void main(String[] args) {
InferenceTest inferenceTest = new InferenceTest();
List<InferenceObject<?>> result = inferenceTest.read();
System.out.println(String.format("Array contains %d element(s)", result.size()));
}
private List<InferenceObject<?>> read() {
List<InferenceObject<?>> simpleList = new ArrayList<>();
InferenceObject<String> infObj = new InferenceObject<>();
simpleList.add(infObj);
// Collections.<InferenceObject<?>>sort(simpleList);
Collections.sort(simpleList);
return simpleList;
}
}
javac InferenceTest.java
产生以下错误:
InferenceTest.java:26: error: no suitable method found for sort(List<InferenceTest.InferenceObject<?>>)
Collections.sort(simpleList);
^
method Collections.<T#1>sort(List<T#1>) is not applicable
(inference variable T#1 has incompatible bounds
equality constraints: InferenceTest.InferenceObject<?>
upper bounds: InferenceTest.InferenceObject<CAP#1>,Comparable<? super T#1>)
method Collections.<T#2>sort(List<T#2>,Comparator<? super T#2>) is not applicable
(cannot infer type-variable(s) T#2
(actual and formal argument lists differ in length))
where T#1,T#2 are type-variables:
T#1 extends Comparable<? super T#1> declared in method <T#1>sort(List<T#1>)
T#2 extends Object declared in method <T#2>sort(List<T#2>,Comparator<? super T#2>)
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ?
1 error
问题是,由于使用的通配符仿制药而导致的推理失败 - 我很困惑此代码为何在Eclipse中编译,而Oracle JDK 8/9拒绝编译此代码 - 可能是回归的回归。错误6468354?
二手环境:Kubuntu 17.10 X86_64,Javac 1.8.0,Javac 1.8.0_131,Javac 1.8.0_151和Javac 9.0.0.0.1
解决方法:
class InferenceObject<T> implements Comparable<InferenceObject<?>> {
@Override
public int compareTo(InferenceObject<?> o) {
return 0;
}
}
在不明确说明类型而不是通配符通用的情况下,不使用略有不同的解决方法,编写此代码的正确方法是什么?
我很难理解为什么以下代码不 在Java 8/9
中编译
该代码不编译(使用1.8.0_161(,因为您要求 collections.sort((对未正确实现可比接口的类型的对象进行分类。从Javadoc for Collections.Sort((:
根据其元素的自然顺序,将指定的列表分为上升顺序。列表中的所有元素必须实现可比接口。
在您的初始代码中,要排序的列表的成员为InferenceObject<?>
类型,但是您 compareTo((方法的参数为InferenceObject<T>
类型,因此有一个编译器错误是正确的。
如果 compareTo((方法的参数为(说(InferenceObject<Float>
,则编译器错误的原因将更加清晰,并且要排序的列表由(例如(InferenceObject<LocalDate>
对象组成。尽管原因不太明显,但在初始代码列表中也适用相同的原则。
如果您的列表包含实现的任何特定类型的可比性的特定类型的inferneoBjects,则您的原始inferenderObject类定义是可以的。例如:
List<InferenceObject<String>> simpleList = new ArrayList<>();
List<InferenceObject<BigInteger>> simpleList = new ArrayList<>();
List<InferenceObject<Year>> simpleList = new ArrayList<>();
我很困惑为什么此代码在Eclipse中编译
所以我是I。它看起来像是Eclipse编译器的错误。您可以提出一个错误报告。
在不明确说明的情况下编写此代码的正确方法是什么 类型而不是通配符通用
您已经在修订的代码中以正确的方式进行操作。您要么要创建类型InferenceObject<?>
的对象列表(即输入未知(,要么要创建一个类型InferenceObject<T>
的对象列表,其中't'是某种特定类型。这是二进制的选择。
(实际上比这更细微差别,因为您可以拥有List<InferenceObject<? extends Number>>
,但我认为您没有问过。(
不使用略有不同的 orkaround ?
不要将其视为"解决方法"。将其视为正确编写代码的先决条件。
,但对您的代码的另一个值得更改将是声明 Simplelist ,因为您知道您想对其元素进行排序:
List<InferenceObject<? extends Comparable>> simpleList = new ArrayList<>();
然后,如果您尝试在列表中添加无效的推理对象,则编译器将标记错误:
simpleList.add(new InferenceObject<String>()); // OK, since String implements Comparable
simpleList.add(new InferenceObject<StringBuffer>()); // Error, since StringBuffer does not implement Comparable