JAVA-The "Generic" of Essay

Posted by ChaosKnight on Fri, 10 May 2019 01:16:02 +0200

What is generics?

The most effective way to understand a technical point is to first look at the official document explanation, OK, the generic definition given by the official website:
Generics are a new feature of Java SE 1.5. The essence of generics is parameterized type, that is to say, the data type being operated on is specified as a parameter.
This parameter type can be used in the creation of classes, interfaces and methods, which are called generic classes, generic interfaces and generic methods respectively.

Simply put: Generics are "parameterized types". It is well known that parameters are divided into "parameters, arguments", and so is the "parameterized type" here. When generics are defined, they are "parameters", and when invoked, specific parameters are passed in, namely "parameters".



Where do generics occur?

Many friends asked, where will generics appear? Among the usual generics, Collection is the most common. Let's first look at the existing code.

Here's an example of ArrayList.

Next, take a look at the classes of ArrayList

There is an E in the red section in the picture. This is the generic type. When creating an Array List, you can give any type: basic data class, reference data type. It can accept any specific type argument that is passed in, and all E in that class or interface is the specific type that is passed in. We often have T, E, K, V and other forms of parameters are generic parameters.



Why use generics:

ITEM-1:

Constraints in encoding. As shown below, our ArrayList gives you a String type. When we add, if the added element is not a String type, your IDEA will give you a red bar, which can't be compiled, because generics are used, that is to say, a qualified type is given directly.

ITEM-2:

ArrayList can also give no specific type when it is coded. That's no problem, but when it takes an element from ArrayList, it's Object type. At this time, it needs to be strongly rotated, so it's easy to have type conversion exception / java.lang.ClassCastException. Using generics, we can avoid such exception as this as far as possible, but we don't need to force it. When we take a value, I need to rotate. DEA has been able to confirm the type of the value.

ITEM-3:

Reduce the development of classes and enhance the generality of classes. In our development, there will be a lot of entity classes. At this time, there are some common methods that need to be sorted out. We need to do the same operation according to different classes (similar to Base Service). At this time, if we create such a public class for each entity class, the workload is huge, and generics just help us solve this problem.



How to use generics:

After we have understood all the long stories, let's use real guns and live ammunition. Take a classic example: school, teacher, student. There are both students and teachers in the school.

/**
 * Create a student type
 */
public class Student {
    private String name;
    private String age;
    ...			// Omitting get set method
}
/**
 * Create a teacher type
 */
public class Teacher {
    private String name;
    private Integer age;
    ...			// Omitting get set method
}
/**
 * Create a type of school and give it a generic type
 * In this class, all places where E is used represent the specific parameter types that are passed in at the time of invocation.
 * @param <E>
 */
public class School<E> {
    private E person;

    public E getPerson() {
        return person;
    }

    public void setPerson(E person) {
        this.person = person;
    }
}

The next step is to write a test class. In order not to let the code look dazzling, let's test one by one. First let's test the student class.

public class SchoolDemo {
    public static void main(String[] args) {
        // Create a Student Object
        Student student = new Student();
        student.setName("Zhang San classmate");
        student.setAge(15);
        // Create a school object and put the Student type into it
        School<Student> school_stu = new School<>();
        // Put Student Objects into School
        school_stu.setPerson(student);
        // Here we call the get method to get the specific object type that corresponds to the incoming object type directly.
        Student person_stu = school_stu.getPerson();
        // Print out the contents
        System.out.println(person_stu.toString());
    }
}

Printed results:

Then let's do the same routine, the same way, to test the class of teachers.

public class SchoolDemo {
    public static void main(String[] args) {
         // Create a teacher object
        Teacher teacher = new Teacher();
        teacher.setName("Miss Wang Meimei");
        teacher.setAge(25);
        // Create a school object and place the Teacher type in it
        School<Teacher> school_tea = new School<>();
        // Put the Teacher object into School
        school_tea.setPerson(teacher);
        // Here we call the get method to get the specific object type that corresponds to the incoming object type directly.
        Teacher person_tea = school_tea.getPerson();
        // Print out the contents
        System.out.println(person_tea.toString());
    }
}

Printed results:

So we don't need to create many School classes to manipulate these two types. We just put different parameters into the creation of School. set and get methods will also restrict your parameter type, reduce the error rate and facilitate the value.



Regarding the type of instance generated:

In the example above, we will think that when we create Schools, we pass in different strength parameters, so is the generated Schools the same?
The answer is the same.

public class SchoolDemo {
    public static void main(String[] args) {

        // Create a Student Object
        Student student = new Student();
        School<Student> school_stu = new School<>(student);


        // Create a teacher object
        Teacher teacher = new Teacher();
        School<Teacher> school_tea = new School<>(teacher);

        // Let's print the class to see if it's true.
        System.out.println("school_stu Class:" + school_stu.getClass());
        System.out.println("school_tea Class:" + school_tea.getClass());
        System.out.println(school_stu.getClass() == school_tea.getClass());

    }
}

Printed results:

Through the example above, although we passed in different generic arguments, we did not really generate different types, that is to say, we passed in different parameter arguments, but there is only one in memory, which is the original basic type (here: School). But logically, we can understand many different types.
This is because when Java puts forward the concept of generics, it only acts in the coding stage. Once it enters the compilation stage, it will check its generics first. After completing the verification, it will erase the relevant information of generics. The successfully compiled class file does not contain any generic information, let alone enter the running stage.
Generic types can logically be seen as multiple types, and they are all the same basic types at runtime.



Type wildcards:

After we Get the basic usage of generics, let's look at the advanced usage. The Student and Teacher above can give them a parent class (Person) and let them inherit this parent class. Let's modify the code.

/**
 * Create the parent Person
 */
public class Person {
    private String name;
    private Integer age;
    
    ...			// Omitting get set method
}
/**
 * Create a student type that inherits Person
 */
public class Student extends Person{
    
}
/**
 * Create a teacher type that inherits Person
 */
public class Teacher extends Person{
    
}

Focus on the test class:

public class SchoolDemo {
    public static void main(String[] args) {

        // Create a Student Object
        Student student = new Student();
        School<Student> school_stu = new School<>(student);
        getPerson(school_stu);		// 1

        // Create a teacher object
        Teacher teacher = new Teacher();
        School<Teacher> school_tea = new School<>(teacher);
        getPerson(school_tea);		// 2
    }

    // Here we add a getPerson method with the parameter School < Person >
    public static void getPerson(School<Person> person){
    	System.out.println(person.getPerson().toString());
    }
}

The above code will be red at 1 and 2, respectively, and won't let you compile it. That's strange. We all inherit the Person class. Why can't we compile it yet? Let's think about this: Although our parameters here are parent classes, when we get Person, are we returning Student? Teacher, and in the compilation process sequence is uncontrollable, when necessary, type judgment must be made, and strong rotation, which is contrary to the concept of generics. So logically, we can't think of Person as the parent class of Student and Teacher.

At this point, we need to use wildcards to make it logically expressible as a reference type of a parent class, so type wildcards come into being.

Type wildcards basically use question marks (?) instead of specific type arguments. Notably, here? It's a type argument, not a form parameter! Logically, it's the parent class of all School < arguments >. Let's look at the code.

public class SchoolDemo {
    public static void main(String[] args) {

        // Create a Student Object
        Student student = new Student();
        School<Student> school_stu = new School<>(student);
        getPerson(school_stu);		// 1

        // Create a teacher object
        Teacher teacher = new Teacher();
        School<Teacher> school_tea = new School<>(teacher);
        getPerson(school_tea);		// 2

		// We put a String type in the school class.
		School<String> school_str = new School(new String());
        getPerson(school_str);		// 3
    }

    // Here we add a getPerson method with the parameter School<?>.
    public static void getPerson(School<?> person){
        System.out.println(person.getPerson().toString());
    }
}

So 1 and 2 can be compiled, and new problems arise. I put a String type school in this position of 3. The compiler will not compile errors, because we are using wildcards, at this time we want to limit the parameters, must be a subclass of Person how to deal with?

// Here we add a getPerson method with the parameter School <? Extends Person >
    public static void getPerson(School<? extends Person> person){
        System.out.println(person.getPerson().toString());
    }

Using type wildcards to go online is the solution. We let wildcards inherit a parent class, so that we can restrict the parameters.

In peacetime development, reasonable use of generics will bring convenience to our development and reduce the amount of code. ~~ OK, that's the knowledge about generics. If there's something wrong, please point out that there are many implications.

Topics: Programming Java encoding