类型参数
泛型有三种实现方式,分别是泛型接口、泛型类、泛型方法,下面通过泛型方法来介绍什么是类型参数。
泛型方法声明方式:访问修饰符 <T,K,S...> 返回类型 方法名(方法参数){方法体}
一、访问修饰符与返回类型中间有个<T,K,S...>,T、K、S等属于类型参数,可以随便定义。
二、返回类型和方法参数可以是或者包含类型参数T、K、S等。
三、可以限定类型参数必须实现某些接口或者继承某个类,多个限定的类、接口中间用&分隔,类必须放在限定列表中所有接口的前面。
四、泛型方法可以定义在普通类中。
示例:
import java.io.Serializable;
 
public class Demo {
public static void main(String[] args) {
B b = new B();
C c = new C();
System.out.println(D.d(b, c));
}
}
 
class A {
@Override
public String toString() {
return "A{}";
}
}
 
class B extends A implements Serializable, Cloneable {
@Override
public String toString() {
return "B{}";
}
}
 
class C extends A {
@Override
public String toString() {
return "C{}";
}
}
 
class D {
public static <T extends A & Serializable & Cloneable, K> K d(T t, K k) {
System.out.println(t);
return k;
}
}
 
输出:
B{}
C{}
 
通配符类型
通配符类型可以理解为一种泛型调用时传递的一种特殊数据类型,表示允许类型参数在某个范围内变化。通配符类型有三种,分别是?、? extends、? super。它有什么用?创建如下三个类:
public class ParentClass{}
 
public class SonClass extends ParentClass{}
 
public class Operate<T> {
 
private T item;
 
public Operate(T item) {
this.item = item;
}
 
public T get() {
return item;
}
 
public void set(T item) {
this.item = item;
}
}
 
? extends X
子类型限定,表示泛型的类型参数不是固定的,而是X及其子类型。
如果存在Operate<ParentClass> operate1 = new Operate<SonClass>(new SonClass()),那么这行代码会报错,编译器提示类型不兼容,因为左边不是右边的基类。此时如果有这样一个方法:
public static void method(Operate<ParentClass> operate) {},
就无法将 new Operate<SonClass>(new SonClass()) 传递给这个方法。解决办法就是使用子类型限定定义方法参数:
public static void method(Operate<? extends ParentClass> operate) {},
就可以将 new Operate<SonClass>(new SonClass()) 传递给这个方法。
子类型限定的副作用是不能传递null以外的类型。
Operate<? extends ParentClass>的方法可以想象成下面这个样子(实际上不能这样写代码):
public ? extends ParentClass get() {
return item;
}
public void set(? extends ParentClass item) {
this.item = item;
}
此时get方法可以正常调用,因为返回的item肯定是ParentClass或者它的子类型。但是set方法就不能传递null以外的类型了,因为编译器只知道需要ParentClass或者它的子类型,但是不知道具体是哪个类,所以只能调用set(null)。如下:
public static void method(Operate<? extends ParentClass> operate) {
operate.get();
operate.set(null);
operate.set(new ParentClass());//报错
operate.set(new SonClass());//报错
}
 
? super X
超类型限定,表示泛型的类型参数不是固定的,而是X及其父类型。
Operate<? super SonClass>的方法可以想象成下面这个样子(实际上不能这样写代码):
public ? super SonClass get() {
return item;
}
public void set(? super SonClass item) {
this.item = item;
}
一、类型参数限定为X及其父类型,直至Object类,因为不知道具体是哪个父类型,因此方法返回的类型只能赋给Object。
二、只能传递null、X及其子类型,因为X及其子类型都是向上转型成X及其父类型。
Operate<? super SonClass> operate3 = new Operate<ParentClass>(new ParentClass())是成立的,所以可以将new Operate<ParentClass>(new ParentClass())传递给以下方法。
public static void method(Operate<? super SonClass> operate) {
SonClass sonClass = operate.get();//报错
ParentClass parentClass = operate.get();//报错
Object object = operate.get();
operate.set(new ParentClass());//报错
operate.set(null);
operate.set(new SonClass());
}
 
?
无类型限定,泛型的类型参数没有限定。
一、只能传递null类型。
二、方法返回的类型只能赋给Object。
new Operate<SonClass>(new SonClass())、new Operate<ParentClass>(new ParentClass())、new Operate<Object>(new Object())、new Operate<String>(new String())等都可以传递给以下方法。
public static void method(Operate<?> operate) {
SonClass sonClass = operate.get();//报错
ParentClass parentClass = operate.get();//报错
operate.set(new ParentClass());//报错
Object object = operate.get();
operate.set(null);
operate.set(new SonClass());//报错
}
有什么作用呢?对于一些不需要实际类型的方法,就显得比泛型方法可读性强,如下。
public static void method(Operate<?> operate) {
System.out.println(operate.get() == null);
}
public static <T> void method(Operate<T> operate) {
System.out.println(operate.get() == null);
}

Java泛型中的类型参数和通配符类型的更多相关文章

  1. 【转】聊一聊-JAVA 泛型中的通配符 T,E,K,V,?

    原文:https://juejin.im/post/5d5789d26fb9a06ad0056bd9 前言 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型 ...

  2. Java泛型中的通配符T,E,K,V

    Java泛型中的通配符T,E,K,V 1.泛型的好处 2.泛型中的通配符 2.1 T,E,K,V,? 2.2 ?无界通配符 2.3 上界通配符 < ? extends E> 2.4 下界通 ...

  3. Java 泛型中的通配符

    本文内容如下: 1. 什么是类型擦除 2.常用的 ?, T, E, K, V, N的含义 3.上界通配符 < ?extends E> 4.下界通配符 < ?super E> 5 ...

  4. Java泛型中的通配符

    Java泛型中的通配符可以直接定义泛型类型的参数.而不用把该函数定义成泛型函数. public class GenericsTest { public static void main(String[ ...

  5. Java泛型中extends和super的理解(转)

    E – Element (在集合中使用,因为集合中存放的是元素) T – Type(Java 类) K – Key(键) V – Value(值) N – Number(数值类型) ? – 表示不确定 ...

  6. Java泛型中extends和super的区别?

    <? extends T>和<? super T>是Java泛型中的"通配符(Wildcards)"和"边界(Bounds)"的概念. ...

  7. Java泛型中的协变和逆变

    Java泛型中的协变和逆变 一般我们看Java泛型好像是不支持协变或逆变的,比如前面提到的List<Object>和List<String>之间是不可变的.但当我们在Java泛 ...

  8. Java泛型中<?> 和 <? extends Object>的异同分析

    相信很多人和我一样,接触Java多年,却仍旧搞不清楚 Java 泛型中 <?>和 <? extends Object>的相似和不同.但是,这应该是一个比较高端大气上档次的Que ...

  9. Java泛型中的细节

    Java泛型中的细节 如果没有泛型 学习Java,必不可少的一个过程就是需要掌握泛型.泛型起源于JDK1.5,为什么我们要使用泛型呢?泛型可以使编译器知道一个对象的限定类型是什么,这样编译器就可以在一 ...

随机推荐

  1. vps的搭建

    最近一直想自己搭建一款vps使用,但是苦于一直没有时间,直到今天得空,与大家一起分享下. 服务商的选择 因为自己之前在 vultr 上还留有余额(60$呢,好几百块大洋呢),所以我的服务商就选择 vu ...

  2. 小案例-WebSocket实现简易聊天室

    前言 在详解 HTTP系列之一讲到HTTP/2.0 突破了传统的"请求-问答模式"这一局限,实现了服务器主动向客户端传送数据.而本章将通过一种在单个TCP连接上进行全双工通信的协议 ...

  3. el-dialog“闪动”解决办法

    问题描述:el-dialog关闭的时候总是出现两次弹窗 解决思路:既然是el-dialog产生的那就直接杀掉el-dialog 代码实践:在el-dialog上添加上一个v-if,值就是用闭窗的值,促 ...

  4. TinkPHP框架开发的CRMEB小程序商城v4.0二次开发集成支付宝支付

    前言 大家都知道支付宝支付和微信支付宝都只能局限在自己的平台,微信内支付宝支付是根本就不能使用,即使是公众号支付也需要跳转到外部浏览器才可以唤起支付宝支付,并且QQ浏览器唤起支付宝支付还是问题很多,所 ...

  5. MSP430-LED中断闪烁代码详解

    使用MSP430F149的开发板,首先对LED闪烁灯的例程进行讲解,然后下边是自己写的,将部分代码写入了新建的led.c程序中 #include  <msp430x14x.h>       ...

  6. oeasy教您玩转linux010105详细手册man

    详细手册 回忆上节课 我们上节课学习了使用命令来了解命令 whatis 我们通过他来发出灵魂之问 whatis到底是干什么的?

  7. Android studio Debug 源码

    原来有的地方打不了断点 会提示no executable code at line xxx 源码sdk里有,sdkManager下好对应版本,然后使用对应版本的模拟器debug就行了 如果要debug ...

  8. 分布式ID生成方案汇总

    1.目标 1.1.全局唯一 不能出现重复的ID,全局唯一是最基本的要求. 1.2.趋势有序 业务上分页查询需求,排序需求,如果ID直接有序,则不必建立更多的索引,增加查询条件. 而且Mysql Inn ...

  9. 小程序开发-使用npm包

    微信小程序引用npm包 微信小程序官方支持使用npm包,地址为 https://developers.weixin.qq.com/miniprogram/dev/devtools/npm.html 实 ...

  10. 13_Python的面向对象编程-类class,对象object,实例instance

    1.面向对象概述 1.类是用来描述对象的工具,把拥有相同属性和行为的对象分为一组     2.对象是由类实例化出来的一个具体的对象         属性: 对象拥有的名词,用变量表示         ...