JavaSE笔记-泛型

定义带泛型的类

public class Cat<T> {
    //可以用T定义实例变量
    private T name;
    //可以用T定义形参
  //构造器没有<> public Cat(T name){ this.name = name; } //可以作为返回值 public T forget(){ System.out.println("我叫啥来着?"); return this.name; } public static void main(String[] args){ Cat<String> cat = new Cat<>("阿猫"); System.out.println(cat.forget()); } }

构造泛型对象可省略类型参数

List<String> list = new ArrayList<>();
//等价于List<String> list = new ArrayList<String>();
//编译器会自己推出后边的类型是String

泛型方法

1.泛型方法可以在普通类或者泛型类

2.类型参数放在修饰符之后,返回值之前

public static <T> void test();

不能在静态变量或者静态方法中使用泛型变量,不能实例化泛型变量

因为泛型是要在对象创建的时候才知道是什么类型的,而对象创建的代码执行先后顺序是static的部分,然后才是构造函数等等。所以在对象初始化之前static的部分已经执行了,如果你在静态部分引用的泛型,那么毫无疑问虚拟机根本不知道是什么东西,因为这个时候类还没有初始化。因此在静态方法、数据域或初始化语句中,为了类而引用泛型类型参数是非法的

public class Entry<k,v>{
//以下2种方式是错误的
private static V value;

public static void setValue(V value){};

}

泛型不同类型相同

        List<String> list1 = new ArrayList<>();
        List<Integer> list2 = new ArrayList<>();
        System.out.println(list1.getClass() == list2.getClass());

上面的代码返回值是true,因此list1和list2都是List类型,与泛型不泛型无关。

类型通配符(?)

    public void getFamaleCat(List<?> list){
        for(int i=0;i<list.size();i++){
            System.out.println(list.get(i));
        }
    }

1.当不确定传入的类型时,使用类型通配符?,不要使用List<Object>,当你想要传入一个List<String>作为参数时,程序编译不会通过,而使用?则可以通过

2.当确定类型是某个类的子类型时,使用<? extends Father>,这时传入的类型只能是Father及其子类

public class Util{
    /*    
    方法实现将src中的数据复制到dest中
    那么src中的数据类型只能是dest中数据类型的子类型
    比如:src中类型是Integer,dest中可以是Integer,Number,Object   
     */
    public static <T> void copy(List<T> dest,List<? extends T> src){
        for(T d : src){
            dest.add(d);
        }
    }

    public static void main(String[] args){
        List<Integer> src = new ArrayList<>();
        src.add(1);
        src.add(2);
        List<Number> dest = new ArrayList<>();
        //泛型的匹配方式是直接把参数拿过来和T比
     //因为dest的类型是Number,所以推出T是Number,所以dest集合中的类型都是Number
        copy(dest,src);
    }
}

3.当确定类型时某个类的父类型时,使用<? super son>,这时传入的类型只能是son及son的父类

上面的例子最后dest中的数据类型都是Number,但是我们清楚的知道其实dest中每个数据的类型都是Integer,使用<? super son>改造

public class Util{
    public static <T> void copy(List<? super T> dest,List<T> src){
        for(T d : src){
            dest.add(d);
        }
    }

    public static void main(String[] args){
        List<Integer> src = new ArrayList<>();
        src.add(1);
        src.add(2);
        List<Number> dest = new ArrayList<>();
        //dest集合中元素都是Integer类型
        copy(dest,src);
    }
}

 4.泛型可以重载,不要包括2个意思相同的泛型方法

 public static <T> void copy(List<? super T> dest,List<T> src);
 public static <T> void copy(List<T> dest,List<? extends T> src);

如果我们把这2个方法定义在同一个类里,main调用copy,编译器不能确定到底调用哪个方法

    public static void main(String[] args){
        List<Integer> src = new ArrayList<>();
        src.add(1);
        src.add(2);
        List<Number> dest = new ArrayList<>();
        copy(dest,src);
    }

类型擦除

所有的泛型类型会被编译成一个原始类型

这样并不会不安全

例如:List<String>,因为泛型会在编译的时候起作用,实际上你传入集合的所用元素都只能是String类型

public class Cat<Object> {
    private Object name;

    public Cat(Object name){
        this.name = name;
    }

    public Object forget(){
        System.out.println("我叫啥来着?");
        return this.name;
    }
}

转载于:https://www.cnblogs.com/vshen999/p/8361453.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值