Interfaces in Java

Saurav Kumar
6 min readSep 17, 2023

--

In Java, an interface is a type that defines a contract of methods that a class implementing the interface must provide. Here are some key points about interfaces in Java:

  • Declaration: You declare an interface using the interface keyword, followed by the interface name and a list of method signatures. For example:
public interface MyInterface {
void method1();
int method2(String str);
}
  • Methods: In an interface, methods are declared without a body. Classes that implement the interface must provide the actual method implementations.
  • Implementing Interfaces: To implement an interface, a class uses the implements keyword. For example:
public class MyClass implements MyInterface {
// Implement the methods defined in MyInterface
@Override
public void method1() {
// Method implementation
}

@Override
public int method2(String str) {
// Method implementation
return str.length();
}
}
  • Multiple Interfaces: A class can implement multiple interfaces, allowing it to inherit method contracts from each interface.
  • Default Methods (Java 8+): Starting from Java 8, interfaces can have default methods with method bodies. These methods provide a default implementation that can be overridden by implementing classes if needed.
  • Static Methods (Java 8+): Interfaces can also have static methods starting from Java 8.
  • Functional Interfaces (Java 8+): Functional interfaces have a single abstract method and can be used with lambda expressions. The @FunctionalInterface annotation can be used to ensure an interface has only one abstract method.
@FunctionalInterface
public interface Calculator {
int calculate(int a, int b);

// Default method
default double sqrt(int a) {
return Math.sqrt(a);
}
}
  • Interface Inheritance: Interfaces can extend other interfaces using the extends keyword.

Here’s an example that illustrates all the key points about interfaces in Java:

// 1. Declaration of an interface
public interface MyInterface {

// 2. Abstract method declaration (without a body)
void abstractMethod();

// 3. Abstract method with parameters
int calculate(int a, int b);

// 4. Default method with a body (Java 8+)
default void defaultMethod() {
System.out.println("This is a default method.");
}

// 5. Static method (Java 8+)
static void staticMethod() {
System.out.println("This is a static method.");
}
}

// 6. Class implementing an interface
public class MyClass implements MyInterface {

// Implementing the abstract method
@Override
public void abstractMethod() {
System.out.println("Abstract method implementation.");
}

// Implementing the abstract method with parameters
@Override
public int calculate(int a, int b) {
return a + b;
}

// 7. Usage of default and static methods
public void useInterfaceMethods() {
defaultMethod();
MyInterface.staticMethod();
}
}

// 8. Multiple interfaces implemented by a class
interface AnotherInterface {
void anotherMethod();
}

class MultiInterfaceClass implements MyInterface, AnotherInterface {

@Override
public void abstractMethod() {
System.out.println("Abstract method implementation.");
}

@Override
public int calculate(int a, int b) {
return a + b;
}

@Override
public void anotherMethod() {
System.out.println("Another method implementation.");
}
}

public class InterfaceExample {
public static void main(String[] args) {
// 9. Creating an object of a class implementing the interface
MyClass obj1 = new MyClass();
obj1.abstractMethod();
int result = obj1.calculate(5, 3);
System.out.println("Calculation result: " + result);
obj1.useInterfaceMethods();

// 10. Creating an object of a class implementing multiple interfaces
MultiInterfaceClass obj2 = new MultiInterfaceClass();
obj2.abstractMethod();
obj2.anotherMethod();
}
}

In this example:

  1. We declare an interface MyInterface.
  2. It defines an abstract method abstractMethod.
  3. Another abstract method calculate with parameters.
  4. A default method defaultMethod.
  5. A static method staticMethod.
  6. We have a class MyClass that implements MyInterface.
  7. MyClass provides implementations for the abstract methods and uses default and static methods.
  8. We create another interface AnotherInterface and a class MultiInterfaceClass that implements both MyInterface and AnotherInterface.
  9. We create an object of MyClass and demonstrate the usage of the interface methods.
  10. We create an object of MultiInterfaceClass and show how it implements methods from both interfaces.

Marker and Functional Interfaces in Java:

In Java, “Marker Interfaces” and “Functional Interfaces” are two different types of interfaces with specific characteristics:

Marker Interface:

  • A marker interface, also known as a “tag” interface, is an interface in Java that doesn’t declare any methods.
  • It serves as a marker or flag to inform the compiler or runtime environment about the class implementing it.
  • Classes that implement marker interfaces indicate that they possess certain characteristics or should be treated in a special way.
  • Examples of marker interfaces in Java include Serializable and Cloneable. When a class implements Serializable, it indicates that instances of that class can be serialized. Similarly, when a class implements Cloneable, it suggests that instances can be cloned.
  • Example:
import java.io.Serializable;

public class MyClass implements Serializable {
// Class implementation
}

Functional Interface:

  • A functional interface is an interface that contains exactly one abstract method (SAM — Single Abstract Method).
  • Functional interfaces are used to represent functional concepts and are often associated with lambda expressions and functional programming in Java.
  • The @FunctionalInterface annotation can be used to explicitly mark an interface as a functional interface. While it's not mandatory, using this annotation helps indicate the intended usage of the interface.
  • Functional interfaces enable the use of lambda expressions, which provide a concise way to implement the single abstract method.
  • Example:
@FunctionalInterface
public interface Calculator {
int calculate(int a, int b);
}

// Usage of a functional interface with a lambda expression
Calculator add = (x, y) -> x + y;
  • In the above example, the Calculator interface is a functional interface because it contains only one abstract method (calculate). The lambda expression (x, y) -> x + y provides an implementation for this method.
  • Functional interfaces are a key feature introduced in Java 8 to support functional programming paradigms and make it easier to work with functions as first-class citizens in the language.

Serializable and Cloneable marker interfaces in Java:

Serializable Interface:

  • The Serializable interface in Java is a marker interface that indicates a class can be serialized, which means its objects can be converted into a stream of bytes and saved to a file, sent over a network, or otherwise persisted in a way that they can be reconstructed later.
  • Classes that implement Serializable are indicating that they are willing to participate in Java's built-in serialization and deserialization mechanism.
  • To make a class serializable, you simply have to implement the Serializable interface, and Java's serialization system will take care of the rest.
  • Example:
package com.tipsontech.demo;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

// A class that implements Serializable
class MyClass implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private int id;
private String name;

public MyClass() {
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "MyClass [id=" + id + ", name=" + name + "]";
}
}

public class SerializationExample {
public static void main(String[] args) {
// Creating an instance of MyClass
MyClass obj = new MyClass();
obj.setId(1);
obj.setName("John");

// Serialization
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.ser"))) {
oos.writeObject(obj);
System.out.println("Object serialized successfully.");
} catch (IOException e) {
e.printStackTrace();
}

// Deserialization
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.ser"))) {
MyClass newObj = (MyClass) ois.readObject();
System.out.println("Object deserialized successfully.");
System.out.println(newObj);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}

In this example, the MyClass class implements Serializable, allowing objects of MyClass to be serialized and deserialized.

Cloneable Interface:

  • The Cloneable interface in Java is a marker interface that indicates a class can be cloned using the clone() method.
  • Classes that implement Cloneable are indicating that they support a cloning operation where a new object with the same state as the original object can be created.
  • However, implementing Cloneable only provides the capability to clone; you still need to override the clone() method in the class to specify how the cloning should be done.
  • Example:
package com.tipsontech.demo;

//A class that implements Cloneable
class Person implements Cloneable {
private String name;
private int age;

public Person(String name, int age) {
this.name = name;
this.age = age;
}

@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // Default cloning behavior
}

@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}

public class CloningExample {
public static void main(String[] args) {
Person original = new Person("Alice", 30);

try {
// Clone the original object
Person cloned = (Person) original.clone();
System.out.println("Original: " + original);
System.out.println("Cloned: " + cloned);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}

--

--

Saurav Kumar
Saurav Kumar

Written by Saurav Kumar

Experienced Software Engineer adept in Java, Spring Boot, Microservices, Kafka & Azure.