文章目录
1.泛型的定义
1.1 什么是泛型?
泛型就是让一个类/一个方法,能够支持多种不同的数据类型。
1.2 为什么要使用泛型?
public class MyArray {
private int [] arr=null;
private int size;
private int capacity;
public MyArray(int capacity){
arr=new int[capacity];
size=0;
this.capacity=capacity;
}
public void add(int index,int data){
if(size<capacity){
arr[size++]=data;
}
}
public int get(int index){
return arr[index];
}
public int size(){
return size;
}
public static void main(String[] args) {
//创建一个MyArray对象,里面存储的是int类型的数据
MyArray m1=new MyArray(10);
m1.add(0,1);
m1.add(1,2);
m1.add(2,3);
for(int i = 0;i<m1.size();++i){
System.out.print(m1.get(i)+" ");
}
System.out.println();
}
}
- 如果没有泛型机制,当前封装的数组类,只能针对int进行,如果需要针对String ,就需要在创建一个类,把里面的int的类型改成String,后续如果需要新增其他的类型,就得如法炮制。
- 有了泛型之后,就可以一套代码可以服务于多种类型
- 在上面的方式中,将存储数据的类型全部有int类型改成Object,因为Java中的Object是所有类的基类
- 如果把类中持有的数组写成Object[],此时是可以用来存储多种不同类型数据的。但是这样写,就得写大量的”类型转换“相关的代码。
public class MyArray {
public Object[] data = null;
private int size = 0;
private int capacity = 10;
public MyArray(){
data=new Object[capacity];
}
public void add(Object data){
if(size >= capacity){
return;
}
this.data[size++]=data;
}
public Object get(int index){
return data[index];
}
public static void main(String[] args) {
MyArray myArray=new MyArray();
myArray.add(new Person("张三",18));
myArray.add(new Person("李四",19));
myArray.add(new Person("王五",20));
Person person=(Person)myArray.get(0);
MyArray myArray2=new MyArray();
myArray2.add(new String("aaa"));
myArray2.add(new String("bbb"));
myArray2.add(new String("ccc"));
String str=(String)myArray2.get(0);
MyArray myArray3=new MyArray();
myArray3.add(new Integer(1));
Integer integer=(Integer)myArray3.get(0);
}
}
- 使用Object来凑合完成”泛型“效果,是比较麻烦的
- 1.需要写一些类型转换的代码
- 2.类型转换的代码容易出错,缺少一些必要的类型检查。
2.泛型类
2.1泛型类的定义
class 泛型类的名称<类型形参列表>{
//这里可以使用类型参数
}
class ClassName<T1,T2,...,Tn>{
//类实现体
}
类型形参一般使用一个大写字母表示,常用的名称有:
- E表示Element
- K表示Key
- V表示Value
- N表示Number
- T表示Type
- S,U,V等等
2.2泛型类的例子
//泛型版本,实现刚才的数组封装类
//类名后面就需要加上<E>,<>表示当前这个类是泛型类
//E相当于是一个形参,E表示某一中具体的类型
//会在实例化的时候确定E具体是哪种类型
public class MyArray2<E>{
//创建的数组,类型不是Object,而是直接使用E作为类型
//后续在实例化这个MyArray2时,确定了E是啥类型,也就知道了data最后的类型
private E[] data=null;
private int size=0;
private int capacity=10;
public MyArray2(){
//由于E这样的类型是不确定的,无法直接创建E类型的实例
data=(E[])new Object[capacity];
}
public void add(E data){
if(size >= capacity){
return;
}
this.data[size++] = data;
}
public E get(int index){
return this.data[index];
}
}
- 使用泛型的时候,在争对对象实例化的时候需要填入泛型参数的实际类型。
- 把这个实际参数填写进去之后,实际的泛型参数就被自动的替换成了String
- Java的泛型只能是引用类型,如果是内置类型,就需要对应的包装类
- Java的泛型,还是基于Object实现的,本质上还是Object[],就是帮助我们完成了类型校验和类型转换。
2.3泛型类的实例化
2.3.1实例化语法
泛型类<类型实参>变量名 :定义一个泛型类的引用。
new 泛型类<类型实参>(构造方法实参): 实例化一个泛型类的对象
2.3.2实例化的例子
public static void main(String[] args) {
//后面的尖括号中的内容可以省略
//因为前后泛型的参数必须是一致的
MyArray2<String> myArray2=new MyArray2<String>();
myArray2.add("hello");
myArray2.add("world");
//此时进行获取元素的时候,就不需要类型转换了
String str=myArray2.get(0);
MyArray2<Integer> myArray3=new MyArray2<>();
myArray3.add(10);
myArray3.add(20);
// myArray3.add("hello");
Integer ret=myArray3.get(0);
}
注意:
- 1.右侧<>中的类型可以省略
MyArray2<Integer> myArray3=new MyArray2<>();
- 在new MyArray2<>()对象时,<>中未明确指明类型,编译器会根据=左侧中<>的类型来推演。
- 2.左侧<>中的类型不能省略
MyArray2<> myArray3=new MyArray2<String>();//省略之后,编译失败
- 编译器在推演时,是根据左侧类型来推演右侧的
- 3.虽然右侧的<>可以不用写类型,但是<>不能省略
MyArray2<String> myArray3=new MyArray2();
- 上述代码会产生警告
2.4泛型类的定义-类型边界
- 类型边界:定义泛型类的时候,对未来实例化的时候传入的参数实参做出限制。
- 泛型参数这里的类型不应该随便填,要根据实际情况做出约束
public class MyArray2<E extends Animal>{
//创建的数组,类型不是Object,而是直接使用E作为类型
//后续在实例化这个MyArray2时,确定了E是啥类型,也就知道了data最后的类型
private E[] data=null;
private int size=0;
private int capacity=10;
public MyArray2(){
//由于E这样的类型是不确定的,无法直接创建E类型的实例
data=(E[])new Object[capacity];
}
public void add(E data){
if(size >= capacity){
return;
}
this.data[size++] = data;
}
public E get(int index){
return this.data[index];
}
public static void main(String[] args) {
//后面的尖括号中的内容可以省略
//因为前后泛型的参数必须是一致的
MyArray2<Bird> myArray4=new MyArray2<>();//编译成功,因为Bird是Animal的子类
MyArray2<String> myArray2=new MyArray2<>();//编译失败,因为String不是Animal的子类
myArray2.add("hello");
myArray2.add("world");
}
}
注意: 没有指定的类型的边界E,可以视为E extends Object