Java中编译时间与运行时间依赖关系有什么区别? 它与班级路径有关,但它们有何不同?编译时间与运行时间依赖关系 - Java
回答
编译器需要以编译成库调用合适的类路径(编译时依赖)
JVM需要以加载库您呼叫的类(运行时依赖)正确类路径。
他们可能会在几个方面有所不同:
1)如果你的类C1调用库类L1,以及L1调用库类L2,那么C1对L1和L2运行时的依赖,但只有一个编译时间依赖于L1。 2)如果你的类C1使用Class.forName()或其他机制动态实例化接口I1,并且接口I1的实现类是类L1,那么C1对I1和L1具有运行时依赖关系,但仅限于编译时依赖于I1。
其他“间接”的依赖关系,其是用于编译时相同,并且运行时间:
3)类C1延伸库类L1,和L1实现接口I1和延伸库类L2:C1具有编译时依赖于L1,L2和I1。
4)你的C1类有一个方法foo(I1 i1)
和一个方法bar(L1 l1)
其中I1是一个接口,L1是一个接口为I1的参数类:C1对I1和L1具有编译时间依赖性。
基本上,为了做任何有趣的事情,你的类需要与类路径中的其他类和接口进行交互。由该组库接口形成的类/接口图产生编译时间依赖关系链。库实现产生运行时间依赖关系链。请注意,运行时依赖链是运行时依赖的或失败缓慢的:如果L1的实现有时依赖于实例化类L2的对象,并且该类只在一个特定的场景中被实例化,那么就没有依赖关系在这种情况下。
Java在编译时并不实际链接任何东西。它只使用它在CLASSPATH中找到的匹配类来验证语法。直到运行时,所有的东西都放在一起,并在当时基于CLASSPATH执行。
编译时间依赖关系只是您正在编译的类中使用的直接的依赖关系(其他类)。运行时依赖包括您正在运行的类的直接和间接依赖关系。因此,运行时依赖关系包括依赖关系的依赖关系以及您在String
中使用但在Class#forName()
中使用的类名称之类的任何反射依赖关系。
一个简单的例子就是看一个像servlet api这样的API。为了让你的servlet能够编译,你需要servlet-api.jar,但是在运行时servlet容器提供了一个servlet api实现,所以你不需要将servlet-api.jar添加到你的运行时类路径中。
编译时依赖:您需要在您的
CLASSPATH
依赖于编译神器。它们的产生是因为您对代码中的硬编码依赖有某种“引用”,例如为某些类调用new
,扩展或实现某些内容(直接或间接)或使用直接reference.method()
表示法进行方法调用。运行时依赖关系:您需要依赖
CLASSPATH
来运行您的工件。它们的产生是因为你执行访问依赖项的代码(以硬编码方式或通过反射或其他方式)。
尽管编译时间依赖通常意味着运行时间依赖性,但您可以只具有编译时间依赖性。这是基于这样一个事实,即Java只在首次访问该类时链接类依赖关系,所以如果您从不在运行时访问特定类,因为从未遍历代码路径,Java将忽略该类及其依赖项。
的这个
在C.java实施例(生成C.class):
package dependencies;
public class C { }
在A.java(生成的A.class):
package dependencies;
public class A {
public static class B {
public String toString() {
C c = new C();
return c.toString();
}
}
public static void main(String[] args) {
if (args.length > 0) {
B b = new B();
System.out.println(b.toString());
}
}
}
在这种情况下,A
编译时依赖于C
到B
,但如果在执行时传递一些参数,它将只对C具有运行时依赖性,因为JVM在执行B b = new B()
时只会尝试解决B
对C
的依赖。此功能允许您在运行时仅提供您在代码路径中使用的类的依赖关系,并忽略工件中其余类的依赖关系。
对于Java,编译时依赖性是您的源代码的依赖关系。例如,如果A类从类B调用一个方法,那么A在编译时依赖于B,因为A必须知道要编译的B(类型B)。这里的技巧应该是这样的:编译代码还不是一个完整的可执行代码。它包括可替换的地址(符号,元数据),这些地址尚未编译或存在于外部容器中。在链接期间,这些地址必须由内存中的实际地址替换。要做到这一点,应该创建正确的符号/地址。这可以用类(B)的类型完成。我相信这是编译时的主要依赖。
运行时间依赖关系与实际的控制流程更相关。它会调用实际的内存地址。这是程序运行时的依赖关系。这里需要类B的细节,而不仅仅是类型信息。如果类不存在,那么你将得到RuntimeException和JVM将退出。
这两个依赖关系,通常和不应该流向相同的方向。不过这是OO设计的问题。
在C++中,编译有点不同(不是及时的),但它也有一个链接器。所以这个过程可能被认为与我猜想的Java类似。
- 1. 使用朋友类减少编译时间和依赖关系
- 2. Java库运行时间与编译时间
- 3. 在Java中编译时间与运行时间?
- 4. 部署和运行时间依赖关系管理的NuGet/OpenWrap
- 5. 运行时间编译VS时间(.NET)
- 6. 编译时间和运行时间?
- 7. 处理运行时依赖关系
- 8. 运行Clippy时排除依赖关系
- 9. 编译时间和运行时错误
- 10. NIX中的构建与运行时依赖关系
- 11. 在Java中查找依赖关系的具体时间
- 12. 解决与从常春藤时间戳SNAPSHOT依赖关系
- 13. Java DAO模式和运行时依赖关系
- 14. 获取UTC时间而不依赖操作系统时间
- 15. 编译时与运行时,Java和C#
- 16. 编译时间和运行时间在厨师食谱
- 17. Maven不会编译Selenium依赖关系
- 18. 仅对编译时的Gradle依赖关系和测试
- 19. Typescript。我可以区分编译时和运行时依赖
- 20. Gigaspaces:设置具有PU的运行时间依赖关系的目录
- 21. Maven:在运行单元测试时忽略模块间依赖关系
- 22. var关键字运行时或编译时间?
- 23. 使用重载vs覆盖,编译时间vs运行时间
- 24. C - 编译包含的依赖关系
- 25. 重新编译Jar依赖关系
- 26. 指定编译顺序依赖关系
- 27. Scala/Clojure编译依赖关系
- 28. EXE和DLL依赖关系 - 何时重新编译EXE?
- 29. 首次编译时的Gradle依赖关系
- 30. 如何在编译静态时摆脱OCI.dll依赖关系
实例1中的编译时间依赖不应该是L1吗? – BalusC 2010-11-24 20:06:30
是,修正了一些错别字。 – 2010-11-24 20:06:49
谢谢,但在运行时如何加载类的工作?在编译时很容易理解。但是在运行时,它是如何操作的,当我有两个不同版本的Jars时?它会选择哪一个? – Kunal 2010-11-24 20:50:59