gpt4 book ai didi

java - eclipse 编译器编译 javac 不会编译的代码 - 代码看起来是合法的

转载 作者:搜寻专家 更新时间:2023-11-01 02:37:12 24 4
gpt4 key购买 nike

以下代码在 Eclipse 版本中编译:Mars.2 Release (4.5.2) Build id:Windows 10 版本 10.0.14393 上的 20160218-0600。它不能在一系列 oracle javac 编译器上编译。关于使用 Eclipse JDT 编译器而非 javac 编译的代码片段还有其他问题。我找不到与此示例类似的示例。这是一段玩具代码,它的唯一目的是展示这种好奇心。

eclipse 编译器是否正确编译它?

注意:如果 eclipse 编译器生成的 .class 被反编译,它会生成可以用 javac 编译的源代码。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class Puzzle {
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void main(String[] args) {
List<List> outer = Arrays.asList(Arrays.asList(new Object(), new Object()),
Arrays.asList(),
Arrays.asList(new Object(), new Object()));

Stream<Boolean> bs1 = outer.stream().flatMap(inner -> inner.stream()).map(obj -> obj.hashCode() % 2 == 0);
boolean b0 = bs1.filter(b -> !b).findAny().isPresent();

boolean b2 = outer.stream().flatMap(inner->inner.stream())
.map(obj -> obj.hashCode() % 2 == 0)
.filter(b -> !b).findAny().isPresent();

System.out.printf("%s %s %s", outer, b0, b2);
}
}

这是编译器错误,在几个版本的编译器中:

C:\Users\tofti>C:\jdk1.8.0_121\bin\javac -version & C:\jdk1.8.0_121\bin\javac Puzzle.java
javac 1.8.0_121
Puzzle.java:23: error: bad operand type Object for unary operator '!'
.filter(b -> !b).findAny().isPresent();
^
1 error

C:\Users\tofti>C:\jdk1.8.0_112\bin\javac -version & C:\jdk1.8.0_112\bin\javac Puzzle.java
javac 1.8.0_112
Puzzle.java:23: error: bad operand type Object for unary operator '!'
.filter(b -> !b).findAny().isPresent();
^
1 error

C:\Users\tofti>C:\jdk1.8.0_141\bin\javac -version & C:\jdk1.8.0_141\bin\javac Puzzle.java
javac 1.8.0_141
Puzzle.java:23: error: bad operand type Object for unary operator '!'
.filter(b -> !b).findAny().isPresent();
^
1 error

下面是在 Eclipse 中编译和执行的代码: Code compiling and running in eclipse

最佳答案

在 Eclipse 4.6.3 中,一个被抑制的“未检查”警告揭示了问题:

Type safety: The expression of type Stream needs unchecked conversion to conform to Stream<Boolean>

在 javac 1.8.0_131 中:

Puzzle.java:12: warning: [unchecked] unchecked conversion
Stream<Boolean> bs1 = outer.stream().flatMap(inner -> inner.stre
am()).map(obj -> obj.hashCode() % 2 == 0);

^
required: Stream<Boolean>
found: Stream

没有任何转换,这里是链中每个方法调用的实际返回类型:

Stream<List> s1 = outer.stream();
Stream s2 = s1.flatMap(inner -> inner.stream());
Stream s3 = s2.map(obj -> obj.hashCode() % 2 == 0);
Stream s4 = s3.filter(b -> !b); // compiler error
Optional opt = s4.findAny();
boolean b = opt.isPresent();

如果加个通配符就变成了List<List<?>> outer ,这就是你得到的:

Stream<List<?>> s1 = outer.stream();
Stream<?> s2 = s1.flatMap(inner -> inner.stream());
Stream<Boolean> s3 = s2.map(obj -> obj.hashCode() % 2 == 0);
Stream<Boolean> s4 = s3.filter(b -> !b); // compiles OK
Optional<Boolean> opt = s4.findAny();
boolean b = opt.isPresent();

所以问题是 .map呼吁原始Stream实际上并没有返回 Stream<Boolean> ,您只是在分配 bs1 时隐式转换它,这修复了链的其余部分中的原始类型。事实上,您可以将此转换添加到单行版本并编译:

boolean b2 = ((Stream<Boolean>) outer.stream().flatMap(inner -> inner.stream())
.map(obj -> obj.hashCode() % 2 == 0))
.filter(b -> !b).findAny().isPresent();

现在,原始 .map调用缺少类类型参数 <T> ,但是 <R>是方法类型参数,为什么不返回Stream<R>raw types Java language specification 部分指出“原始类型的非静态类型成员被认为是原始的”。给出的示例是一个通用内部类,但假设它也适用于通用方法,这应该是 <R> 的原因。 .map 的参数在原始 Stream 上调用时被丢弃,导致它返回另一个原始的 Stream .

编辑:在 an Eclipse bug report 中找到这个:

It looks like javac infers the return type of the method invocation to be the raw type I when passed in arguments are raw types. This may be motivated by the almost last bit of §18.5.2 after bounds set 4 has been generated

[...]

If unchecked conversion was necessary for the method to be applicable during constraint set reduction in §18.5.1, then the parameter types of the invocation type of m are obtained by applying θ' to the parameter types of m's type, and the return type and thrown types of the invocation type of m are given by the erasure of the return type and thrown types of m's type.

关于java - eclipse 编译器编译 javac 不会编译的代码 - 代码看起来是合法的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45725882/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com