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.