Fork me on GitHub

泛型的运用理解

参考博客:https://blog.csdn.net/s10461/article/details/53941091

阅后笔记:

一.  概念特性

  1.1  泛型,参数化类型,参数包括实参<?><Integer>、形参<T><E>,参数化类型通俗点举例就是:<String> <Integer>

  1.2  泛型使用时注意:存入的是自定义类或者包装类如Integer、Character等等,不能使用简单类型的int char 。

  1.3  特性:只在编译时生效,编译检测正确的泛型时会被擦除。

二。  具体使用

  包含泛型类、泛型接口、泛型方法

  2.1  泛型类

//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
//在实例化泛型类时,必须指定T的具体类型
public class Generic<T>{ 
    //key这个成员变量的类型为T,T的类型由外部指定  
    private T key;

    public Generic(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定
        this.key = key;
    }

    public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
        return key;
    }
} 
//泛型的类型参数只能是类类型(包括自定义类),不能是简单类型
//传入的实参类型需与泛型的类型参数类型相同,即为Integer.
Generic<Integer> genericInteger = new Generic<Integer>(123456);

//传入的实参类型需与泛型的类型参数类型相同,即为String.
Generic<String> genericString = new Generic<String>("key_vlaue");
Log.d("泛型测试","key is " + genericInteger.getKey());
Log.d("泛型测试","key is " + genericString.getKey());

泛型类也可以不指定实参

Generic generic = new Generic("111111");
Generic generic1 = new Generic(4444);
Generic generic2 = new Generic(55.55);
Generic generic3 = new Generic(false);

这样也是可行的。

注意:不能对确切的泛型类型使用instanceof操作。

 

  2.2泛型接口

和泛型类基本类似

/**
 * 未传入泛型实参时,与泛型类的定义相同,在声明类的时候,需将泛型的声明也一起加到类中
 * 即:class FruitGenerator<T> implements Generator<T>{
 * 如果不声明泛型,如:class FruitGenerator implements Generator<T>,编译器会报错:"Unknown class"
 */
class FruitGenerator<T> implements Generator<T>{
    @Override
    public T next() {
        return null;
    }
}

  2.3泛型通配符

Generic<Ingeter>Generic<Number>实际上是相同的一种基本类型。

同一种泛型可以对应多个版本,但是这些版本实例化后就不兼容了

例如

public void showKeyValue1(Generic<Number> obj){
    Log.d("泛型测试","key value is " + obj.getKey());
}

Generic<Integer> gInteger = new Generic<Integer>(123);
Generic<Number> gNumber = new Generic<Number>(456);

showKeyValue(gNumber);

// showKeyValue这个方法编译器会为我们报错:Generic<java.lang.Integer> 
// cannot be applied to Generic<java.lang.Number>
// showKeyValue(gInteger);

解决方案是:

public void showKeyValue1(Generic<?> obj)

值得注意的是,<?>是实参不是形参。可以想象成Object,<?>是所有类型的父类。

2.4泛型方法
public <T,K> K showKeyName(Generic<T> container){
            ...
            }

注意格式,出现多种泛型要在方法名中加入!

方法名前不加<xx>而参数中有形参泛型的属于普通方法。

如果静态方法要使用泛型的话,必须将静态方法也定义成泛型方法 。

注意下列用例

class GenerateTest<T>{
        public void show_1(T t){
            System.out.println(t.toString());
        }

        //在泛型类中声明了一个泛型方法,使用泛型E,这种泛型E可以为任意类型。可以类型与T相同,也可以不同。
        //由于泛型方法在声明的时候会声明泛型<E>,因此即使在泛型类中并未声明泛型,编译器也能够正确识别泛型方法中识别的泛型。
        public <E> void show_3(E t){
            System.out.println(t.toString());
        }

        //在泛型类中声明了一个泛型方法,使用泛型T,注意这个T是一种全新的类型,可以与泛型类中声明的T不是同一种类型。
        public <T> void show_2(T t){
            System.out.println(t.toString());
        }
    }

    public static void main(String[] args) {
        Apple apple = new Apple();
        Person person = new Person();

        GenerateTest<Fruit> generateTest = new GenerateTest<Fruit>();
        //apple是Fruit的子类,所以这里可以
        generateTest.show_1(apple);
        //编译器会报错,因为泛型类型实参指定的是Fruit,而传入的实参类是Person
        //generateTest.show_1(person);

        //使用这两个方法都可以成功
        generateTest.show_2(apple);
        generateTest.show_2(person);

        //使用这两个方法也都可以成功
        generateTest.show_3(apple);
        generateTest.show_3(person);
    }
}

 

 

 

 

posted @ 2020-12-15 21:45  卡卡北  阅读(144)  评论(1)    收藏  举报