精华内容
下载资源
问答
  • java 泛型上限和下限

    2021-09-06 11:48:31
    首先需要明确的是泛型上限和下限是定义在方法的参数的,如果参数包含一个带有泛型的类,可以用上限或者下限给这个类做相应的限制,如果直接定义在类上会编译错误,比如不会这样定义: 定义泛型类: class ...

    泛型上限:? extends

    泛型下限:? super

    首先需要明确的是泛型上限和下限是定义在方法的参数或者用来声明对象时定义的,如果参数包含一个带有泛型的类,可以用上限或者下限给这个类做相应的限制,如果直接定义在类上会编译错误,比如不会这样定义:

    定义泛型类:

    class GenericTest<T> {
            private T first;
            private T last;
            public GenericTest(T first, T last) {
                this.first = first;
                this.last = last;
            }
    
            public void setFirst(T first) {
                this.first = first;
            }
    
            public void setLast(T last) {
                this.last = last;
            }
    
            public T getFirst() {
                return first;
            }
            public T getLast() {
                return last;
            }
        }

     定义父类Fruit:

    public class Fruit {
        public String name;
    
        public Fruit(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    

    定义两个子类Apple和Banana:

    public class Apple extends Fruit{
    
        public Apple(String name) {
            super(name);
        }
        
    }
    public class Banana extends Fruit{
        public Banana(String name) {
            super(name);
        }
    }

     1. 使用? extends 

    定义方法:

          String testextends(GenericTest<? extends Fruit> p) {
    //        用Fruit接收不会有转型出错的风险,无需强制转型
              Fruit first = p.getFirst();
    
              //需要强制转型,会有类型转换出错的风险
              // 因为像下面的 String result2 = testextends(p2),传进的是GenericTest<Banana> p2,Banana不可以用Apple接收
              // 编译时期就报错可以很好的预防运行时的类型转换出错;
    //          Apple first1 = (Apple) p.getFirst();
    
              //无论setFirst的是Fruit、Apple还是Banana,编译都会报错,因为不确定testextends传进来的GenericTest使用了哪种泛型
              // 比如调用时是testextends(p2),那p.setFirst(new Apple("Apple 3"))是错误的,因为p2使用了GenericTest<Banana>
              // 所以无论setFirst设置的是哪一种数据,都可能会出错,所以有了规定,对于使用了? extends的类,是不可以使用set方法的;
    //          p.setFirst(new Fruit("Fruit 1"));
    //          p.setFirst(new Apple("Apple 3"));
    //          p.setLast(new Banana("Apple 4"));
            return p.getFirst().toString() + p.getLast().toString();
        }

    调用:

            //GenericTest的泛型只能是Fruit或者Fruit的子类,也就是说定义了泛型的上限
            GenericTest<Fruit> p0 = new GenericTest<>(new Apple("Fruit 1"), new Apple("Fruit 2"));
            GenericTest<Apple> p1 = new GenericTest<>(new Apple("Apple 1"), new Apple("Apple 2"));
            GenericTest<Banana> p2 = new GenericTest<>(new Banana("Banana 1"), new Banana("Banana 2"));
            String result0 = testextends(p0);
            String result1 = testextends(p1);
            String result2 = testextends(p2);
            System.out.println("result1 = "+result0);
            System.out.println("result2 = "+result2);
            System.out.println("result2 = "+result2);

    测试结果:

     2.使用? super

    定义BigApple继承Apple,即BigApple是Apple的子类,而Apple是Fruit的子类

    public class BigApple extends Apple{
        public BigApple(String name) {
            super(name);
        }
    }

    定义方法:

    1.? super后面跟的是最小的类型

       //? super BigApple
     String testSuper(GenericTest<? super BigApple> p) {
    //        和? extend一样,调用get方法都需要强制转型,都有转型出错的风险
    //        因为不确定testSuper(GenericTest<? super BigApple> p)被调用时是哪种类型,所以会有转型出错的风险
    //        Fruit first0 = (Fruit) p.getFirst();
    //        Apple first1 = (Apple) p.getFirst();
    //        BigApple first2 = (BigApple) p.getFirst();
    
    //         setFirst的是Fruit或者Apple,编译都会报错
    //         只有传入是BigApple类型才不会报错
    //         因为不确定testSuper(GenericTest<? super BigApple> p)被调用时是哪种类型,
    //         而getFirst()是可以用子类以上的全部类型来接收的,如果setFirst不做规定,很可能会出现转型失败
    //         所以setFirst只能传入BigApple类型
    //          p.setFirst(new Fruit("Fruit 1"));
    //          p.setFirst(new Apple("Apple 1"));
            p.setFirst(new BigApple("BigApple 01"));
            p.setLast(new BigApple("BigApple 02"));
            return p.getFirst().toString() + p.getLast().toString();
        }

    调用:

    //GenericTest的泛型只能是BigApple或者BigApple的父类,也就是说定义了泛型的下限
            GenericTest<Fruit> p00 = new GenericTest<>(new Fruit("Fruit 1"), new Fruit("Fruit 2"));
            GenericTest<Apple> p01 = new GenericTest<>(new Apple("Apple 1"), new Apple("Apple 2"));
            GenericTest<BigApple> p02 = new GenericTest<>(new BigApple("BigApple 1"), new BigApple("BigApple 2"));
            String result00 = testSuper(p00);
            String result01 = testSuper(p01);
            String result02 = testSuper(p02);
            System.out.println("result00 = "+result00);
            System.out.println("result01 = "+result01);
            System.out.println("result02 = "+result02);

     结果:

    2..? super后面跟的是最大的类型

    //? super Fruit
        String testSuper2(GenericTest<? super Fruit> p) {
    //        和? extend一样,调用get方法都需要强制转型,都有转型出错的风险
    //        因为不确定testSuper(GenericTest<? super Fruit> p)被调用时是哪种类型,所以会有转型出错的风险
            Fruit first0 = (Fruit) p.getFirst();
    //         只能传入Fruit及Fruit的子类
            p.setFirst(new Apple("Apple 01"));
            p.setLast(new Banana("Banana 02"));
            p.setLast(new Fruit("Fruit 02"));
            return p.getFirst().toString() + p.getLast().toString();
        }

    调用:

     GenericTest<Fruit> fruitGenericTest = new GenericTest<>(new Fruit("123"),new 
     Fruit("456"));
     System.out.println(testSuper2(fruitGenericTest));

    结果:

    总结:1.使用了?extend的方法,不可以在方法内调用类的set方法,并且调用get方法需要强制转型,有转型出错风险

               2.使用了?super的方法,方法内再调用类的set方法的话,泛型只能是?super后面跟的类或者它的子类,而get方法可以用所有的父类类型来接收,但是也需要强制转型,也会有转型出错的风险

    展开全文
  • Java泛型上限和下限

    2020-11-28 14:18:35
    泛型上限 格式: 类型名称 <? extends 类 > 对象名称 意义: 只能接收该类型及其子类 泛型下限 格式: 类型名称 <? super 类 > 对象名称 意义: 只能接收该类型及其父类型 例子:Object类,String ...

    泛型的上限

    格式: 类型名称 <? extends 类 > 对象名称
    意义: 只能接收该类型及其子类

    泛型的下限

    格式: 类型名称 <? super 类 > 对象名称
    意义: 只能接收该类型及其父类型

    例子:Object类,String 类,Number类,Integer类
    public static void main(String[] args) {
    List list1 = new ArrayList();
    List list2 = new ArrayList();
    List list3 = new ArrayList();
    List list4 = new ArrayList();
    //上限示例
    upperLimit(list1);
    upperLimit(list2);//报错
    upperLimit(list3);
    upperLimit(list4);//报错
    //下限示例
    lowerLimit(list1);//报错
    lowerLimit(list2);//报错
    lowerLimit(list3);
    lowerLimit(list4);
    }

    // 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类
    public static void upperLimit(List<? extends Number> list) {
    }
    
    // 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类
    public static void lowerLimit(List<? super Number> list) {
    }
    
    展开全文
  • 从前面已经知道,ArrayList 集合 ArrayList、ArrayList 集合等不存在继承关系,所有方法的形参不能使用ArrayList,那么该如何实现呢? 方式一:不使用泛型: public class WildcardTest { public static void ...

    1. 通配符基本使用

    假设有这样的需求:定义一个方法,可以遍历任意数据类型的ArrayList集合。

    从前面已经知道,ArrayList 集合和 ArrayList、ArrayList 集合等不存在继承关系,所有方法的形参不能使用ArrayList,那么该如何实现呢?

    方式一:不使用泛型:

    public class WildcardTest {
        public static void main(String[] args) {
            ArrayList<String> list1 = new ArrayList<>();
            list1.add("aaa");
            list1.add("bbb");
            list1.add("ccc");
            getElement(list1);
    
            ArrayList<Integer> list2 = new ArrayList<>();
            list2.add(1);
            list2.add(2);
            list2.add(3);
            getElement(list2);
    
        }
    
        static <E> void getElement(ArrayList list) {
            Iterator iterator = list.iterator();
            while (iterator.hasNext()) {
                Object o = iterator.next();
                System.out.println(o);
            }
        }
    }
    

    集合元素都会转为Object类型

    方式二:使用泛型方法

    public class WildcardTest {
        public static void main(String[] args) {
            ArrayList<String> list1 = new ArrayList<>();
            list1.add("aaa");
            list1.add("bbb");
            list1.add("ccc");
            getElement(list1);
    
            ArrayList<Integer> list2 = new ArrayList<>();
            list2.add(1);
            list2.add(2);
            list2.add(3);
            getElement(list2);
    
        }
    
        static <E> void getElement(ArrayList<E> list) {
            Iterator<E> iterator = list.iterator();
            while (iterator.hasNext()) {
                E e = iterator.next();
                System.out.println(e);
            }
        }
    }
    

    这种方法需要声明泛型形参 T

    方式三:使用类型通配符

    public class WildcardTest {
        public static void main(String[] args) {
            ArrayList<String> list1 = new ArrayList<>();
            list1.add("aaa");
            list1.add("bbb");
            list1.add("ccc");
            getElement(list1);
    
            ArrayList<Integer> list2 = new ArrayList<>();
            list2.add(1);
            list2.add(2);
            list2.add(3);
            getElement(list2);
    
        }
    
        static void getElement(ArrayList<?> list) {
            Iterator<?> iterator = list.iterator();
            while (iterator.hasNext()) {
                Object o = iterator.next();
                System.out.println(o);
            }
        }
    }
    

    为了表示各种泛型List的子类,可以使用类型通配符,类型通配符是一个问号 ?,将一个问号作为类型实参传给List集合,写作:List<?>,List<?>是List<String>List<Object> 等各种泛型List的父类。

    用List<?> 声明的变量可以接收List集合的任意泛型对象,只要在创建List集合子类对象时,<>中写一个引用类型都是可以的。

    List<?> list = new ArrayList<Object>();//合法
    list = new ArrayList<Integer>(); //合法
    list = new ArrayList<String>(); //合法
    

    一旦使用了类型通配符 ?,只能接收数据不能往该集合中存储数据, 唯一的例外是null

    代码示例:

    ArrayList<?> list = new ArrayList<String>();
    list.add(null);
    list.add("aaa"); //编译不通过
    

    使用注意点

    • 注意点1:不能用在泛型方法声明上,返回值类型前面<>不能使用?
    //编译不通过
    public <?> void test(ArrayList<?> list) {
    
    }
    
    • 注意点2:不能用在泛型类的声明上
    //编译不通过
    class GenericClass<?> {
        
    }
    
    • 注意点3:不能用在创建对象上,右边属于创建集合对象,左边是声明泛型集合的引用
    //编译不通过
    Collection<?> collection = new ArrayList<?>();
    

    2. 受限泛型

    在 Java 中默认可以使用任何类型来实例化一个泛型类对象,也可以对泛型类实例的类型进行限制。

    泛型的上限

    • 格式: 类型名称 <? extends T> 对象名称
    • 意义: 只能接收T类型及其子类

    泛型的下限

    • 格式: 类型名称 <? super T> 对象名称
    • 意义: 只能接收T类型及其父类型

    比如:现已知Object类,String 类,Number类,Integer类,其中Number是Integer的父类

    public static void main(String[] args) {
        Collection<Integer> list1 = new ArrayList<>();
        Collection<String> list2 = new ArrayList<>();
        Collection<Number> list3 = new ArrayList<>();
        Collection<Object> list4 = new ArrayList<>();
        
        getElement1(list1);
        getElement1(list2);//报错
        getElement1(list3);
        getElement1(list4);//报错
      
        getElement2(list1);//报错
        getElement2(list2);//报错
        getElement2(list3);
        getElement2(list4);
      
    }
    // 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类
    public static void getElement1(Collection<? extends Number> coll){}
    // 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类
    public static void getElement2(Collection<? super Number> coll){}
    

    受限泛型集合数据的读取和写入

    public class WildcardTest {
        public static void main(String[] args) {
            ArrayList<Integer> list1 = new ArrayList<>();
            list1.add(5);
            list1.add(12);
            test1(list1);
    
            ArrayList<Number> list2 = new ArrayList<>();
            list2.add(2.5);
            list2.add(1.5f);
            list2.add(10);
            test2(list2);
        }
    
        static void test1(ArrayList<? extends Number> list) {
            list.add(null);
            //list.add(10); //报错
            for (Number number : list) {
                System.out.println(number);
            }
        }
    
        static void test2(ArrayList<? super Number> list) {
            list.add(12.5);
            list.add(20);
            for (Object o : list) {
                System.out.println(o);
            }
        }
    }
    

    <? extends T> 只能用来读取数据,不能向集合中存储数据,不能使用 add 方法;<? super T> 既能读取数据(需声明为 Object 类型),也能存储数据。

    频繁往外读取内容的,适合用 <? extends T > ;经常往集合里插入数据的,适合用 <? super T>

    展开全文
  • 设置泛型对象的上限使用extends,表示参数类型只能是该类型或该类型的子类: 声明对象:类名<? extends 类> 对象名 定义类:类名<泛型标签 extends 类>{} 设置泛型对象的下限使用super,表示参数类型...

    设置泛型对象的上限使用extends,表示参数类型只能是该类型或该类型的子类:

    声明对象:类名<? extends 类> 对象名

    定义类:类名<泛型标签 extends 类>{}

    设置泛型对象的下限使用super,表示参数类型只能是该类型或该类型的父类:

    声明对象:类名<? super 类> 对象名称

    定义类:类名<泛型标签 extends类>{}

     

    public static void  show(List<? extends Number> l){

     

    }

    public static void  show(List<? super String> l){

     

    }

    public static void show(List<? extends Number> l){}

    public static void show(List<? super String> l){}

     

    泛型的上限

     

    public static void main(String[] args) {

            Person<Integer> p1 = new Person<>();

            p1.setVal(99);

            Person<Double> p2 = new Person<>();

            p2.setVal(3.14);

            Person<String> p3 = new Person<>();

            p3.setVal("007");

            show(p1);//√

            show(p2);//√

            show(p3);//×

        }

        public static void show(Person<? extends Number> p){//此处限定了Person的参数类型只能是Number或者是其子类,而String并不属于Number。

            System.out.println(p.getVal());

        }

     

    泛型的下限

     

        public static void main(String[] args) {

            Person<Integer> p1 = new Person<>();

            p1.setVal(99);//Integer

            Person<Double> p2 = new Person<>();

            p2.setVal(3.14);//Double

           

            Person<String> p3 = new Person<>();

            p3.setVal("007");//String

            Person<Object> p4 = new Person<>();

            p4.setVal(new Object());//Object

     

            show(p1);//×

            show(p2);//×

            show(p3);//√

            show(p4);//√

        }

        public static void show(Person<? super String> p){

            System.out.println(p.getVal());

        }

     

    很好的例子!

    package generic;

     

    import java.util.ArrayList;

    import java.util.List;

     

    public class GenericDemo3 {

        public static void main(String[] args) {

            //因为show方法是用List<?>通配符接收的,所以可以是任意类型!

            List<String> l1 = new ArrayList<>();//new ArrayList<String>()

            show(l1);

            List<Double> l2 = new ArrayList<>();

            show(l2);

            List<Number> l3 = new ArrayList<>();

            show(l3); 

            List<Object> l4 = new ArrayList<>();

            show(l4);

            //使用up方法的话接收类型为Number或者其子类

            //up(l1);//错误,因为up方法接收类型为Number或者其子类,l1(String)不符合!

            up(l2);

            up(l3);

            //使用down方法的话接收类型为Number或者其父类

            //down(l2);error

            down(l3);

            down(l4);

        }

    public static void down(List<? super Number> l){

           

            for (Object object : l) {

                System.out.println(object);

            }

        }

    public static void up(List<? extends Number> l){

           

            for (Object object : l) {

                System.out.println(object);

            }

        }

        public static void show(List<?> l){

           

            for (Object object : l) {

                System.out.println(object);

            }

        }

    }

    转载于:https://www.cnblogs.com/fanweisheng/p/11136181.html

    展开全文
  • 泛型 上限,下限

    千次阅读 2018-12-11 09:26:49
    1.回顾泛型类  泛型类:具有一个或多个泛型变量的类被称之为泛型类。 class ClassGenericity&amp;amp;lt;T&amp;amp;gt; { //在类里面可以直接使用T的类型 T aa; public void test11(T bb) { //...
  • 可以通过泛型上限和下限的配置实现更加严格的类范围定义。 【类或方法】设置泛型的上限(? extends 类):只能够使用当前类或当前类的子类设置泛型类型。例如:? extends Number可以设置Number或Number子类(如:...
  • 泛型上限下限所操作的运行时对象类型,永远是所给类型的子类型; (1)上限保证返回值类型、对象能够调用的方法一定正确,但是编译器不会知道现在拿到的元素具体是哪一个子类型,既然不知道具体子类型,那也就无法...
  • 泛型的上下限我们都知道,但是泛型的可读可写模式却是第一次听说,在这里记录一下。 泛型上限 extends 上限 Person or Person的所有子类 都可以, 最高的类型只能是Person,把最高的类型给限制住了 泛型下限 ...
  • java 泛型上限下限 设置泛型对象的上限使用extends,表示参数类型只能是该类型或该类型的子类: 声明对象:类名<? extends 类> 对象名 定义类:类名<泛型标签 extends 类>{} 设置泛型对象的下限使用...
  • 程序代码如下: 定义了3个不同类型的ArrayList,...方法n3:把数值型的集合对象获取过来进行遍历---泛型上限 格式:泛型上限:? extends 类/接口 可以接收类/接口以及子类/子接口 方法n4:把String 当做下...
  • extends:泛型上限 1.一般用于限制操作 2.不能使用者添加数据操作上,一般都是读取操作 3.规则 List---->List List---->List List------> 不能存放 List因为它等同于List super:泛型下限>= 即父类 1.一般用于...
  • java中类的继承extends和super我们平常经常用到,但是还有上下限和读写模式需要了解,二者是不一样的东西 先定义FatherClass最为父类,ChildClass继承自FatherClass,SonClass继承自ChildClass class FatherClass ...
  • import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import cn.itcast.p2.bean.Person; import cn.itcast.p2.bean.Student; import cn.itcast.p2.bean.Worker; public class ...
  • v一.程序中无形之中用到的泛型 import java.util.*; class Person implements Comparable<Person>{ String name; int age; Person(){ name = ""; age = 0; } Person(...
  • 为什么containsAll的泛型是collection,,不能是collection<E>
  • java 泛型下限

    2019-11-13 08:28:53
    java泛型下限 作用:使用泛型上下限可以限制可使用的数据类型范围 ********************************************* 泛型上下限使用 类的泛型上限:T只能为Number或者Number的子类 接口的泛型使用类似 ...
  • 本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 情花打雪 即可关注,每个工作日都有文章更新。 泛型方法 所有泛型方法声明都有...一个泛型参数,也被称为一个类型变量,是用于指定一个泛型
  • ①为什么要使用泛型通配符 请参考这篇随笔的下半部分 https://www.cnblogs.com/baxianhua/p/9194369.html ②通配符上限和通配符下限的简单解释 <? extends T>上限通配,表示?是T的一个未知子类。 <?...
  • 泛型上限:此时的 泛型?必须是 E的本身或者E的子类 ? extends E 泛型下限:此时的泛型?必须是E的本身或者父类 ? supper E 如demo: publice static void getElement1(Collection<? extends Number&...
  • Java泛型4—泛型的上限和下限

    千次阅读 多人点赞 2011-11-27 20:37:58
    在写程序的时候,我们希望某一个函数接收的参数,有一个范围的限制,这时候我们就可以考虑使用泛型上限和下限去解决。我们先看一段代码,然后再去详细解释。 class Point { private T x; private T y; ...
  • java泛型下限

    2019-01-20 00:45:28
    v前言:  java的泛型上下限不是很好理解,尤其像我这种菜鸡。反反复复看了好几遍了...,真是... v一、简单的继承体系 ...v二、泛型上限(extends 关键字) public static void upperB...
  • 定义使用含有泛型的类 /* 说明:泛型是一个未知的数据类型,当我们不确定使用什么数据类型的时候,可以使用泛型; 简单来说,就是在定义类或类的成员变量的类型的时候不把类型写死了。在创建对象的时候,想用啥...
  • 如:限定了T的取值上限只能取Dog或Dog的子类 public class Zookeeper { //表示管理员管理的动物 private T animal; public T getAnimal() { return animal; } public void setAnimal(T animal) { this.animal...
  • java泛型上限下限

    2011-04-14 15:27:00
    java泛型实现的擦拭法解释,编译后会是如下的伪代码:   public void lowerBound(List list) { Timestamp now = new Timestamp(System.currentTimeMillis()); list.add(now); Timestamp time = ...
  • 泛型限行上限和下限

    2016-07-18 22:04:50
    泛型 泛型的作用是给我们用来判断类型的... java代码 无泛型。 定义了两个javabean类。里面有String name public class Demo{ List list = new LinkedList(); public static void main(String[] args){ lis
  • 泛型通配符<?> 泛型继承 list1与list2之间根本没有关系,它们是相互独立的. ArrayList<Object> list1 = null; ArrayList<String> list2 = null; list2 = list1; 编译不通过 list1 = list2; ...
  • 【Java基础知识 11】java泛型方法的定义使用

    千次阅读 多人点赞 2020-06-17 16:47:31
    Java泛型是J2 SE1.5中引入的一个新特性,其本质是参数化类型,也就是说所操作的数据类型被指定为一个参数(type parameter)这种参数类型可以用在类、接口方法的创建中,分别称为泛型类、泛型接口、泛型方法。...
  • 泛型上限限定:? extends E 代表使用的泛型只能是E的子类或者本身 泛型下限限定:? super E 代表使用的泛型只能是E的父类或者本省 先看继承关系 Integer extends Number extends Object String extengs Object...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,859
精华内容 3,143
关键字:

java泛型的上限和下限

java 订阅