有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

增强Java 8库,同时保持向后兼容性

我正在用Java开发一个开源库,希望它能方便Java 8用户,并尽可能利用Java 8中的新概念(lambdas等)

同时,我绝对需要保持向后兼容性(该库必须仍然适用于使用Java 6或7的用户)

我可以采用Java 8中哪些有用的功能,这些功能对库用户有益,而不会破坏旧Java版本用户的库兼容性


共 (4) 个答案

  1. # 1 楼答案

    我不知道你的图书馆,这个建议可能有点不对劲

    兰巴斯:别担心。任何函数接口都可以使用Lambda表达式实现

    方法引用:与lambdas一样,它们应该只是可用的

    :如果这适合你的库,你应该使用它们,但在这里保持兼容性更难。向后兼容性可以通过使用第二个库部件来实现,该部件环绕基础库并连接到基础库的公共API。因此,它可以在不放弃Java6/7的情况下提供额外的功能

    默认方法:务必使用这些方法!它们是在不破坏现有实现的情况下增强现有实现的快速/廉价/好方法。您添加的所有默认方法都将自动用于实现类。然而,它们还需要第二个库部分,因此您应该在基础库中提供基础接口,并从配套库中扩展接口

    不要放弃旧的库,因为仍然有许多开发人员不能使用Java 8,甚至Java 7。如果你的库可以在Android上使用,请保持兼容性

  2. # 2 楼答案

    正如其他人所说,提供和使用带有单个方法的接口,以便在使用Java 8时可以使用lambdas或方法引用来实现它们,这是一种在不破坏Java 7兼容性的情况下支持Java 8的好方法


    这可以通过您的库提供方法来补充,这些方法适合Java 8的标准函数类型之一(例如Supplier(Bi)Consumer(Bi)Function),以便Java 8开发人员可以为Java 8 API方法创建对它们的方法引用。这意味着它们的签名与其中一个功能接口匹配,并且不会抛出已检查的异常。这通常是自然而然的,例如getFoo()可以充当FunctionisBar()充当Predicate,但有时可以通过考虑可能的Java 8使用场景来改进方法

    例如,如果提供了一个包含两个参数的方法,那么选择第一个参数更可能是Map中的键的顺序非常有用。因此,它更有可能对带有方法引用的Map.forEach有用

    并避免使用签名不明确的方法。例如,如果你有一个类Foo,它有一个实例方法ReturnType bar()和一个static方法ReturnType bar(Foo),它们都不能再用作方法引用,因为Foo::bar是不明确的。删除或重命名这些方法之一

    重要的是,这些方法没有未记录的内部状态,当被多个线程使用时,这些状态会导致意外行为。否则,它们不能被并行流使用


    另一个不应低估的机会是,对符合Java8API引入的模式的类、接口和成员使用名称。例如,如果您必须为您的库引入某种过滤器接口和测试方法,该测试方法也应该与Java 7一起使用,那么您应该将接口Predicate和方法test命名,以将其与Java 8的类似命名功能接口相关联

  3. # 3 楼答案

    如果希望代码能被使用Java 6的虚拟机使用,那么必须使用Java 6语言兼容性编写代码。唉。字节码格式从6改为7,所以7和8的代码不会加载到6。(我在将自己的代码迁移到7时发现了这一点;即使我使用的是multi-catch(应该可以在6字节码中写入),我也无法为6目标构建它。编译器拒绝了。)

    我还没有尝试使用8,但您必须小心,因为如果您依赖任何新的Java包或类,您将仍然无法使用旧版本;旧的消费虚拟机根本无法访问相关类,也无法加载代码。特别是lambdas definitely won't work

    Well, can we target a different classfile version? There's no combination of source and target that will actually make javac happy with this.

    kevin$ $JAVA8/bin/javac -source 1.8 -target 1.7 *.java
    javac: source release 1.8 requires target release 1.8
    

    So there's simply no way to compile Java source with lambdas into a pre-Java 8 classfile version.

    我的一般看法是,如果你想支持旧版本的Java,你必须使用旧版本的Java来支持。您可以使用Java 8工具链,但需要Java 7或Java 6源代码。你可以通过分叉代码,为你想要支持的所有Java版本维护版本来做到这一点,但这远远超出了你作为一个独立开发人员所能证明的工作量。选择最简单的版本,然后继续(唉,现在就和那些有趣的新功能吻别吧)

  4. # 4 楼答案

    如果您在Java8中使用任何新的语言功能,它还需要使用Java8字节码

    $ javac -source 1.8 -target 1.7
    javac: source release 1.8 requires target release 1.8
    

    这意味着你的选择非常有限。不能使用lambda、方法引用、默认方法、流等并保持向后兼容性

    您仍然可以做两件事,Java 8的用户将从中受益。第一种是在公共API中使用函数接口。如果您的方法将可运行项、可调用项、比较器等作为参数,那么Java 8的用户将能够传入lambdas。您可能还想创建自己的单一抽象方法接口。如果您发现需要函数和谓词,我建议重用GS Collections或Guava附带的函数和谓词,而不是编写自己的函数和谓词

    您可以做的第二件事是使用丰富的collections API,它可以从使用功能接口中获益。同样,这意味着使用GS系列或番石榴。例如,如果您有一个返回List的方法,则返回MutableListImmutableList。这样,该方法的调用方将能够链接这些接口公开的富API的使用