泛型
目录
一、泛型是什么
泛型本质是指类型参数化。
意思是允许在定义类、接口、方法的时候使用类型形参,在真正使用时
指定具体类型,所有使用该泛型参数的地方都被统一化,保证类型一致。如果未指定具体类型,默认是Object类型。集合体系中的所有类都增加了泛型,泛型也主要用在集合。
二、为什么需要泛型
在没有泛型之前(JDK1.5之前),许多错误只能在运行才可以发现,通过引入泛型,可以使其部分错误在编译期就报错,大大提高了代码的健壮性。
具体好处为:
- 编译时确定类型,保证类型安全,避免类型转换异常。
- 免除强制类型转换。
- 使代码可重用性更高,增加通用性。
三、使用
一般泛型使用的3种方式
// 1、泛型类:T表示任意类型
public class Demo<T> {
//...
}
// 2、泛型接口: 和定义类一样(接口就是一个特殊类)
public interface ImplDemo<T,V>{
// ...
}
// 3、泛型方法:无返回类型
public <T> void demo1(T name){
System.out.println(name);
}
// 泛型方法:返回泛型类型值
public <T> T demo2(T t){
return t;
}
四、泛型擦除
public static void main(String[] args) {
List<String> a = new ArrayList<>();
List<Integer> b = new ArrayList<>();
System.out.println(a.getClass()); // class java.util.ArrayList
System.out.println(b.getClass()); // class java.util.ArrayList
System.out.println(a.getClass() == b.getClass()); // true
}
// 如上述代码所示,最终系统返回结果是true,说明List<Integer> 和List<String>只是在编译期间有效果,当代码在实际运行时,会自动转化成class java.util.ArrayList
五、什么是通配符
除了用 <T> 表示泛型外,还有 <?> 这种形式。"?"被称为通配符。
六、通配符上、下限
在JDK集合框架中大量的使用了通配符,可以去参考
<?> // 无限定通配符
<? extends T> // 有上限通配符
<? super T> // 有下限通配符
七、举例
1、普通泛型
- 例一:一个泛型类型
// 此处可以随便写标识符号,T是type的简称
class Point<T> {
// var的类型由T指定,即:在真正使用时由外部指定
private T value;
// 返回值的类型由外部决定
public T getValue() {
return value;
}
// 设置的类型也由外部决定
public void setValue(T value) {
this.value = value;
}
}
public class Test {
// 测试
public static void main(String[] args) {
// 里面的var类型为String类型
Point<String> a = new Point<>();
// 设置字符串
a.setValue("it");
// 取得字符串的长度
System.out.println(a.getValue().length());
}
}
- 例二:两个泛型类型
class Notepad<K, V> {
private K key;
private V value;
public K getKey() {
return this.key;
}
public V getValue() {
return this.value;
}
public void setKey(K key) {
this.key = key;
}
public void setValue(V value) {
this.value = value;
}
}
public class Test {
// 测试
public static void main(String[] args) {
Notepad<String, Integer> t = new Notepad<>();
t.setKey("汤姆");
t.setValue(20);
System.out.print("姓名;" + t.getKey());
System.out.print(",年龄;" + t.getValue());
}
}
2、无限定通配符
class Info<T> {
private T value;
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
// 测试
public class Test {
public static void main(String[] args) {
Info<String> i = new Info<>();
i.setValue("it");
fun(i);
}
// 可以接收任意的泛型对象
public static void fun(Info<?> temp) {
System.out.println("内容:" + temp.getValue());
}
}
3、有限定通配符
3.1、上限通配符(extends)
class Info<T> {
private T value;
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
// 测试
public class Test {
public static void main(String[] args) {
Info<Integer> a = new Info<>();
Info<Float> b = new Info<>();
a.setValue(30);
b.setValue(30.1F);
fun(a);
fun(b);
}
// 只能接收Number子类继承链上的类型
public static void fun(Info<? extends Number> temp) {
System.out.print(temp.getValue());
}
}
3.2、下限通配符(super)
class Info<T> {
private T value;
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
// 测试
public class Test {
public static void main(String args[]) {
Info<String> a = new Info<String>();
Info<Object> b = new Info<Object>();
a.setValue("hello");
b.setValue(new Object());
fun(a);
fun(b);
}
// 只能接收 String 父类继承链上的类型
public static void fun(Info<? super String> temp) {
System.out.print(temp.getValue());
}
}
4、泛型类型转换
泛型类型向上、向下均无法转换
class Info<T>{
private T value;
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
// 测试
public class Test{
public static void main(String[] args) {
Info<String> a = new Info<>();
Info<Object> b = null;
// java: 不兼容的类型: T.Info<java.lang.String>无法转换为T.Info<java.lang.Object>
// b = a;
// java: 不兼容的类型: T.Info<java.lang.Object>无法转换为T.Info<java.lang.String>
// a = b;
}
}
5、泛型接口
- 子类实现未确定泛型类型的接口,子类也需要将接口的泛型类型一同继承
interface Info<T> {
T getValue();
}
class InfoImpl<T> implements Info<T> {
private T value;
public InfoImpl(T value) {
this.value = value;
}
@Override
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
public class Test {
public static void main(String[] args) {
Info<String> a = new InfoImpl<>("汤姆");
System.out.println("内容:" + a.getValue());
}
}
- 子类实现已确定泛型类型的接口,子类可不指定泛型类型
interface Info<T> {
T getValue();
}
class InfoImpl implements Info<String> {
private String value;
public InfoImpl(String value) {
this.value = value;
}
@Override
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
public class Test {
public static void main(String[] args) {
Info<String> a = new InfoImpl("汤姆");
System.out.println("内容:" + a.getValue());
}
}
6、泛型方法
class Demo {
public <T> T fun(T value) {
return value;
}
}
public class Test {
public static void main(String[] args) {
Demo a = new Demo();
String b = a.fun("汤姆");
System.out.println(b);
int c = a.fun(30);
System.out.println(c);
}
}
7、泛型参数 + 返回泛型+ 上限通配符
class Info<T extends Number> {
private T value;
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
public class Test {
public static void main(String[] args) {
Info<Integer> a = fun(30);
System.out.println(a.getValue());
}
public static <T extends Number> Info<T> fun(T param) {
Info<T> temp = new Info<T>();
temp.setValue(param);
return temp;
}
}
8、泛型参数+返回泛型类型+无限通配符
class Info<T> {
private T value;
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
public class Test {
public static void main(String[] args) {
Info<String> a = new Info<>();
Info<Integer> b = new Info<>();
Info<String> c = new Info<>();
a.setValue("HELLO");
b.setValue(123);
c.setValue("汤姆");
add(a, b);
add2(a, b);
add3(a, b);
add4(a, c);
}
// 穷举
public static void add(Info<?> a, Info<?> b) {
System.out.println(a.getValue() + " " + b.getValue());
}
public static <ADBCDEF> void add2(Info<?> a, Info<?> b) {
System.out.println(a.getValue() + " " + b.getValue());
}
public static void add3(Info a, Info b) {
System.out.println(a.getValue() + " " + b.getValue());
}
public static <T> void add4(Info<T> a, Info<T> b) {
System.out.println(a.getValue() + " " + b.getValue());
}
}
9、泛型数组
public class Test {
public static void main(String[] args) {
Integer[] a = fun(1, 2, 3, 4, 5, 6);
fun2(a);
String[] b = fun("a", "b", "c");
fun2(b);
}
public static <T> T[] fun(T... arg) {
return arg;
}
public static <T> void fun2(T[] param) {
System.out.print("接收泛型数组:");
for (T t : param) {
System.out.print(t + "\t");
}
System.out.println();
}
}
10、泛型类型复杂嵌套
class Info<K, V> {
private K key;
private V value;
public Info(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public void setKey(K key) {
this.key = key;
}
public V getValue() {
return value;
}
public void setValue(V value) {
this.value = value;
}
}
class Demo<S> {
private S info;
public Demo(S info) {
this.setInfo(info);
}
public void setInfo(S info) {
this.info = info;
}
public S getInfo() {
return this.info;
}
}
public class Test {
public static void main(String[] args) {
Info<String, Integer> b = new Info<String, Integer>("汤姆", 30);
Demo<Info<String, Integer>> a = new Demo<Info<String, Integer>>(b);
System.out.println("内容一:" + a.getInfo().getValue());
System.out.println("内容二:" + a.getInfo().getValue());
}
}
11、根据类对象返回泛型值
public class Test {
public static void main(String[] args) {
ArrayList<String> a = newArrayList(String.class);
ArrayList<Integer> b = newArrayList(Integer.class);
ArrayList<Class> c = newArrayList(Class.class);
}
public static <E> ArrayList<E> newArrayList(Class<E> clazz) {
return new ArrayList<>();
}
}
八、其它
https://www.jianshu.com/p/0384b0e3641b
https://www.cnblogs.com/sunwei2012/archive/2010/10/08/1845938.html
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix