DEV Community

Cover image for What are Generics in Java?
Wagner Negrão 👨‍🔧
Wagner Negrão 👨‍🔧

Posted on

What are Generics in Java?

Hello, today I will talk about Generics in Java, this text is focused on beginners who seek to learn a little more about Java.

Generics is an undefined type that can assume any kind, it has been added to Java seeking to avoid excessive code or casting repetitions.

To make it clearer we will create a scenario in which we need to print an object, but we do not know what types will use our method.

I will create the animal abstract class and extend it from two Dog and Cat classes.

abstract class Animal {
    public abstract void search();
}

class Dog extends Animal {
    String dog;

    public Dog(String dog) {
        this.dog = dog;
    }

    @Override
    public void search() {
        System.out.println("find Dog");
    }

    // Method to string was omitted.
}

class Cat extends Animal {

    String cat;

    public Cat(String cat) {
        this.cat = cat;
    }

    @Override
    public void search() {
        System.out.println("find Cat");
    }

    // Method to string was omitted.
}

Enter fullscreen mode Exit fullscreen mode

Now let's create a method to present the information of an object at the terminal, as a rule, we can define that every method that has one toString() can be presented by the so-called Print. We can see that in class Printer() we do not have the specific type to be passed on the builder, it can be any object, the method print will present the information and if it does not have the method toString() the object's memory address will be presented. This method is that in some cases we want to present some information on Debug we can invoke this method.

class Printer <T> {
    T toPrint;

    public Printer(T toPrint) {
        this.toPrint = toPrint;
    }

    public void print() {
        System.out.println(toPrint);
    }
}
Enter fullscreen mode Exit fullscreen mode
Case 01:
public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog("Dog");
        Cat cat = new Cat("Cat");

        Printer<Integer> printer = new Printer(dog);
        printer.print();
    }
}
Enter fullscreen mode Exit fullscreen mode

Now let's create a method to print the lists.

public static void printAnimal(List<? extends Animal> animals) {
    animals.stream().forEach(a -> a.search());
}
Enter fullscreen mode Exit fullscreen mode

In this method is defined the type of the list as whatever type extend of animals, an important information is that we can not add anything to the list because Java in compilation time does not know what is within the list, so we will have the error in compilation time and not execution.

In this method we will all have Animal extension, containing Cat and Dog, this guarantees us a defensive programming, ensuring that we will present only what we want and nothing beyond.

Case 02:
public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog("Dog");
        Cat cat = new Cat("Cat");

        List<Dog> dogList = Arrays.asList(dog);
        List<Cat> catList = Arrays.asList(cat);
        List<Animal> animals = Arrays.asList(dog, cat);

        printAnimal(dogList);
        printAnimal(catList);
        printAnimal(animals);
    }
}

Enter fullscreen mode Exit fullscreen mode

Now I will present the last case that aims to create a list of 2 objects of different types.


public static <T, V> List<Object> createList(T thing, V otherThing) {

    return Arrays.asList(thing, otherThing);
}
Enter fullscreen mode Exit fullscreen mode

This method is possible to create a list of different types without worrying about what will be inserted, this is useful when we have a situation that we can receive information that is not expected, so we can guarantee that we will be able to receive the information and later treat it.

In this case we will only make the object print on the terminal, but the idea is to understand basicly to apply to something larger.

Case 03:

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog("Dog");
        Cat cat = new Cat("Cat");

       createList(dog, cat).stream().forEach(e -> {
           System.out.println(e);
       });
    }
}
Enter fullscreen mode Exit fullscreen mode

An important thing is to know that generics exist only in the time of compilation in this way it keeps back the retro compatibility with Java versions, another important point is to point out that the examples presented here are for didactic purposes.

Top comments (0)