10

I just encountered a behavior I first thought it was a bug in Eclipse. Consider this simple class:

public class Foo {
    public static interface Callback {
        public void onAction();
    }
}

This is perfectly valid. However, this isn't:

public class Foo implements Callback {
    public static interface Callback {
        public void onAction();
    }

    public void onAction() { /*some implementation*/ }
}

But this is valid, too:

public class Foo {
    public static interface Callback {
        public void onAction();
    }

    private final Callback mCallback = new Callback() {
        public void onAction() { /*some implementation*/ }
    };
}

Why does Java force me to kind of 'waste' a member for it, if it could simply save it by letting me implement this itself? I'm well aware of the 'workaround' to put this interface in its own file, but out of curiosity: Is there a reason why this won't work?

Rafael T
  • 15,401
  • 15
  • 83
  • 144
  • AFAIK, you cannot do a new on an interface, so new Callback() is invalid – Miguel Prz Feb 12 '13 at 15:22
  • 2
    I'm not sure of the official rationale for this not working, but I don't see any reason why you would want to have a class implement an interface which it contains -- why wouldn't you just define the class with the methods you're trying to put into the interface? Why do you want an interface at all in this case? – Reinstate Monica -- notmaynard Feb 12 '13 at 15:22
  • 2
    @MiguelPrz he's creating an implementation of the interface inline using `{}` – Miquel Feb 12 '13 at 15:23
  • @MiguelPrz Actually, that's instantiating an anonymous class which implements `Callback`. It is valid, and can be useful. – Reinstate Monica -- notmaynard Feb 12 '13 at 15:23
  • 1
    [This post](http://stackoverflow.com/questions/71625/why-would-a-static-inner-interface-be-used-in-java) has some good explanation on inner interfaces and their semantics. – sbk Feb 12 '13 at 15:25
  • Does `implements Foo.Callback` work? I don't think you're in the scope of `Foo` at that point. This area is mucky. IIRC, in the early days it wasn't well defined, with javac getting updates to cover more cases. IMO, most of this stuff should have been outlawed because there are lots of corner cases and it isn't something you'd want to see in real code. – Tom Hawtin - tackline Feb 12 '13 at 15:29
  • @TomHawtin-tackline, no unfortunatly it doesn't work to declare `Foo.Callback` @iamnotmaynard because my class is holding in fact a List of those Callbacks. It should get triggered first, and then dispatch it to the others... – Rafael T Feb 12 '13 at 15:52
  • @sbk thanks, good point – Rafael T Feb 12 '13 at 15:53

2 Answers2

8

Using this code

public class Foo implements Callback{

public static interface Callback{
    public void onAction()
}

public void onAction(){//some implementation}
}

what is Callback ? The compiler (btw which is different from Eclipse, ) doesn't know what is Callback.

You defined the Callback interface after you used it.

banuj
  • 3,080
  • 28
  • 34
  • 1
    can't the compiler look ahead and get a list of all classes to come ?! feels kinda silly – NikkyD Jun 24 '14 at 17:11
  • It is an unfortunate statement, in Java language textually "before" and "after" is not relevant as in some other languages. Here "before" and "after" should be read as "as the compiler can reach it". The compiler first try to compile the class header, then the class body (maybe for eliminating the opportunity of recoursive definition checks...) - thus in the header you can't use a definition what reside in the body. – MGM Jul 24 '20 at 08:12
6

In your 2nd case, since the signatures are checked before the bodies of the classes, when the compiler tries to compile the Foo class, the Callback interface isn't defined yet.

sp00m
  • 47,968
  • 31
  • 142
  • 252