Java based generics

catalogue

1. Generic problem derivation

2. Definition of generics

3. Generic wildcard

4. Generic interface

5. Generic method

1. Generic problem elicitation

The generic type is jdk1 5 and then added to the java language. The main purpose is to solve the ClassCastException problem. There may be security risks during object downward transformation.

give an example

public class Point {
    private Object x;
    private Object y;


    public Object getX() {
        return x;
    }

    public void setX(Object x) {
        this.x = x;
    }

    public Object getY() {
        return y;
    }

    public void setY(Object y) {
        this.y = y;
    }
}
public class JavaDemo {
    public static void main(String[] args) {
        Point point = new Point();

        point.setX(10);
        point.setY("dsfdf");

        int x = (Integer) point.getY();
        int y = (Integer) point.getX();

        System.out.println(x + "====" + y);
    }
}

In this case, there seems to be no problem, but there are security risks. Due to the use of Object, the string type cannot be forcibly converted to Integer, and there will be no error during compilation, so there are security risks. In order to avoid this hidden danger, we introduce the concept of generics. Using generics can directly expose this hidden danger in the compilation process.

2. Definition of generics

The essence of generics is that the types of parameters and return values of properties or methods in a class can be dynamically determined when the object is instantiated.

Usage: a placeholder (generic tag) that is clearly defined when defining a class, for example:

public class Point<T> {
    private T x;
    private T y;


    public T getX() {
        return x;
    }

    public void setX(T x) {
        this.x = x;
    }

    public T getY() {
        return y;
    }

    public void setY(T y) {
        this.y = y;
    }
}

As shown above, after using generic tags, the data types of the x and y attributes in the Point class are not clear, and they are determined externally.

public class JavaDemo {
    public static void main(String[] args) {
        Point<Integer> point = new Point();

        point.setX(10);
        point.setY("dsdf");//Direct error reporting during compilation

        int x = point.getY();
        int y = point.getX();

        System.out.println(x + "====" + y);
    }
}

As mentioned above, when instantiating the Point class, the data types of x and y are specified as Integer (hint: if not specified here, Point still uses Object, which is the default result). If incorrect type conversion is used, an error will be reported directly during the compilation process, avoiding the potential safety hazard at runtime.

3. Generic wildcard

The introduction of generic wildcards is mainly to prevent arbitrary tampering with the data types of method parameters. The following cases are shown:

public class Message<T> {

    private T content;

    public T getContent() {
        return content;
    }

    public void setContent(T content) {
        this.content = content;
    }
}
public class JavaDemo {
    public static void main(String[] args) {

        Message<String> msg1  = new Message<>();
        msg1.setContent("www.loong.cn");
        fun(msg1);

        Message<Integer> msg2  = new Message<>();
        msg2.setContent(234);
        fun(msg2);
    }

    public static void fun(Message temp){
        System.out.println(temp.getContent());
    }
}

There seems to be no problem with the above use, but there are hidden dangers. As for the problem of tampering with parameters mentioned above, we can redefine the data type of Message in the method. As follows: the output results are completely different. Both instantiated objects print "haha"

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

        Message<String> msg1  = new Message<>();
        msg1.setContent("www.loong.cn");
        fun(msg1);

        Message<Integer> msg2  = new Message<>();
        msg2.setContent(234);
        fun(msg2);
    }

    public static void fun(Message temp){
        temp.setContent("hahaha");

        System.out.println(temp.getContent());
    }
}

So we have a new concept, generic wildcard, which can be used as follows

Used? Later, although the method can accept all types of parameters, the parameters can no longer be modified and can only be obtained.

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

        Message<String> msg1  = new Message<>();
        msg1.setContent("www.loong.cn");
        fun(msg1);

        Message<Integer> msg2  = new Message<>();
        msg2.setContent(234);
        fun(msg2);
    }

    public static void fun(Message<?> temp){
        temp.setContent("hahaha");//This line of compilation directly reports an error

        System.out.println(temp.getContent());
    }
}

Two other generic wildcards:

3.1 ? Extensions class: sets the upper limit of generics

For example:? Extensions Number: indicates that only Number or subclass of Number can be set for this generic type.

give an example:

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

        Message<String> msg1  = new Message<>();
        msg1.setContent("www.loong.cn");
        fun(msg1);//This line reports an error during compilation

        Message<Integer> msg2  = new Message<>();
        msg2.setContent(234);
        fun(msg2);
    }

    public static void fun(Message<? extends Number> temp){

        System.out.println(temp.getContent());
    }
}

3.2 ? super class: sets the lower bound of generics

For example:? super String: indicates that the generic type can only set String or the parent class of String

give an example:

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

        Message<String> msg1  = new Message<>();
        msg1.setContent("www.loong.cn");
        fun(msg1);

        Message<Integer> msg2  = new Message<>();
        msg2.setContent(234);
        fun(msg2);//report errors
    }

    public static void fun(Message<? super String> temp){

        System.out.println(temp.getContent());
    }
}

4. Generic interface

In addition to being defined on classes, generics can also be used on interfaces

public interface Imessage<T> {
    public String echo(T t);
}

For subclasses of generic interfaces, there are two implementations:

4.1 continue to set generics in subclasses:

public class MessageImpl<S> implements Imessage<S> {

    @Override
    public String echo(S s) {
        return "Hello: " + s;
    }
}
public class JavaDemo {
    public static void main(String[] args) {
        Imessage<String> imessage1 = new MessageImpl<>();
        System.out.println(imessage1.echo("Brother long"));
    }
}

4.2 subclasses are directly defined when implementing the parent class interface

public class MessageImpl implements Imessage<String> {

    @Override
    public String echo(String s) {
        return "Hello: " + s;
    }
}
public class JavaDemo {
    public static void main(String[] args) {
        Imessage<String> imessage1 = new MessageImpl();
        System.out.println(imessage1.echo("Brother long"));
    }
}

5. Generic method

If you write a generic tag on a method, such a method is called a generic method

public class JavaDemo {
    public static void main(String[] args) {
        Integer[] num = fun(1, 2, 3);
        for (int temp : num) {
            System.out.println(temp + "! ");
        }

        String[] strings = fun("a", "b", "c");

        for (String temp : strings) {
            System.out.println(temp + "! ");
        }

    }


    public static <T> T[] fun(T... args) {
        return args;

    }
}

Keywords: Java

Added by pqdrummer on Thu, 20 Jan 2022 04:02:36 +0200