Java中泛型的通配符(2022.5.15)

泛型中的通配符

在没有使用通配符时:

    package zhai.Fx;
    
    import java.util.List;
    
    public class FxDemo7 {
        // 在不适用通配符的编写方法
        public void a(List<Object> list) {
    
        }
    
        public void a(List<String> list) {
            // 这时候虽然重载了 a 方法参数是不一样,但是还会报错
            // 因为在泛型标签中不存在继承关系 它 Object和String只是并列关系
        }
    
        public void a(List<Integer> list) {
            // 它这样其实就不是重载方法,因为在底层它们是一样的,都是把List接口作为参数进行传入
            // 这样的创建方法只是重复定义方法
        }
    }

使用通配符后:<?>

    package zhai.Fx;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class FxDemo8 {
        public static void main(String[] args) {
            // 使用通配符后的编写
            List<Object> list1 = new ArrayList<>();
            List<String> list2 = new ArrayList<>();
            List<Integer> list3 = new ArrayList<>();
            List<?> list = null;
            list = list1;
            list = list2;
            list = list3;
        }
    }

案例:如:A和B是继承关系,G <A>和G<B> 并不是继承关系,只是并列关系;
注意:加入通配符 <?> 后,G<?>就变成了G<A>和G<B>的父类。

    package zhai.Fx;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class FxDemo7 {
        // 在不适用通配符的编写方法
    //    public void a(List<Object> list) {
    //
    //    }
    //
    //    public void a(List<String> list) {
    //        // 这时候虽然重载了 a 方法参数是不一样,但是还会报错
    //        // 因为在泛型标签中不存在继承关系 它 Object和String只是并列关系
    //    }
    //
    //    public void a(List<Integer> list) {
    //        // 它这样其实就不是重载方法,因为在底层它们是一样的,都是把List接口作为参数进行传入
    //        // 这样的创建方法只是重复定义方法
    //    }
        class Test{
            public void a(List<?> list){
    			// 遍历使用 Object 进行接收
                for (Object o:list) {
                    System.out.println(o);
                }
                Test test = new Test();
          	// 使用当前类调用当前类中的方法
          // 使用<?> 通配符后,此时这个<?>就相当于是整个泛型参数的父类,可以传入任何类型的泛型参数
                test.a(new ArrayList<Integer>()); 
                test.a(new ArrayList<String>());
                test.a(new ArrayList<Double>());
            }
        }
    }

注意:使用通配符<?>后,其实就是相当于给整个泛型参数加上一个父类,既然是父子类关系后,就可以定义任何参数类型来进行使用。

遍历:就是使用通配符后的遍历,可以直接拿Object类型进行接收,<?> 不能为接收类型。

使用通配符进行写入和读取操作:

    package zhai.Fx;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class FxDemo7 {
        // 在不适用通配符的编写方法
    //    public void a(List<Object> list) {
    //
    //    }
    //
    //    public void a(List<String> list) {
    //        // 这时候虽然重载了 a 方法参数是不一样,但是还会报错
    //        // 因为在泛型标签中不存在继承关系 它 Object和String只是并列关系
    //    }
    //
    //    public void a(List<Integer> list) {
    //        // 它这样其实就不是重载方法,因为在底层它们是一样的,都是把List接口作为参数进行传入
    //        // 这样的创建方法只是重复定义方法
    //    }
        class Test{
            public void a(List<?> list){
                // 写入数据
    //            list.add("abc");   ---> 错误,不能随意添加数据
                // 读取数据
                Object o1 = list.get(0); // 读取的时候,因为不知道是什么类型的数据,所以使用Object类型来进行接收数据
                for (Object o:list) {
                    System.out.println(o);
                }
                Test test = new Test();
                // 使用当前类调用当前类中的方法
                // 使用<?> 通配符后,此时这个<?>就相当于是整个泛型参数的父类,可以传入任何类型的泛型参数
                test.a(new ArrayList<Integer>());
                test.a(new ArrayList<String>());
                test.a(new ArrayList<Double>());
            }
        }
    }

泛型受限:

    package zhai.Fx;
    
    import java.util.ArrayList;
    import java.util.List;
    
    // 测试类
    public class FxDemo9 {
        public static void main(String[] args) {
            // 这个泛型参数中,并没有父子级关系,而是并列关系
            List<Object> a = new ArrayList<>();
            List<Person> b = new ArrayList<>();
            List<Student> c = new ArrayList<>();
            // 受限:
            /*
             * 上限
             */
            List<? extends Person> list = null; // 使用?extends 父类时为上限
    //        list = a;   ---> 错误代码 使用 extends 就不能使用父类以上的祖父类参数类型
            list = b;  // 这是父类不报错
            list = c;  // 这是子类也不报错
    
            
            /*
             * 下限
             */
            List<? super Person> list1 = null;
            list1 = a;
            list1 = b;
    //        list1 = c;  ---> 错误,因为使用super的话就是只能放入父类的参数类型
             
        }
    }
    
    // 父类
    class Person {
    
    }
    
    // 子类
    class Student extends Person {
    
    }

上下限总结:

  • 上限:参数中使用<? extends 父类>时,就为上限,不能传入父类以上的参数,只能传入父类本身以及子类。

  • 下限:参数中使用<? super 父类>时,就为下限,不能传入父类一下的参数,只能传入父类以上的祖父类等…

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值