目录
一、泛型
(1)泛型的含义:
一般的类和方法,只能使用具体的类型: 要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大。
泛型是在JDK1.5引入的新的语法,通俗讲,泛型就是适用于许多类型。从代码上讲,就是对类型实现了参数化。
(2)泛型的主要目的:
就是指定当前的容器,要持有什么类型的对象。让编译器去做检查。此时,就需要把类型,作为参数传递。需要什么类型,就传入什么类型。
(3)泛型类:
1.语法:
class 泛型类名称<类型形参列表> {
// 这里可以使用类型参数
}
class ClassName<T1, T2, ..., Tn> {
}
class 泛型类名称<类型形参列表> extends 继承类/* 这里可以使用类型参数 */ {
// 这里可以使用类型参数
}
class ClassName<T1, T2, ..., Tn> extends ParentClass<T1> {
// 可以只使用部分类型参数
}
泛型类<类型实参> 变量名; // 定义一个泛型类引用
new 泛型类<类型实参>(构造方法实参); // 实例化一个泛型类对象
2.代码实例:
class MyArray<T>为自定义的泛型数组类,可以根据需要往数组填入整型(Integer)、浮点型(Float)、字符串型(String)等各种引用类型。
public class Generic为泛型测试类。 MyArray<Integer>myArray=new MyArray<>();类型后加入 <Integer> 指定当前类型。
注意:只能使用整型的参数,如果使用别的类型会报错。例如:myArray.setValue(1,“泛型”);“泛型”为字符串类型,程序会报错。
public class Generic {
public static void main(String[] args) {
MyArray<Integer>myArray=new MyArray<>();//泛型类的使用
myArray.setValue(0,7);
myArray.setValue(1,18);
int ret= myArray.getPosition(1);//无需类型转换
System.out.println(ret);
}
}
class MyArray<T>{
public T []array=(T[])new Object[10];//. 类名后的 <T> 代表占位符,表示当前类是一个泛型类
public T getPosition(int position){
return this.array[position];
}
public void setValue(int position,T value){
this.array[position]=value;
}
}
(4)泛型方法:
1.语法:
方法限定符 <类型形参列表> 返回值类型 方法名称(形参列表) { ... }
2.代码实例:
swap(E[ ]array,int i,int j)是自定义的一个泛型方法。相较之前每改变一个数组元素类型,就得重新定一个交换方法来说,使用泛型方法可以编写一个交换方法,实现各种元素类型的交换,类似于c++中的模板,十分简便。
public class Generic {
public static void main(String[] args) {
Integer[]array={1,2,3,4,5,6,7};
swap(array,0,1);
System.out.println(Arrays.toString(array));
String[]string={"hello","world"};
swap(string,0,1);
System.out.println(Arrays.toString(string));
}
//泛型方法
public static <E>void swap(E[]array,int i,int j){
//静态的泛型方法 需要在static后用<>声明泛型类型参数
E tmp=array[i];
array[i]=array[j];
array[j]=tmp;
}
}
(5)裸类型:
裸类型是一个泛型类但没有带着类型实参,MyArray list = new MyArray();(了解即可)
(6)泛型的上界:
在定义泛型类时,有时需要对传入的类型变量做一定的约束,可以通过类型边界来约束。
1.语法:
class 泛型类名称<类型形参 extends 类型边界> {
...
}
2.代码实例:
public class MyArray<E extends Number> {
...
}
只接受 Number 的子类型作为 E 的类型实参
MyArray<Integer> l1; // 正常,因为 Integer 是 Number 的子类型
MyArray<String> l2; // 编译错误,因为 String 不是 Number 的子类型
没有指定类型边界 E,可以视为 E extends Object
(7)泛型注意点:
1.泛型<...>闭合尖括号
2.泛型Object[],Object是所有类(包含接口)的祖先类,上层引用可以指向下层类型
3.java的泛型只能在编译阶段起作用
4.java的泛型只支持引用类型,不支持基本类型
二、包装类
因为java的泛型只支持引用,不支持基本类型。故而引出包装类
(1)基本数据类型及其包装类:
基本数据类型 | 包装类 |
byte | Byte |
int | Integer |
short | Short |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
(2)拆箱和装箱:
基本类型->包装类 装箱
包装类->基本类型 拆箱
1.代码实例:
以Integer,int类型为例
public class MyBoxing {
public static void main(String[] args) {
int a=1;
Integer ai=new Integer(1);//引用类型完整写法
// Integer ai=1;简写
a=ai.intValue();//装箱
ai=Integer.valueOf(a);//拆箱
}
}
但是编译器可以自动完成拆箱、装箱,所以如下写法也正确
public class MyBoxing {
public static void main(String[] args) {
int a=1;
Integer ai=new Integer(1);//引用类型完整写法
// Integer ai=1;
a=ai;//编译器可以自动完成
ai=a;
}
}
2.Integer和int比较问题:
int和int比较时,==和equals都可以,Integer和Integer比较时,==和equals有区别。==表示相等性,equals表示同一性。Integer和int比较,java会自动拆箱,变成int和int比较。
public class MyBoxing {
public static void main(String[] args) {
Integer b=1000;
Integer c=1000;
System.out.println(b==c);//false
System.out.println(b.equals(c));//true
int d=1000;//Integer和int比较,java会自动拆箱,变成int和int比较
System.out.println(d==c);//true
System.out.println(c.equals(d));//true
}
}
(3)类型转化:
x类型 a y类型 b
1.a=b语法不报错有一些几种情形
A.x类型和y类型是同一个类型
B.x类型和y类型都是基本类型,x表示范围>y
C.x类型和y类型都是引用类型,x类型是y类型的上级类型a)x是一个接口,y是一个类,y实现了x接口
b)x,y都是一个接口,y继承自x
c)x,y都是一个类,y继承自x
2.a=(x)b语法不报错有一些几种情形:
a)隐示转换
b)x类型和y类型都是基本类型,x范围<y
c)x类型和y类型都是引用类型,必须在继承链上