//泛型没有指定类型,默认就是Object
ArrayList list = new ArrayList();
list.add("Hello");
list.add("World");
list.add(100);
list.add(false);
//集合中的数据就比较混乱,会给获取数据带来麻烦
for (Object obj : list) {
String str = (String) obj;
//当遍历到非String类型数据,就会报异常出错
System.out.println(str + "长度为:" + str.length());
}
泛型在代码运行时,泛型会被擦除。后面学习反射的时候,可以实现在代码运行的过程中添加其他类型的数据到集合
当一个类定义其属性的时候,不确定具体是什么类型时,就可以使用泛型表示该属性的类型
举例 :
public class Student<X,Y>{
X xObj;
}
package com.itheima.genericity_demo.genericity_class;
import java.time.Period;
/*
需求 : 定义一个人类,定义一个属性表示爱好,但是具体爱好是什么不清楚,可能是游泳,乒乓,篮球。
*/
public class GenericityDemo {
public static void main(String[] args) {
Person<BasketBall> person = new Person<>();
person.setHobby(new BasketBall());
Person<Swim> person2 = new Person<>();
person2.setHobby(new Swim());
Person person3 = new Person<>();// 如果没有指定泛型 , 那么默认使用Object数据类型
}
}
class Person<H> {
// 定义属性表达爱好
private H hobby;
public H getHobby() {
return hobby;
}
public void setHobby(H hobby) {
this.hobby = hobby;
}
}
class Swim {
}
class PingPang {
}
class BasketBall {
}
当定义接口时,内部方法中其参数类型,返回值类型不确定时,就可以使用泛型替代了。
public interface Collection<E>{
public boolean add(E e);
}
package com.itheima.genericity_demo.genericity_interface;
/*
需求:
模拟一个Collection接口,表示集合,集合操作的数据不确定。
定义一个接口MyCollection具体表示。
*/
// 泛型接口
public interface MyCollection<E> {
// 添加功能
public abstract void add(E e);
// 删除功能
public abstract void remove(E e);
}
// 指定泛型的第一种方式 : 让实现类去指定接口的泛型
class MyCollectionImpl1 implements MyCollection<String>{
@Override
public void add(String s) {
}
@Override
public void remove(String s) {
}
}
// 指定泛型的第二种方式 : 实现类不确定泛型,延续泛型,回到泛型类的使用
class MyCollectionImpl2<E> implements MyCollection<E>{
@Override
public void add(E a) {
}
@Override
public void remove(E a) {
}
}
当定义方法时,方法中参数类型,返回值类型不确定时,就可以使用泛型替代了
package com.itheima.genericity_demo.genericity_method;
import java.util.ArrayList;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
// Collection集合中 : public <T> T[] toArray(T[] a) : 把集合中的内容存储到一个数组中 , 进行返回
ArrayList<String> list = new ArrayList<>();
list.add("abc");
list.add("ads");
list.add("qwe");
String[] array = list.toArray(new String[list.size()]);
System.out.println(Arrays.toString(array));
}
// 接收一个集合 , 往集合中添加三个待指定类型的元素
public static <X> void addElement(ArrayList<X> list, X x1, X x2, X x3) {
list.add(x1);
list.add(x2);
list.add(x3);
}
}
当我们对泛型的类型确定不了,而是表达的可以是任意类型,可以使用泛型通配符给定
符号就是一个问号:? 表示任意类型,用来给泛型指定的一种通配值。如下
public static void shuffle(List<?> list){
//…
}
说明:该方法时来自工具类Collections中的一个方法,用来对存储任意类型数据的List集合进行乱序
泛型通配符结合集合使用
package com.itheima.genericity_demo;
import java.util.ArrayList;
import java.util.List;
public class Demo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("abc");
list.add("asd");
list.add("qwe");
// 方法的参数是一个集合 , 集合的泛型是一个通配符 , 可以接受任意类型元素的集合
show(list);
}
public static void show(List<?> list) {
// 如果集合的泛型是一个通配符 , 那么集合中元素以Object类型存在
Object o = list.get(0);
// 如果集合的泛型是一个通配符 , 那么此集合不能进行添加和修改操作 , 可以删除和获取
// list.add(??);
// 删除可以
list.remove(0);
// 获取元素可以
for (Object o1 : list) {
System.out.println(o1);
}
}
}
package com.itheima.genericity_demo;
import java.util.ArrayList;
/*
已知存在继承体系:Integer继承Number,Number继承Object。
定义一个方法,方法的参数是一个ArrayList。
要求可以接收ArrayList<Integer>,ArrayList<Number>,ArrayList<Object>,ArrayList<String>这些类型的数据。
结论 : 具体类型的集合,不支持多态 , 要想接收任意类型集合 , 需要使通配符集合
*/
public class Test1 {
public static void main(String[] args) {
ArrayList<Integer> list1 = new ArrayList<>();
ArrayList<Number> list2 = new ArrayList<>();
ArrayList<String> list3 = new ArrayList<>();
ArrayList<Object> list4 = new ArrayList<>();
useList5(list1);
useList5(list2);
useList5(list3);
useList5(list4);
}
// 此方法只能接收存储Integer类型数据的集合
public static void useList1(ArrayList<Integer> list) {
}
// 此方法只能接收存储Number类型数据的集合
public static void useList2(ArrayList<Number> list) {
}
// 此方法只能接收存储String类型数据的集合
public static void useList3(ArrayList<String> list) {
}
// 此方法只能接收存储Object类型数据的集合
public static void useList4(ArrayList<Object> list) {
}
public static void useList5(ArrayList<?> list) {
}
}
受限泛型是指,在使用通配符的过程中 , 对泛型做了约束,给泛型指定类型时,只能是某个类型父类型或者子类型
分类 :
package com.itheima.genericity_demo.wildcard_demo;
import java.util.ArrayList;
/*
wildcardCharacter
基于上一个知识点,定义方法
show1方法,参数只接收元素类型是Number或者其父类型的集合
show2方法,参数只接收元素类型是Number或者其子类型的集合
*/
public class Test2 {
public static void main(String[] args) {
ArrayList<Integer> list1 = new ArrayList<>();
ArrayList<Number> list2 = new ArrayList<>();
ArrayList<Object> list3 = new ArrayList<>();
show1(list3);
show1(list2);
show2(list2);
show2(list1);
}
// 此方法可以接受集合中存储的是Number或者Number的父类型 , 下限泛型
public static void show1(ArrayList<? super Number> list) {
}
// 此方法可以接受集合中存储的是Number或者Number的子类型 , 上限泛型
public static void show2(ArrayList<? extends Number> list) {
}
}