Java泛型
Posted DullFan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java泛型相关的知识,希望对你有一定的参考价值。
文章目录
前言
提示:以下是本篇文章正文内容,下面案例可供参考
一、泛型
1.泛型的好处
1.适用于多种数据类型执行相同的代码.
2.泛型中的类型在使用指定时,不需要强制执强制转型
2.泛型的本质
泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
3.泛型类
//泛型类是允许多个类型变量
public class Generic<T,K>
private T data;
private K data2;
public Generic(T data, K data2)
this.data = data;
this.data2 = data2;
4.泛型接口
public interface GenericInterface<T>
public T next();
泛型接口的实现
public class Generic implements GenericInterface<String>
@Override
public String next()
return "null";
5.泛型方法
泛型方法,是在调用方法的时候指名泛型的具体类型,泛型方法可以在任何地方和任何场景使用,包括普通类和泛型类,注意普通方法和泛型方法的区别:
public class Generic
//<T>必须加上才是泛型接口,要不然就是普通接口,T为返回值,T...a为可变参数
public <T> T generics(T...a)
return a[a.length/2];
public static void main(String[] args)
Generic generic =new Generic();
//输出结果:"zhang"
System.out.println(generic.generics("make","zhang","li"));
//输出结果:36
System.out.println(generic.generics(12,24,36,48));
5.限定类型变量
将T限制为实现了接口Comparable的类
public static <T extends Comparable> T min(T a, T b)
if (a.compareTo(b) > 0) return a;
else return b;
T extends Comparable中
T表示绑定类型的子类型,Comparable表示绑定类型,子类型和绑定类型可以是类也可以是接口.
同时extends可以允许多个,如:T extends Comparable & Serializable
注意限定类型中,只允许有一个类,如果有类的话,这个类必须是限定列表第一个,
这种限定类型变量即可以使用在泛型方法上,也可以使用在泛型类中
public static <T extends Comparable & Serializable> T min(T a, T b)
if (a.compareTo(b) > 0) return a;
else return b;
6.泛型的约束和局限性
1.不能使用基本数据类型实例化类型参数
//List<int>list = new ArrayList<>();错误
List<Integer>list = new ArrayList<>();
2.不能捕获泛型类的实例
//这样是不行的,泛型类不能extends Exception/Throwable
public class prom <T> extends Exception
//不能捕获泛型类对象
public <T extends Throwable> void work(T t)
try
catch (T a)
但是可以这样
public <T extends Throwable>void doing(T t) throws T
try
catch (Throwable a)
throw a;
3.不能创建参数化类型数组
4.不能实例化类型变量
…
还有几点网上很多,我就不一一列举了
7.通配符类型
先定义几个类,一个泛型类,两个方法
//一个方法
public class Generic
//方法
public static void print(Generics<Fruit> p)
public static void use()
//泛型类
class GenericTest<T>
private T data;
public T getData()
return data;
public void setData(T data)
this.data = data;
//继承关系类
//水果类
class Fruit
//苹果继承水果
class Apple extends Fruit
//继承水果
class Banana extends Fruit
//小黄人需要香蕉
class Minions extends Banana
如果在use方法中调用print方法并传入几个参数,会发现Fruit的子类传不了
public static void use()
GenericTest<Fruit>a = new GenericTest<>();
print(a);
GenericTest<Banana>b = new GenericTest<>();
//此处添加不进去
//print(b);
为了解决以上问题,于是提出了通配符类型 “?”
有两种使用方式:
-
? extends X 表示类型的上界,类型参数是X的子类
-
? super X 表示类型的下界,类型参数是X的超类
? extends X
表示传递给方法的参数,必须是X的子类(包括X本身)
class Generic
//将print()方法修改
public static void print(GenericTest<? extends Fruit> p)
public static void use()
GenericTest<Fruit>a = new GenericTest<>();
print(a);
GenericTest<Banana>b = new GenericTest<>();
//可以添加了
print(b);
如果泛型类提供了get和set类型参数变量的方法的话,set方法是不允许调用的,会出现编译错误
public static void use()
GenericTest<? extends Fruit>genericTest = new GenericTest<>();
Apple apple = new Apple();
Banana banana =new Banana();
//出现编译错误
genericTest.setData(apple);
//get则没有问题,返回一个Fruit类型的值
Fruit data = genericTest.getData();
造成这样的原因是因为,? extends X表示类型的上限,类型参数是X的子类,那么get方法返回的一个是个X(不管的X或者X的子类)编译器是可以确定知道的,但是set方法只知道传入的是个X,至于具体是X的哪个子类不知道
总结 : 主要用于安全地访问数据,可以访问X及子类型,并且不能写入非null的数据
? super X
表示传递给方法的参数,必须是X的超类(包括X本身)
//修改方法
public static void print(GenericTest<? super Banana> p)
public static void use()
GenericTest<Fruit> fruitGenericTest = new GenericTest<>();
GenericTest<Apple> appleGenericTest = new GenericTest<>();
GenericTest<Banana> bananaGenericTest = new GenericTest<>();
GenericTest<Minions> minionsGenericTest = new GenericTest<>();
print(fruitGenericTest);
//Apple和Banana属于同级
// print(appleGenericTest);
print(bananaGenericTest);
//小黄人属于Banana的子类
// print(minionsGenericTest);
如果泛型类提供了get和set类型参数变量的方法的话,set方法是可以被调用的,且只能传入的参数只能是X或者X的子类
public static void use()
GenericTest<? super Banana>g = new GenericTest<>();
//Fruit属于父类,
// g.setData(new Fruit());
g.setData(new Banana());
g.setData(new Minions());
//get方法只会返回一个Object的类型
Object data = g.getData();
父类?编译器不知道.但是可以肯定的说Object一定是它的父类,所以get方法返回Object编译器肯定知道,对于set方法来说,编译器不知道他确切类型,但是X和X的子类可以完全转型为X
总结 : 主要用于安全地写入数据,可以写入X及其子类型
无限定通配符
表示对类型没有什么限制,可以把" ? "看成所有类型的父类,如:Pair<?>
比如:
// 指定集合元素只能是T类型
ArrayList<T> al=new ArrayList<T>();
//集合元素可以是任意类,这种没有意义,一般是方法中,只是为了说明用法。
ArrayList<?> al=new ArrayList<?>();
在使用上:
//返回值只能赋给 Objeck
? getFirst();
//setFirst 方法不能被调用,甚至不能用 Object 调用
void setFirst(?);
总结
下面这句话是我这几个月以来也许最深刻的一句话,每次赖床的时候就会想想这句话.
“你要清楚你每天睡醒之前有两个选择要么趴下做你未完成的梦,要么拉开被子做你未完成的梦想。我不相信什么一夜成名,我只相信百炼成钢。要么努力的向上爬,要么烂在社会的最底层。这,就是现实。”
以上是关于Java泛型的主要内容,如果未能解决你的问题,请参考以下文章