java之泛型
时间:2022-07-23
本文章向大家介绍java之泛型,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
什么是泛型?
泛型是JDK1.5新加入的,解决数据类型的安全性问题,其主要原理是在类声明时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这样在类声明或实例化时只要指定好需要的具体的类型即可。
为什么要有泛型?
java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException异常。同时,代码更加简洁、健壮。
java中的泛型只有在编译阶段有效。在编译过程中,正确检验泛型结果后,会将泛型的相关信息檫出,并且在对象和离开方法的边界处添加类型检查和类型转换的方法。也就是说,泛型信息不会进入到运行阶段。
举个例子:在利用泛型声明一个集合之后,例如List<String> list = new ArrayList<String>();在进行list.add(1);时就会提示:The method add(int, String) in the type List<String> is not applicable for the arguments (int),此时仍处于编译阶段。
怎么使用泛型?
1.泛型类
package collections;
import java.util.ArrayList;
import java.util.List;
public class Test6 {
public static void main(String[] args) {
A<String> a1 = new A<String>();
//这里setKey中接受的参数为String类型,因为在实例化的时候声明了String泛型
a1.setKey("a");
System.out.println(a1.getKey());
A<Integer> a2 = new A<Integer>();
//这里setKey中接受的参数为Integer类型,因为在实例化的时候声明了Integer泛型
a2.setKey(1);
System.out.println(a2.getKey());
A a3 = new A();
//假设不指定泛型,那么默认接受为Object
a3.setKey(1);
System.out.println(a3.getKey());
//同样的类,指定了不同的泛型,就不能进行相互赋值,比如a1=a2
}
}
//此处的泛型T可以任意取名,一般用T,表示Type
class A<T>{
private T key;
public void setKey(T key){
this.key = key;
}
public T getKey(){
return this.key;
}
}
2.泛型接口
package collections;
public class Test7 {
public static void main(String[] args) {
Mm<Integer> mm = new Mm<Integer>();
mm.test(1);
//这种情况下不能指定泛型
Mn mn = new Mn();
mn.test("a");
}
}
interface M<T>{
T test(T t);
}
//未传入泛型实参时,与泛型类的定义相同,在声明类的时候,需要将泛型的声明也一起加入到类中
class Mm<T> implements M<T>{
@Override
public T test(T t) {
// TODO Auto-generated method stub
return null;
}
}
//传入实参时,则需要都修改成实参
class Mn implements M<String>{
@Override
public String test(String t) {
// TODO Auto-generated method stub
return null;
}
}
3.泛型方法
package collections;
public class Test8 {
public static void main(String[] args) {
P<Object> p = new P<Object>();
p.test("aa");
//泛型方法在调用前没有固定的数据类型
//在调用时,传入的参数是什么类型,就会把泛型改成什么类型
p.test1(1);
p.test1(true);
}
}
class P<E>{
//在类上定义的泛型,可以在普通方法中使用
private E e;
public static <T> void test3(T t) {
//在静态方法中不能使用类定义的泛型,如果要使用泛型,只能使用静态方法自己定义的泛型
System.out.println(t);
}
//无返回值的泛型
public <T> void test(T t) {
}
//有返回值的泛型
public <T> T test1(T s) {
System.out.println(this.e);
return s;
}
//带有可变参数方法的泛型
public <T> void test2(T... args) {
for(T arg:args) {
System.out.println(arg);
}
}
}
4.通配符?
package collections;
import java.util.ArrayList;
import java.util.List;
public class Test9 {
public static void main(String[] args) {
Q q = new Q();
List<String> list1 = new ArrayList<String>();
q.test(list1);
List<Integer> list2 = new ArrayList<Integer>();
q.test(list2);
}
}
class Q{
//test里面需要传递一个集合List,但是不知道List里面参数的类型
public void test(List<?> list) {
}
}
有限制的通配符:
- <? extends Person> [无穷小, Person] 只允许泛型为Person及Person子类的引用调用
- <? super Person> [Person, 无穷大] 只允许泛型为Person及Person父类的引用调用
- <? extends Comparable 只允许泛型为Comparable接口的实现类引用调用
package collections;
import java.util.ArrayList;
import java.util.List;
public class Test9 {
public static void main(String[] args) {
Q q = new Q();
List<B1> b1 = new ArrayList<B1>();
List<C1> c1 = new ArrayList<C1>();
List<D1> d1 = new ArrayList<D1>();
//q.test1(b1);传入b1会报错
q.test1(c1);
q.test1(d1);
//q.test2(d1);传入d1会报错
List<M1Impl> m1Impl = new ArrayList<M1Impl>();
q.test3(m1Impl);
}
}
class Q{
//test里面需要传递一个集合List,但是不知道List里面参数的类型
public void test(List<?> list) {
}
//参数的元素数据类型为C1及其子类
public void test1(List<? extends C1> list) {}
//参数的元素数据类型为C1及其父类
public void test2(List<? super C1> list) {}
//参数的元素数据类型为C1及其父类
public void test3(List<? extends M1> list) {}
}
class A1{
}
class B1 extends A1{}
class C1 extends B1{}
class D1 extends C1{}
interface M1{}
class M1Impl implements M1{}
- PDF.js专题
- CentOs7.3 编译安装 Nginx 1.9.9
- 基础篇章:关于 React Native 之 RefreshControl 组件的讲解
- CentOs7.3 安装 JDK1.8
- 基础篇章:关于 React Native 之 ListView 组件的讲解
- maven环境快速搭建
- CentOs7.3 搭建 RabbitMQ 3.6 Cluster 集群服务
- CentOs7.3 搭建 Redis-4.0.1 Cluster 集群服务
- CentOs7.3 搭建 Redis-4.0.1 单机服务
- Shodan新手入坑指南
- 我用过的——Spring定时任务的几种用法
- CentOs7.3 搭建 SolrCloud 集群服务
- CentOs7.3 搭建 Solr单机服务
- CentOs7.3 搭建 ZooKeeper-3.4.9 Cluster 集群服务
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- [周末往期回顾]redis的介绍及安装
- [Oracle 日常管理]使用BBED定位数据位置
- [Oracle 日常管理]表的相关操作
- JsonPath实践(二)
- C# 使用OpenCV在一张图片里寻找人脸
- 【DB笔试面试858】在Oracle中,ipcs和ipcrm命令的作用有哪些?
- Qt音视频开发13-mpv录像存储
- Oracle参数解析(spfile)
- ROS2机器人笔记20-08-18
- C sharp实例:华盾武器门数据接收和解析
- JsonPath实践(三)
- 有序链表转换二叉搜索树
- 128. 最长连续序列
- 【DB笔试面试859】在Oracle中,内核参数kernel.shmall、kernel.shmall等分别代表什么含义?
- Nginx配置SSL证书