Introduction to wildcards in java generics

? Represents an uncertain java type
T (type) represents a specific java type
KV (key value) represents the Key Value in the java key value
E (element) represents Element

a simple generic class

The GenericsTest class introduces a type variable T, which specifies the return type of the method and the types of domains and local variables. You
can see that it needs to be forced when the type is not specified, and it is not needed when the type is specified.

public class GenericsTest<T> {
    
    

    private T t;
    public void set(T t){
    
    
        this.t=t;
    }
    public T get(){
    
    
        return this.t;
    }


    @Test
    void test(){
    
    
        GenericsTest number=new GenericsTest();
        number.set(13);
        //不指定类型时需要强转
        Integer num =(Integer) number.get();
        System.out.println(num);
        GenericsTest<String>name=new GenericsTest<>();
        name.set("liuyuan");
		//指定类型就不需要强转了
        String getName = name.get();
        System.out.println(getName);
    }

}

generic method

Generic methods can be defined in ordinary classes or in generic classes. When calling generic methods, you can put specific types in angle brackets before the method name

public class GenericsTest<T> {
    
    

    private T t;
    public void set(T t){
    
    
        this.t=t;
    }
    public T get(){
    
    
        return this.t;
    }
    /**
     *  类型变量放在修饰符public static后面,返回类型的前面
     * @param a
     * @param <T>
     * @return
     */
    public static <T> T getMiddle(T ...a){
    
    
        return a[a.length/2];
    }

    @Test
    void testGetMiddle(){
    
    
        //大多情况可以直接省略<String>不写,编译器能够推断出类型
        String middle = GenericsTest.getMiddle("left", "middle","middle2", "right");
        System.out.println(middle);
        // 可以指定类型
        Integer middle1 = GenericsTest.<Integer>getMiddle(123, 22, 56);
        System.out.println(middle1);
    }

}

Qualification of type variables

Scenario: You want the minimum value for sorting the array, but the following smallest must implement the Comparable interface before we can use its compareTo method to judge it. At this time, the class to which T belongs is determined by setting a limit on the type variable
<T extends Comparable>
T. The compareTo method can achieve the result we want

public static <T extends Comparable> T getMinNum(T arr[]){
    
    
        if(arr == null || arr.length== 0 ) return null;
        T smallest=arr[0];
        for (int i = 0; i < arr.length; i++) {
    
    
            if(smallest.compareTo(arr[i])>0){
    
    
                smallest=arr[i];
            }
        }
        return smallest;
    }

    @Test
    void getMinNumTest(){
    
    
        String arr []=new String[]{
    
    "b","a","d"};
        String minNum = getMinNum(arr);
        System.out.println(minNum);
        Integer arr1 []=new Integer[]{
    
    6,4,1};
        System.out.println(getMinNum(arr1));
    }

Just a word: why the keyword here is defined by extends, T should be a subclass of the bound type, and T and the bound type can be interfaces or classes, and the choice of extends is closer to the concept of subclasses, so there is no need for implements
. In addition: one Type variables or wildcards can have multiple restrictions
T extends Comparable & Seralizable, limited types are separated by &, and commas are used to separate type variables

Maximum and Minimum Cases

1. <T extends Comparable>Limit the type variable
2. The parameter returns Pair

    public static <T extends Comparable> Pair<T> getMAxAndMin(T arr[]){
    
    

        if(arr == null || arr.length == 0)return null;
        T min=arr[0];
        T max=arr[0];
        for (int i = 0; i < arr.length; i++) {
    
    
            if(min.compareTo(arr[i])>0){
    
    
                min=arr[i];
            }
            if(max.compareTo(arr[i])<0){
    
    
                max=arr[i];
            }
        }
        return new Pair(min,max);
    }
@AllArgsConstructor
public  class Pair<T>{
    
    
    @Getter
    @Setter
    T first;
    @Getter
    @Setter
    T second;
}

Generic Type Inheritance Rules

When using generic types, such as subclasses of List<Animal.Dog>yes ? List<Animal>? ? Certainly not

wildcard type

What problem do wildcards solve??? :
For example, if you want to print information about animals:

 public void printAnimal2(List<Animal> animals){
    
    
    for (int i = 0; i < animals.size(); i++) {
    
    
        System.out.println(animals.get(i));
 }

But you can't pass in List<Animal.Dog>, which is a collection of dogs. This is limited. The solution is to use wildcard types.
1. public void printAnimal3(List<? extends Animal>animals)The type List<Animal.Dog>is List<Animal>a subtype
2. Change the posture to achieve the above requirements.
public <T extends Animal> void printAnimal(List<T> animals)Specify that List<T> animalsit can only be a subclass of Animal.
The implementation code is as follows:

@AllArgsConstructor
@Data
public class Animal {
    
    

    private String name;


    private String sex;


    private Integer age;

   public static class Dog extends Animal{
    
    

        public Dog(String name, String sex, Integer age) {
    
    
            super(name, sex, age);
        }
    }

    public static class Cat extends Animal{
    
    
        public Cat(String name, String sex, Integer age) {
    
    
            super(name, sex, age);
        }
    }

}

I want to print List<Animal.Dog> and report an error

@Test
    void testPrintAnimal(){
    
    
        List<Animal.Dog> dogs=new ArrayList<>();
        dogs.add(new Animal.Dog("dog","1",18));
        // error
        printAnimal2(dogs);

    }
        public void printAnimal2(List<Animal> animals){
    
    
        for (int i = 0; i < animals.size(); i++) {
    
    
            System.out.println(animals.get(i));
        }
    }

And this can be done both ways

//<T extends Animal> 对T进行了限制 只能是Animal子类 
  public <T extends Animal> void printAnimal(List<T> animals){
    
    
        for (int i = 0; i < animals.size(); i++) {
    
    
            System.out.println(animals.get(i));
        }
    }
    //? extends Animal 标示任何泛型List类型,类型参数是Animal子类即可
    public void printAnimal3(List<? extends Animal>animals){
    
    
        for (int i = 0; i < animals.size(); i++) {
    
    
            System.out.println(animals.get(i));
        }
    }
        @Test
    void testPrintAnimal(){
    
    
        List<Animal.Dog> dogs=new ArrayList<>();
        dogs.add(new Animal.Dog("dog","1",18));
        printAnimal(dogs);
        printAnimal3(dogs);

    }

Guess you like

Origin blog.csdn.net/qq_43566782/article/details/129441099