tags:

views:

57

answers:

4

I got a very weird problem and a weird solution:

class Parent {
    protected void aProtectedMethod() { doSomething(); }
} 

class Child extends Parent {
    void anotherMethod() {
      new SomeInterface() {
          public void interfaceMethod() {
              aProtectedMethod();
          }
      };
    }
}

When child.anotherMethod() is run, I got IllegalAccessException at myProtectedMethod(), saying my inner class doesn't have access to the Parent class...

However, if I add:

protected void aProtectedMethod() { super.aProtectedMethod(); } 

in my Child class, everything is fine...

I wonder why this is?

A: 

It kind of makes sense, in a way. The protected method in Parent is accessible to Parent, and anything that subclasses Parent. The inner class has access to anything in its containing class, which the protected method in Parent technically ISN'T. So, it's not until you add a protected method to Child, when then just calls Parent's method.

(Hmm, I'm not actually sure that my explanation is any clearer than the original code. Sorry. :) )

Curtis
I dont know about that...it comes down to scoping. The protected method is visible to the child class, and inner class (non-static, of course) inside the child class has the same access.
EnToutCas
It definitely comes to scoping. But I'm not sure it's true that the inner class has "the same access" as its parent. If it was, your original code would work. If the rule is that the inner class has "complete access to its parent" though, it explains the behavior you're seeing - the protected method on Parent is accessible to Child, but not actually present IN child.
Curtis
I think GWT deferred binding is throwing me off. The problem only occurs at hosted mode. When I compile it down to Javascript, everything is fine.
EnToutCas
A: 

I'm not sure I understand your question. This code executes just fine:

interface SomeInterface {
    public void interfaceMethod();
}

class Parent {
    private void doSomething() { System.out.println("hello world"); }
    protected void aProtectedMethod() { doSomething(); }
} 

class Child extends Parent {

    public static void main(String... args) {
        new Child().anotherMethod();
    }

    void anotherMethod() {
      new SomeInterface() {
          public void interfaceMethod() {
              aProtectedMethod();          // line A
          }
      }.interfaceMethod();
    }
}

(Prints hello world as expected.)

However, what may be confusing you is that at line A (see above code), the this reference actually refers to an instance of an object of type SomeInterface and not to a Child, which may explain why you have trouble calling aProtectedMethod. You can access the references to Childs this, by writing Child.this.


From the documentation on IllegalAccessException:

An IllegalAccessException is thrown when an application tries to reflectively create an instance (other than an array), set or get a field, or invoke a method, but the currently executing method does not have access to the definition of the specified class, field, method or constructor.

Are you using the reflection API?

aioobe
Now that I think of it, it definitely has something to do with reflection. The error only occurs in GWT hosted mode, not when I compile it to Javascript.
EnToutCas
Then I have absolutely no idea what's going on and why. Sorry.
aioobe
A: 

I tried, and it worked for me in plain java (not GWT compiled).

It could be a bug (or a feature) in the GWT compiler.

You could try to explicitly call the method like this:

Child.this.aProtectedMethod();
Nicolas
Child.this.aProtectedMethod() didn't work for me. But I think it's the problem with GWT deferred binding and hosted mode. I compiled it down to Javascript and things are fine.
EnToutCas
+1  A: 

I think you're running into this bug: http://code.google.com/p/google-web-toolkit/issues/detail?id=3646.

jgindin
exactly! seems like it's a known issue.
EnToutCas