泛型

一. 泛型类、接口

1. 泛型类定义与使用



查看代码
 // <T> 是泛型标识, 相当于 类型形参
// 在外部使用类的时候指定
class Generic<T> {
    private T val;

    public Generic(T val) {
        this.val = val;
    }

    public T getVal() {
        return val;
    }

    public void setVal(T val) {
        this.val = val;
    }
}

class Test {
    public static void main(String[] args) {
        // 这里的 <String> 相当于是实参
        Generic<String> stringGeneric = new Generic<>("abc");
        System.out.println(stringGeneric.getVal());

        Generic<Integer> integerGeneric = new Generic<>(123);
        System.out.println(integerGeneric.getVal());
    }
}

 

泛型类注意点 

泛型类,如果没有指定具体的数据类型,此时,操作类型是Object

泛型的类型参数只能是类类型,不能是基本数据类型

泛型类型在逻辑上可以看成是多个不同的类型,但实际上都是相同类型

 

2. 泛型的作用

1. 编译的时候 检查类型

2. 帮助进行类型转换

查看代码
 // 泛型类
class MyArray<T> {

    public Object[] array = new Object[10];

    public void setValue(int pos,T val) {
        array[pos] = val;
    }

    public T getValue(int pos) {
        return (T) array[pos];
    }

}

class Test {
    public static void main(String[] args) {
        MyArray<String> myArray = new MyArray<>();

        // 泛型的作用1: 编译的时候 检查类型
        // myArray.setValue(1,1);  // 报错 !
        myArray.setValue(0,"abc");

        // 泛型的作用2: 帮助进行类型转换
        String str = myArray.getValue(0); // 不需要强转 
        System.out.println(str);
    }
}

 

3. 泛型类的继承

查看代码
package Generics;

//父类
class Parent<E> {
    private E value;
    public E getValue() {
        return value;
    }
    public void setValue(E value) {
        this.value = value;
    }
}

/**
 * 泛型类派生子类,子类也是泛型类,那么子类的泛型标识要和父类一致。
 * @param <T>
 */

// 子类ChildFirst会把 T类型 当做参数, 传递给父类Parent
// Parent 只有与子类有相同的泛型标识, 才能接收子类传递过来的参数
class ChildFirst<T> extends Parent<T> {

    @Override
    public T getValue() {
        return super.getValue();
    }
}

class Test4 {
    public static void main(String[] args) {
        ChildFirst<String> childFirst = new ChildFirst<>();
        childFirst.setValue("abc");
        String str = childFirst.getValue();
        System.out.println(str);
    }
}

 

查看代码
package Generics.demo2;

class Parent<E> {
    private E value;
    public E getValue() {
        return value;
    }
    public void setValue(E value) {
        this.value = value;
    }
}


// 因为子类没泛型标识, 没办法传递类型给父类
// 所以, 父类要明确数据类型
class ChildSecond extends Parent<Integer> {
    @Override
    public Integer getValue() {
        return super.getValue();
    }
    @Override
    public void setValue(Integer value) {
        super.setValue(value);
    }
}

class Test {
    public static void main(String[] args) {
        ChildSecond childSecond = new ChildSecond();
        childSecond.setValue(123);
        System.out.println(childSecond.getValue());
    }
}

 

 

4. 泛型接口

实现泛型接口的类,不是泛型类,需要明确实现泛型接口的数据类型

查看代码
 interface Generator<T> {
    T getKey();
}

/**
 * 实现泛型接口的类,不是泛型类,需要明确实现泛型接口的数据类型。
 */
class Apple implements Generator<String> {
    @Override
    public String getKey() {
        return "hello generic";
    }
}

class Test {
    public static void main(String[] args) {
        Apple apple = new Apple();
        System.out.println(apple.getKey());
    }
}

 

泛型类实现泛型接口, 要保证实现接口的泛型类泛型标识,包含泛型接口的泛型标识

查看代码
package Generics.demo2;


interface Generator<T> {
    T getKey();
}

// 泛型类实现泛型接口
// 要保证实现接口的泛型类, <T,E> 泛型标识 包含 泛型接口的泛型标识 <T>
class Pair<T,E> implements Generator<T> {

    private T key;
    private E value;

    public Pair(T key, E value) {
        this.key = key;
        this.value = value;
    }

    @Override
    public T getKey() {
        return key;
    }

    public E getValue() {
        return value;
    }
}

class Test {
    public static void main(String[] args) {
        Pair<String,Integer> pair = new Pair<>("num",100);
        System.out.println( pair.getKey() );
        System.out.println( pair.getValue() );

    }
}

 

二. 泛型的上界

class MyArray<T extends Number> {

    public Object[] array = new Object[10];

    public void setValue(int pos,T val) {
        array[pos] = val;
    }

    public T getValue(int pos) {
        return (T) array[pos];
    }

}

class Test {
    public static void main(String[] args) {
        
        // 传入的数据类型必须是 Number类型本身 或者子类
        // 报错 !
        MyArray<String> myArray = new MyArray<>();
        myArray.setValue(0,"abc");

        MyArray<Integer> myArray1 = new MyArray<>();
        myArray1.setValue(1,1);
    }
}

 

// <T extends Comparable<T>> 表示
// 传入的数据类型 必须实现 Comparable接口
class Alg<T extends Comparable<T>> {

    public T findMaxVal(T[] array) {
        T max = array[0];
        for (int i = 1; i < array.length; i++) {
            if(array[i].compareTo(max) > 0) {
                max = array[i];
            }
        }
        return max;
    }
}

class Test {
    public static void main(String[] args) {
        Integer[] array = {1,4,3,8,7,5};
        Alg<Integer> alg = new Alg<>();
        System.out.println(alg.findMaxVal(array));

    }
}

 

三. 泛型方法

class Alg3 {

    // 泛型方法
    public static <T extends Comparable<T>> T findMaxVal(T[] array) {
        T max = array[0];
        for (int i = 1; i < array.length; i++) {
            if(array[i].compareTo(max) > 0) {
                max = array[i];
            }
        }
        return max;
    }
}
class Test {
    public static void main(String[] args) {
        Integer[] array = {1, 4, 3, 8, 7, 5};
        System.out.println(Alg3.<Integer>findMaxVal(array));
        System.out.println(Alg3.findMaxVal(array));
    }
}

 

四. 类型通配符

1. 通配符

查看代码
package Generics.demo2;


import java.util.Objects;

class Box<E> {
    E val;

    public E getVal() {
        return val;
    }

    public void setVal(E val) {
        this.val = val;
    }
}

class Test {

    // 不能传入box2, 因为box2指定的类型为Integer
   /* public static void print(Box<Number> box) {
        System.out.println(box.getVal());
    }*/

    // 类型通配符
    // ? 表示任意类型实参 ex: Number,Integer
    // 一定要注意区分 ? 表示任意类型 实参, 而不是形参 T,K,V
    public static void print(Box<?> box) {
        System.out.println(box.getVal());
    }

    public static void main(String[] args) {
        Box<Number> box1 = new Box<>();
        box1.setVal(1);
        print(box1);

        Box<Integer> box2 = new Box<>();
        box2.setVal(2);
        print(box2);
    }
}

 

2. 类型通配符的上限

查看代码
package Generics.demo2;

class Box<E> {
    E val;

    public E getVal() {
        return val;
    }

    public void setVal(E val) {
        this.val = val;
    }
}

class Test {
    
    // <? extends Number> 表示 传入实参类型, 是 Number本身 或者 Number子类
    public static void print(Box<? extends Number> box) {
        System.out.println(box.getVal());
    }

    public static void main(String[] args) {
        Box<Number> box1 = new Box<>();
        box1.setVal(1);
        print(box1);

        Box<Integer> box2 = new Box<>();
        box2.setVal(2);
        print(box2);
    }
}

 

3. 通配符的下限

查看代码
 package Generics.demo2;

class Box<E> {
    E val;

    public E getVal() {
        return val;
    }

    public void setVal(E val) {
        this.val = val;
    }
}

class Test {

    // <? super Integer> 表示 传入实参类型, 是 Integer 或者 Integer 父类
    
    public static void print(Box<? super Integer> box) {
        System.out.println(box.getVal());
    }

    public static void main(String[] args) {
        Box<Number> box1 = new Box<>();
        box1.setVal(1);
        print(box1);

        Box<Integer> box2 = new Box<>();
        box2.setVal(2);
        print(box2);
    }
}

 

posted @ 2024-04-16 16:18  qyx1  阅读(39)  评论(0)    收藏  举报