泛型
泛型的使用
- 1.
jdk5.0
新增特性 - 2.在集合中使用泛型
1、集合接口或集合类在jdk5.0时都修改为带泛型的结构
2、在实例化集合类时,指明具体的泛型类型
- 3、指明类型后,在集合类或接口中凡是定义类或接口时,内部结构(方法、构造器、属性)等使用泛型的位置都指定为实例化的泛型类型
比如:add(E e) —>实例化后add(Integer e)
- 4、注意:泛型必须是类,不能是基本数据类型。需要用到基本数据类型的位置,使用包装类替换
- 5.如果实例化时,没有指明泛型的类型。默认类型为Object类型
在集合中不使用泛型
@Test
//在集合中不使用泛型的情况
public void test(){
ArrayList list = new ArrayList();
list.add(123);
list.add(23);
list.add(245);
//问题一:类型不安全
list.add("zmj");
//遍历
for(Object obj : list){
//问题二:强转时,可能出现异常ClassCastException
Integer integer = (Integer) obj;
System.out.println(integer);
}
}
在集合中使用泛型
- 指明泛型后,非泛型指定类型直接会在编译时进行类型检查,保证数据的安全
@Test
public void test1(){
ArrayList<Integer> list = new ArrayList<>();
list.add(123);
list.add(23);
list.add(245);
//指明泛型后,非泛型指定类型直接会在编译时进行类型检查,保证数据的安全
//list.add("zmj");
//遍历
for(Integer integer : list){
System.out.println(integer);
}
}
@Test
public void test3(){
//在集合中使用泛型的情况:以HashMap为例
HashMap<String, Integer> map = new HashMap<>();
map.put("AA",123);
map.put("CC",125);
map.put("BB",124);
//遍历所有的key
Set<String> set = map.keySet();
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println("**********");
//遍历所有的value
Collection<Integer> values = map.values();
for(Integer integer:values){
System.out.println(integer);
}
//遍历所有的key-value
//方式一、entrySet()
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
Iterator<Map.Entry<String, Integer>> iterator1 = entrySet.iterator();
while (iterator1.hasNext()){
//entrySet集合中的元素都是entry
Map.Entry<String, Integer> entry = iterator1.next();
System.out.println(entry.getKey() + "===>" + entry.getValue());
}
// //遍历所有的key-value
// //方式二、分别遍历key和value,然后显示
// Set set1 = map.keySet();
// Collection values1 = map.values();
// Iterator iterator2=set.iterator();
// Iterator iterator3=values.iterator();
// while (iterator2.hasNext()&&iterator3.hasNext()){
// System.out.println(iterator2.next() + "===>" + iterator3.next());
// }
//
}
泛型类
- 静态方法中不能使用类的泛型
- 异常类不能使用泛型
/**
* Created by KingsLanding on 2022/6/29 15:03
*/
public class Order<T> {
String orderName;
int orderId;
//类的内部结构就可以使用类的泛型
T orderT;
public Order() {
}
public Order(String orderName, int orderId, T orderT) {
this.orderName = orderName;
this.orderId = orderId;
this.orderT = orderT;
}
public T getOrderT() {
return orderT;
}
public void setOrderT(T orderT) {
this.orderT = orderT;
}
@Override
public String toString() {
return "Order{" +
"orderName='" + orderName + '\'' +
", orderId=" + orderId +
", orderT=" + orderT +
'}';
}
//静态方法中不能使用类的泛型
// public static void show(T orderT){
//
// }
//异常类不能使用泛型
//泛型方法:在方法中出现的泛型结构,泛型参数和类的泛型参数没有任何关系
//泛型方法所属的类是不是泛型类都无所谓
//泛型方法可以声明为静态的。原因:泛型参数是在调用方法是才确定的,并非在实例化时确定
public <E> List<E> copyFromArrayToList(E[] arr){
ArrayList<E> list = new ArrayList<>();
for(E e : arr){
list.add(e);
}
return list;
}
}
泛型类的实例化
public void test(){
//如果定义了泛型类,实例化没有指明类的泛型,则默认此泛型类型为Object类型
//要求:如果定义了类是带泛型的,建议在实例化时要指明类的泛型
Order order = new Order();
order.setOrderT(12);
order.setOrderT("zmj");
//指明实例化时类的泛型
Order<String> order1 = new Order<String>("zmj",12,"ZMJ");
// Order<String> order1 = new Order<String>("zmj",12,20);//指定了泛型,这里就不能设置为除String之外的数据了
}
泛型方法
//泛型方法:在方法中出现的泛型结构,泛型参数和类的泛型参数没有任何关系
//泛型方法所属的类是不是泛型类都无所谓
//泛型方法可以声明为静态的。原因:泛型参数是在调用方法是才确定的,并非在实例化时确定
public <E> List<E> copyFromArrayToList(E[] arr){
ArrayList<E> list = new ArrayList<>();
for(E e : arr){
list.add(e);
}
return list;
}
方法调用
@Test
public void test2(){
Order<String> order = new Order<>();
Integer[] arr = new Integer[]{1,2,3,4};
//泛型方法在调用是,指明泛型参数的类型
List<Integer> list = order.copyFromArrayToList(arr);
System.out.println(list);
}
泛型在继承中的体现
非泛型类继承泛型类
public class SubOrder extends Order<Integer>{//SubOrder不是泛型类
}
泛型类之间的继承
/**
* Created by KingsLanding on 2022/6/29 15:14
*/
public class SubOrder1<T> extends Order<T> {//SubOrder1<T>仍然是泛型类
}
实例化
public void test1(){
SubOrder subOrder = new SubOrder();
//由于子类在继承带泛型的父类时,指明了泛型类型,则实例化子类对象时,不需要指明泛型,只能遵循父类的要求
subOrder.setOrderT(12);
SubOrder1<String> stringSubOrder1 = new SubOrder1<>();
stringSubOrder1.setOrderT("zmj");
}
- 虽然类A是B的父类,但是G 和G二者不具备子父类关系,二者是并列关系
- 补充:类A是类B父类,A 的父类
/*
1.泛型在继承方面的体现
虽然类A是B的父类,但是G<A> 和G<B>二者不具备子父类关系,二者是并列关系
补充:类A是类B父类,A<G> 是B<G>的父类
*/
public void test(){
Object obj=null;
String str=null;
obj=str;
//没有子父类关系,编译不通过
// Date date=null;
// str=date;
Object[] arr1=null;
String[] arr2=null;
arr1=arr2;
List<Object> list=null;
List<String> list1 =null;
//此时的list和list1的类型不具有子父类关系,编译不通过
// list= list1;
}
public void test2(){
List<String> list1=null;
ArrayList<String> list2=null;
//此时的list1和list1的类型具有子父类关系,编译通过
list1 = list2;
}
通配符
- 通配符:?
通配符的使用
@Test
public void test3(){
/*
2.通配符的使用
通配符:?
*/
List<Object> list=new ArrayList<>();
List<String> list1=new ArrayList<>();
list.add(123);
list1.add("zmj");
List<?> list2=null;
list2=list;
list2=list1;
//添加:对于List<?>不能向其内部添加数据
//除了添加null之外
// list2.add("除了null都添加不了");
list2.add(null);
//获取:允许读取数据,读取的数据类型为Object
Object o = list2.get(0);
System.out.println(o);
//通配符使用:同一个方法可以传不同类型的集合
test4(list);
test4(list1);
}
public void test4(List<?> list){
Iterator<?> iterator = list.iterator();
while (iterator.hasNext()){
Object obj = iterator.next();
System.out.println(obj);
}
}
有限制条件的通配符
- ?extends A:
G<? extends A> 可以作为G和G的父类,其中B是A的子类 <=
G<? super A> 可以作为G和G的父类,其中B是A的父类 >=
父类
/**
* Created by KingsLanding on 2022/6/29 19:42
*/
public class Person {
}
子类
/**
* Created by KingsLanding on 2022/6/29 19:42
*/
public class Student extends Person {
}
/*
3.有限制条件的通配符的使用
?extends A:
G<? extends A> 可以作为G<A>和G<B>的父类,其中B是A的子类 <=
G<? super A> 可以作为G<A>和G<B>的父类,其中B是A的父类 >=
*/
public void test5(){
List<Student> student = new ArrayList<>();
List<Person> person = new ArrayList<>();
List<Object> obj = new ArrayList<>();
List<? extends Person> list=null;
List<? super Person> list1=null;
list = student;
list = person;
//编译不通过,<=
// list = obj;
//编译不通过,>=
// list1=student;
list1=person;
list1=obj;
//读取数据
Person person1 = list.get(0);
//编译不通过
// Student stu = list.get(0);
Object object = list1.get(0);
//编译不通过
// Person pson = list1.get(0);
//写入数据
//编译不通过
// list.add(new Student());
// list.add(new Person());
//编译通过
list1.add(new Person());
list1.add(new Student());
}