1.包装类
在 Java 中,由于基本类型不是继承自 Object ,为了在泛型代码中可以支持基本类型, Java 给每个基本类型都对应了 一个包装类型。
1.1.基本的数据类型对应的包装类
1.2装箱和拆箱
//装箱
int a=10;
Integer c=Integer.valueOf(a);
System.out.println(c);
//拆箱
Integer b=new Integer(100);
int d=b.intValue();
System.out.println(d);
如图代码所示:
装箱:把一个基本数据类型转化为包装类型的过程。
拆箱:将 Integer 对象中的值取出,放到一个基本数据类型中。
1.3自动装箱与拆箱
//自动拆箱
Integer e=new Integer(100);
int f=e;
System.out.println(f);
//自动装箱
int t=99;
Integer g=t;
System.out.println(g);
2.泛型
什么是泛型:就是适用于许多许多类型。从代码上讲,就是对类型实现了参数化。
3.引出泛型
如果我们创建一个数组,可以存储所有基本类型的数据,纳闷该如何实现呢
1. 我们以前学过的数组,只能存放指定类型的元素,例如: int[] array = new int[10]; String[] strs = new String[10];2. 所有类的父类,默认为 Object 类。数组是否可以创建为 Object?
代码实现如下:
Array array=new Array();
array.set(0,"string");
array.set(1,1);
Object ret=array.get(0);
Object ret1=array.get(1);
System.out.println(ret);
System.out.println(ret1);
}
}
class Array{
Object o[]=new Object[10];
public void set(int index,Object data){
o[index]=data;
}
public Object get(int index){
return o[index];
}
}
输出:
string 1
可以看到完成了,存储多种类型的数据。
但是如果我们指定一种类型去接收时:必须完成强转
虽然在这种情况下,当前数组任何数据都可以存放,但是,更多情况下,我们还是希望他只能够持有一种数据类 型。而不是同时持有这么多类型。所以,泛型的主要目的:就是指定当前的容器,要持有什么类型的对象。让编译 器去做检查。
3.1.语法
定义泛型类:
class 泛型类名称 < 类型形参列表 > {// 这里可以使用类型参数}
class 泛型类名称 < 类型形参列表 > extends 继承类 /* 这里可以使用类型参数 */ {// 这里可以使用类型参数}
实例化:
泛型类 < 类型实参 > 变量名 ; // 定义一个泛型类引用new 泛型类 < 类型实参 > ( 构造方法实参 ); // 实例化一个泛型类对象
对上述代码进行改进后:
Array<String> array=new Array<>();
array.set(1,"string");
String ret= array.get(1);
System.out.println(ret);
}
}
class Array<T>{
Object[] o=new Object[10];
public void set(int index,T data){
o[index]=data;
}
public T get(int index){
return (T) o[index];
}
}
可以看到此时在实例化的时候,就可以指定参数类型。
1.注意:再返回数据时,要进行强转,因为在数组声明时就规定了类型。
那为啥不对T类型的数组进行实例化呢?
因为泛型不能进行实例化。
2.在set方法存入数据时,因为指定了类型为String类型,所以不能放入其他类型,否则就会报错。
3.在实例化时加入尖括号里面的内容是包装类型。
4.泛型小结
1. 泛型是将数据类型参数化,进行传递2. 使用 <T> 表示当前类是一个泛型类。3. 泛型目前为止的优点:数据类型参数化,编译时自动进行类型检查和转换
5.泛型擦除机制
即编译的时候将所有的T擦除为Object,运行的时候没有泛型这样的概念,简单来说,泛型的擦除机制只存在于编译当中。
有关泛型擦除机制的文章截介绍:https://zhuanlan.zhihu.com/p/51452375
6.泛型的上界
在定义泛型类时,有时需要对传入的类型变量做一定的约束,可以通过类型边界来约束。
6.1.语法
class 泛型类名称 < 类型形参 extends 类型边界 > {...}
public class MyArray < E extends Number > {...}在这里用Number为子类的,MyArray < Integer > l1 ; // 正常,因为 Integer 是 Number 的子类型MyArray < String > l2 ; // 编译错误,因为 String 不是 Number 的子类型
这里如果没有上界,可以视为:
E extends Object
6.2.复杂实例
如图所示:
在定义一个泛型类来比较大小时,报错了。
此时我们就要去设置一个上界。
代码如下:
Array<String> array = new Array<>();
String arr[] = {"hello","world"};
String a = array.findMax(arr);
System.out.println(a);
}
}
class Array<T extends Comparable<T>> {
public T findMax(T[] array){
T max=array[0];
for (int i = 0; i <array.length ; i++) {
if(array[i].compareTo(max)>0){
max=array[i];
}
}
return max;
}
}
小编在这里设置了一个上界comparable,可以进行comparaTo方法的调用,当然改为整型也是可以的。
为啥比较是出现问题?
因为泛型的擦除机制,将T类型换成了Object,此时两个Object不能比较,要引用comparaTo方法。
7.泛型的方法
方法限定符 < 类型形参列表 > 返回值类型 方法名称 ( 形参列表 ) { ... }
实例代码:
Array1 array1=new Array1();
String arr1[]={"hello","world"};
String ret=array1.<String>findMax(arr);
System.out.println(ret);
}
}
class Array1{
public <T extends Comparable<T>> T findMax(T[] array){
T max=array[0];
for (int i = 0; i <array.length ; i++) {
if(array[i].compareTo(max)>0){
max=array[i];
}
}
return max;
}
}
当然在调用时,也不用加尖括号声明类型形参,因为在编译时,会自动匹配所对应的类型。
如果不想实例化对象,可以将方法设置为静态方法。
8.总结
由于小编能力有限,可能存在一些有误的地方,希望各位uu提出宝贵意见。
制作不易,麻烦给小编点个赞吧。