Learning Java generics

Posted by kjtocool on Thu, 13 Jan 2022 21:28:22 +0100

Although I have written Java code for some time, I still can't figure it out and give up selectively as long as I see generics. However, I found that generics are used in many places when looking at the code of the company leaders today, so I'll sort out the generics I understand today.

What is generics

generic programming is a style or paradigm of programming language. Generics allow programmers to use some later specified types when writing code in strongly typed programming languages, and indicate these types as parameters when instantiating. There are two main definitions of generics: 1 ⃣ In program coding, some types contain type parameters, that is, generic parameters can only represent classes, not individual objects. two ⃣  some classes containing parameters in program coding. Its parameters can represent classes or objects, and so on.

👆 The above explanation comes from Baidu Encyclopedia. In short, generics is a code paradigm.

Java generics

The parameters of Java generics can only represent classes, not individual objects. Because the actual type of the type parameter of Java generic type will be eliminated at compile time, the type of its type parameter cannot be known at run time, and the basic value type cannot be directly used as the generic type parameter.

Java generic design principles:

Postpone type specific work until you create an object or call a method to specify a particular type. As long as there are no warnings at compile time, ClassCastException exceptions will not appear at run time.

Here is an example of a simple generic type:

public class Generic {

    public static void main(String[] args) {
        // C can accept String
        C<String> stringC = new C<>("Hello world");
        System.out.println(stringC);
        
        // C can accept Integer
        C<Integer> integerC = new C<>(100);
        System.out.println(integerC);

    }
}

// C can accept initialization of any type of data
class C<T> {
    private T item;

    public C(T t){
        item = t;
    }

    @Override
    public String toString() {
        return  item + "";
    }
}
Copy code

T,E,K,V

T. E, K, and V are essentially wildcards. Coding is sometimes about convention. For example, we can use any letter between A-Z to represent wildcards, which will not affect the normal operation of the program. Generally, t, e, K and V are agreed as follows:

  • ? Represents an ambiguous Java type
  • T (type) represents a specific Java type
  • K V (Key Value) respectively represents the Key Value in the Java Key Value
  • E (Element) stands for Element

wildcard

  • Upper bound wildcard? extends T

    For example, list <? The purpose of extensions number > is to accept the data type of list < integer > or list < long >.

  • Lower bound wildcard? super T

    For example, list <? The purpose of super number > is to make up for the shortage that only one specific type of data can be stored.

public class Generic {

    public static void main(String[] args) {
        // sure
        List<? super Number> list = new ArrayList<>();
        list.add(10);
        list.add(20L);
        list.add(20.2);

        System.out.println(list);

        List<Integer> list1 = new ArrayList<>();
        List<Long> list2 = new ArrayList<>();

        list1.add(10);
        list1.add(20);

        list2.add(10L);
        list2.add(20L);

        read(list1);
        read(list2);
    }

    private static void read(List< ? extends Number> list) {
        Number first = list.get(0);
        Number last = list.get(list.size() - 1);
        System.out.println("first = " + first.toString() + " last = " + last.toString());
    }
    
}
Copy code

Finally, let's look at the PECS (producer extensions consumer super) principle:

  • If the content is frequently read out, it is suitable to use the upper bound extensions
  • It is often inserted in, which is suitable for using the lower bound Super

Generic case

// Multiparametric generics 
class Person<N, A, S> {

    private N name;
    private A age;
    private S sex;

    Person(N name, A age, S sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public N getName() {
        return name;
    }
    public void setName(N name) {
        this.name = name;
    }
    public A getAge() {
        return age;
    }
    public void setAge(A age) {
        this.age = age;
    }
    public S getSex() {
        return sex;
    }
    public void setSex(S sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "full name:" + name + ",Age:" + age + ",Gender:" + sex;
    }
}

// use
public class Generic {

    public static void main(String[] args) {

        Person<String, Integer, Character> person = new Person<String, Integer, Character>("Fried rice with egg", 28, 'male');
        printPerson(person);
        // Name: fried rice with egg, age: 28, gender: Male
    }
    
    // generic method 
    private static <T> void printPerson(T person){
        if ( person != null) {
            System.out.println(person);
        }
    }
}
Copy code

Topics: Java Spring Spring Boot Algorithm Back-end