1.前言
泛型 其实就是对类型的进行参数化(可以传类型)!
类型参数化又是啥呢?
栗子:
实现一个类,类中有一个数组,该数组可以存放任意类型的数据!
答:将数组定义为Object(是所有类的父类)。但是如果想取出的时候,Object数组不能强转!
原因:可以理解为 无法确定Object数组内全都是String类型,不能进行转换!
总结:Object数组不能强转
<T> 是占位符 代表该类是泛型类
class MyArray<T>{
public T[] obj = (T[])new Object[10]; //这里其实也是错的
public T getObj(int pos) {
return obj[pos];
}
public void setObj(T val,int pos) {
obj[pos] = val;
}
}
public class Test {
public static void main2(String[] args) {
MyArray<Integer> myArray = new MyArray<>();
myArray.setObj(12,3);
myArray.setObj(1,2);
myArray.setObj(2,1);
myArray.setObj(22,0);
//System.out.println(myArray.getObj(0));
MyArray<String> m = new MyArray<>();
m.serObj("ss",1);
//以前都是传数据,这里直接传类型
}
}
这样做 取数的时候就不需要强转!
因此泛型存在的意义:
1.存元素的时候,会进行类型检查
2.取的时候,不需要类型转换 (都在编译的时候完成)
2.语法
class 泛型类名称<类型形参列表> {
// 这里可以使用类型参数
}
class ClassName<T1, T2, ..., Tn> {
}
<> 里面必须存放的是 类类型!!!
3.泛型是如何编译的?
擦除机制:在编译的时候,将所有的T擦除成Object
Java的泛型机制是在编译级别实现的。编译器生成的字节码在运行期间并不包含泛型的类型信息。
那有擦除的话
public T[] obj = new T[10];//为什么会报错呢?
因为,如果是这样想,假如说有个return 整个obj数组的方法,用什么接受呢?
4.泛型的上界
public class MyArray<E extends Number>{
//extends 不是继承的意思,而是 E 是Number的子类或者是其自身!
}
(拦着你,不会被擦成object 而是擦成Number)
栗子:找最大值
class Alg<T extends Comparable<T>>{
public T findMax(T[] array){
T max = array[0];
for(int i = 1;i < array.length;i++){
if(max.compareTo(array[i]) < 0){
max = array[i];
}
}
return max;
}
}
public class Test {
public static void main(String[] args) {
Alg<Integer> alg = new Alg<>();
Integer[] arr = {12,32,213,245,23,5246,24};
System.out.println(alg.findMax(arr));
}
}
如果我们不想new一个alg对象吗?
(泛型方法)
class Alg2{
public static<T extends Comparable<T>> T findmax(T[] array){
T max = array[0];
for(int i = 1;i < array.length;i++){
if(max.compareTo(array[i]) < 0){
max = array[i];
}
}
return max;
}
}
泛型方法(非静态)
class Alg3{
public <T extends Comparable<T>> T findmax(T[] array){
T max = array[0];
for(int i = 1;i < array.length;i++){
if(max.compareTo(array[i]) < 0){
max = array[i];
}
}
return max;
}
}
需要new对象,但不需要传泛型参数
5.通配符
如果出现这种情况该怎么办呢?
public class TestDemo {
public static void main(String[] args) {
Message<Integer> message = new Message() ;
message.setMessage(99);
fun(message); // 出现错误,只能接收String
}
public static void fun(Message<String> temp){
System.out.println(temp.getMessage());
}
使用通配符!
public class TestDemo {
public static void main(String[] args) {
Message<Integer> message = new Message() ;
message.setMessage(55);
fun(message);
}
// 此时使用通配符"?"描述的是它可以接收任意类型,但是由于不确定类型,所以无法修改
public static void fun(Message<?> temp){
//temp.setMessage(100); 无法修改!
System.out.println(temp.getMessage());
}
因此在这里的尖括号中,直接给你擦没了
不参与类型的组成!!!!
6.通配符的上界/下界
? extends 类:设置泛型上限
? super 类:设置泛型下限