目录
泛型
泛型的语法:
泛型类
基本数据类型和对应的包装类
泛型方法:
语法:
小结:
如下是定义了一个类,这个类中可以存放一组 int 类型的数据。
class Number{
int[] arr;
public Number(int a) {
this.arr = new int[10];
this.arr[0] = a;
}
public void setArr(int n, int data) {
this.arr[n] = data;
}
public int getArr(int n) {
return arr[n];
}
}
可是虽然这样写没有问题可是它的应用范围实在是太小了,它只能存储 int 类型的数据。如果我们现在想让这个类中可以存放任何类型的数据应该怎么做呢?
在 JAVA 中利用泛型就可以实现这点。
泛型:就是适用于许多许多类型。从代码上讲,就是对类型实现了参数化。
class 泛型类名称<类型形参列表> {
}class ClassName<T1, T2, ..., Tn> {
}
类名后的
类型形参一般使用一个大写字母表示,常用的名称有:
- E 表示 Element
- K 表示 Key
- V 表示 Value
- N 表示 Number
- T 表示 Type
- S, U, V 等等 - 第二、第三、第四个类型
我们将开始的代码进行改进:
class Number{
Object[] arr;//这里可以暂时忽略Object,下文会说
public Number(T a) {
this.arr = new Object[10];
this.arr[0] = a;
}
public void setArr(int n, T data) {
this.arr[n] = data;
}
public T getArr(int n) {
return (T)arr[n];
}
}
在 JAVA 中由于数组比较特殊,不能new泛型类型的数组,数组在new的时候必须要指定其类型所以如果定义成这样就会报错 。
为了不让它报错就需要进行强制类型转换因为 Object类 是所有类的父类所以也可以这样定义:
虽然这样写编译器没有报错可是还是报了警告,也就是说我们这样写会存在安全隐患。
这里推荐将数组定义成这样:
调用的时候需要注意:
如果是简单类型(如:int , char……)必须要传对应的包装类。
基本数据类型 | 包装类 |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
这个表看起来多其实除了 Integer 和 Character, 其余基本类型的包装类都是首字母大写。
如图,此时我们的类泛用性就非常高了,我们可以使用 main 方法测试一下:
public static void main(String[] args) {
Number a = new Number<>(3);
Number b = new Number<>(3.14);
Number c = new Number<>("hello");
System.out.println(a.getArr(0));
System.out.println(b.getArr(0));
System.out.println(c.getArr(0));
}
泛型除了可以应用于类之外也可以应用于方法。
方法限定符 <类型形参列表> 返回值类型 方法名称(形参列表) { ... }
public static void swap(T[] array, int i, int j) {
T t = array[i];
array[i] = array[j];
array[j] = t;
}
泛型方法也和类一样不能使用基本类型,需要使用对应的包装类。
我们可以测试一下:
public static void main(String[] args) {
Integer[] b = {1,2,3,4};
swap(b, 0, 1);
System.out.println(Arrays.toString(b));
}
泛型类<类型实参> 变量名; // 定义一个泛型类引用
new 泛型类<类型实参>(构造方法实参); // 实例化一个泛型类对象,此时可以省略类型实参Number
a = new Number<>(3); Number
list = new Number (3);
- 泛型是将数据类型参数化,进行传递
- 使用
表示当前类是一个泛型类。 - 泛型目前为止的优点:数据类型参数化,编译时自动进行类型检查和转换