gpt4 book ai didi

java - 为什么 javac 需要引用类的接口(interface)而 ECJ 不需要?

转载 作者:行者123 更新时间:2023-12-02 06:29:10 25 4
gpt4 key购买 nike

当编译一个 Client 时,它使用接口(interface) I 的某些实现(例如 O),I 的类文件code> 也必须出现在类路径中。奇怪的是,这只是 javac 的情况,因为 Eclipse 编译器 (ECJ) 不需要 I 进行编译。

是什么让 JDK 需要编译父类(super class)型,而 ECJ 编译就很好?

它不是默认方法,正如评论的那样in the bug report , 和 compatibility guide也同意:

When compiling a class against another class implementing an interface which is defined in yet another class file, such class file (where interface is defined) must be available in the class path used by javac during compilation. This is a new requirement as of JDK 8 - a failure to do so will result in a compilation error.


更新:

  • 类似问题:Java 8 interface/class loader changes?
  • I.doit()default 还是纯抽象方法都没有关系,行为是一样的
  • I.doit() 是否在 O 中被覆盖当然很重要;如果没有被覆盖,那么 ECJ 也会到达 I 以获取 doit()
  • 的定义

接口(interface)(api/a/I.java):

package a;
public interface I {
default void doit() {
System.out.println("In I");
}
}

实现(impl/b/O.java):

package b;
public class O implements a.I {
public void doit() {
System.out.println("In O");
}
}

客户端(client/c/Client.java):

package c;
import b.O;
public class Client {
public void test() {
O o = new O();
o.doit();
}
public static void main(String[] args) {
new Client().test();
}
}

Makefile:

# bug report:
# Javac requires interface on classpath when using impl
# https://bugs.openjdk.java.net/browse/JDK-8055048
#
# compatibility guide:
# http://www.oracle.com/technetwork/java/javase/8-compatibility-guide-2156366.html
# (Synopsis: Interfaces need to be present when compiling against their implementations)
#
# ECJ downloaded from:
# http://central.maven.org/maven2/org/eclipse/jdt/core/compiler/ecj/4.6.1/ecj-4.6.1.jar

ifeq (${V}, ecj)
JC := java -jar ecj-4.6.1.jar -8
else
JC := javac -source 1.8 -target 1.8 -implicit:none
endif

rebuild: clean lib client

lib: api/a/I.class impl/b/O.class

client: lib client/c/Client.class

clean:
rm -f api/a/I.class impl/b/O.class client/c/Client.class

%.class: %.java
${JC} ${OPT} $<

impl/b/O.class: OPT = -cp api
client/c/Client.class: OPT = -cp impl

日志:

$ make V=ecj rebuild                                                                                                                                                                                               
rm -f api/a/I.class impl/b/O.class client/c/Client.class
java -jar ecj-4.6.1.jar -8 api/a/I.java
java -jar ecj-4.6.1.jar -8 -cp api impl/b/O.java
java -jar ecj-4.6.1.jar -8 -cp impl client/c/Client.java

$ make rebuild
rm -f api/a/I.class impl/b/O.class client/c/Client.class
javac -source 1.8 -target 1.8 -implicit:none api/a/I.java
javac -source 1.8 -target 1.8 -implicit:none -cp api impl/b/O.java
javac -source 1.8 -target 1.8 -implicit:none -cp impl client/c/Client.java
client/c/Client.java:8: error: cannot access I
o.doit();
^
class file for a.I not found
1 error
make: *** [client/c/Client.class] Error 1

最佳答案

似乎对Compatibility Guide for JDK 8的目的有误解.

这不是关于编译器或环境应该行为方式的规范,而是关于 JDK 行为方式的文档,以发现潜在的兼容性问题。这并不意味着另一个编译器必须表现出完全相同的行为。

之所以提到该特定行为,是因为 javac 将其行为从 JDK 7 更改为 JDK 8,这可能会导致兼容性问题。

如解释here ,形式化过程描述为一个方法调用搜索所有可能适用的成员方法,但并没有说在保证程序正确性的情况下不能走捷径。

所以 that bug report已关闭,因为新行为在规范内,不一定是因为替代行为会违反规范。

关于java - 为什么 javac 需要引用类的接口(interface)而 ECJ 不需要?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45030100/

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