Related
During one of my interview, I was asked "If we can instantiate an abstract class?"
My reply was "No. we can't". But, interviewer told me "Wrong, we can."
I argued a bit on this. Then he told me to try this myself at home.
abstract class my {
public void mymethod() {
System.out.print("Abstract");
}
}
class poly {
public static void main(String a[]) {
my m = new my() {};
m.mymethod();
}
}
Here, I'm creating instance of my class and calling method of abstract class. Can anyone please explain this to me? Was I really wrong during my interview?
Here, i'm creating instance of my class
No, you are not creating the instance of your abstract class here. Rather you are creating an instance of an anonymous subclass of your abstract class. And then you are invoking the method on your abstract class reference pointing to subclass object.
This behaviour is clearly listed in JLS - Section # 15.9.1: -
If the class instance creation expression ends in a class body, then
the class being instantiated is an anonymous class. Then:
If T denotes a class, then an anonymous direct subclass of the class named by T is declared. It is a compile-time error if the
class denoted by T is a final class.
If T denotes an interface, then an anonymous direct subclass of Object that implements the interface named by T is declared.
In either case, the body of the subclass is the ClassBody given in the class instance creation expression.
The class being instantiated is the anonymous subclass.
Emphasis mine.
Also, in JLS - Section # 12.5, you can read about the Object Creation Process. I'll quote one statement from that here: -
Whenever a new class instance is created, memory space is allocated
for it with room for all the instance variables declared in the class
type and all the instance variables declared in each superclass of the
class type, including all the instance variables that may be hidden.
Just before a reference to the newly created object is returned as the
result, the indicated constructor is processed to initialize the new
object using the following procedure:
You can read about the complete procedure on the link I provided.
To practically see that the class being instantiated is an Anonymous SubClass, you just need to compile both your classes. Suppose you put those classes in two different files:
My.java:
abstract class My {
public void myMethod() {
System.out.print("Abstract");
}
}
Poly.java:
class Poly extends My {
public static void main(String a[]) {
My m = new My() {};
m.myMethod();
}
}
Now, compile both your source files:
javac My.java Poly.java
Now in the directory where you compiled the source code, you will see the following class files:
My.class
Poly$1.class // Class file corresponding to anonymous subclass
Poly.class
See that class - Poly$1.class. It's the class file created by the compiler corresponding to the anonymous subclass you instantiated using the below code:
new My() {};
So, it's clear that there is a different class being instantiated. It's just that, that class is given a name only after compilation by the compiler.
In general, all the anonymous subclasses in your class will be named in this fashion:
Poly$1.class, Poly$2.class, Poly$3.class, ... so on
Those numbers denote the order in which those anonymous classes appear in the enclosing class.
The above instantiates an anonymous inner class which is a subclass of the my abstract class. It's not strictly equivalent to instantiating the abstract class itself. OTOH, every subclass instance is an instance of all its super classes and interfaces, so most abstract classes are indeed instantiated by instantiating one of their concrete subclasses.
If the interviewer just said "wrong!" without explaining, and gave this example, as a unique counterexample, I think he doesn't know what he's talking about, though.
= my() {}; means that there's an anonymous implementation, not simple instantiation of an object, which should have been : = my(). You can never instantiate an abstract class.
Just observations you could make:
Why poly extends my? This is useless...
What is the result of the compilation? Three files: my.class, poly.class and poly$1.class
If we can instantiate an abstract class like that, we can instantiate an interface too... weird...
Can we instantiate an abstract class?
No, we can't. What we can do is, create an anonymous class (that's the third file) and instantiate it.
What about a super class instantiation?
The abstract super class is not instantiated by us but by java.
EDIT: Ask him to test this
public static final void main(final String[] args) {
final my m1 = new my() {
};
final my m2 = new my() {
};
System.out.println(m1 == m2);
System.out.println(m1.getClass().toString());
System.out.println(m2.getClass().toString());
}
output is:
false
class my$1
class my$2
You can simply answers, in just one line
No, you can never instance Abstract Class
But, interviewer still not agree, then you can tell him/her
all you can do is, you can create an Anonymous Class.
And, according to Anonymous class, class declared and instantiate at the same place/line
So, it might be possible that, interviewer would be interested to check your confidence level and how much you know about the OOPs .
The technical part has been well-covered in the other answers, and it mainly ends in:
"He is wrong, he doesn't know stuff, ask him to join SO and get it all cleared :)"
I would like to address the fact(which has been mentioned in other answers) that this might be a stress-question and is an important tool for many interviewers to know more about you and how do you react to difficult and unusual situations. By giving you incorrect codes, he probably wanted to see if you argued back. To know whether you have the confidence to stand up against your seniors in situations similar to this.
P.S: I don't know why but I have a feeling that the interviewer has read this post.
Abstract classes cannot be instantiated, but they can be subclassed. See This Link
The best example is
Although Calender class has a abstract method getInstance(), but when you say Calendar calc=Calendar.getInstance();
calc is referring to the class instance of class GregorianCalendar as "GregorianCalendar extends Calendar "
Infact annonymous inner type allows you to create a no-name subclass of the abstract class and an instance of this.
Technical Answer
Abstract classes cannot be instantiated - this is by definition and design.
From the JLS, Chapter 8. Classes:
A named class may be declared abstract (§8.1.1.1) and must be declared
abstract if it is incompletely implemented; such a class cannot be
instantiated, but can be extended by subclasses.
From JSE 6 java doc for Classes.newInstance():
InstantiationException - if this Class represents an abstract class, an interface, an array
class, a primitive type, or void; or if the class has no nullary constructor; or if the
instantiation fails for some other reason.
You can, of course, instantiate a concrete subclass of an abstract class (including an anonymous subclass) and also carry out a typecast of an object reference to an abstract type.
A Different Angle On This - Teamplay & Social Intelligence:
This sort of technical misunderstanding happens frequently in the real world when we deal with complex technologies and legalistic specifications.
"People Skills" can be more important here than "Technical Skills". If competitively and aggressively trying to prove your side of the argument, then you could be theoretically right, but you could also do more damage in having a fight / damaging "face" / creating an enemy than it is worth. Be reconciliatory and understanding in resolving your differences. Who knows - maybe you're "both right" but working off slightly different meanings for terms??
Who knows - though not likely, it is possible the interviewer deliberately introduced a small conflict/misunderstanding to put you into a challenging situation and see how you behave emotionally and socially. Be gracious and constructive with colleagues, follow advice from seniors, and follow through after the interview to resolve any challenge/misunderstanding - via email or phone call. Shows you're motivated and detail-oriented.
It is a well-established fact that abstract class can not be instantiated as everyone answered.
When the program defines anonymous class, the compiler actually creates a new class with different name (has the pattern EnclosedClassName$n where n is the anonymous class number)
So if you decompile this Java class you will find the code as below:
my.class
abstract class my {
public void mymethod()
{
System.out.print("Abstract");
}
}
poly$1.class (the generated class of the "anonymous class")
class poly$1 extends my
{
}
ploly.cass
public class poly extends my
{
public static void main(String[] a)
{
my m = new poly.1(); // instance of poly.1 class NOT the abstract my class
m.mymethod();
}
}
About Abstract Classes
Cannot create object of an abstract class
Can create variables (can behave like datatypes)
If a child can not override at least of one abstract method of the parent, then child also becomes abstract
Abstract classes are useless without child classes
The purpose of an abstract class is to behave like a base. In inheritance hierarchy you will see abstract classes towards the top.
No, you can't instantite an abstract class.We instantiate only anonymous class.In abstract class we declare abstract methods and define concrete methods only.
Extending a class doesn't mean that you are instantiating the class. Actually, in your case you are creating an instance of the subclass.
I am pretty sure that abstract classes do not allow initiating. So, I'd say no: you can't instantiate an abstract class. But, you can extend it / inherit it.
You can't directly instantiate an abstract class. But it doesn't mean that you can't get an instance of class (not actully an instance of original abstract class) indirectly. I mean you can not instantiate the orginial abstract class, but you can:
Create an empty class
Inherit it from abstract class
Instantiate the dervied class
So you get access to all the methods and properties in an abstract class via the derived class instance.
It's impossible to instantiate an abstract class.
What you really can do, has implement some common methods in an abstract class and let others unimplemented (declaring them abstract) and let the concrete descender implement them depending on their needs.
Then you can make a factory, which returns an instance of this abstract class (actually his implementer). In the factory you then decide, which implementer to choose. This is known as a factory design pattern:
public abstract class AbstractGridManager {
private LifecicleAlgorithmIntrface lifecicleAlgorithm;
// ... more private fields
//Method implemented in concrete Manager implementors
abstract public Grid initGrid();
//Methods common to all implementors
public Grid calculateNextLifecicle(Grid grid){
return this.getLifecicleAlgorithm().calculateNextLifecicle(grid);
}
public LifecicleAlgorithmIntrface getLifecicleAlgorithm() {
return lifecicleAlgorithm;
}
public void setLifecicleAlgorithm(LifecicleAlgorithmIntrface lifecicleAlgorithm) {
this.lifecicleAlgorithm = lifecicleAlgorithm;
}
// ... more common logic and getters-setters pairs
}
The concrete implementer only needs to implement the methods declared as abstract, but will have access to the logic implemented in those classes in an abstract class, which are not declared abstract:
public class FileInputGridManager extends AbstractGridManager {
private String filePath;
//Method implemented in concrete Manager implementors
abstract public Grid initGrid();
public class FileInputGridManager extends AbstractGridManager {
private String filePath;
//Method implemented in concrete Manager implementors
abstract public Grid initGrid();
public Grid initGrid(String filePath) {
List<Cell> cells = new ArrayList<>();
char[] chars;
File file = new File(filePath); // for example foo.txt
// ... more logic
return grid;
}
}
Then finally the factory looks something like this:
public class GridManagerFactory {
public static AbstractGridManager getGridManager(LifecicleAlgorithmIntrface lifecicleAlgorithm, String... args){
AbstractGridManager manager = null;
// input from the command line
if(args.length == 2){
CommandLineGridManager clManager = new CommandLineGridManager();
clManager.setWidth(Integer.parseInt(args[0]));
clManager.setHeight(Integer.parseInt(args[1]));
// possibly more configuration logic
...
manager = clManager;
}
// input from the file
else if(args.length == 1){
FileInputGridManager fiManager = new FileInputGridManager();
fiManager.setFilePath(args[0]);
// possibly more method calls from abstract class
...
manager = fiManager ;
}
//... more possible concrete implementors
else{
manager = new CommandLineGridManager();
}
manager.setLifecicleAlgorithm(lifecicleAlgorithm);
return manager;
}
}
The receiver of AbstractGridManager would call the methods on him and get the logic, implemented in the concrete descender (and partially in the abstract class methods) without knowing what is the concrete implementation he got. This is also known as inversion of control or dependency injection.
You can say: we can't instantiate an abstract class, but we can use new keyword to create an anonymous class instance by just adding {} as implement body at the the end of the abstract class.
No, we can't create the object of abstract class, but create the reference variable of the abstract class. The reference variable is used to refer to the objects of derived classes (Sub classes of Abstract class)
Here is the example that illustrates this concept
abstract class Figure {
double dim1;
double dim2;
Figure(double a, double b) {
dim1 = a;
dim2 = b;
}
// area is now an abstract method
abstract double area();
}
class Rectangle extends Figure {
Rectangle(double a, double b) {
super(a, b);
}
// override area for rectangle
double area() {
System.out.println("Inside Area for Rectangle.");
return dim1 * dim2;
}
}
class Triangle extends Figure {
Triangle(double a, double b) {
super(a, b);
}
// override area for right triangle
double area() {
System.out.println("Inside Area for Triangle.");
return dim1 * dim2 / 2;
}
}
class AbstractAreas {
public static void main(String args[]) {
// Figure f = new Figure(10, 10); // illegal now
Rectangle r = new Rectangle(9, 5);
Triangle t = new Triangle(10, 8);
Figure figref; // this is OK, no object is created
figref = r;
System.out.println("Area is " + figref.area());
figref = t;
System.out.println("Area is " + figref.area());
}
}
Here we see that we cannot create the object of type Figure but we can create a reference variable of type Figure. Here we created a reference variable of type Figure and Figure Class reference variable is used to refer to the objects of Class Rectangle and Triangle.
Actually we can not create an object of an abstract class directly. What we create is a reference variable of an abstract call. The reference variable is used to Refer to the object of the class which inherits the Abstract class i.e. the subclass of the abstract class.
I don't understand why this compiles. f() and g() are visible from the inner classes, despite being private. Are they treated special specially because they are inner classes?
If A and B are not static classes, it's still the same.
class NotPrivate {
private static class A {
private void f() {
new B().g();
}
}
private static class B {
private void g() {
new A().f();
}
}
}
(Edit: expanded on the answer to answer some of the comments)
The compiler takes the inner classes and turns them into top-level classes. Since private methods are only available to the inner class the compiler has to add new "synthetic" methods that have package level access so that the top-level classes have access to it.
Something like this (the $ ones are added by the compiler):
class A
{
private void f()
{
final B b;
b = new B();
// call changed by the compiler
b.$g();
}
// method generated by the compiler - visible by classes in the same package
void $f()
{
f();
}
}
class B
{
private void g()
{
final A a;
a = new A();
// call changed by the compiler
a.$f();
}
// method generated by the compiler - visible by classes in the same package
void $g()
{
g();
}
}
Non-static classes are the same, but they have the addition of a reference to the outer class so that the methods can be called on it.
The reason Java does it this way is that they did not want to require VM changes to support inner classes, so all of the changes had to be at the compiler level.
The compiler takes the inner class and turns it into a top level class (thus, at the VM level there is no such thing as an inner class). The compiler then also has to generate the new "forwarding" methods. They are made at the package level (not public) to ensure that only classes in the same package can access them. The compiler also updated the method calls to the private methods to the generated "forwarding" methods.
You can avoid having the compiler generate the method my declaring the methods as "package" (the absence of public, private, and protected). The downside to that is that any class in the package can call the methods.
Edit:
Yes, you can call the generated (synthetic) method, but DON'T DO THIS!:
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class Main
{
public static void main(final String[] argv)
throws Exception
{
final Class<?> clazz;
clazz = Class.forName("NotPrivate$A");
for(final Method method : clazz.getDeclaredMethods())
{
if(method.isSynthetic())
{
final Constructor constructor;
final Object instance;
constructor = clazz.getDeclaredConstructor(new Class[0]);
constructor.setAccessible(true);
instance = constructor.newInstance();
method.setAccessible(true);
method.invoke(null, instance);
}
}
}
}
I think this quote sums it up nicely:
...inner classes can access all members of the declaring class, even private members. In fact, the inner class itself is said to be a member of the class; therefore, following the rules of object-oriented engineering, it should have access to all members of the class.
And following from that, since both inner classes are really just part of the containing class, they should be able to access each others private members as well.
Java compiles in special accessors with $ in them. So you can't write Java that access the private methods. Explained here:
http://www.retrologic.com/innerclasses.doc7.html
There is one more category of compiler-generated members. A private member m of a class C may be used by another class D, if one class encloses the other, or if they are enclosed by a common class. Since the virtual machine does not know about this sort of grouping, the compiler creates a local protocol of access methods in C to allow D to read, write, or call the member m. These methods have names of the form access$0, access$1, etc. They are never public. Access methods are unique in that they may be added to enclosing classes, not just inner classes.
As User 'A Dude' explained it in the comments of the accepted answer:
It compiles, because it is required to be working in that way by the language specifation, ie. the Java Lang Spec says so:
6.6.1 Determining Accessibility (at least since JLS6)
"Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor."
I.e. the "access-scope" of a private member is: everywhere within the lexical boundaries of the top-level class body.
That means: all private members that are defined within the class-body of the outermost class can be accessed from everywhere else in this class-body.
For instance the private method of an inner class can be accessed from methods of the outer class or from any method of another inner class of the outer class.
Assume that A is a custom class, and consider the following declaration of an anonymous inner class:
A Obj = new A() {
#Override
public String toString() {
return "Hello!";
}
}
In this scenario, Obj is an instance of an anonymous inner class whose toString method has been overridden. Since it was declared with type A, the anonymous class must be a subclass of A. So then, why isn't this class called an Anonymous Subclass instead of an anonymous inner class? Where does the 'inner' come from?
Yes, obj is an instance of a subclass of A. And you can verify the superclass by calling obj.getClass().getSuperclass():
That prints something like:
class stackoverflow.Test$1 //obj.getClass()
class stackoverflow.A //obj.getClass().getSuperclass()
So then, why isn't this class called an Anonymous Subclass instead of an anonymous inner class?
Those are just semantics. It's a name. There could be many reasons, however, one of which being that anonymous classes can implement interfaces directly:
Runnable r = new Runnable() {
public void run() {}
}
This is not a subclass of anything (but Object, but what isn't a subclass of Object...), but it's an anonymous class too.
Why isn't this class called an Anonymous Subclass instead of an anonymous inner class?
Because (in general) anonymous inner class aren't necessarily subclasses1. An anonymous inner class can extend an interface rather than a class.
Because the "subclass-ness" is not important2 in most contexts where we talk about anonymous inner classes.
Because humans are lazy3 and "Anonymous Inner Subclasses" is one extra syllable. Or to put it another way, there is a natural tendency for people to optimize their speech and writing patterns.
Because ... convention.
Where does the 'inner' come from?
Inner has a technical meaning in Java. It means two things.
It means that the class is declared inside another class.
It means that the class is permitted to refer to the this of an instance of the enclosing class.
See the nice taxonomy in #Andreas's answer.
Historical footnote.
In fact, the official terminology is Anonymous Class. Indeed, Sun used the terminology "Anonymous Class" rather than "Anonymous Inner Class" way back in Java 1.1 when the construct was added to the language. For example, the "Inner Class Specification" from the Java 1.1.4 release notes refers to them as "Anonymous Classes" ... most of the time.
I suspect that what happened was that there was some inconsistency in earlier Sun presentations or papers, and various non-Sun authors latched onto the "anonymous inner class" version in their writings. The Sun team tried to quietly correct this by using "Anonymous Class" in the official Java Language Spec and Tutorial. But it was too late. The books were in the bookshops, the articles were on the web.
1 - Except in the trivial sense. Every class that isn't Object must be a subclass of some class.
2 - Likewise, you would normally say "I am taking the dog for a walk", not "I am taking the black Labrador for a walk".
3 - In this case, "good lazy".
Subclass and inner class are two different aspects of the anonymous class. Because of the syntax, an anonymous class is obviously a subclass of the named class, so the inner aspect is more relevant for the categorization.
Java classes are categories like this1:
Top-Level class (§7.6)
Nested class (§8.5, §9.5)
Static Nested class
Inner class (§8.1.3)
Local class (§14.3)
Anonymous class (§15.9.5)
As you can see, an anonymous class is an inner nested class.
The categorization doesn't specify whether the class is a subclass, a base class, or a standalone class. Classes of any category can be a subclass or base class. As ernest_k mentioned in another answer, an anonymous class may be defined from an interface, in which case it's not a subclass at all.
1) Excerpt of bigger hierarchy at end of this other answer.
To answer your question's title, yes, they are. Anonymous inner classes are actually subclasses.
"Since it was declared with type A, the anonymous class, [Obj], must be a subclass of A."
Good job. :)
Anyways, to answer why the "inner" is there: If you declare an anonymous class inside another class (and the anonymous class isn't declared statically, more on that below) then it would be able to access its surrounding class just like an inner class would. For example:
public class Outer {
private final int someRandomValue = 4;
public final Object anonymousInnerInstance = new Object() {
#Override
public String toString() {
// Notice how this class has access to a field declared inside a different
// class. More specifically, this anonymous class can access someRandomValue,
// even though someRandomValue belongs to the class, Outer.
return "Anonymous Inner Class: " + someRandomValue;
}
};
public class RegularInner {
#Override
public String toString() {
// This regular inner class is inside Outer, (just like the anonymous class),
// and can access any of Outer's fields (amongst Outer's other things).
return "Regular Inner Class: " + someRandomValue;
}
}
public final RegularInner regularInnerInstance = new RegularInner();
public static void main(String[] args) {
Outer outerInstance = new Outer();
System.out.println(outerInstance.anonymousInnerInstance);
System.out.println(outerInstance.regularInnerInstance);
// By the way, you can make new RegularInner instances off of our Outer
// instance:
RegularInner newInnerInstance = outerInstance.new RegularInner();
// When you write "outerInstance.new SomeClass()" you're saying:
// "I'd like to initialize my 'SomeClass' object with 'outerInstance',
// as its container." This effectively means that any variables that
// belong to Outer that your SomeClass needs to access, it will access
// from the Outer instance you gave it.
}
}
So, anonymousInnerInstance's underlying class, and the class RegularInner, both have access to Outer's fields, and other instance-specific content belonging to Outer. That's why an anonymous class may sometimes be called an "inner" class.
Any instance of an inner class needs to be created with an instance of an outer class to back it up, or it won't know which object, (not class), it belongs to.
Static Trash
If an anonymous class is declared as static, it won't have access to its surrounding class's content and wouldn't be an "inner" class (instead, it would be an anonymous "nested" class).
public class Outer {
private final int someRandomValue = 4;
public static final Object anonymousStaticInstance = new Object() {
#Override
public String toString() {
// someRandomValue belongs to an INSTANCE of Outer. (So each Outer object you
// have has its own someRandomValue). Since this anonymous class
// is now static, it is no longer tied to an instance of Outer. It doesn't have
// an Outer object that it can read "someRandomValue" from. The same goes for
// RegularStatic, below.
return "Anonymous Inner Class: " + someRandomValue;
}
};
public static class RegularStatic {
#Override
public String toString() {
return "Regular Inner Class: " + someRandomValue;
}
}
public final RegularStatic regularInnerInstance = new RegularStatic();
public static void main(String[] args) {
Outer outerInstance = new Outer();
System.out.println(outerInstance.anonymousStaticInstance);// Java warns you here and
// tells you to access anonymousStaticInstance statically. This is because
// anonymousStaticInstance no longer belongs to any given instance of Outer.
// There is only one anonymousStaticInstance, that "belongs" to the class Outer,
// rather than multiple anonymousInnerInstances which each belong to an instance
// of Outer.
System.out.println(outerInstance.regularInnerInstance);
}
}
Remember that anonymous classes can be "inner" OR "nested". So when talking about them in general, just say "anonymous class". (Anonymous inner classes are a type of anonymous class). Also, do make sure to read the comments as they give most of the explanation.
Any questions? :)
I have studied some books for OCPJP 7 certification and in the inner classes chapter there were some strange/incomplete informations. I've tried to create an interface inside a method, but it seems you can't do that, you can only create classes inside a method. Is there any reason why you can't do that or it's just a missing feature?
Sample code:
public class Outer {
public void method() {
class C {} // allowed
interface I {} // interface not allowed here
}
}
If you read carefully the Java Tutorials, you will see that:
You cannot declare an interface inside a block, because interfaces are inherently static.
This means that if you have an interface, like this one:
public class MyClass {
interface MyInterface {
public void test();
}
}
You will be able to do
MyClass.MyInterface something = new MyClass.MyInterface() {
public void test () { .. }
};
because MyInterface will be explicitly static. It doesn't make sense to be tied to an instance of the enclosing class, because it just provides some abstraction which doesn't have to be bound to a specific instance or a state of the enclosing class.
Same thing goes to the case, in which the interface is nested in a method. Nothing inside the method could be (explicitly) static (because non-static methods are tied to a specific instance of the enlosing class) and thus you can't have a local interface.
interface Int {
public void show();
}
Int t1 = new Int() {
public void show() {
System.out.println("message");
}
to.show();
You're defining an anonymous class that implements the interface Int, and immediately creating an object of type thatAnonymousClassYouJustMade.
This notation is shorthand for
Int t1 = new MyIntClass();
// Plus this class declaration added to class Test
private static class MyIntClass implements Int
public void show() {
System.out.println("message");
}
}
So in the end you're creating an instance of a concrete class, whose behavior you defined inline.
You can do this with abstract classes too, by providing implementations for all the abstract methods inline.
What this special syntax for anonymous inner classes does under the hood is create a class called Test$1. You can find that class file in your class folder next to the Test class, and if you printed t1.getClass().getName() you could also see that.
i think your object has nothing to do with the interface. If you comment out the whole interface, still you will get the same output. Its just anonymous class created. I think, unless you use the class "implements" you cant implement the interface. But i dunno how naming collision doesn't happen in your case.