来自模板化对象的Java 8函数构造函数
我正在使用EclipseLuna服务版本2(4.4.2),Java8U51 我正在尝试创建一个方法,该方法将基于另一个方法参数创建已传递对象的实例。原型简化为来自模板化对象的Java 8函数构造函数,java,eclipse,generics,functional-programming,java-8,Java,Eclipse,Generics,Functional Programming,Java 8,我正在使用EclipseLuna服务版本2(4.4.2),Java8U51 我正在尝试创建一个方法,该方法将基于另一个方法参数创建已传递对象的实例。原型简化为 public <T> T test(Object param, T instance) { Constructor<?> constructor = instance.getClass().getConstructors()[0]; // I actually choose a proper constru
public <T> T test(Object param, T instance) {
Constructor<?> constructor = instance.getClass().getConstructors()[0]; // I actually choose a proper constructor
// eclipse reports "Unhandled exception type InvocationTargetException"
Function<Object, Object> createFun = constructor::newInstance;
T result = (T) createFun.apply(param);
return result;
}
publicttest(对象参数,T实例){
构造函数Constructor=instance.getClass().getConstructors()[0];//我实际上选择了一个合适的构造函数
//eclipse报告“未处理的异常类型InvocationTargetException”
函数createFun=constructor::newInstance;
T result=(T)createFun.apply(param);
返回结果;
}
联机使用函数
声明eclipse报告未处理的异常类型InvocationTargetException
编译器错误。我需要函数
,以便以后在流中使用
我试图添加各种try/catch块,抛出声明,但没有任何东西修复这个编译器错误
如何使此代码工作?您不能使用
函数
目标类型从lambda抛出已检查的异常,因为其应用
方法不会抛出异常。因此,您需要将其转换为未经检查的异常,例如通过包装:
Function<Object, Object> createFun = o -> {
try {
return constructor.newInstance(o);
} catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
throw new RuntimeException(e);
}
};
函数createFun=o->{
试一试{
返回构造函数newInstance(o);
}catch(实例化异常|调用目标异常|非法访问异常e){
抛出新的运行时异常(e);
}
};
另一种方法是让编译器认为这是未经检查的异常,与上面的选项相比,它会生成更干净的堆栈跟踪:
Function<Object, Object> createFun = o -> {
try {
return constructor.newInstance(o);
} catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
return uncheck(e);
}
};
函数createFun=o->{
试一试{
返回构造函数newInstance(o);
}catch(实例化异常|调用目标异常|非法访问异常e){
返回取消选中(e);
}
};
使用以下实用方法:
@SuppressWarnings("unchecked")
public static <E extends Throwable, T> T uncheck(Throwable t) throws E {
throw ((E) t);
}
@SuppressWarnings(“未选中”)
公共静态T取消选中(可丢弃T)抛出E{
投掷((E)t);
}
这是因为方法引用的是编译时错误中指定的异常的方法。单一抽象方法R适用(T T
)在java.util.Function
不会抛出这些异常。因此,java.util.Function的函数类型与方法引用的类型不匹配
使用带有匹配方法的函数类型可以。。。例如:
interface MyFunction<T,R> {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t) throws Throwable;
}
public <T> T test(Object param, T instance) throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
Constructor<?> constructor = instance.getClass().getConstructors()[0]; // I actually choose a proper constructor
// eclipse reports "Unhandled exception type InvocationTargetException"
MyFunction<Object,Object> createFun = constructor::newInstance;
T result = (T) createFun.apply(param);
return result;
}
接口函数{
/**
*将此函数应用于给定参数。
*
*@param t函数参数
*@返回函数结果
*/
R应用(T)可丢弃;
}
公共T测试(对象参数,T实例)抛出实例化异常、IllegalAccessException、,
IllegalArgumentException,InvocationTargetException{
构造函数Constructor=instance.getClass().getConstructors()[0];//我实际上选择了一个合适的构造函数
//eclipse报告“未处理的异常类型InvocationTargetException”
MyFunction createFun=构造函数::newInstance;
T result=(T)createFun.apply(param);
返回结果;
}
您可以从lambda抛出选中的异常。但不是来自应该实现函数的lambda,因为Function.apply()不会引发选中的异常。您可以通过引入
绑定来收紧取消选中的方法,这样您就不必进行任何类型的强制转换。您也可以在取消选中方法的内部执行抛出操作;当你可以只使用一个方法时,不需要两个方法。你认为函数
绕道比在构造函数
上简单调用newInstance
有什么好处?@Holger我在流中使用newInstance
在构造函数
上,它产生了相同的消息,所以我创建了一个这样的SSCE。函数detour实际上是保持相对可读的stream()
链所必需的。我明白了。因此,对于用例和lambda表达式,assylias建议的应该可以工作,这有点过于简单了。但我现在想知道的是,对于结果类型是否是实例
(可能是T
的子类)的确切类型,是否真的有严格的要求,换句话说,诉诸反射是否真的有必要…@Holger我找不到无反射的解决方案。该方法确实用于T的许多子类。我想要一个具有清晰定义但可能具有丑陋但单一实现的方法。我最终传递了一个类,而不是T的一个实例。如果在调用方的站点上有一个已知的具体类型,则可以使用类似Function f=B::new的构造代码>应该是可能的。如果调用方本身是泛型的,那么工作起来就不那么容易了,但是它必须从某处获取类
对象,不是吗?也许有一个无反射的解决方案,但这似乎值得打开另一个问题(关于用例的更多信息)…