【问题标题】:Java Compiler transistive type checking behaviourJava 编译器传递类型检查行为
【发布时间】:2019-09-20 12:03:46
【问题描述】:

考虑以下场景:

假设我的项目的“src”文件夹中有一个 A 类。

class A {

  void foo() {
     B b = new B();
  }

}

B 类定义在另一个 jar 中,该 jar 作为依赖项包含在 build.gradle 中

class B extends C {


}

现在,C 类在另一个 jar 中定义,它将在运行时而不是在编译时提供。 Gradle 能够正确编译 Class A。

但是,当我在 A 类中导入 c 类时,它会给出“找不到类”。


import other.C; // this line gives error 

class A {

  void foo() {
     B b = new B();
  }

}

如果没有直接导入,这是 Java 编译器忽略 C 类的期望行为吗?

另外,如果使用 A 类中的函数使用 B 类中的对象,该对象在 C 类中但在 B 类中没有被覆盖,会发生什么情况。

【问题讨论】:

  • 当你不直接在 A 中使用 C 类时,为什么 Java 编译器还要关心它? A 只需要 B 并且这是可用的。 B 本身依赖于其他东西,这对 A 来说并不重要。
  • 包含B的jar是如何创建的?如果 B 扩展了 C,那么 C.jar 需要成为这个 jar 的编译依赖,并且应该成为每个使用 B 的项目的依赖。
  • @dpr 是的,B.jar 将依赖于 C.jar,但我的问题是,如果我们在编译 A 类时没有提供它,那么会发生什么。
  • @Tom 您可以提供一些参考来验证您的评论。我也假设应该是这种情况,但我不完全确定,也没有找到任何关于它的参考。此外,如果使用 A 类中的函数使用 B 类中的对象,该对象在 C 类中但在 B 类中未被覆盖,会发生什么情况。
  • 为了得到答案,您应该将 gradle 文件添加到您的问题中。这在很大程度上取决于如何为项目 A 和 B 指定依赖项。

标签: java gradle


【解决方案1】:

您问题的确切答案取决于 Java 编译器版本以及它是否需要访问 C 才能完成工作。

总而言之,我会说这样的设置很脆弱,你不应该这样做。如果定义A 的库需要B,它有效地在其公共API 中使用C,就像extends 的情况一样,那么C 应该对您的库可见。

【讨论】:

  • 如果它被命名为导入,它需要访问类C
【解决方案2】:

首先我们需要了解java编译器是如何工作的。 无论您在代码中通过名称或作为“令牌”引用的任何内容,编译器都应该在编译阶段可以访问。

您使用Class.forloadgetClass 方法加载的类不需要在类路径中可用。

您所指的编译时和运行时本质上是关于打包的。

您所说的特定依赖项说 C 类将在运行时提供,它是捆绑任务以在构建 jar 时忽略该依赖项的指令。因此,如果您将应用程序编译并部署为 jar,则 C 类将不会出现在其中。同时,包含 B 类的 jar 将包含在您的部署包中。

如果您提供确切的 gradle 文件,我也许可以更准确地回答。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-13
    • 2020-02-07
    • 1970-01-01
    相关资源
    最近更新 更多