当前位置: 首页 > news >正文

环境设计专业网站网站服务器和ftp空间

环境设计专业网站,网站服务器和ftp空间,计算机编程网课,电气建设网站文章目录 泛型的传参若函数里的参数使用基类接受所有的派生类,怎么做? 类型通配符的上限类型通配符的下限 泛型的传参 注意 若类 Base 是类 Derived 的基类(父类),那么数组类型 Base[] 是 Derived[] 的基类&#xff0…

文章目录

    • 泛型的传参
      • 若函数里的参数使用基类接受所有的派生类,怎么做?
    • 类型通配符的上限
    • 类型通配符的下限

泛型的传参

注意
若类 Base 是类 Derived 的基类(父类),那么数组类型 Base[] 是 Derived[] 的基类(父类)。但是集合类型 List<Base> 不是 List<Derived> 的基类(父类)。

若函数里的参数使用基类接受所有的派生类,怎么做?

例如:函数里的参数要接受所有的List类,包括 List<Integer>, List<String> 等。

public class Test01 {public static void main(String[] args) {ArrayList<String> strList = new ArrayList<String>();strList.add("good");strList.add("man");strList.add("helo");testGenericParameter(strList);}
// 形参类型 可以使用  List (会有警告),List<?> (推荐,没有警告), 不可以使用 List<Object>private static void testGenericParameter(List<?> list) {for (int i = 0; i < list.size(); i++) {System.out.println(list.get(i));}}
}	

例如:Shape 是基类,Circle、Rectangle 是派生类
只想要接受所有Shape派生类的入参

//  ? extends Shape   表示 所有从Shape派生出的类
void testGenericParameter(List<? extends Shape> list) {}
  • ? extends Shape 表示 所有 Shape 的派生类
  • ? super Shape 表示所有 Shape 的基类(父类)

类型通配符的上限

List<? extends Shape> 是受限制通配符的例子,此处的问号(? )代表一个未知的类型,就像前面看到的通配符一样。但是此处的这个未知类型一定是Shape的子类型(也可以是Shape本身),因此可以把Shape称为这个通配符的上限(upper bound)。
类似地,由于程序无法确定这个受限制的通配符的具体类型,所以不能把Shape对象或其子类的对象加入这个泛型集合中。例如,下面代码就是错误的
在这里插入图片描述

与使用普通通配符相似的是,shapes.add()的第二个参数类型是 ? extends Shape,它表示Shape未知的子类,程序无法确定这个类型是什么,所以无法将任何对象添加到这种集合中。
简而言之,这种指定通配符上限的集合,只能从集合中取元素(取出的元素总是上限的类型或其子类),不能向集合中添加元素(因为编译器没法确定集合元素实际是哪种子类型)。
对于更广泛的泛型类来说,指定通配符上限就是为了支持类型型变。比如Foo是Bar的子类,这样A<Foo> 就相当于A<? extends Bar> 的子类,可以将A<Foo> 赋值给A<? extends Bar> 类型的变量,这种型变方式被称为协变

对于协变的泛型而言,它只能调用泛型类型作为返回值类型的方法(编译器会将该方法返回值当成通配符上限的类型);而不能调用泛型类型作为参数的方法。 口诀是:协变只出不进!

提示:没有指定通配符上限的泛型类,相当于通配符上限是Object 。例如 List<?> 表示 类型上限是Object

类型通配符的下限

除可以指定通配符的上限之外,Java也允许指定通配符的下限,通配符的下限用<? super 类型> 的方式来指定,通配符下限的作用与通配符上限的作用恰好相反。
指定通配符的下限就是为了支持类型型变。比如Foo是Bar的子类,当程序需要一个A<? super Foo> 变量时,程序可以将A<Bar> 、A<Object> 赋值给A<? super Foo> 类型的变量,这种型变方式被称为逆变
对于逆变的泛型集合来说,编译器只知道集合元素是下限的父类型,但具体是哪种父类型则不确定。因此,这种逆变的泛型集合能向其中添加元素(因为实际赋值的集合元素总是逆变声明的父类),从集合中取元素时只能被当成Object类型处理(编译器无法确定取出的到底是哪个父类的对象)。

对于逆变的泛型而言,它只能调用泛型类型作为参数的方法;而不能调用泛型类型作为返回值类型的方法。 口诀是:逆变只进不出!

设自己实现一个工具方法:实现将src集合中的元素复制到dest集合的功能,因为dest集合可以保存src集合中的所有元素,所以dest集合元素的类型应该是src集合元素类型的父类。
对于上面的copy()方法,可以这样理解两个集合参数之间的依赖关系:不管src集合元素的类型是什么,只要dest集合元素的类型与前者相同或者是前者的父类即可,此时通配符的下限就有了用武之地。
下面程序采用通配符下限的方式来实现该copy()方法。

public class TestGenericType {public static void main(String[] args) {ArrayList<Number> list1 = new ArrayList<Number>();ArrayList<Integer> list2 = new ArrayList<Integer>();list2.add(1);list2.add(2);list2.add(3);Integer last = copy(list1, list2);//①System.out.println(list1);}// dest 集合里的元素的类型必须是 src 集合元素的类型 或 其父类public static <T> T copy(Collection<? super T> dest, Collection<T> src) {T last = null;for (T ele : src) {last = ele;//逆变的泛型集合添加元素是安全的dest.add(ele);}return last;}
}

使用这种语句,就可以保证程序的①处调用后推断出最后一个被复制的元素类型是Integer,而不是笼统的Number类型。

实际上,Java集合框架中的TreeSet< E> 有一个构造器也用到了这种设定通配符下限的语法,如下所示。

    public TreeSet(Comparator<? super E> comparator) {//...}

正如前一章所介绍的,TreeSet会对集合中的元素按自然顺序或定制顺序进行排序。如果需要TreeSet对集合中的所有元素进行定制排序,则要求TreeSet对象有一个与之关联的Comparator对象。上面构造器中的参数comparator就是进行定制排序的Comparator对象。
Comparator接口也是一个带泛型声明的接口

public interface Comparator<T> {int compare(T o1, T o2);
}

通过这种带下限的通配符的语法,可以在创建TreeSet对象时灵活地选择合适的Comparator。
假定需要创建一个TreeSet<String> 集合,并传入一个可以比较String大小的Comparator,这个Comparator既可以是Comparator<String> ,也可以是Comparator<Object> 只要尖括号里传入的类型是String的父类型(或它本身)即可。

	private static void test02() {// 既可以使用 new Comparator<Object> 因为 Object 是 String 的父类,也可以使用 Comparator<String> 作为构造器的参数TreeSet<String> set1 = new TreeSet<String>(new Comparator<Object>() {@Overridepublic int compare(Object o1, Object o2) {return o1.hashCode() > o2.hashCode() ? 1 :o1.hashCode() < o2.hashCode() ? -1 : 0;}});set1.add("hello");set1.add("wa");TreeSet<String> set2 = new TreeSet<String>(new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return o1.length() > o2.length() ? -1 :o1.length() < o2.length() ? 1 : 0;}});set2.add("hello");set2.add("wa");System.out.println(set1);System.out.println(set2);}

通过使用这种通配符下限的方式来定义TreeSet构造器的参数,就可以将所有可用的Comparator作为参数传入,从而增加了程序的活性。当然,不仅TreeSet有这种用法,TreeMap也有类似的用法,具体的请查阅Java的API文档。

http://www.15wanjia.com/news/192038.html

相关文章:

  • 网站首页上海网站建设公司网站建设禁止性规定
  • 怎么新增网站推广佛山建设外贸网站公司吗
  • 企业网站开发模板下载如何做商业网站推广
  • 网站开发主要都做些什么和外国人做ic生意的网站
  • h5效果展示网站程序开发步骤不包括
  • 安阳市网站建设用微信登陆 wordpress
  • 企业网站教程杭州做小型app的公司
  • 网站编程薪资资源网站推荐几个
  • 石家庄专业网站设计如何免费域名
  • 广西建设厅考试网站首页程序员给别人做的网站违法了
  • 哪个网站设计好国家高新技术企业名录
  • php租车网站北京vi设计公司北京广告设计公司
  • 网站开发现状深圳市年年卡网络科技公司是什么
  • 兴义市住房城乡建设局网站广东省政务服务网
  • 网站开发的专业能力国内免费域名
  • 温江 网站建设wordpress 调用子分类
  • 电商网站开发平台用什么人开发wordpress项目下载
  • 黄冈建设局网站怎样建外贸公司网站
  • 徐州网站建设 网站推广html制作个人简历代码带照片
  • 做饲料机械的网站企业网站的建设 英文摘要
  • php网站好吗怎样做免费网站的推广
  • 厚街响应式网站建设展馆设计案例
  • 网站运营服务中心建设方案wordpress移除google相关
  • 东莞网站建设营销平台的广州市口碑seo推广
  • 网站打开慢原因如何弄自己的网站
  • 建行个人网站济南网站制作 泉诺
  • 佛山免费建站公司seo网页优化服务
  • 建网站用什么工作站在线开发
  • PHP做克隆网站信誉好的邢台做网站
  • vps建两个网站要两个程序池吗电影网站建设教程下载