Question

I have a class that I can't change as follows:

public class Foo {
    public final int ID=0;
    public int bar;
    public final Object baz=null;
}

I want to have an anonymous inner class that overrides Foo such as:

public Foo newFoo(final int mID, final int mbar, final Object mbaz) {
    return new Foo(){
        public final int ID = mID;
        public int bar = mbar;
        public final Object baz = mbaz;
    };
}

I then have a javax.script.ScriptEngine that I want to call something like this in JS: newFoo(0,0,undefined)["ID"]

My problem is that I get an exception like this:

sun.org.mozilla.javascript.internal.WrappedException: Wrapped java.lang.IllegalAccessException: Class sun.org.mozilla.javascript.internal.JavaMembers can not access a member of class Baz$1 with modifiers "public final" (mod.js#9) in test.js at line number 9

I don't understand how I could be getting a problem here: this works just fine if newFoo returns a plain 'ol Foo, but if I try to override Foo with an anonymous inner class, I can't access any overridden members even if they're public.

Was it helpful?

Solution

I think there are two aspects to this problem.

Your Java code is syntactically valid (I think), but it almost certainly does not do what you want it to do. Specifically, the declarations in the anonymous class don't replace the declarations in the Foo class. Instead, each instance of the anonymous class gets two sets of fields. The methods declared in Foo will only see the original fields, and any methods declared in the anonymous class will see the new fields.

If you want to have different values for the fields in the anonymous subclass, then:

  • they cannot be final, and
  • they need to be assigned to not redeclared.

I can't really advise the best way to solve this, but I think you will need to start by making the Foo fields private, and providing getters and/or setters for them. In the case of the setters, you can use access modifiers to allow the anonymous subclass to set the field, but not unrelated code.

The bottom line is that you cannot override fields in Java. What your code is doing is not overriding, it is hiding the fields.


The other aspect is the wrapped exception is coming from the Javascript engine. I think that the problem is that anonymous classes are implicitly private, and that your Javascript snippet is therefore trying to access a field on a private class. When the Javascript engine tries to do this (using Java reflection, I expect), it gets a runtime exception.

The only unfortunate thing here is that the exception message doesn't say why it can't access the member, but your Java code is sufficiently "strange" that this doesn't surprise me.

As a work-around, I'd suggest replacing the anonymous class with a non-nested class.

OTHER TIPS

You don't have a class like this :

public class Foo {
    public final int ID=0;
    public int bar;
    public final Object baz;
}

Because that wouldn't compile (baz cannot not be declared).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top