代码之家  ›  专栏  ›  技术社区  ›  shubhamgarg1

如果对具体类进行了更改,依赖于接口而不是具体类是否会减少Java中的编译时间?

  •  1
  • shubhamgarg1  · 技术社区  · 7 年前

    参考书章节: https://www.safaribooksonline.com/library/view/working-effectively-with/0131177052/ch07.html

    我同意这一点,但是在java中的这种变化中观察到编译时间有很大的区别吗?或者C++中的上下文更重要吗?

    3 回复  |  直到 7 年前
        1
  •  0
  •   David Soroko    7 年前

    在javac之外,构建系统可能会做一些明智的事情,例如: https://blog.gradle.org/incremental-compiler-avoidance

    编辑 :只是仔细检查了一下, javac 重新编译源 即使没有改变 :

    $ java -version
    openjdk version "10.0.2" 2018-07-17
    
    $ javac *.java && ls -l A.*
    -rw-rw-r-- 1 usr usr 143 Oct 14 20:07 A.class
    -rw-rw-r-- 1 usr usr  59 Oct 14 19:57 A.java
    

    等了一分钟。。。

    $ javac *.java && ls -l A.*
    -rw-rw-r-- 1 usr usr 143 Oct 14 20:08 A.class
    -rw-rw-r-- 1 usr usr  59 Oct 14 19:57 A.java
    
        2
  •  0
  •   rzwitserloot    7 年前

    关键是:给定文件'MySource.java',包含某种类型的MySource,如果MySource的任何父类型被重新定义,你真的应该重新编译这个类。你不必这样做,java会尽最大努力,但是现在你可以创建疯狂的场景(例如,如果你更新父类型来添加一个新的抽象方法,比如,一个必须实现的方法,现在你仍然有一个没有实现的子类型。当您尝试混合这些由不同编译运行生成的类时,会引发运行时错误。

    你可能认为这意味着:嘿,太好了,现在我甚至不需要重新编译这个文件。但这并不是真的相关;java编译时间比C(几秒钟内完成大量项目)要快得多,而且很难有一个足够聪明的构建系统来实现在这种情况下不需要重新编译。不;关键是有点自我控制:如果你有一个拆分的项目,其中接口/父类在源repo a中,子类在B中,事情就要破裂了:除非a和B由同一个人维护并同时重建,否则你就有问题了。

    所以,关键是:你有“public API”,比如说,除非你有很好的理由这样做,否则你不能更改你所指定的类型。使接口更清楚地知道哪些位不会改变。这使source repo A的作者可以自由地更改(不是公共的/导出的)实现类,只要他们不弄乱接口,而不必去给source repo B的优秀人员打电话,告诉他们:呃,对不起,我们更改了一些东西,您必须进行完整的重建。

        3
  •  0
  •   Robert Fischer    7 年前

    如果更改了具体类,则只需要重新编译具体类及其调用者。如果您有一个接口,并且人们正在调用接口而不是具体类,那么他们就不算作具体类的调用方,也不需要重新编译。这是接口帮助减少编译时间的唯一方法,AFAICT。

    每个对接口进行类型优化的Java实现都将这种优化推迟到运行时(HotSpot)优化器:有关更多信息,您要查找的术语是“专门化”。Java编译器本身(即:Java=>字节码编译器(bytecode compilers)实际上很少进行优化,这是因为它无法在运行时对代码进行推理(cf:Haskell's compiler)。这是因为您可以进行动态代码加载:可以在运行时通过类路径修改和反射来更改接口的可能实现集。