generics
generics
Bounded types allow developers to impose constraints on the types that can be used as generic
parameters in classes, interfaces, and methods. By defining these constraints, developers can ensure
that certain operations are supported and prevent errors at compile-time. In this article, we'll delve into
bounded types in Java and explore how they can be leveraged to write more robust and flexible code.
A bounded type parameter is a generic type that is restricted to a specific subset of types. It can be
defined using the extends keyword followed by the upper bound. The upper bound can be a class or
an interface, and it indicates that the generic type must be a subclass of the specified class or
implement the specified interface.
Syntax:
Wildcards in Java
The wildcard can be used in a variety of situations such as the type of a parameter, field, or local
variable; sometimes as a return type. Unlike arrays, different instantiations of a generic type are not
compatible with each other,
Types of wildcards in Java
1. Upper Bounded Wildcards:
These wildcards can be used when you want to relax the restrictions on a variable. For example, say
you want to write a method that works on List < Integer >, List < Double >, and List < Number >, you
can do this using an upper bounded wildcard.
To declare an upper-bounded wildcard, use the wildcard character (‘?’), followed by the extends
keyword, followed by its upper bound.
public static void add(List<? extends Number> list)
// Java program to demonstrate Upper Bounded Wildcards
import java.util.Arrays;
import java.util.List;
class WildcardDemo {
public static void main(String[] args)
{
// Double list
List<Double> list2 = Arrays.asList(4.1, 5.1, 6.1);
return sum;
}
}
Output
Total sum is:22.0
Total sum is:15.299999999999999
Explanation:
In the above program, list1 and list2 are objects of the List class. list1 is a collection of Integer and
list2 is a collection of Double. Both of them are being passed to method sum which has a wildcard
that extends Number. This means that list being passed can be of any field or subclass of that field.
Here, Integer and Double are subclasses of class Number.
2. Lower Bounded Wildcards:
It is expressed using the wildcard character (‘?’), followed by the super keyword, followed by its
lower bound: <? super A>.
Syntax: Collectiontype <? super A>
import java.util.Arrays;
import java.util.List;
class WildcardDemo {
public static void main(String[] args)
{
// Lower Bounded Integer List
List<Integer> list1 = Arrays.asList(4, 5, 6, 7);
// Number list
List<Number> list2 = Arrays.asList(4, 5, 6, 7);
Similar to generic class, when an interface is defined using generic type parameter, it is called generic
interface in Java.
When a generic interface is implemented by either a generic class or non-generic class, the type
argument must be specified.
The generic interface has main two advantages that are as:
A generic interface can be implemented for different types of data.
It allows placing constraints (i.e. bounds) on the types of data for which interface can be implemented.
The general syntax to write an implementation class that implements the above interface, as follows:
class class-name<T> implements interface-name<T>
{
public void method-name(T t)
{
// Write code for this method as per requirement.
}
}
JAVACopy code
Here, T represents a generic parameter that specifies any data type.
Let’s take an example program where we will create a generic interface and implementation class.
Then the implementation class will be used to display the class name of object passed to the method.
Example 2:
public interface Fruit<T>
{
// This method can accept any type of object.
public void taste(T fruit);
}
public class AnyFruit<T> implements Fruit<T>
{
public void taste(T fruit)
{
// Get the class name of object passed to this method.
String fruitname = fruit.getClass().getName();
System.out.println(fruitname);
}
}
public class Banana {
}
public class Orange {
}
public class GenericClass {
public static void main(String[] args)
{
// Create an object of class Banana and pass it to class AnyFruit.
Banana b = new Banana();
AnyFruit<Banana> fruit1 = new AnyFruit<Banana>();
fruit1.taste(b);
// Create an object of Orange and pass it to class AnyFruit.
Orange o = new Orange();
AnyFruit<Orange> fruit2 = new AnyFruit<Orange>();
fruit2.taste(o);
}
}
JAVACopy code
Output:
genericsProgram.Banana
genericsProgram.Orange
Generic means parameterized types introduced in java5. These help in creating classes, interfaces,
methods, etc. A class or method which works on parameterized type known as “generic class ” or
“generic method”. Generics is a combination of language properties of the definition and use of
Generic types and methods. Collections were used before Generics which holds any type of objects
i.e. non-generic. Using Generics, it has become possible to create a single class, interface, or method
that automatically works with all types of data(Integer, String, Float, etc). It has expanded the ability
to reuse the code safely and easily. Generics also provide type safety (ensuring that an operation is
being performed on the right type of data before executing that operation).
Hierarchical classifications are allowed by Inheritance. Superclass is a class that is inherited. The
subclass is a class that does inherit. It inherits all members defined by super-class and adds its own,
unique elements. These uses extends as a keyword to do so.
Sometimes generic class acts like super-class or subclass. In Generic Hierarchy, All sub-classes move
up any of the parameter types that are essential by super-class of generic in the hierarchy. This is the
same as constructor parameters being moved up in a hierarchy.
Example 1: Generic super-class
Java
// Helper class 1
// Class 1 - Parent class
class Generic1<T> {
// Member variable of parent class
T obj;
// Helper class 2
// Class 2 - Child class
class Generic2<T, V> extends Generic1<T> {
// Member variable of child class
V obj2;
Generic2(T o1, V o2)
{
// Calling super class using super keyword
super(o1);
obj2 = o2;
}
Output
value :
100
Note: A subclass can freely add its own type parameters, if necessary.
Example 2: Non-generic sub-class of generic sub-class
Java
import java.io.*;
// non-generic super-class
class NonGen {
int n;
NonGen(int i) { n = i; }
int getval() { return n; }
}
// generic class sub-class
class Gen<T> extends NonGen {
T obj;
Gen(T o1, int i)
{
super(i);
obj = o1;
}
T getobj() { return obj; }
}
class GFG {
public static void main(String[] args)
{
Output
Hello 2021