A generic interface is an interface that declares one or more type parameters, allowing the interface to work with different types. The syntax for declaring a generic interface is similar to that of a generic class. It is used to deal with abstract data types. This is implemented for different data types. Generic interfaces are specified just like generic classes. Let’s explore the syntax of a generic interface in Java
Syntax:
The syntax for declaring a generic interface in Java is similar to that of a generic class. Here’s the basic syntax:
interface MyGenericInterface<T> {
T someMethod(T arg);
}
Here, T
is a type parameter that represents a placeholder for the actual data type. The interface declares a method someMethod
that can work with the type T
.
Basic Example with Explanation:
Let’s consider a simple example of a generic interface for a container that can hold a value of any type.
Step 1: Define the Generic Interface
// Generic interface
interface Container<T> {
T getValue();
void setValue(T value);
}
In this step, we define a generic interface called Container
with a type parameter T
. It declares two methods: getValue
to retrieve the value, and setValue
to set the value.
Step 2: Implement the Interface for Integer
// Implementation for Integer type
class IntegerContainer implements Container<Integer> {
private Integer value;
@Override
public Integer getValue() {
return value;
}
@Override
public void setValue(Integer value) {
this.value = value;
}
}
Here, we create a class IntegerContainer
that implements the Container
interface with the specific type parameter Integer
. It provides concrete implementations for the getValue
and setValue
methods.
Step 3: Implement the Interface for String
// Implementation for String type
class StringContainer implements Container<String> {
private String value;
@Override
public String getValue() {
return value;
}
@Override
public void setValue(String value) {
this.value = value;
}
}
Similarly, we create another class StringContainer
that implements the Container
interface with the type parameter String
. It also provides concrete implementations for the getValue
and setValue
methods.
Step 4: Usage in Main Class
// Usage
public class Main {
public static void main(String[] args) {
// Create an instance of IntegerContainer
Container<Integer> intContainer = new IntegerContainer();
intContainer.setValue(42);
// Retrieve and print the Integer value
System.out.println("Integer Value: " + intContainer.getValue());
// Create an instance of StringContainer
Container<String> stringContainer = new StringContainer();
stringContainer.setValue("Hello, Generics!");
// Retrieve and print the String value
System.out.println("String Value: " + stringContainer.getValue());
}
}
In the main
method, we demonstrate how to use the generic interface and its implementations. We create instances of IntegerContainer
and StringContainer
, set values, and retrieve/print the values.
when you run this program, you will see following output:
Integer Value: 42
String Value: Hello, Generics!
Use Case of Generic Interface in java :
The use case of a generic interface lies in scenarios where you want to create reusable components that can work with various data types without sacrificing type safety. For example:
1. Collections Framework:
Java’s java.util
package contains generic interfaces like List<T>
, Set<T>
, and Map<K, V>
. These interfaces allow you to create collections that can hold elements of any type while ensuring type safety.
List<String> stringList = new ArrayList<>();
stringList.add("Hello");
stringList.add("World");
Set<Integer> integerSet = new HashSet<>();
integerSet.add(42);
integerSet.add(100);
2. Custom Data Structures:
When designing custom data structures, a generic interface allows you to create structures like a generic stack or queue that can handle any data type.
interface Stack<T> {
void push(T item);
T pop();
}
3. Wrapper Classes:
Generic interfaces are useful when creating wrapper classes that encapsulate different types of data.
interface Wrapper<T> {
T getValue();
}
class StringWrapper implements Wrapper<String> {
private String value;
@Override
public String getValue() {
return value;
}
}
In Android development, the use of generic interfaces can be beneficial in various scenarios. Here are some use cases of generic interfaces in Android:
4. AdapterViews and RecyclerViews:
When working with AdapterViews
(like ListView
or GridView
) or RecyclerView
, generic interfaces can be used to define adapters that work with different types of data. This allows for the creation of flexible and reusable adapters.
public interface ItemClickListener<T> {
void onItemClick(T item);
}
public class MyAdapter<T> extends RecyclerView.Adapter<MyViewHolder> {
private List<T> dataList;
private ItemClickListener<T> itemClickListener;
// Constructor and other adapter methods
public void setItemClickListener(ItemClickListener<T> listener) {
this.itemClickListener = listener;
}
// ViewHolder and other adapter methods
}
This way, you can create an adapter that works with any type of data, and the ItemClickListener
can handle item clicks for any data type.
5. ViewModels and LiveData:
In Android architecture components like ViewModels
and LiveData
, generics are often used to handle and observe different types of data.
public class MyViewModel<T> extends ViewModel {
private MutableLiveData<T> data = new MutableLiveData<>();
public LiveData<T> getData() {
return data;
}
public void setData(T newData) {
data.setValue(newData);
}
}
This allows you to create a ViewModel that can handle and expose LiveData for any type of data.
In these use cases, generic interfaces provide flexibility, reusability, and type safety, allowing developers to create more versatile and robust code.