我的任务是迁移两个独立的模块,以兼容Java 7编译和运行时。我想知道我是否把所有的事情都考虑进去了(也就是说,将来会有很多副作用,限制等等)。
这些模块称为ModuleA和ModuleB,结构如下:
ModuleA <- Runtime Library
\-pack1 <- This contains ~15 interfaces, ~3 layers of inheritance, and occasionally static/default methods
\-pack2 <- This contains some standard implementations of interfaces in package1
ModuleB <- Main app. Depends on ModuleA
\-main <- Classes here call static/default ModuleA.package1.* interface methods a lotModuleB可以定期更改,而ModuleA是专有/内部API,不太可能更改。将源代码转换为Java 7兼容性是一个一直给我带来麻烦的过程。
我最初计划这样做的方法是在每个接口中创建一个静态内部类,并在内部类中迁移静态和默认方法,然后更改所有这些方法( static )。我将在更改签名/实现后标记(前)默认方法,将实例添加为参数列表中的第一个参数,然后添加注释@Default (因此我将知道如何在ModuleB中转换实现)。所以这个:
interface Foo {
void doFoo(String bar);
default String toFancyString() {
return this.toString() + "called from a default method";
}
static int getFooDefault() {
return 0xCAFEBABE;
}
}将改为:
interface Foo {
void doFoo(String bar);
final class Util {
@Default
static String toFancyString(Foo impl) {
return impl.toString() + "called from a default method";
}
static int getFooDefault() {
return 0xCAFEBABE;
}
}
}在更改两个ModuleA包之后,我会将ModuleB (在编译时)更改为等效于更改以下内容:
int i = foo.getFooDefault() + 1;
Foo f = bar -> System.out.println(bar);
String fancyString = f.toFancyString();对此:
int i = Foo.Default.getFooDefault() + 1;
Foo f = // anonymous class bloat here
String fancyString = Foo.Default.toFancyString(f);我想知道的是:
Util类中的方法都是静态的,所以我考虑将所有静态方法添加到存在超类方法的子类中,并从子类静态方法手动调用最近的上链静态方法,但是可能有一个更简单的解决方案。代码行/复杂性并不重要,因为我可以编写大部分源转换的脚本。我的目标只是在JRE7中运行时能够产生与在8中相同的精确输入/输出,而无需使用任何反射/鸭子类型的。(而且,我只担心静态/默认问题,而不是任何新的JDK8 API)
发布于 2017-05-10 13:48:58
将jdk-8迁移到jdk-7,在接口上使用默认方法/静态方法。您可以用抽象类替换接口。然后,使用迁移模块的其他模块不需要修改。例如:
abstract class Foo {
public abstract void doFoo(String bar);
public String toFancyString() {
return this.toString() + "called from a default method";
}
public static int getFooDefault() {
return 0xCAFEBABE;
}
}但是,当您使用java 代理 api时,引入抽象类并将所有静态方法提取到抽象类中还有另一个原因。然后,让所有已实现Foo的类扩展AbstractFoo,例如:
interface Foo {
void doFoo(String bar);
String toFancyString();
}
abstract class AbstractFoo implements Foo {
public String toFancyString() {
return this.toString() + "called from a default method";
}
static int getFooDefault() {
return 0xCAFEBABE;
}
}
class SimpleFoo extends AbstractFoo {
@Override
public void doFoo(String bar) {/*todo*/}
}备注:其他模块在第二种方法中调用静态方法时需要修改,因为静态方法所在的位置发生了更改。
发布于 2017-05-09 23:27:52
我相信您已经知道,在Java8中引入的接口中的@FunctionalInterface和默认实现,在此之前,interface...this中没有任何实现都必须在任何实现中完成。一般说来,我还是会说这是一种糟糕的做法。我的想法是,如果我想将方法添加到已经存在的接口中,而不是破坏所有正在使用的方法(比如列表接口上的forEach )。
话虽如此,我不知道是否有一条笔直的路要走。您可以做一个已经实现了这些的抽象类,但是只能从一个抽象类继承,所以这可能不起作用,或者静态方法described...but将继承从水中吹出。
@FunctionalInterface很简单,它只是强制在编译时接口中只有一个非默认方法。只要删除注释,Java 7就可以使用了。
https://stackoverflow.com/questions/43880947
复制相似问题