Java 泛型方法/接口、泛型限定
一、为什么要定义泛型方法
1、从泛型类到泛型方法的演变过程
我们先来看个例子
//定义一个泛型类,并定义如下两个方法
class Test<T>
{public void show(T t){System.out.println(t);}public void print(T t){System.out.println(t);} /* 以前是这样定义,现在一个方法搞定public void show(String t){ }public void show(Integer t){ }或者public void show(Object obj){ }*/
}//在manin方法代码如下public static void main(String[] args) {Test<String> d = new Test<String>();d.show("java");d.print("Object-C");Test<Integer> e = new Test<Integer>();e.show(2);e.print(new Integer(5)); }
上面是一个简单的代码demo,运行没问题,正常输出。但是你会发现,其实代码有点冗余。我们定义了一个泛型类,并定义了 show(T t)和print(T t)方法。
发现: 泛型类定义的泛型,在整个类中有效。如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所要操作的类型已经固定了。就像上面main方法中。对象d,只能操作String类型,如果你要操作其他类型,只能额外去创建其他泛型对象e。
设想下,如果我能把泛型定义在方法上,这样不就可以优雅解决问题。于是变化代码如下
//定义一个类,并定义如下两个泛型方法
class Test
{public <T> void show(T t){System.out.println(t);}public <T> void print(T t){System.out.println(t);} public <U,T> void sum(U u,T t){System.out.println(u+" version is "+t);}
}
// main方法如下
public static void main(String[] args) {Test d = new Test();d.show("java");d.print(5);d.sum("java", new Double(8));}
Test不再是泛型类,泛型方法show(T t)、print(T t)、sum(U u,T t) 更具有扩展性。
2、定义泛型方法的好处
- 泛型方法可以让不同方法操作不同类型,且类型还不确定。
- 与泛型类不同,泛型方法的类型参数只能在它锁修饰的泛型方法中使用。
二、创建一个泛型方法格式
1、常用的形式
访问修饰符 [static][final] <类型参数列表> 返回值类型 方法名([形式参数列表])
备注:[] 代可有可无的意思,泛型方法可以是实例方法或静态方法,类型参数可以在静态方法中,这是与泛型类最大的区别。
三、泛型接口
1、格式
interface 接口名<类型参数表>
2、例子
定义一个泛型接口
interface showInterface<T>
{public void show(T t);}
(1) 实现类确定了类型
class ShowClass implements showInterface<String>{public void show(String t){System.out.println("show:"+t);}
}
(2) 实现类类型不确定
class ShowClass<T> implements showInterface<T>{public void show(T t){System.out.println("show:"+t);}
}
main方法public static void main(String[] args) {ShowClass<Integer> obj = new ShowClass<Integer>();obj.show(6);/*ShowClass obj = new ShowClass();obj.show("java");*/}
四、类型通配符(泛型的高级应用)
1、什么是通配符 (?)
看个例子就明白了。定义两个集合,分别输出两个集合的元素。
public static void main(String[] args) {ArrayList<String> a1 = new ArrayList<String>();a1.add("a");a1.add("b");a1.add("c");ArrayList<Integer> a2 = new ArrayList<Integer>();a2.add(1);a2.add(2);a2.add(3);}
在我们没学习泛型之前,我们会封装静态方法如下:
public static void printList(ArrayList list){for (Iterator iterator = list.iterator(); iterator.hasNext();) {Object object = (Object) iterator.next();System.out.println(object); }}
代码买啥毛病,运行也正确。会有一个疑问。为什么参数没定义泛型,但是却可以接受泛型呢?泛型是jdk1.5出来的,老版本肯定要兼容新版本。
在我们学习泛型方法后,我们进一步将代码修改如下:
public static <T>void vistor(ArrayList<T> a){Iterator<T> iterator = a.iterator();while(iterator.hasNext()){T t = iterator.next(); System.out.println(t);}}
定义一个泛型方法。如果是泛型类,是不允许泛型定义在static上面的。
如果不想定义泛型方法,又能够解决问题呢?这就要用到一个通配符的玩意
//占位符,也称为通配符。表示元素类型可以匹配任意类型
public static void sop(ArrayList<?> a){for(Iterator<?> it = a.iterator();it.hasNext();){System.out.println(it.next());}}
泛型方法T如果是具体类型的话,可以接收T t = iterator.next();。?是占位符,不明确具体类型,无法接收。
这种带通配符ArrayList<?> a的List 仅仅表示他是各种泛型的父类,并不能把元素添加到其中。
我做了奇怪的例子
ArrayList<?> list = new ArrayList<String>();
list.add(null);
上面说,带通配符ArrayList<?> a的List 仅仅表示他是各种泛型的父类,并不能把元素添加到其中。是不是想违背了?仔细想想,null是任意引用类型的实例。这比较特殊。
2、类型通配符上限定(? extends T)
同样看一个例子。 定义一个集合,遍历元素的方法并输出。
//定义一个Person类
class Person {private String name;public Person(String name) {this.name = name;}public String getNmae() {return this.name;}// 定义一个Student 并继承 Personstatic class Student extends Person {Student(String name) {super(name);}}public static void main(String[] args) {ArrayList<Person> a1 = new ArrayList<Person>();a1.add(new Person("abc1"));a1.add(new Person("abc2"));a1.add(new Person("abc3"));printMethod(a1);// 下面是错误的。an存的是Person,类型安全问题,左右两边要一致
// ArrayList<Person> an = new ArrayList<Student>();//泛型是父类,可以存子类ArrayList<Student> a = new ArrayList<Student>();a.add(new Student("abc--1"));a.add(new Student("abc--2"));a.add(new Student("abc--3"));//错误,因为要求是Person,而传入的是Student//printMethod(a);//使用通配符可以。printMethod2(a);//泛型是父类,可以存子类ArrayList<Person> a2 = new ArrayList<Person>();a2.add(new Student("abc--1"));a2.add(new Student("abc--2"));a2.add(new Student("abc--3"));printMethod(a2);//如果我想调用也printMethod(a2);没毛病。怎么做?。 第一想法直接给占位符。但是带来一问题,不能调用具体方法。}// 与main方法同级的静态工具类方法public static void printMethod(ArrayList<Person> a1) {Iterator<Person> it = a1.iterator();while (it.hasNext()) {System.out.println(it.next().getNmae());}}// 与main方法同级的静态工具类方法public static void printMethod2(ArrayList<? extends Person> a1) {Iterator<? extends Person> it = a1.iterator();while (it.hasNext()) {System.out.println(it.next().getNmae());}}
}
如果我想调用也printMethod(a2); 第一想法直接给占位符。但是带来一问题,不能调用具体方法。泛型也是一样的。如果我们想两者兼得,既能打印Stuednt,也能打印Person,我们将printMethod修改如下
public static void printMethod(ArrayList<? extends Person> a1){Iterator<? extends Person> it = a1.iterator();while(it.hasNext()){System.out.println(it.next().getNmae());}}
我们称? extends T 为 泛型上限定: 可以接收T和T的子类
3、类型通配符下限定<? super T>
接收T类型或者T的父类型
从集合TreeSet的构造方法我们可以看到 下限定的运用。我们也可以集合实际例子。
TreeSet<Person> ts = new TreeSet<Person>(); //Comparator<? super E> comparator
ts.add(new Person("d"));
ts.add(new Person("f"));
ts.add(new Person("g"));
比较器如下// 这边的T写Student和Person都是可以的
class comp implements Comparator<Person>
{public int compare(Person s1,Person s2){return s1.getNmae().compareTo(s2.getNmae());}
}
其实限定的目的是为了扩展指定类型。
通过上面比较器参数和我们实现的比较器。如果我们比较器的泛型为 Student,那么只能比较Student。当未来某一天,Person有新子类出现的话,那么该比较器就不适用了。所以Java 的API 的考虑扩展性的同时,已经设置了泛型下限定,你可以传T类型或者T的父类型。
参考:https://blog.csdn.net/qq_18505715/article/details/88381607
Java 泛型方法/接口、泛型限定相关推荐
- java泛型方法 通配符_Java泛型教程–示例类,接口,方法,通配符等
java泛型方法 通配符 泛型是Java编程的核心功能之一,它是Java 5中引入的.如果您使用的是Java Collections ,并且版本5或更高版本,则可以肯定使用了它. 将泛型与集合类一起使 ...
- 【Java学习笔记(七十六)】之 泛型编程, 泛型类,泛型方法,类型参数限定,类型擦除
本文章由公号[开发小鸽]发布!欢迎关注!!! 老规矩–妹妹镇楼: 一. 为什么要使用泛型编程 (一) 未使用泛型编程时 在没有泛型编程的时候,我们要实现同一个功能,但是一个参数可能有不同的类型,就只能 ...
- java模型给泛型_java 泛型详解-绝对是对泛型方法讲解最详细的,没有之一
对java的泛型特性的了解仅限于表面的浅浅一层,直到在学习设计模式时发现有不了解的用法,才想起详细的记录一下. 1. 概述 泛型在java中有很重要的地位,在面向对象编程及各种设计模式中有非常广泛的应 ...
- Java 泛型详解(超详细的java泛型方法解析)
Java 泛型详解(超详细的java泛型方法解析) 1. 什么是泛型 泛型:是一种把明确类型的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型.也就是说在泛型使用过程中,操作的数据类型被指定为 ...
- Java泛型(泛型类,泛型方法,静态方法泛型,泛型类与泛型方法例子)
泛型 泛型简介 泛型可以理解为参数化类型,主要作用在类,方法和接口上. Java泛型 与 C++ 模板 : Java 中的泛型 , 是仿照 C++ 中的模板开发的 , 目的是让开发者可以写出通用,灵活 ...
- java泛型方法作用_java泛型的作用与使用方法是什么?
泛型,即"参数化类型".一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参.那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变 ...
- java接口 泛型_java泛型接口是肿么一回事,干什么用的
1.泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类.泛型接口.泛型方法. Java语 ...
- 【Java 泛型】泛型用法 ( 泛型类用法 | 泛型方法用法 | 泛型通配符 ? | 泛型安全检查 )
文章目录 一.泛型类用法 二.泛型方法用法 三.泛型通配符 <?> 四.泛型安全检查 五.完整代码示例 1.泛型类 / 方法 2.main 函数 一.泛型类用法 泛型类用法 : 使用时先声 ...
- java多态和泛型_Java面向对象(二) 接口、多态和泛型
一.接口 二.多态 多态是同一个行为具有多个不同表现形式或形态的能力. 2.1 类型转换 转换方式 隐式 向上转型 对于基本数据类型,存储容量低的可自动向存储容量高的类型转换 对于引用变量,子类可被转 ...
最新文章
- PHP的学习--PHP的引用
- C++去掉字符串首尾的特殊字符(比如空格)
- wxWidgets:wxCommandLinkButton类用法
- UnityShader RenderTypeQueue 渲染顺序
- Cloudera完善企业数据云愿景,新品进一步扩展无处不在的云体验
- POJ 3278 Catch That Cow
- python自带笔记本电脑_Python执行速度:笔记本电脑与台式机
- 博途v15 固件升级包_使用博途TIA 15.1对SIMATIC S7-1200进行硬件组态和固件版本在线升级(博途V15和1200学习笔记一)...
- 移动光猫路由改桥接降低延时初尝试
- 4-5. do...while循环
- j2ee课程设计—基于activiti的请休假系统
- 传感器系列之4.10 酒精传感器
- 【自然语言处理(NLP)】基于FNN网络的电影评论情感分析
- 【独家】微软中国开始挖人,看中搜索人才
- 多表(三个表)插入与删除操作
- 几点项目里的经验教训
- 《Java 2 实用教程》读书笔记(四)4.4
- java基于springboot+vue的校园跑腿系统 nodejs前后端分离
- ucloud如何新建一个虚拟机以及注意的地方
- Java全栈技术体系汇总----主目录----持续更新
热门文章
- U-Net: Convolutional Networks for Biomedical Image Segmentation论文翻译
- 人工智能及其应用——第一章学习笔记
- 推荐 7 个牛哄哄的电商项目
- 电磁兼容——电子系统的EMC要求
- 单源最短路和多源最短路
- Jedis使用lua脚本完成令牌桶限流
- 计算机房精密空调术语,精密空调8大制冷形式,40个专业术语
- 每日一道 LeetCode (16):求 x 的平方根
- go语言泛型在IDE中语法报错
- 【工程应用七】接着折腾模板匹配算法 (Optimization选项 + no_pregeneration模拟 + 3D亚像素插值)...