Polymorphism is the ability of an object to take on many forms. The most common use of polymorphism in OOP occurs when a parent class's reference is used to refer to a child class object.
Polymorphism is an 'OOPS' concept which advice use of common interface instead of concrete implementation while writing code.
When we program for interface, our code is capable of handling any new requirement or enhancement that may arise in near future due to new implementation of our common interface.
If we don't use common interface and rely on concrete implementation, we always need to change and duplicate most of our code to support new implementation.
Its not only Java but other object oriented languages like C++ that supports polymorphism and its a fundamental along with other OOPS concepts like Encapsulation, Abstraction and Inheritance.
A class that has multiple functions with same name but different parameters then in such case it is known as 'Method Overloading'.
Method overloading increases the readability of the program. On the other hand, method overriding provides the specific implementation of the method that is already provided by its super class.
Parameter must be different in case of overloading whereas it must be same in case of overriding.
Overloading in Java occurs when two or more methods in the same class have the same name, but different parameters.
On the other hand, in method overriding a child class redefines the same method as a parent class. Overridden methods must have the same name, argument list and return type. The overriding method may not limit the access of the method it overrides.
A static member class behaves just like an ordinary top-level class, except that it can access the static members of the class that contains it.
The static nested class can be accessed just like the other static members of the enclosing class without having an instance of the outer class. The static class can contain non-static and static members as well as methods.
public class InnerClass {
static class StaticInner {
static int i = 9;
int no = 6;
private void method() {}
public void method1() {}
static void method2() {}
final void method3() {}
}
}
The static inner class can be accessed by the Outer Class in the following manner :
InnerClass.StaticInner staticObj = new InnerClass. StaticInner ();
No outer class instance is required to instantiate the nested static class because the static class is a static member of the enclosing class.
The different types of static inner classes are:
Non-static inner classes - classes associated with the object of the enclosing class.
Member class - Classes declared outside a function (hence a "member") and not declared "static". The member class can be declared as public, private, protected, final and abstract. E.g.
public class InnerClass {
class MemberClass {
public void method1() { }
}
}
Method local class - The inner class declared inside the method is called 'method local inner class'. 'Method local inner class' can only be declared as final or abstract and can only access global variables or method local variables if declared as 'final'.
public class InnerClass {
int i = 9;
public void method1() {
final int k = 6;
class MethodLocal {
MethodLocal() {
System.out.println(k + i);
}
}
}
}
Anonymous inner class - These are the local classes which are automatically declared and instantiated in the middle of an expression. Apart from this, just like local classes, anonymous classes cannot be public, private, protected, or static. They can specify arguments to the constructor of the superclass, but cannot have a constructor of its own. They can implement only one interface or extend a class.
public class MyFrame extends JFrame {
JButton btn = new JButton();
MyFrame_JBK() {
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {}
});
}
}
// Anonymous class used with comparator
List l = new ArrayList();
l.add(new Parent(2));
l.add(new Parent(3));
Collections.sort(l, new Comparator() {
public int compare(Object o1, Object o2) {
Parent prt1 = (Parent) o1;
Parent prt2 = (Parent) o2;
if (prt1.getAge() > prt2.getAge()) {
return -1;
}
else if(prt1.getAge() {
return 1;
}
else {
return 0;
}
}
});
No, a static nested class cannot have an access to the enclosing class's 'non-static methods' or 'instance variables'.
The embedding of inner class into the outer class is possible only by one class when the inner class is to be used i.e. the outer class makes the package more streamlined. Nesting the inner class code where it is used (inside the outer class) makes the code more readable and maintainable.
The inner class shares a special relationship with the outer class because the inner classes has access to all members of the outer class and still have its own type which is the main advantage of Inner class. One of the other advantages of inner class is that they can be hidden from the other classes in the same package and still have the access to all the members (private also) of the enclosing class. So the outer class members which are going to be used by the inner class can be made private and the inner class members can be hidden from the classes in the same package. This increases the level of encapsulation.
If a 'Class A' is requires another 'Class B' for its own use, there are two ways to do this. One way is to write a separate 'Class B' or to write an inner 'Class B' inside 'Class A'. Advantage of writing the inner 'Class B' in the 'Class A' is that one can avoid having a separate class. Inner classes are best used in the event handling mechanism and to implement the helper classes. The advantage of using inner class for event handling mechanism is that the use of if/else to select the component to be handled can be avoided. If inner classes are used each component gets its own event handler and each event handler implicitly knows the component it is working for.
Using inner class increases the total number of classes being used by the application. For all the classes created by JVM and loaded in the memory, JVM has to perform some tasks like creating the object of type class. JVM may have to perform some routine tasks for these extra classes created which may result into slower performance if the application is using more number of inner classes.
Inner classes get limited support of ide/tools as compared to the top level classes, so working with the inner classes is sometimes annoying for the developer.
Plain old anonymous class type one –
class superclass {
void doSomething() {
System.out.println(“Doing something in the Super class”);
}
}
class hasAnonymous {
superClass anon = new superClass(){
void doSomething() {
System.out.println(“Doing something in the Anonymous class”);
}
};
}
Here 'anon' is a reference variable which is of type 'superClass' that is extended by the anonymous class i.e. superclass of the anonymous class. The method 'doSomething()' is the super class method overridden by the anonymous class. Plain old anonymous class type two –
interface Eatable {
public void prepareSweets();
}
class serveMeal {
Eatable food = new Eatable(){
public void prepareSweets(){
//come implementation code goes here
}
};
}
Here, 'food' is reference variable of type 'Eatable interface' which refers to the anonymous class that is an implementer of the interface 'Eatable'. The anonymous implementer class of the interface 'Eatable' implements its method 'prepareSweets()' inside it.
Argument defined anonymous class –
interface Vehicle {
void getNoOfWheels();
}
class Car {
void getType(Vehicle v) { }
}
class BeautifulCars {
void getTheBeautifilCar() {
Car c = new Car();
c.getType (new Vehicle () {
public void getNoOfWheels () {
System.out.println("It has four wheels");
}
});
}
}
'Anonymous class' is defined as the argument of the method 'getTheBeautifilCar()' and this anonymous class is the implementer of the interface 'Vehicle'. The method of class 'Car', 'getTheBeautifilCar()' expects the argument as an object of type 'Vehicle'. So first we create an object of 'Car' referenced by the variable ‘c’. On this object of 'Car' we call the method 'getTheBeautifilCar()' and in the argument we create an anonymous class in place which is the implementer of interface 'Vehicle' hence of type 'Vehicle'
If an inner class enclosed with an outer class is compiled, then there is one ".class" file and a inner class ".class" file for each outer class. e.g.
class EnclosingOuter
{
class Inner{ }
}
If you compile the above code with command :
% javac EnclosingOuter.java
Two files will be created. Though a separate inner class file is generated, the inner class file is not accessible in the usual way.
EnclosingOuter.class
EnclosingOuter$Inner.class