33

What is the difference between these two ways of instantiating new objects of a class as follows:

Test t1=new Test();
Test t2=new Test(){ };

When I tried the following code, I could see that both objects could access the method foo(), but t2 cannot access the variable x (variable x cannot be resolved):

public class Test
{ 
    int x=0;
    public void foo(){ }

    public static void main (String args[])
    {
        Test t1=new Test();
        Test t2=new Test(){ };
        t1.x=10;
        t2.x=20;
        t1.foo();
        t2.foo();
        System.out.println(t1.x+" "t2.x);
    }
}
Crusaderpyro
  • 2,163
  • 5
  • 29
  • 53
  • 3
    I'd say none, other then the second way allows you the opportunity to override methods within the parent class without needing to create a dedicated sub class – MadProgrammer Mar 04 '14 at 05:56
  • 2
    If you make it compilable by transforming `t1.x+" "t2.x` into `t1.x+" "+t2.x`, it compiles fine. – JB Nizet Mar 04 '14 at 05:56
  • 1
    @Ankur Shanbhag That's an invalid edit. – Suresh Atta Mar 04 '14 at 05:57
  • @sᴜʀᴇsʜᴀᴛᴛᴀ : Hey brother, I did not see your post before I made the edit. I did not mean to take away your credit. In fact I made the change as it had nothing to do with the inner class concept. – Ankur Shanbhag Mar 04 '14 at 05:59
  • @AnkurShanbhag No issues, but don't go for those type of edit's. You can see the impact in this case :) – Suresh Atta Mar 04 '14 at 06:01
  • @sᴜʀᴇsʜᴀᴛᴛᴀ: Sure. I will be careful with my edits. – Ankur Shanbhag Mar 04 '14 at 06:03
  • 2
    @AnkurShanbhag Just sharing. I got the warning from Mod's even, in my earlier days of making edits ;) – Suresh Atta Mar 04 '14 at 06:04
  • 2
    Additionally can say that the second method is just not a "way of instantiating new object". It is specific to Java, i.e. you can't do this in `C#`. – Dims Mar 05 '14 at 10:34

7 Answers7

62

Test t2=new Test(); will create the object of Test class.

But Test t2=new Test(){ }; will create a object of subclass of test (i.e. anonymous inner class in this case).

you can provide implementation for any method over there like

Test t2=new Test(){ 
public void foo(){ System.out.println("This is foo");}
};

so that when foo() method called from object t2 it will print This is foo.

Addition

Compile time error in your code is due to missing concatination operator

System.out.println(t1.x+" "+t2.x);
                          ###
eatSleepCode
  • 4,427
  • 7
  • 44
  • 93
  • @eatSleepCode. Not really. But sure it doesn't deserve 5 upvotes in current state. There is just a minor mistake, which you should resolve. – Rohit Jain Mar 04 '14 at 06:04
  • @RohitJain isn't `t2` a object of class `test`? – eatSleepCode Mar 04 '14 at 06:06
  • 2
    @eatSleepCode Well, `t2 instanceof Test` will return `true`, but that doesn't mean `new Test() { }` creates an object of `Test`. No it doesn't. A subclass object is always an `instanceof` all it's super classes. – Rohit Jain Mar 04 '14 at 06:07
  • Since new Test(){ }; doesn't override anything...isn't it exactly the same class? – Solace Mar 04 '14 at 06:08
  • 4
    @Solace No, not at all. Try compiling the class, you'll see two class files generated. One with the name `Test$1` – Rohit Jain Mar 04 '14 at 06:10
  • @eatSleepCode Exactly. – Rohit Jain Mar 04 '14 at 06:11
  • 1
    You might want to go through [this](http://stackoverflow.com/q/13670991/1679863), [this](http://stackoverflow.com/q/18656107/1679863), and [this](http://stackoverflow.com/a/19350126/1679863) answer of mine. – Rohit Jain Mar 04 '14 at 06:14
  • 1
    Do you want to add the output of `t2.getClass()` to your answer? It might make it more clear (instead of a comment about two `.class` files being generated). – ashes999 Mar 04 '14 at 14:25
  • 1
    @eatSleepCode To complete the answer, you may want to explain why x is not accessible from the subclass and how to make it accessible. – hopia Mar 05 '14 at 09:09
16

The runtime type of both the references would be different. Try:

System.out.println(t1.getClass());  // class Test
System.out.println(t2.getClass());  // class Test$1

You will see different output. Reason being, the new Test() { } expression creates instance of an anonymous subclass of Test. So, Test$1 is a subclass of Test.

Now, the reason you're getting that error is, you're missing a + sign:

System.out.println(t1.x + " " + t2.x);
                              ^

You can find more details on this post, and this post

Community
  • 1
  • 1
Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
  • If `x` was private then `t2` would legitimately not be able to see it? – Cruncher Mar 04 '14 at 18:13
  • 1
    @Cruncher Yup, it won't. In current code, since the `main` method is in the class itself, it would seem that it is able to access, but if you move it outside the class, neither `t1` nor `t2` would be able to access `x`. – Rohit Jain Mar 04 '14 at 18:14
  • You're right. In that case, I don't think mentioning the fact that `x` has the default modifier is relevant. For any modifier either `t1` and `t2` can see it, or neither can. – Cruncher Mar 04 '14 at 19:19
5
test t1=new test();

This will create a new instance of class test

test t2=new test(){ };  

This is an anonymous inner class which extends class test

Ankur Shanbhag
  • 7,746
  • 2
  • 28
  • 38
5
Test t1=new Test();

Here, you are creating an instance of Test class and assigned it to t1

Test t2=new Test(){ };

Here, You have created an anonymous sub class of Test and instantiate it and assigned to t2

And, you did a mistake here in the following line, corrected it, you missed +

System.out.println(t1.x + " " + t2.x);
Abimaran Kugathasan
  • 31,165
  • 11
  • 75
  • 105
4

a)

 Test t1=new Test();

By doing this you create an Object of class Test by calling default constructor

b)

Test t2=new Test(){ };

And by doing this you are creating an object of a class that extends Test class, this class has no name and hence it is called "Anonymous Inner Class" eg.

     Test t2=new Test(){ 
// this is the body of the anonymous(un-named) class 
//you can overide the method foo() here
// you can write more methods here but you will not be able to call them 
// for example
public void doSomething(){}
};

doSomething() is not accessible outside, as t2 i.e reference(pointer) to this object(object of anonymous inner class that extends Test) understands only foo() method as it is reference of parent class

doSomething() can be called only if you do this

  Test t2=   new Test(){
            public void foo()
            {
              doSomething();


            }
            public void doSomething(){
                  System.out.println("Do Something");
            }

        };

i.e. explicitly call doSomething() in foo() and foo() is accessible outside

t2.foo();

Note: Please write name of class properly, the first letter of class must be capital like

public class Test{}

When you start writing huge chunks of code it will help you and others as it makes your code Readable.

Oliver
  • 6,152
  • 2
  • 42
  • 75
  • ya I know that class names always start with a capital Letter. This was just created to test the difference between the two methods. Anyways, thanks for the detailed answer. – Crusaderpyro Mar 05 '14 at 07:58
3

you miss the + operator in below line try this

System.out.println(t1.x+" "t2.x);

use this

System.out.println(t1.x+" "+t2.x);
Rishi Dwivedi
  • 908
  • 5
  • 19
2
Test t2=new Test();` 

will create the object of Test class.

Test t2=new Test(){ };

will create a object of subclass of test (i.e. anonymous inner class in this case).

Test t2=new Test(){ 
public void foo(){ System.out.println("foo");}
};

when foo() method called from object t2, it will print foo.

CCUSER
  • 59
  • 6