I am making changes to a Java class of ours, and I noticed the following line of code:
OurClass<OurInterface1> ourClass = new OurClass<OurInterface1>() {};
What I find strange about that line is that OurClass is an abstract class - here's the definition of OurClass:
public abstract class OurClass<T extends OurInterface1> implements OurInterface2<T>
When I remove the {} at the end of the line, Eclipse tells me Cannot instantiate the type OurClass<OurInterface1>, but when I put the {} back, everything is OK.
How does {} allow you to instantiate an abstract class?
Adding the {} introduces the syntax for an anonymous inner class.
The anonymous class expression consists of the following:
The new operator
The name of an interface to implement or a class to extend. In this example, the anonymous class is implementing the interface HelloWorld.
Parentheses that contain the arguments to a constructor, just like a normal class instance creation expression. Note: When you implement an interface, there is no constructor, so you use an empty pair of parentheses, as in this example.
A body, which is a class declaration body. More specifically, in the body, method declarations are allowed but statements are not.
You are declaring an anonymous inner class that subclasses OurClass. The body of this class is empty: {}. This anonymous inner class is not abstract, so you are able to instantiate it.
When you remove the {}, the compiler thinks that you are directly instantiating OurClass, an abstract class, so it disallows it.
You can actually extend and override methods on the fly when you instantiate off an interface or extendible class. This is called an anonymous inner class.
What you did in your example is create an anonymous inner class, but it had no effect because you didn't override anything. You could have put overridden methods in those curly brackets {}.
OurClass<OurInterface1> ourClass = new OurClass<OurInterface1>() {};
A commonly applied use of anonymous inner class is on the Runnable interface, which defines a single void run() method. You can implicitly instantiate an object that implements Runnable and override run() on the fly.
Runnable someTask = new Runnable() {
#Override
public void run() {
System.out.println("Running a task!");
}
};
Anonymous inner classes are disliked by a lot of developers because they are pretty verbose. Fortunately in Java 8, you can use lambda expressions to replace most anonymous inner classes that implement a single method. The compiler infers the anonymous inner class for you basically, allowing you to write the code more concisely.
Runnable someTask = () -> System.out.println("Running a task!");
The block after the call to the new operator (new OurClass<OurInterface1>() {}) is infact creating an instance of an anonymous class which extends OutClass.
Since this class is no longer abstract, there's no problem to instantiate it.
You cannot instantiate an abstract class without implementing the abstract functions within the class. This is usually done by instatiating abstract classes with implemented class.
Refer: https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
In your case, the {} used after the instantiation allows you to implement any of the abstract functions in the abstract class.
For example,
Consider
public abstract class DummyClass {
abstract void test() ;
}
is the abstract class with a abstract function.
The class can be initiated by:
DummyClass d = new DummyClass(){
void test(){
//test() implementation here
}
} ;
Hope this helps! :)
Related
View.setOnClickListener( new View.OnClickListener(){
#override
public void onClick(View view){
//Some code implementing this method
}
});
Here OnClickListener is a static Interface declared inside View. Since it is static, it won't be categorized as an Inner class (correct me if I'm wrong here).
Then how can we use an anonymous class to inline implement this static nested interface?
Since, as I know they are only used to inline implement inner classes which are nested types without the static keyword for enclosed type.
First of all: inner interfaces are "static" by default. It is not possible to have an "inner" interface that wouldn't be static! See here for some more thoughts on that aspect.
From that point of view, interfaces are just that: interfaces. Doesn't matter if they are a top level interface sitting in their own .java file, or if the interface sits within some class or so.
And any interface can be implemented using an anonymous inner class.
That is really all there is to this.
To answer to the comment:
so the inline implementation ie the anonymous class itself becomes an inner class of the interface it implements?
No, an anonymous inner class is an inner class of the class that wraps around it. It happens to implement some interface. It is not an inner class of the interface. Inner is really meant in a "physical" sense, as in lines of code sitting inside other blocks of code.
class Outer {
class/interface Inner {
Inner is called an inner class/interface because it lives inside Outer.
How can i call an non static method of Abstract class, without using its sub class or extends it because abstract class and sub class is too complex so i do not want to cause any side effect.
for example concrete static methods of an abstract class can be call with class name an dot operator, without creating sub class. Similar is there any way to call a non static method.
i just want to run a method and i do not want run any other code. i tried to use reflection but it requires instance
Abstract classes are abstract, meaning that you cannot create an instance of the class.
Therefore, you cannot call instance methods of an abstract class.
public abstract class Foo {
static void bar();
void foobar();
}
you can call Foo.bar() as it is not an instance method (meaning that it does not require an instance of the class) but you cannot call foobar() since you cannot do new Foo().foobar().
Foo.bar(); // OK, we don't need an instance.
Foo foo = new Foo(); // Not OK - we cannot instantiate an abstract class.
foo.foobar();
For a way to create an instance of an abstract class without having to use derived classes, see ernest_k's answer utilizing anonymous classes.
The short answer is that you can't. You need an instance.
An easy way to create an instance is using an anonymous class:
AbstractClass o = new AbstractClass(){
//implement abstract methods... or just leave stubs
};
o.concreteMethod();
A class automatically becomes abstract class when any of its method declared as abstract.
I take this point in some blog. Can someone explain me Why entire class becomes abstract when we use only one abstract method.?
Because it can't be instantiated directly anymore. Also, it's then a compiler error if you don't mark the class itself as abstract.
First of all, I'm going to guess that the blog you mentioned was actually discussing C++. In Java, it's a compiler error to declare an abstract method within a class that is declared with the abstract keyword. With that said, Consider this (erroneous) code:
class A
{
abstract void foo();
}
A a = new A();
a.foo(); //Whoa! what are we supposed to do??!
If A had been declared as abstract (as would be required in real code), it would have been impossible to instantiate it.
If any part of a class is missing (that is, it is declared abstract), the class must be abstract because parts of it cannot be used.
In C++, there is no abstract keyword-- a class is automatically abstract if it has any abstract methods (referred to as pure virtual functions in C++).
In Java on the other hand, a class is only abstract if it is declared with the abstract keyword. However, this keyword is required if there are any abstract methods, so the only difference between the two systems in practice is that Java allows abstract classes to not have any abstract methods. In both languages, a class must be abstract if it has any abstract methods: in C++, this is simply how abstract classes are defined, and in Java it is required via the mechanics of the abstract keyword.
Once a method is abstract, it is declared to have no implementation. How would you suggest the VM instantiate an instance of that class?
An abstract method is one that defines a contract for a method but does not implement the functionality.
To instantiate a class with methods that cannot meet the contract defined as there is no implementation wouldn't work. Thus an abstract method means that you should not be able to instantiate the class.
A class automatically becomes abstract class when any of its method declared as abstract.
Can someone explain me Why entire class becomes abstract when we use
only one abstract method.?
The class has to be declared Abstract because the compiler expects a body for a normal class's method otherwise it will throw error. So either you write the method's body or declare the class Abstract
Example:
class SomeClass{
// Method without body
public void SomeMethod();
public static void main(String[] args) {
}
}
When you try to compile it, you will get:
SomeClass.java:4: missing method body, or declare abstract
public void SomeMethod();
Is there a way to refer to any inner class?
I would like to specify a return type compatible with an inner class e.g.
Class<OuterClass.*> some_method();
I understand this syntax is invalid. Is there a way to express this?
I know I can't use something like Class<? extends OuterClass> because an inner class doesn't extend an outer class.
Well, you can refer to specific inner classes, at least:
<T extends OuterClass.InnerClass> Class<T> some_method()
Besides that, what would you gain by returning an object of any inner class? That would be comparable to returning any object plus the fact that the inner instance has a special relation to the outer instance. However, you'd probably not be able to directly use that special relation anyways.
Edit:
As others pointed out already InnerClass might be a super class extended by other inner classes. This would allow you to return any class, that extends that class.
If you'd use an interface, you aren't restricted to inner classes only, since for this restriction you'd need non-static inner interfaces. However, inner interfaces are static by default.
I would rather define an (inner) interface, let all inner class implement it, and then :
Class<OuterClass.MyInterface> someMethod();
This would be more type secure than trying to refer to any inner class. And you wouldn't have any problem the day you need another inner class for another usage, or the day you decide to extract a class.
No there isn't. Just as you cannot reference packages with wildcards:
Class<com.example.*> some_method();
Class<com.example.?> some_method();
The use cases for such declarations would be so limited, it just wouldn't make it into the JLS. Note, you cannot use such "location match types" outside the scope of generics either. E.g. you cannot declare:
void some_method(OuterClass.* argument);
void some_method(com.example.* argument);
Class<InnerClass> is allowed in java. Are you looking for something specific?
public class Client
{
interface InnerType
{
}
public class InnerClass implements InnerType
{
}
public Class<? extends Client.InnerType> test()
{
return InnerClass.class;
}
}
You can define marker interface and Implement it by Inner class.
<T implements CustomMarkerInterface> Class<T> some_method()
So this would be applicable to all inner classes of OuterClass
public class Outer {
public class Inner implements CustomMarkerInterface{
}
public class Inner1 implements CustomMarkerInterface{
}
public class Inner2 implements CustomMarkerInterface{
}
}
I've noticed that:
class A {
ClassB b = new ClassB() { // anonymous class
/* some expression using this */
}
}
Whenever I use the this keyword inside an anonymous class, the this refers to the enclosing outer class/enum and not to the anonymous class.
Does this mean this can never represent an anonymous class? Just "normal" classes and enums?
Also, can this or super represent an interface?
Your initial assumption is wrong - this always represents the current instance, that is the instance of the current class, even if it's anonymous.
Your statement about using this is incorrect. When you use this inside an anonymous class, it always refers to the anonymous class. It never refers to the enclosing outer class unless you use OuterClassName.this.
this or super can never represent an interface, since an interface cannot have defined methods.
In Java this is always the current class even if it is an anonymous class. No, this or super cannot represent an interface.
Your anonymous class always extends another class. Even if you explicitly implement an interface, you are extending java.lang.Object and you can only call methods of java.lang.Object via super calls.
Runnable r = new Runnable() {
public void run() {
super.run(); // Error: run() is not a method of java.lang.Object
super.toString(); // OK: toString() is inherited from java.lang.Object
}
};
Use A.this from the inner class.
And it cannot represent an interface, because you cannot define anynomous non-static classes within interfaces, because there wil never be an instance of the interface.
EDIT: Clarified by adding info from the comment.