32

Why first way is correct, but second isn't?


First way:

new Object() {
    public void a() {
        /*code*/
    }
}.a();

Second way:

Object object = new Object() {
    public void a() {
        /*code*/
    }
};

object.a();

And where can I find more information about it?

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
Sekobune
  • 338
  • 3
  • 7

4 Answers4

44

java.lang.Object has no a methods declared (2), while the anonymous class returned by the class instance creation expression new Object() { public void a() {} } does (1).

Use Java 10's local variable type inference (var) to make the second option as valid as the first one.

var object = new Object() {
    public void a() {}
};
object.a();
Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
  • 1
    Note that `var` was introduced in Java 10 and will not be available in lower versions. – nasch Dec 28 '18 at 20:03
  • 5
    @ernest_k It's really not that hard or interesting. By saying `Object object = ` you are downcasting to an `Object`, `var` gives `object` its actual correct type that has `a()` defined. – Hatted Rooster Dec 28 '18 at 20:41
  • 2
    @SombreroChicken I understand the effect of `var` here. But beside the first syntax in the question, there was no other way (that I know) to have a static reference to the anonymous type. Now I know that `var` can be used for that. Even more, it allows one to make multiple method calls from the anonymous class. I find that strangely new and interesting! – ernest_k Dec 28 '18 at 20:46
  • 2
    You can also declare an interface that has the `a()` method and create an anonymous object from *that* instead of `Object`, which would work in lower versions that don't support `var`. E.g., `private interface HasA { public void a(); }` then `HasA object = new HasA() { public void a() { ... } };`. – jpmc26 Dec 28 '18 at 23:33
  • 1
    @AndrewTobilko Yes, but then the implementation is not inlined. I presumed that they were inlining it for a reason. Different options for different usages, of course. – jpmc26 Dec 28 '18 at 23:56
  • 1
    @ernest_k there is, since Java 8. E.g. `Optional.of(new Object() { public void a() { /*code*/ } }) .ifPresent(object -> object.a());` It’s all about defining variables without having to name the type, see also [Implied anonymous types inside lambdas](https://stackoverflow.com/q/43987285/2711488). – Holger Jan 30 '19 at 09:05
  • @Holger Thanks! Now that you mention that, I can even think of `(new Object() {public void b() {System.out.println("bbbb");}}).b();` :-) - usable in even older versions, I suppose. – ernest_k Jan 30 '19 at 10:07
  • @ernest_k yes, that was possible in earlier versions too, but I assumed you were aware of it when you wrote your comment, as you mentioned that the new syntax “*allows one to make multiple method calls from the anonymous class*”, which is the fundamental difference between calling a method directly on the creation expression and using a lambda expression or `var` declaration for it. – Holger Jan 30 '19 at 10:10
  • @Holger Fair enough. But before this answer, none of this had never occurred to me (one method or many, I'd just never seen this trick)... And your `Optional`-based approach is nifty. I'm thinking of using it in the next code I submit for peer review :-). – ernest_k Jan 30 '19 at 10:20
22

In the second option, you assign your new object to a reference of type Object. Because of this, only methods defined in java.lang.Object could be called on that reference.

And in the first option, you basically create new object of anonymous class that extends java.lang.Object. That anonymous class has the additional method a(), which is why you can call it.

MTCoster
  • 5,868
  • 3
  • 28
  • 49
Ivan
  • 8,508
  • 2
  • 19
  • 30
2

Java is statically typed. When you say object.a() it is looking for the method a in the Object class which is not present. Hence it does not compile.

What you can do is get the method of object using reflection as shown below :

Object object = new Object() {
  public void a() {
     System.out.println("In a");
  }
}

Method method = object.getClass().getDeclaredMethod("a");
method.invoke(object, null);

This would print

In a

fastcodejava
  • 39,895
  • 28
  • 133
  • 186
  • 2
    That's not true. Java uses static typing (you can see it in your example - `Object object` - you just declared its type!). It uses polymorphism to determine which method should be called, but that's a different thing than dynamic typing. Some debate about dynamic vs static can be found [here](https://stackoverflow.com/questions/1517582/what-is-the-difference-between-statically-typed-and-dynamically-typed-languages) – MatthewRock Dec 28 '18 at 19:39
  • 2
    you should have pointed out that calling the method through reflection is the last thing OP wants :) – Andrew Tobilko Dec 28 '18 at 20:17
  • @MatthewRock The JVM does support dynamic dispatch, however. – Solomon Ucko Dec 29 '18 at 19:27
  • @SolomonUcko JVM is not Java. Dynamic dispatch is also not something that makes a language a static one. C++ has dynamic dispatch for virtual methods, but is still a static language. – MatthewRock Dec 29 '18 at 20:59
0

Don't worry, you will have to do a bit of correction Both are ways to access the private member of a class. By using first way you don' have to pre-declare the method.ex: -

public class demo {

    public static void main(String[] args) {
    new Object() {
        public void a() {
            /*code*/
            System.out.println("Hello");
        }
    }.a();

}

}

But by using second way you will have to explicitly declare the method a(); either in abstract class or in interface then you can override it. like: -

interface Object
{
public void a();
}
class demo {

public static void main(String[] args) {
    Object object = new Object() {
        public void a() {
            System.out.println("Hello");
        }

    }; object.a();


}

}

I hope it will help a bit.

MAYANK
  • 5
  • 8