Java泛型全面解析

Java中的泛型可以说让新手一头雾水,而且多个泛型同时使用会让人一脸懵逼。现在就来看看各个情况吧。

 

1.最简单的泛型举例

 

public class TTest<T> {

    public void test(){
        List<T> list = new ArrayList<>();
    }

    public static void main(String args[]){
        TTest<String> t = new TTest<String>();
        t.test();
    }

}

这个就是最简单的泛型,可以看到在TTest类定义的地方写了一个<T>,这就是泛型的定义,类里面方法(静态方法除外),都可以使用这个类,具体是什么意思呢?

可以在main()方法里面看到,TTest<String> t ,这里就是把<String>传入了进去,test()方法里面的List<T> t = new ArrayList<>();其实就变成了List<String> t = new ArrayList<>();泛型的主要意义,也就是为了限定或者给定某个类型。当然泛型的这个<T>名字可以随便取比如<U>,<X>等等。

2.多个泛型的使用

public class TTest<T, U> {

    public void test(){
        List<T> tList = new ArrayList<>();
        List<U> uList = new ArrayList<>();
    }

    public static void main(String args[]){
        TTest<String, Integer> t = new TTest<>();
        t.test();
    }

}

这里使用了两个泛型<T, U>,在传入的时候,写入TTest<String,Integer> t 然后在类里面就可以去轻松愉快的使用了,两个泛型也是比较常见的,比如HashMap<K, V>。

3.泛型的继承

public class TTest<T extends TTest.Base> {

    public static class Base{

    }

    public static class Child extends Base{

    }

    public void test(){
        List<T> tList = new ArrayList<>();
    }

    public static void main(String args[]){
        TTest<String> st = new TTest<>();//编译错误
        TTest<Base> bt = new TTest<>();//编译正确
        TTest<Child> ct = new TTest<>();//编译正确
    }

}


这里可以看到<T extends TTest.Base>也就是说,我传入的泛型是要继承自Base类的,所以在new TTest的时候可以看到,如果写了TTest<String>就会编译错误,因为String不是继承自Base的。写成TTest<Base>或者TTest<Child>都是正确的,因为Child是继承自Base的。

 

4.在静态方法中泛型的使用

 

public class TTest<T> {

    public static <M> List<M> get(){
        Class<M> m;//编译正确
        Class<T> t;//编译错误
        return null;
    }

    public void test(){
        TTest<Integer>.<String>get();//编译错误,因为调用静态方法不需要写类的泛型
        TTest.<String>get();//编译正确
    }
}

 

因为静态方法其实是属于类的,不属于对象,所以普通定义的泛型,在静态方法里面是无法使用的,会编译错误,比如在上面代码中get()方法里面的Class<T>就会编译错误。

 

在如果要在静态方法中使用的泛型的话,需要重新定义,在static关键字和返回类型中间添加泛型<M>,然后在返回类型或者方法体中,就可以去使用这个泛型了。在使用的时候,就用TTest.<String>get();去调用,public static <M> List<M>get()方法就会变成public static List<String>get(),方法体里面的Class<M>也就变成了Class<String>,其实就是把<M>替换成了<String>。

5.普通方法中使用泛型

@Nullable
public final <T extends View> T findViewById(@IdRes int id) {
        if (id == NO_ID) {
            return null;
        }
        return findViewTraversal(id);
}

protected <T extends View> T findViewTraversal(@IdRes int id) {
        if (id == mID) {
            return (T) this;
        }
        return null;
}

这里是Android源码中的findViewById()方法,方法中在返回类型T前定义了<T>,这样就可以在最后return时,把类型强制转化为T。这样写的好处是,不需要每次在调用findViewById()后去强制转化为TextView或ImageView了。

小节:

前面讲到了好几种泛型的使用场景,使用泛型的好处就是,你知道了传入的类型,就可以在方法定义时直接转为想要的类型,而不需要方法的调用者再去强转。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值