我想编写一个支持JRE7
作为基线的java框架,但利用JRE8
功能,如果在上下文中运行一个JRE8
(向上兼容??)。
(或者我可能倒退了......即JRE8
是基线,但是优雅降级以支持JRE7
)。
Java是否提供了这样做的方法?
我认为我可以通过与javascript
功能检测类似的方式解决此问题,我可以通过编程方式测试我的Java8
方法是否存在,如果它以编程方式调用它,则回退到{{ 1}}库。
IMO这是一个非常艰巨的方法。如果这个"功能切换/检测"它会很棒。可以由Java7
/ Java Runtime Environment
处理。这可能吗,还是我服用疯狂药?
免责声明:我还没有解决编译问题,这会排除此解决方案的有用性(如果我使用Java Compiler
进行编译,则无法添加{{ 1}}到已编译的类。)
Java7
答案 0 :(得分:6)
首先,使用Reflection来确保通用代码和可选API之间没有代码依赖关系是正确的。由于在何时解析类和成员引用时允许使用不同的策略,因此在一个JVM上运行的非反射延迟创建可能会在另一个JVM上失败。
但是这引发了一个问题,即当每个API使用必须通过Reflection进行编码时,某些操作很难实现,特别是当您放松编译时检查时,运行时性能也可能会受到影响。
一般的解决方案是使用Java从一开始就提供的OO技术。创建定义该功能的interface
或abstract class
。实现Java 8解决方案和Java 7后备。在应用程序初始化期间或第一次需要该功能时,您可以一个反射检查是否可以使用您的最佳解决方案依赖的功能,如果可用,则实例化最佳实现,但实例化否则就是后退。从那时起,您通过接口使用实现,就像普通对象一样。
在简单的情况下,您可以将类的数量减少到两个,定义特性的基类和提供回退行为,以及专用子类用其专用的类重写实现。
将Java 8实现保存在单独的源文件夹中,并使用Java 8编译器进行编译。其他代码将使用Java 7编译器进行编译,确保不依赖于Java 8实现。
通用Java 7兼容代码:
import java.lang.reflect.Method;
public class Index {
static final MethodDescription DESC_ACCESSOR;
static {
MethodDescription md;
try {
Method.class.getMethod("getParameters");// test JRE feature
// instantiate specialized solution
md=(MethodDescription) Class.forName("MethodDescriptionJ8").newInstance();
} catch(ReflectiveOperationException|LinkageError ex) {
md=new MethodDescription(); // J7 fall-back
}
DESC_ACCESSOR=md;
}
void tellme(String yourname) {
/* ... */
}
public static void main(String[] args) throws Exception {
Method tellme = Index.class.getDeclaredMethod("tellme", String.class);
String desc=DESC_ACCESSOR.get(tellme);
System.out.println(desc);
}
}
class MethodDescription {// base class defining application specific feature
public String get(Method tellme) {// and providing fall-back implementation
return String.format("(java7) %s %s(%s %s){/*...*/}",
tellme.getReturnType(),
tellme.getName(),
tellme.getParameterTypes()[0].getName(),
"arg0");
}
}
使用Java 8单独编译:
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class MethodDescriptionJ8 extends MethodDescription {
@Override
public String get(Method tellme) {
Parameter param = tellme.getParameters()[0];
return String.format("(java8) %s %s(%s %s){/*...*/}",
tellme.getReturnType(),
tellme.getName(),
param.getType(),
param.getName());
}
}
但请注意,关于此特定功能,结果可能会令人失望。参数 names 仅在使用带有-parameters
标志的Java 8编译内省类时才可用。因此,即使在运行时使用Java 8方法,检查Java 7兼容类也不会为您提供参数名称。