【百日精通JAVA | 数据结构篇】 一文了解泛型体系
一、初识泛型
在推出泛型以前,程序员可以创建一个元素类型Object的集合,该集合能够存储任意的数据类型对象,而在使用该集合的过程中,需要明确知道存储每个元素的类型,否则容易引发ClassCastException异常。
泛型是JDK1.5引入的新语法,通俗讲,泛型:就是适用于许多许多类型。从代码讲,就是对类型实现了参数化。
JAVA为什么推出泛型?
当Integer类型转换成String型时,会发生类型转换错误,并且编译时不会发生错误,很容易项目上线时,发生报错,为了应对这种情况,推出了泛型。
泛型的概念?
Java泛型时JDK5引入的一个新特性,泛型提供了编译时类型安全监测机制,该机制允许我们编译时检测到非法的类型数据结构
泛型的优点?
1.编译时,类型检查
2.编译时,类型转换
注意:泛型只存在编译时,运行时不存在泛型这个概念,同时泛型只能接收包装类型,不能接受普通类型
实现了一类,类中包含了一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中某个下标的值
二、泛型类、接口
泛型类的语法
Generic.java
package demo;
/*
@param<T>泛型标识————类型形参T 创建对象的时候里指定具体的数据类型
*/public class Generic<T>
{private T key;public Generic(T key){this.key = key;}public T getKey() {return key;}public void setKey(T key) {this.key = key;}@Overridepublic String toString() {return "Generic{" +"key=" + key +'}';}
}
MainClass.java
public class MainClass {public static void main(String[] args) {//泛型类在创建对象的时候,来具体类型Generic<String> strGeneric = new Generic("a");String k1 = strGeneric.getKey();System.out.println(k1);System.out.println("---------------------------------");Generic<Integer> integerGeneric = new Generic<>(123123213);int key2 = integerGeneric.getKey();System.out.println(key2);System.out.println("-------------------------");Generic gen = new Generic();//"当我们不对其使用泛型指定类型时,里面可存储的值可以为类型类型"}
}f
注意:
泛型不支持基本数据类型,只支持类类型
引用类型无法通过大于和小于进行比较
泛型类型逻辑上可以看作不同类型,实际上都是相同类型
三、泛型的接口
泛型接口的定义语法
Interface 接口名称<泛型标识,泛型标识,...>{
泛型标识 方法名();
}
实现泛型接口的类,不是泛型类,需要明确实现泛型接口的数据类型。
四、泛型方法
前面我们知道,泛型类,是在实例化类的时候指明泛型的具体类型;而泛型方法,是在调用方法的时候指明泛型的具体类型。
最重要的一点我们之前使用的方法,其实只是实参是泛型参数的普通方法,并不叫做泛型方法。
public class xx<T>
{
private T key;
Public T setKey(T key)
{this.key = key;
}
Public T getKey()
{return key;}
}
定义一个泛型方法需要在返回值前面定义一个<>,里面填入泛型参数,T E ... 等等泛型参数
Public 与返回键中间<T>非常重要,可以理解为声明此方法为泛型方法
只有声明了<T>的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。
<T>表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T
泛型方法与可变参数
为什么静态方法访问不了类上的泛型参数
这是因为,我们在指定泛型参数的具体类型时,是在实例化该类时指定的,实例化后和类型有关,所以静态方法和静态属性访问 泛型参数,必须在static后添加<T,E......>
五、类型通配符
类型通配符一般是使用”?“代替具体实参类型
所以,类型通配符是类型实参,而不是类型形参。
Box.java
package Demo01;public class Box<E> {private E first;public E getFirst() {return first;}public void setFirst(E first) {this.first = first;}}
Test.java
package Demo01;
public class Test {public static void main(String[] args) {Box<Number> box1= new Box<>();box1.setFirst(100);showBox(box1);Box<Integer> box2 = new Box<>();box2.setFirst(200);showBox(box2);}public static void showBox(Box<?> box){Object first = box.getFirst();System.out.println(first);}
}
六、类型擦除
编译阶段,编译器会进行类型检测, 一旦通过编译检测,进入运行阶段,此时泛型这个概念就会消失,通常我们说的,泛型只停留在编译阶段就是这个道理,所有的对象都属于普通类,所以下面这段代码的运行结果为true.
类型参数带来了许多弊端
①、不支持基本类型
②、只有原始类型class
③、不能实例化类型参数
④、不能实例化泛型数组
七、类型的上界
这个地方意味着T必须实现他的上界Comparabe<T>接口
class Alg<T extends Comparable<T>>
{public T findMax(T[] array){T max = array[0];for (int i = 0; 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[] array = {1,5,2,7,19,4};Integer max = alg.findMax(array);System.out.println(max);}
}