我想编写一个Java框架,该框架支持JRE7
作为基线,但是JRE8
如果在JRE8
(向上兼容?)的上下文中运行,则可以利用这些功能。
(或者也许我有这个倒退……即JRE8
是基线,但会优雅地下降以支持JRE7
)。
Java是否提供执行此操作的方法?
我以为我可以以与javascript
特征检测类似的方式解决此问题,我可以以编程方式测试我的Java8
方法的存在(如果存在)以编程方式调用它,否则回退到Java7
库。
海事组织这是一个非常艰巨的做法。如果此“功能切换/检测”可以由Java Runtime Environment
/处理,那就太好了Java Compiler
。这可能吗,还是我正在服用疯狂药丸?
免责声明:我尚未解决编译问题,这将排除该解决方案的实用性(如果使用进行编译Java7
,则无法添加-parameters
到已编译的类中)。
public class Index {
void tellme(String yourname) {
/* ... */
}
public static void main(String[] args) throws Exception {
Method tellme = Index.class.getDeclaredMethod("tellme", String.class);
Method java8Params = null;
try {
java8Params = Method.class.getMethod("getParameters");
} catch (NoSuchMethodException t) { /* ignore */ }
if (java8Params != null) {
// java 1.8 !!
Object param = ((Object[]) java8Params.invoke(tellme))[0];
System.out.printf("(java8) %s %s(%s %s){/*...*/}",
tellme.getReturnType(),
tellme.getName(),
param.getClass().getMethod("getType").invoke(param),
param.getClass().getMethod("getName").invoke(param));
} else {
// java 1.7 ...
System.out.printf("(java7) %s %s(%s %s){/*...*/}",
tellme.getReturnType(),
tellme.getName(),
tellme.getParameterTypes()[0].getName(),
"arg0");
}
}
}
首先,使用反射来确保您的通用代码和可选API之间没有代码依赖性是正确的。由于在何时解析类和成员引用方面存在不同的策略,因此碰巧在一个JVM上起作用的非反射型惰性创建可能在另一个JVM上失败。
但这带来了一个问题,当必须通过反射对每个API的用法进行编码时,尤其是在您松散编译时检查时,某些操作难以实现,并且运行时性能也可能会受到影响。
通用的解决方案是使用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());
}
}
但是请注意,关于此特定功能,结果可能令人失望。仅当自省类使用带有标志的Java 8编译时,参数名称才可用-parameters
。因此,即使在运行时使用Java 8方法,检查Java 7兼容类也不会为您提供参数名称。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句