泛型的理解
泛型类似于标签,告诉java这里面存放的是什么类型的东西。
把元素的类型设计成一个 参数,这个类型参数叫做泛型。
泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类 型或者是某个方法的返回值及参数类型。这个类型参数将在使用时(例如, 继承或实现这个接口,用这个类型声明变量、创建对象时)确定(即传入实 际的类型参数,也称为类型实参)。
泛型的基本使用
package Generic;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
/**
* 一、泛型是在jdk5.0 新增的特性
*
* 二、在集合中使用泛型:
* 1 集合接口或集合类在jdk 5.0 之后修改为了带泛型的结构
* 2 在实例化集合类时,可以指明具体的泛型类型
* 3 指明完之后,在集合类或者接口中凡是定义了类或接口时
* 比如内部结构(构造器、方法、属性等)使用到了泛型的位置,都指定为实例化的泛型类型
* eg: add(E e) ---> 实例化之后: add(Integer e)
*
* 注意点:泛型的类型必须是类,不是基本数据类型
* 所以需要使用基本数据类型的位置,需要包装类替换
*
* 三、如何自定义泛型的结构: 泛型类、泛型接口、泛型方法
*
*
*/
// 定义泛型类
class Order<T>{
String name;
int age;
//内部结构距可以使用类的泛型
T OrderT;
public Order() {
}
public Order(String name, int age, T orderT) {
this.name = name;
this.age = age;
OrderT = orderT;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public T getOrderT() {
return OrderT;
}
public void setOrderT(T orderT) {
OrderT = orderT;
}
@Override
public String toString() {
return "Order{" +
"name='" + name + '\'' +
", age=" + age +
", 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;
}
}
// 在subClass里面指明泛型的类型
class IntSubOrder extends Order<Integer>{
}
// 在subClass里面不指明泛型的类型
class SubOrder<T> extends Order<T>{
}
public class genericTest {
@Test
public void test1(){
Order<String> order = new Order("Order1",232,"OrderT");
order.setOrderT("AA");
}
@Test
public void test2(){
// 如果说在子类里面指明了 带泛型的父类,则子类就不再是泛型类
IntSubOrder intSubOrder = new IntSubOrder();
intSubOrder.setOrderT(222);
// 如果在子类中没有指明 泛型的父类,则子类也是泛型类
SubOrder<String> stringSubOrder = new SubOrder<>();
stringSubOrder.setOrderT("String Order");
}
@Test
public void test3(){
// 泛型不同的引用不能相互赋值 eg
ArrayList<String> list1 = new ArrayList<>();
ArrayList<Integer> list2 = new ArrayList<>();
// list1 = list2;
}
// 测试泛型的方法
@Test
public void tet4(){
Order<String> order = new Order<>();
Integer[] arr = new Integer[]{1,2,3};
// 泛型方法在调用时,指明泛型参数的类型,与 泛型类的 泛型 没有任何关系
List<Integer> integers = order.copyFromArrayToList(arr);
System.out.println(integers);
}
}
泛型在继承方面的体现
package Generic;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
*
* 1 泛型在继承方面的体现
*
* 对于泛型的类型:类A 是 类B 的父类,eg: G<A> 和 G<B>二者是不具备子父类关系的。二者是并列关系
*
* 对于泛型的继承,还是表现在类的继承上面:
* 类A 是 类B 的父类,A<G> 和 B<G> 是继承关系
*
* 2 通配符的使用
* 通配符:?
* 类A 是 类B 的父类,G<A> 和 G<B>二者是不具备子父类关系的。二者共同的父类是:G< ? >
*
*/
public class genericTest1 {
/**
* 泛型在继承方面的体现
*/
@Test
public void test1(){
List<Object> list1 = null;
List<String> list2 = null;
// 编译不通过
// 此时list1 和 list2 的类型不具有子父类关系
// list1 = list2;
}
// 通配符的使用
// 通配符: ?
// 他其实是为了解决在泛型中的多态性问题
@Test
public void test2(){
List<Object> list1 = null;
List<String> list2 = null;
List<?> list = null;
list = list1;
list = list2;
// 通用父类的使用:
List<String> list3 = new ArrayList<>();
list3.add("AA");
list3.add("BB");
list3.add("CC");
list = list3;
// 添加(写入): 对于list<?> 不能向其内部添加数据
// 出了null;
// list.add("DD");
list.add(null);
// 读取: 允许读取,读取的类型为object
Object o = list.get(0);
System.out.println(o);
}
// 如果没有通配符的话,我们做遍历的话,对于每一个类型的list 都要写一个对于的遍历方法
public void showString(List<String> str){
//do something
}
public void showInteger(List<Integer> integer){
//do something
}
//运用通配符
// 做一个通用的调用
public void show(List<?> list){
Iterator<?> iterator = list.iterator();
while (iterator.hasNext()){
Object next = iterator.next();
System.out.println(next);
}
}
/** 有限制条件的通配符的使用
? extends A:
? Super A:
*/
}
class Person{
}
class Student extends Person{
}