
In this post, we will be learning about the following concepts.
- Instance Vs Static Methods
- Interfaces Vs Abstract Classes
- Inner Vs Anonymous Classes
1. Instance Vs Static Methods
What are static methods?
These methods are declared using the static modifier. They are mainly used when we don’t require any data access through the instance of a class. For the same reason, static methods do not have access to this keyword referring to the current instance of a class.
Syntax of Static methods
class MyClass {
public static void staticMethodName() {
System.out.println("This is a static method");
}
}
// Accessing a static method
MyClass.staticMethodName();
When to use static methods?
- Declare a method as static when it doesn’t use any class instance variables.
- When every instance of a class should share the same copy of variables and methods, declare them as static.
What are instance methods?
Instance methods are those that are accessible through an instance of a class created using the new keyword. These methods can access the current instance of the class using this keyword.
Syntax of Instance methods
class MyClass {
public void methodName() {
System.out.println("This is an instance method");
}
}
// Accessing an instance method requires an object to be created
MyClass object = new MyClass();
object.methodName();
When to use instance methods?
- If the method uses or modifies instance variables, then declare them as instance methods.
- When each instance of a class should have its own copy of variables, use instance variables and methods.
2. Interfaces Vs Abstract Classes
What are interfaces?
Interfaces contain declaration of methods of a class but not their implementation, but they can contain default and static methods from Java 8. Therefore, they define the type of operations that an object can perform but the details of those operations are to be defined by classes that implement an interface. They can also be Extended by other interfaces.
Interfaces cannot be instantiated because they represent a contract that the class that implements an interface will be able to perform all the operations declared in it. You can also think of it this way, if the methods contain no implementations at all to use or modify class variables, would there be any use to instantiating an interface?
Syntax of interfaces
public interface MyInterface {
// Fields should be constant and are static and final
final int number = 1;
// Notice that the methods are abstract by default
public void method1();
public void method2();
public void method3(int number);
}
An interface can be implemented using the implements keyword
class MyClass implements MyInterface {
@Override
public void method1() {
System.out.println("Implementation of method 1");
}
@Override
public void method2() {
System.out.println("Implementation of method 2");
}
@Override
public void method3(int number) {
System.out.println("Implementation of method 3");
}
}
An interface cannot be instantiated, but it is possible to declare a variable of an interface type and assign a class instance to it implementing that interface.
public class Main {
public static void main(String[] args) {
// A class instance declared using interface type
MyInterface myClassInstance;
myClassInstance = new MyClass();
}
}
// This is not valid
MyInterface sampleInterface = new MyInterface();
When to use interfaces?
- When completely unrelated classes should be able to implement the interface. Example: Comparable and Cloneable.
- To specify the overall behavior without worrying about who implements them or how.
An excellent example of an interface is the Java collections API. Notice how various classes such as ArrayList, LinkedList and Stack all have the same APIs such as add(), isEmpty(), remove(), size() etc with different implementation details.
What are abstract classes?
Abstract classes cannot be instantiated into an object as well. They can contain methods with and without implementation details.
An abstract class can extend from only one parent class although it can implement multiple interfaces. The issue of being able to extend from only one class is not only limited to abstract classes. You can read more about the diamond problem here.
Syntax of abstract classes
public abstract class myAbstractClass {
private String myVariable;
public myConstructor(String myVariable) {
this.myVariable = myVariable;
}
// Note how abstract classes can contain regular and abstract methods
public abstract void myAbstractMethod1();
public abstract void myAbstractMethod2();
public String getMyVariable() {
return myVariable;
}
}
// Abstract classes can be extended this way
public class myExtendedClass extends myAbstractClass {
public myExtendedClass(String myVariable) {
super(myVariable);
}
@Override
public void myAbstractMethod1() {
System.out.println("Implementation of myAbstractMethod1");
}
@Override
public void myAbstractMethod2() {
System.out.println("Implementation of myAbstractMethod2");
}
public void printMyVariable() {
System.out.println("My variable is " + getMyVariable());
}
}
When to use abstract classes?
- If a class contains abstract methods ie., methods without implementation details, then the class should be declared as abstract.
- To share code with related classes.
- To do things interfaces (Java < 9) don’t do – to enable classes to extend abstract classes and define fields or methods with access modifiers such as private, protected and to declare non-static and non-final fields.
To summarize, use abstract classes when you need a base class with certain definitions that different derived classes can share.
Java has several examples of abstract classes such as InputStream, OutputStream Reader etc. Note how they all extend only from one class but implement multiple interfaces.
3. Inner Vs Anonymous Classes
What are inner classes?
Inner classes are those that are declared inside another class or interface without a static modifier aka non-static nested classes. There are three main types.
- Member inner class – lives inside a class
- Anonymous inner class – to create an instance of an object with some extra functionality, to overload existing methods of a class or interface
- Local inner class – lives inside a method
In most cases, they are declared as private so that they aren’t exposed to other classes.
The inner class can access all the member variables and methods of the outer class include private ones.
Syntax of inner classes
// This example shows a member inner class
class MyOuterClass {
class MyInnerClass {
}
}
// Example code to create an object of inner class
MyOuterClass outerObject = new MyOuterClass();
MyOuterClass.MyInnerClass innerObject = outerObject.new MyInnerClass();
// This example shows an anonymous inner class
// This is similar to a constructor invocation with class definition inside a block
MyClass object = new MyClass() {
@Override
public void method() {
System.out.println("This is an anonymous inner class with a method overriding the method of MyClass that implemented from another interface");
}
};
// To call the method
object.method();
When to use inner classes?
- If a class is only useful inside the scope of another class and is coupled to it, then create an inner class ie., without an existing outer class object, there is no chance of existing inner class object.
- Create an anonymous inner class to provide an additional functionality to an object.
- To program a class that no other class can access except an outer class.
- Declare an inner class as private if no other classes should be able to create an object of that inner class except the outer class.
What are anonymous classes?
We already learnt about anonymous classes in the previous section, but let’s get into a little more detail here. Anonymous classes are inner classes in Java that do not have a name and are declared and instantiated in the same statement.
Since they do not have a name, we can’t create instances of anonymous classes or define a constructor inside the class body.
They extend the top level class and implement an interface or extend an abstract class.
Syntax of anonymous classes
Runnable action = new Runnable() { // Runnable is a Java interface
@Override
public void run() {
System.out.println("This is an anonymous class method");
}
}; // Semicolon is important since anonymous classes are expressions
When to use anonymous classes?
- To use a local class only once.
- To quickly override a small amount of functionality instead of the overhead of creating a separate class.
- To use variables or constants declared in the code right away in an anonymous class instead of passing it through the constructor of a class.
- To avoid having to override all the unimplemented methods of an interface or abstract class.
- Do not use them to override a lot of functionality since this can make the code unreadable.
Hope this article clarified some of the confusing concepts in Java to enable you to use them in the right places. Please feel free to give feedback if any part of article can be improved. Happy coding!
