泛型 (常用的泛型标识:T、E、K、V)
<? extends Person> 泛型上限 类型为Person 或Person的子类
<? super student> 泛型下限 类型为student 或student的父类
泛型上限:可以在定义泛型类和方法参数上使用
泛型下限:主要在方法参数上使用
1、泛型类:(是在实例化类的时候指明泛型的具体类型)
1)、泛型的类型参数只能是引用类型,值类型需要使用对应的包装类类型
2)、泛型类,如果没有指定具体的数据类型,此时操作类型是Object
3)、泛型类型在逻辑上可以看成是多个不同的类型,但实际上都是相同类型
4)、泛型类的成员方法,不能定义为 static
public class A<T>{
private T key;
public A(T key){
this.key = key;
}
public T getKey(){
return key;
}
public void setKey(T key){
this.key = key;
}
// 泛型类的成员方法,不能定义为 static
// public static T methodA(){
// }
}
2、泛型方法:(是在调用方法的时候指明泛型的具体类型)
Integer[] arr = {1, 8, 15, 6, 3};
Double[] douArr = {10.5, 25.1, 4.9, 1.8};
String[] strArr = {"我","是","字","符","串"};
methodB(strArr); // 如果不是泛型,就要对这三种类型的数据分别重载methodB的方法
public <E> E methodA(ArrayList<E> list){
return list.get(random.nextInt(list.size));
}
public <E> E methodB(E[] arr){
return arr[2];
}
public <E> E methodC(E e){
return e;
}
public static <E> void methodB(E[] arr){
for(int i=0;i<arr.length; i++){
System.out.println(arr[i]);
}
}
3、继承:
子类也是泛型类,子类和父类的泛型类型要一致
class ChildGeneric < T > extends Generic < T >
子类不是泛型类,父类要明确泛型的数据类型
class ChildGeneric extends Generic< String >
//子类也是泛型类,子类和父类的泛型类型要一致
public class ChildGeneric<T> extends Generic<T> {
public ChildGeneric(T key) {
super(key);
}
}
//子类不是泛型类,父类要明确泛型的数据类型
public class ChildGeneric extends Generic<String> {
public ChildGeneric(String key) {
super(key);
}
}
// 父类
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;
}
@Override
public String toString() {
return "Generic{" +
"key=" + key +
'}';
}
}
4、泛型接口:
1、实现类不是泛型类,接口要明确数据类型
class B implements A < String > {}
2、实现类也是泛型类,实现类和接口的泛型类型要一致
class B < T > implements A < T > {}
interface 接口名 <泛型标识1,泛型标识2,...>{
泛型标识 方法名();
...
}
//实现类不是泛型类,接口要明确数据类型
public class Test01 implements I_Generic<String> {
@Override
public String getKey() {
return null;
}
}
//实现类也是泛型类,实现类和接口的泛型类型要一致
public class Test01<T> implements I_Generic<T> {
@Override
public T getKey() {
return null;
}
}
public interface I_Generic<T> {
T getKey();
}
5、类型擦除
//无限制类型擦除
public class Erasure<T>{
public T key;
public T getKey(){
return key;
}
public void setKey(T key){
this.key = key;
}
}
=>
public class Erasure {
public Object key;
public Object getKey(){
return key;
}
public void setKey(Object key){
this.key = key;
}
}
//有限制类型擦除
public class Erasure<T extends Number>{
public T key;
public T getKey(){
return key;
}
public void setKey(T key){
this.key = key;
}
}
=>
public class Erasure {
public Number key;
public Number getKey(){
return key;
}
public void setKey(Number key){
this.key = key;
}
}
//擦除方法中类型定义的参数
public <T extends Number> T getValue(T value){
return value;
}
=>
public Number getValue(Number value){
return value;
}
//桥接方法
public interface Info<T>{
T info(T var);
}
public class InfoImpl implements Info<Integer>{
@Override
public Integer info(Integer var){
return var;
}
}
=>
public interface Info{
Object info(Object var);
}
public class InfoImpl implements Info{
public Integer info(Integer var){
return var;
}
// 桥接方法,保持接口和类的实现关系
@Override
public Object info(Object var){
return info((Integer) var);
}
}
6、泛型数组的创建
可以声明带泛型的数组引用,但是不能直接创建带泛型的数组对象
//不能直接创建带泛型的数组对象
ArrayList<String>[] listArr = new ArrayList<String>[5]
ArrayList<String>[] listArr = new ArrayList[5];
ArrayList<Integer>[] listArr = new ArrayList<>();
//弊端例子:
ArrayList[] list = new ArrayList[5];
ArrayList<String>[] listArr = list;
ArrayList<Integer>intList = new ArrayList<>();
intList.add(100);
list[0] = intList; //整数数组付给了String泛型数组
//就会出现数据类型转换异常“java.lang.ClassCastException”
//可以通过java.lang.reflect.Array的newInstance(Class<T>,int) 创建T[]数组
实例:抽奖活动
1、抽奖品
2、抽现金
//RaffleTest.java
import java.util.ArrayList;
public class RaffleTest {
public static void main(String[] args) {
//1、抽奖品
ArrayList<String> list = new ArrayList<>();
list.add("笔记本电脑");
list.add("华为手机");
list.add("机器人扫地机");
Raffle<String> raffle1 = new Raffle<>();
String raf1 = raffle1.getRaffle(list);
System.out.println(raf1);
System.out.println("-----------------------------------");
//2、抽现金
ArrayList<Integer> list2 = new ArrayList<>();
list2.add(5000);
list2.add(3000);
list2.add(2000);
list2.add(1000);
Raffle<Integer> raffle2 = new Raffle<>();
Integer raf2 = raffle2.getRaffle(list2);
System.out.println(raf2);
}
}
// Raffle.java
import java.util.ArrayList;
import java.util.Random;
public class Raffle<T> {
private T raf;
public Raffle() {
}
public Raffle(T raf) {
this.raf = raf;
}
public T getRaf() {
return raf;
}
public void setRaf(T raf) {
this.raf = raf;
}
Random random = new Random();
public <E> E getRaffle(ArrayList<E> list){
int i =random.nextInt(list.size());
return list.get(i);
}
}