3

I came across the following java code, and i am not sure what it means. Can we write code in '{' after we instantiate a class , eg new TestClass { */ code goes here */ }

But when i try to run the code i do not see 'Z is 10' in the output. Can someone please give me some link where i can get some more info related to this feature of java.

class TestClass {
    int z;
    public TestClass(){
    z=10;
    }
    public int getZ(){
    return z;
    }
    public void setZ(int z){
    this.z=z;
    }
}

class A
{   
    public static void main (String[] args) throws java.lang.Exception
    {
    TestClass TC = new TestClass() {
            public void testprint() {
        System.out.println("Z is " + getZ());
        }
     };
    }
}
Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
user2588495
  • 93
  • 1
  • 5

5 Answers5

8

This is an anonymous inner class. It creates an object that is an instance of some class that subclasses TestClass, where you don't want to give that subclass a name (because you just need to create the object on the fly and you don't need to use that class anywhere else).

The code only initializes the object, you're not actually calling the methods on the object you're creating, so that's why you don't see any output. You could add a line to your code

public static void main (String[] args) throws java.lang.Exception
{
    TestClass TC = new TestClass() {
        public void testprint() {
            System.out.println("Z is " + getZ());
        }
    };
    // <- call the new method (>_< this won't compile)
    TC.testprint(); 
}

except this won't work because testprint isn't defined as a method on TestClass, the local variable referencing the object has the type TestClass, so the compiler expects to find methods defined on TestClass or on superclasses of TestClass. You could add some kind of method to TestClass, like this:

abstract class TestClass {
    int z;
    public TestClass(){
        z=10;
    }
    public int getZ(){
        return z;
    }
    public void setZ(int z){
        this.z=z;
    }
    // add new method
    public abstract void testprint();
}

Now the compiler knows to expect that an object of type TestClass will have a method called testprint. I didn't have to make TestClass abstract, I could have added an impelmentation of testprint to it. However, because TestClass is abstract, it's evident that the new object is not a TestClass but is some subclass of it.

Or alternatively, call this method through a different already-public method of TestClass. Use your TestClass unaltered but change the main method to:

public static void main (String[] args) throws java.lang.Exception
{
    TestClass TC = new TestClass() {
        public void testprint() {
            System.out.println("Z is " + super.getZ());
        }
        // override Z getter to call testprint
        @Override public int getZ(){ 
            testprint();
            return z;
        }
    };
    TC.getZ(); // <- call method on object created above
}

testprint had to change to call the superclass' version of Z's getter so we won't have an infinite recursion. Now the Z getter on the anonymous subclass calls the testprint method, so you can call the getter and see output:

Z is 10

The code doesn't assign the subclass a name but it still gets one assigned to it. If I add a line to the end of main to see what the anonymous class is called internally:

    System.out.println(TC.getClass());

it prints

class A$1

In practice not being able to call new methods directly that are defined in an anonymous class is not a limitation. You supply an anonymous class in cases where you want to pass an implementation of a class into a method of some other object, the thing that takes the object of the anonymous class wouldn't know (and shouldn't know, see LSP) how to call the new method anyway.

Community
  • 1
  • 1
Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
  • 1
    The issue is, that if testprint() isn't a method of TestClass but only defined in the anonymous class (-> doesn't override a method), you can't call it like this... – Puce Apr 25 '14 at 13:35
  • as an alternative you could call the method from a another method or initializer of the anonymous class, if the base class doesn't define it as well. – Puce Apr 25 '14 at 13:39
  • Thanks Nathan , so its basically a subclass but in this case, anonymous class can not declare a new method which was not declared in super class. I am right? – user2588495 Apr 25 '14 at 14:43
  • @user2588495: It can declare whatever it wants, that works fine. The problem is getting the method called. You create it in order for it to be called by something else, the thing that calls it needs to know about the method somehow (unless it is only used internally). my example making TestClass abstract shows making the thing calling aware of the method, the example overriding the Z getter shows using the method internally. – Nathan Hughes Apr 25 '14 at 14:47
2

It is the example of anonymous inner class.It is just like a class that extends TestClass. So you are not calling any method of that class so it will not print

niiraj874u
  • 2,180
  • 1
  • 12
  • 19
1

When doing this, you're implicitly subclassing TestClass and instantiating it right away, adding a method testPrint().

This is called an Anonymous Class.

Joffrey
  • 32,348
  • 6
  • 68
  • 100
1

In your code

TestClass TC = new TestClass() {
            public void testprint() {
        System.out.println("Z is " + getZ());
        }
     };

This is called Annonymous Inner Class So this will only Initialize. You can use TC.testprint(); after above code snippet.

Note - TC is ok. but According to Java Naming Convention Rules use simple letters. You can read more from here - http://www.iwombat.com/standards/JavaStyleGuide.html

Lasitha Benaragama
  • 2,201
  • 2
  • 27
  • 43
0

This is called an anonymous class. What it does behind the scenes is create a subclass extending the given class or implementing given interface. You can read more about anonymous classes here: http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html

Bartek Maraszek
  • 1,404
  • 2
  • 14
  • 31