栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java 泛型与通配符

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java 泛型与通配符

泛型

        介绍不多赘述,泛型在使用的时候通常用一个大写字母来标识,但是如果你愿意,你可以用任何字母来使用,比如

//T是泛型
public  void fun1(List list){
    T t = list.get(0);
}
//abc也是泛型
public  void fun2(List list){
    abc s = list.get(0);
}

        那么为什么可以呢?因为在函数前面有泛型定义。

        在使用泛型前,要先用尖括号来让编译器知道此处的符号是一个泛型,在上面的fun1和fun2中,和分别是两个函数的泛型定义。泛型定义的位置也是有讲究的,只能放在函数返回值之前,如:

 void fun1(T t){
}

public  void fun2(T t){
}

public static  void fun3(T t){
}

public static final  void fun4(T t){
}

public abstract  void fun5(T t);

        泛型的定义除了在单个函数上,也能定义在类上和接口上,如:

interface TestInterface{
    void impl(T t);
}

class TestClass{
    T t;
    void fun(T t){
    }
}

        以上的泛型能在函数中直接使用,是因为在定义接口和类的时候就已经声明了。

上界

        想象一下在泛型出现之前的java世界,如果一个函数需要接收一个类及其子类的情况,我们一般只能在参数定义的时候用这个类作为参数,并且在函数体中进行强转成相应的子类再进行操作,这一整个流程在编译期不会有任何的异常,但是在运行期可能会出现类型转换异常的问题。

        但是有了泛型,我们就能避免这个问题,因为在调用的时候就能够确定具体是用的对象类型。

        泛型的上界定义在泛型声明的时候,如,上界可以是类,也可以是接口,且可以设置多重上界,如,当设置多重上界时,至多只能有一个类上界,且类上界只能放在第一个位置。如:

    public  void fun(T t){
        //编译成功
    }

    public  void fun(T t){
        //两个上界都是对象,编译失败
    }

    public  void fun(T t){
        //类不是第一个上界,编译失败
    }

    public  void fun(T t){
        //编译成功
    }

        泛型的传参类型不能混淆,比如String虽然是Object的子类,但是List不是List的子类。如:

public class Test{

    public static void fun(List list){

    }

    public static void main(String[] main){
        List stringList = new ArrayList<>();
        List objectList = new ArrayList<>();
        fun(stringList);//编译不通过
        fun(objectList);//编译通过
    }

}
 

        但是参数定义中设置上界,就能解决这个问题,即List是List的资关系,如:

public class Test{

    public static  void fun(List list){

    }

    public static void main(String[] main){
        List stringList = new ArrayList<>();
        List objectList = new ArrayList<>();
        fun(stringList);//编译通过  
        fun(objectList);//编译通过
    }

} 
形参 

        当泛型作为某个形参定义时,在函数体内的使用是不确定具体类型的,如:

public static  void fun(List list){
    list.add(new Object());//编译不通过
    list.add("字符串");//编译不通过
    list.add(null);//编译通过

    String s = list.get(0);//编译通过
}

        以上的list中的对象,虽然我们知道一定是String或String的子类,但是这个是用来约束函数入参的,上层调用处传参可以是String的子类,可能是List,在函数体中,我们并不能确定具体的T是什么类型,所以不能往里面添加任何对象,唯独null可以,这个也可以理解。而为什么可以调用get呢,因为list中的数据约束了必须是String的子类,即可以用String来接收。

通配符

        通配符和泛型在一起看的时候,很容易搞混淆,所以先彻底认识泛型再来理解通配符会更轻松。可以认为通配符是泛型的约束

        通配符不需要额外声明,用在函数泛型参数的定义,不仅跟泛型一样可以设置上界,还可以设置下界,如:

public class Test{

    public static void fun1(List list){
        //无界限
    }

    public static void fun2(List list){
        //设置上界
    }

    public static void fun3(List list){
        //设置下界
    }

}

        通配符上界与泛型上界的用法及注意事项基本一致,但是只支持单个上界。

        通配符的下界限定与上界限定对函数体中入参的使用会带来不一样的影响。

public static void fun3(List list){
    list.add("字符串");//编译通过
    String s = list.get(0);//编译不通过
    }

        以上函数中,因为约束了传进来的list的数据必须是String的父类,所以往list中添加数据的时候,只要符合是String或者String的子类,都能够接收。而不能取,也是因为?有可能是更上层的父类对象,比如List,所以在函数体中无法确定具体的类来接收。

        一般来说可以这么记,上界只能取,下界只能存。

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号