• 泛型-通配符,受限泛型(上限和下限)


    掌握通配符“?”的使用。

    掌握受限泛型的设置。

    掌握泛型与子类继承的限制。

    具体内容

    1.1匹配任意类型的通配符

      在开发中对象的引用传递(向上向下传递)是最常见的,但是,在泛型的操作中,在进行引用传递的时候泛型类型必须匹配才可以传递,否则不能传递。

      例如,如下没有进行泛型类型匹配,一个是String,一个是Object类型。

    package Thread1;
    class Info<T>{
        private T var ;        // 定义泛型变量
        public void setVar(T var){
            this.var = var ;
        }
        public T getVar(){
            return this.var ;
        }
        public String toString(){    // 直接打印
            return this.var.toString() ;
        }
    };
    public class demo1{
        public static void main(String args[]){
            Info<String> i = new Info<String>() ;        // 使用String为泛型类型
            i.setVar("MLDN") ;                            // 设置内容
            fun(i) ;                    //把String泛型类型的i对象传递给Object泛型类型的temp。
        }
        public static void fun(Info<Object> temp){        // 接收Object泛型类型的Info对象
            System.out.println("内容:" + temp) ;
        }
    };

      编译发生错误。

    Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
        The method fun(Info<Object>) in the type demo1 is not applicable for the arguments (Info<String>)
    
        at Thread1.demo1.main(demo1.java:18)

      泛型对象进行引用传递的时候,类型必须一致,如果非要传递,则可以将fun方法中Info参数的泛型取消掉(变成 void fun(Info temp)。、

      以上确实改进了功能,但是似乎不是很妥当,毕竟之前指定过泛型。

      以上程序在fun()方法中使用"Info<?>"的代码形式,表示可以使用任意的泛型类型对象,这样的话fun()方法定义就合理了,但是使用以上方法也有需要注意的地方,

    即:如果使用“?“接收泛型对象的时候,则不能设置被泛型指定的内容

    class Info<T>{
        private T var ;        // 定义泛型变量
        public void setVar(T var){
            this.var = var ;
        }
        public T getVar(){
            return this.var ;
        }
        public String toString(){    // 直接打印
            return this.var.toString() ;
        }
    };
    public class GenericsDemo14{
        public static void main(String args[]){
            Info<String> i = new Info<String>() ;        // 使用String为泛型类型
            i.setVar("MLDN") ;                            // 设置内容
            fun(i) ;
        }
        public static void fun(Info<?> temp){        // 可以接收任意的泛型对象
            System.out.println("内容:" + temp) ;
        }
    };

      如果使用”?“意味着可以接收任意的内容,但是此内容无法直接使得用”?“修饰的泛型的对象进行修改。如下就会出问题:

    package Thread1;
    class Info<T>{
        private T var ;        // 定义泛型变量
        public void setVar(T var){
            this.var = var ;
        }
        public T getVar(){
            return this.var ;
        }
        public String toString(){    // 直接打印
            return this.var.toString() ;
        }
    };
    public class demo1{
        public static void main(String args[]){
            Info<?> i = new Info<String>() ;        // 使用String为泛型类型
            i.setVar("MLDN") ;                            // 设置内容,这里会出错,因为”?“通配符修饰的对象只能接收,不能修改,也就是不能设置。
        }
    };

      运行结果:

    Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
        The method setVar(capture#1-of ?) in the type Info<capture#1-of ?> is not applicable for the arguments (String)
    
        at Thread1.demo1.main(demo1.java:17)

      在使用”?“只能接收,不能修改。

    1.2受限泛型

      之前设置泛型的时候,实际上是可以任意设置的,只要是类就可以设置。但是在JAVA的泛型中可以指定一个泛型的上限和下限。

      

    设置上限

    class Info<T>{
        private T var ;        // 定义泛型变量
        public void setVar(T var){
            this.var = var ;
        }
        public T getVar(){
            return this.var ;
        }
        public String toString(){    // 直接打印
            return this.var.toString() ;
        }
    };
    public class GenericsDemo17{
        public static void main(String args[]){
            Info<Integer> i1 = new Info<Integer>() ;        // 声明Integer的泛型对象
            Info<Float> i2 = new Info<Float>() ;            // 声明Float的泛型对象
            i1.setVar(30) ;                                    // 设置整数,自动装箱
            i2.setVar(30.1f) ;                                // 设置小数,自动装箱
            fun(i1) ;
            fun(i2) ;
        }
        public static void fun(Info<? extends Number> temp){    // 只能接收Number及其Number的子类
            System.out.print(temp + "、") ;
        }
    };

      运行成功。但是,如果传人的泛型类型为String的话就不行,因为String不是Number子类。

      在类中使用泛型上限。

    package Thread1;
    class Info<T extends Number>{    // 此处泛型只能是数字类型
        private T var ;        // 定义泛型变量
        public void setVar(T var){
            this.var = var ;
        }
        public T getVar(){
            return this.var ;
        }
        public String toString(){    // 直接打印
            return this.var.toString() ;
        }
    };
    public class demo1{
        public static void main(String args[]){
            Info<Integer> i1 = new Info<Integer>() ;        // 声明Integer的泛型对象
        }
    };

      如果在使用Info的时候设置成String类型,则编译的时候将会出现错误(String不是Number子类):

    设置下限

      

    class Info<T>{
        private T var ;        // 定义泛型变量
        public void setVar(T var){
            this.var = var ;
        }
        public T getVar(){
            return this.var ;
        }
        public String toString(){    // 直接打印
            return this.var.toString() ;
        }
    };
    public class GenericsDemo21{
        public static void main(String args[]){
            Info<String> i1 = new Info<String>() ;        // 声明String的泛型对象
            Info<Object> i2 = new Info<Object>() ;        // 声明Object的泛型对象
            i1.setVar("hello") ;
            i2.setVar(new Object()) ;
            fun(i1) ;
            fun(i2) ;
        }
        public static void fun(Info<? super String> temp){    // 只能接收String或Object类型的泛型,String类的父类只有Object类
            System.out.print(temp + "、") ;
        }
    };

      Object类和String类都是String的父类,所有运行成功,但是如果此时用Integer则会出错,因为integer并不是String父类。

    1.3解释:泛型与子类继承的限制。

      一个类的子类可以通过对象多态性,为其父类实例化,但是在泛型操作中,子类的泛型类型是无法使用父类的泛型类型接收的。例如:Info<String>不能使用Info<Object>

    接收。

      例如,以下肯定出错。

    class Info<T>{
        private T var ;        // 定义泛型变量
        public void setVar(T var){
            this.var = var ;
        }
        public T getVar(){
            return this.var ;
        }
        public String toString(){    // 直接打印
            return this.var.toString() ;
        }
    };
    public class GenericsDemo23{
        public static void main(String args[]){
            Info<String> i1 = new Info<String>() ;        // 泛型类型为String
            Info<Object> i2 = null ;
            i2 = i1 ;                  //这里因为对象泛型类型不同,而出错。
        }
    };

      Object肯定比String大。

    总结

      1)使用?可以接收任意泛型对象。

      2)泛型的上限:?extends 类型。

      3)泛型的下限:?super 类型。相对了解一些就可。

      4)了解为什么泛型子类之间的继承无法直接转换的原因。

  • 相关阅读:
    C++ MFC学习 (二)
    C++ MFC字符转换
    C++ MFC学习 (一)
    Windows.h 文件学习
    Git 学习
    Git 学习
    php压缩文件夹并下载到本地
    接口类型无限级分类
    mysql 共享锁 排它锁
    docker基础命令
  • 原文地址:https://www.cnblogs.com/alsf/p/5690052.html
Copyright © 2020-2023  润新知