Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/378.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当参数是谓词时,EL 3.0(JSR-341)不起作用?_Java_El - Fatal编程技术网

Java 当参数是谓词时,EL 3.0(JSR-341)不起作用?

Java 当参数是谓词时,EL 3.0(JSR-341)不起作用?,java,el,Java,El,此测试显示了我的问题: public static String testMe(Predicate<String> filter) { return "yeah!"; } @Test public void testPredicateAsArgument() throws ClassNotFoundException, NoSuchMethodException { final ELProcessor elp = new ELProcessor(); elp

此测试显示了我的问题:

public static String testMe(Predicate<String> filter) {
    return "yeah!";
}

@Test
public void testPredicateAsArgument() throws ClassNotFoundException, NoSuchMethodException {
    final ELProcessor elp = new ELProcessor();
    elp.defineFunction("", "", "test.EL3Test", "testMe");
    try {
        Object result = elp.eval("testMe(o->true)"); // IllegalArgumentException
        // ...
    } catch (javax.el.ELException ex) {
        fail(Exceptions.getCauseMessage(ex));
    }
}
公共静态字符串testMe(谓词过滤器){
回答“是的!”;
}
@试验
public void testPredicateAsArgument()引发ClassNotFoundException、NoSuchMethodException{
最终elp处理器elp=新elp处理器();
elp.defineFunction(“,”,“test.EL3Test”,“testMe”);
试一试{
Object result=elp.eval(“testMe(o->true)”;//IllegalArgumentException
// ...
}catch(javax.el.ELException-ex){
失败(异常。getCauseMessage(ex));
}
}
它抛出:
IllegalArgumentException:无法转换javax.el。LambdaExpression@511baa65类型类javax.el.LambdaExpression到接口java.util.function.Predicate

这是EL 3的缺陷或限制还是我遗漏了什么

测试版本:
org.glassfish:javax.el:jar:3.0.0
org.glassfish:javax.el:jar:3.0.1-b08


另外,EL3.0是在Java1.7(JavaEE7的目标)而不是Java1.8期间创建的。换句话说,它早于Java原生lambdas,因此不可能对它们有任何了解


你能做的最好的事情就是为下一个EL版本发布一个增强问题。我们目前已经在使用JavaEE8(针对Java1.8),但还没有EL3.1。您必须等待Java EE 9,以便任何增强请求都可能在EL中结束。下一步。

对于任何对解决方案感兴趣的人:

/**
 * {@code FunctionalInterfaceResolver} intercepts method calls with EL lambda expressions as
 * arguments which need to coerce to Java 8 functional interfaces.
 *
 * A custom `ELResolver` is always consulted before the default resolvers.
 *
 * Example usage:
 * ```` java
 * final ELProcessor elp = new ELProcessor();
 * elp.getELManager().addELResolver(new FunctionalInterfaceResolver());
 * final Object result = elp.eval("p.findResources(o->o.getContentType() eq 'image/png')");
 * ````
 *
 * @author <a href="mailto:rmuller@xiam.nl">Ronald K. Muller</a>
 */
public final class FunctionalInterfaceResolver extends ELResolver {

    @Override
    public Object invoke(final ELContext context, final Object base, final Object method,
        final Class<?>[] paramTypes, final Object[] params) {

        if (context == null || base == null || !(method instanceof String) || params == null) {
            return null;
        }
        // takes about 5ms. Try out caching if it becomes a bottleneck
        for (int i = 0; i < params.length; ++i) {
            if (params[i] instanceof javax.el.LambdaExpression) {
                for (Method m : base.getClass().getMethods()) {
                    if (m.getName().equals(method) && m.getParameterCount() == params.length) {
                        final Class[] types = m.getParameterTypes();
                        if (types[i].isAnnotationPresent(FunctionalInterface.class)) {
                            params[i] = coerceToFunctionalInterface(context,
                                (LambdaExpression)params[i], types[i]);
                        }
                    }
                }
            }
        }
        return null;
    }

    @Override
    public Class<?> getType(ELContext context, Object base, Object property) {
        return null;
    }

    @Override
    public void setValue(ELContext context, Object base, Object property, Object value) {
    }

    @Override
    public boolean isReadOnly(ELContext context, Object base, Object property) {
        return false;
    }

    @Override
    public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
        return null;
    }

    @Override
    public Class<?> getCommonPropertyType(ELContext context, Object base) {
        return String.class;
    }

    @Override
    public Object convertToType(ELContext context, Object obj, Class<?> targetType) {
        if (obj instanceof LambdaExpression &&
            targetType.isAnnotationPresent(FunctionalInterface.class)) {
            context.setPropertyResolved(obj, targetType);
            return coerceToFunctionalInterface(context, (LambdaExpression)obj, targetType);
       }
       return null;
    }

    private Object coerceToFunctionalInterface(
        final ELContext context, final LambdaExpression elLambda, final Class<?> targetType) {

        assert targetType.isAnnotationPresent(FunctionalInterface.class);
        return Proxy.newProxyInstance(targetType.getClassLoader(),
            new Class[]{targetType}, (Object obj, Method method, Object[] args) -> {

            // a FunctionalInterface has exactly one abstract method
            if (Modifier.isAbstract(method.getModifiers())) {
                // the "functional method"
                return elLambda.invoke(context, args);
            } else if ("toString".equals(method.getName())) {
                return "Proxy[" + targetType.getName() + ", wrapping " +
                    elLambda.getClass().getName() + ']';
            } else {
                throw new AssertionError("Method not expected: " + method.getName());
            }
        });
    }

    @Override
    public Object getValue(ELContext context, Object base, Object property) {
        return null;
    }

}
/**
*{@code FunctionInterfaceResolver}截取EL lambda表达式为
*需要强制到Java8函数接口的参数。
*
*在默认冲突解决程序之前,始终先咨询自定义“ELResolver”。
*
*用法示例:
*``` java
*最终elp处理器elp=新elp处理器();
*elp.getELManager().addELResolver(新功能接口解析器());
*最终对象结果=elp.eval(“p.findResources(o->o.getContentType()eq'image/png');
* ````
*
*@作者
*/
公共最终类FunctionInterfaceResolver扩展了ELResolver{
@凌驾
公共对象调用(最终上下文上下文、最终对象基、最终对象方法、,
最终类[]参数类型,最终对象[]参数){
if(context==null | | base==null | |!(字符串的方法实例)| | params==null){
返回null;
}
//大约需要5毫秒。如果缓存成为瓶颈,请尝试缓存
对于(int i=0;i{
//功能接口只有一个抽象方法
if(Modifier.isAbstract(method.getModifiers())){
//“函数法”
返回elLambda.invoke(上下文,args);
}else if(“toString.equals(method.getName())){
返回“Proxy[”+targetType.getName()+”,换行”+
elLambda.getClass().getName()+']';
}否则{
抛出新的断言错误(“不需要方法:+Method.getName());
}
});
}
@凌驾
公共对象getValue(ELContext上下文、对象基、对象属性){
返回null;
}
}

谢谢。我感到困惑的是,lambda是从el3.0(使用java8语法)开始支持的,同样的情况也适用于流的支持(包括使用lambda语法的过滤器操作)。但是,刚刚检查了实现,所有这些功能都是使用Java7模拟的。