java.lang.IllegalAccessException:无法使用修饰符"public"访问类java.util.Collections $ UnmodifiableCollection的成员

Kar*_*ter 11 el jsf-2

我有课程PrimitivePropertyComplexProperty界面Property.我想创建一个Property的实现,它强制执行一个空的不可修改的Property实例集作为返回值Property.getProperties,例如

public interface Property {
    Set<Property> getProperties();
}

public class ComplexProperty implements Property {
    private Set<Property> properties; 
    //getter overrides the interface method
}

public class PrimitiveProperty implements Property {
    private final static Set<Property> EMPTY_PROPS = Collections.unmodifiableSet(new HashSet<Property>(1));

    @Override
    public Set<Property> getProperties() {
        return EMPTY_PROPS;
    }
}
Run Code Online (Sandbox Code Playgroud)

使用Glassfish 4.0,我得到了

java.lang.IllegalAccessException:类javax.el.E​​LUtil无法使用修饰符"public"访问类java.util.Collections $ UnmodifiableCollection的成员

当我在leafRichfaces 的属性中访问属性时tree,例如

<r:tree id="aTree" 
        toggleType="ajax" var="item" >
  <r:treeModelRecursiveAdaptor roots="#{aCtrl.roots}" 
                               nodes="#{item.properties}" leaf="#{item.properties.isEmpty()}">
    <r:treeNode>
      #{item.name}
    </r:treeNode>
    <r:treeModelAdaptor nodes="#{item.properties}" leaf="#{item.properties.isEmpty()}"/>
  </r:treeModelRecursiveAdaptor>
</r:tree>
Run Code Online (Sandbox Code Playgroud)

如果我使EMPTY_PROPS常量可修改(通过赋值HashSet而不是返回值的实例),这个问题就会消失,Collections.unmodifiableSet这不是我的意图.

是否有可能实现我想做的事情?我是否必须发明或使用Collections$UnmodifiableCollection与JSF访问需求兼容的(子类)做的实现?

Bal*_*usC 12

这是问题所在:

leaf="#{item.properties.isEmpty()}"
Run Code Online (Sandbox Code Playgroud)

您正在尝试直接在UnmodifiableSet实例上调用方法.虽然实现了Collection,这就是public,在UnmodifiableSet执行本身,EL(读:反射API)正在试图寻找在类中的方法,是不是 public.

确切地说,这个问题在普通Java(main()方法)中是可重现的,如下所示:

Set<Object> set = Collections.unmodifiableSet(new HashSet<>());
for (Method method : set.getClass().getMethods()) {
    if ("isEmpty".equals(method.getName())) {
        method.invoke(set); // IllegalAccessException.
    }
}
Run Code Online (Sandbox Code Playgroud)

这实际上是所使用的EL实现中的一个错误.

你最好只使用EL自己的empty运算符:

leaf="#{empty item.properties}"
Run Code Online (Sandbox Code Playgroud)

  • ......再一次,JSF抽象结果泄露了实现细节:使用EL,人们不应该知道它与Reflection API交互的具体细节(在私有类中实现的公共方法可以是通过使用`setAccessible(true)`或通过声明方法的公共超类型的方法对象通过反射调用. (3认同)