1.包装类
1.1基本数据类型和对应的包装类
在Java中,由于基本数据类型不是继承自Object,为了在泛型代码中可以支持基本类型,java给每个基本类型都对应了一个包装类型。
基本数据类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
除了int和char,其余的都是对应的首字母大写。
1.2装箱和拆箱
装箱:把基本数据类型变为包装类型
int a=10;
Integer val=a;//自动
Integer val2=Integer.valueOf(a);//显示装箱
Integer val3=new Integer(a);//显示装箱
拆箱:把包装类型变为基本数据类型
Integer val=10;
int a=val;//拆箱-》引用类型变为了基本数据类型
//显示拆箱
int b=val.intValue();
double d=val.doubleValue();
Integer类里面有很多这样的方法:
问题1.1:
下面代码输出什么?
上述代码隐式的调用了valueOf()方法,此方法中当i>=low(-128)&&i<=high(127)时,返回cache数据中下标为【0,256】当中的值。所以当i>=-128&&i<=127时,上述代码返回true,否则新建一个Integer的对象,返回false。
2.泛型
一般的类和方法,只能使用具体的数据类型(基本数据类型或自定义的类),为了取消这种束缚,映出了泛型。
public static void main1(String[] args) {
MyArray myArray=new MyArray();
myArray.setObj(0,10);
myArray.setObj(1,"hello");
myArray.setObj(2,10.0);
double d=(double)myArray.getPos(2);
}
class MyArray{
public Object[] obj=new Object[3];
public Object getPos(int pos){
return obj[pos];
}
public void setObj(int pos,Object val){
obj[pos]=val;
}
}
上述代码实现后发现任何数据都可以存放,但是必须进行强制类型转换。所以我们让它只允许存放一中数据类型,泛型的主要目的就是指定当前的容器持有什么类型的对象,让编译器去做检查。这样就可以把类型作为参数传递,需要什么类型就传入什么类型。
对上述代码做改写:
public static void main(String[] args) {
//实例化对象的同时,指定当前泛型类型的参数类型是Integer
MyArray1<Integer> myArray=new MyArray1<>();
//这样就可以存储指定类型的数据
myArray.setObj(0,10);
myArray.setObj(1,12);
myArray.setObj(2,34);
Integer d=myArray.getPos(2);
}
class MyArray1<T>{//泛型类
//不能new泛型类型的数组
public T[] obj=(T[])new Object[3];
public T getPos(int pos){
return obj[pos];
}
public void setObj(int pos,T val){
obj[pos]=val;
}
}
类名后面的代表当前类是一个泛型类。
规范:E表示Element,K表示Key,V表示Value,N表示Number,T表示Type,S,U,V表示第二,第三,第四个类型。
泛型的好处:存储元素的时候,可以进行自动类型检查,获取元素的时候,可以进行类型转换。
类型推导:当编译器可以根据上下文推导出实参时,可以省略类型实参的填写
//可以推导出实例化需要的类型实参位Integer
MyArray1<Integer> myArray1=new MyArray1<>();
问题3.1:
Java泛型怎么编译的?
擦除机制:JVM运行时没有泛型的概念,编译完成后泛型类型擦除为Object。
public Object[] obj=new Object[3];
public E getPos(int pos){
return (E)obj[pos];
}
4.泛型的上界
class Alg<E extends Comparable<E>>{}
称为泛型的上界,代表将来指定的参数类型一定实现了这个接口。
代表E是Number的子类或E是Number本身
下面一段代码实现了用泛型找出数组中的最大元素:
class Alg<E extends Comparable<E>>{
public E findMax(E[] array){
E max=array[0];
for(int i=1;i<array.length;i++){
//小于0代表max<array[i]
if(max.compareTo(array[i])<0){
max=array[i];
}
}
return max;
}
}
public class Test2 {
public static void main(String[] args) {
Alg<Integer> alg=new Alg<>();
Integer[] array={1,4,1,10,5,6,8};
Integer val=alg.findMax(array);
System.out.println(val);
}
}
泛型方法:
class Alg2{
public<E extends Comparable<E>> E findMax(E[] array){
E max=array[0];
for(int i=1;i<array.length;i++){
//小于0代表max<array[i]
if(max.compareTo(array[i])<0){
max=array[i];
}
}
return max;
}
}