泛型
# 泛型
泛型是将使用了类型具体化,像方法中获取参数类型一样,泛型所定义的类型是抽象化,在对象实例化时才开始定义泛型的具体类型
在向下转型时,一般是要强制更改类型才能使用,但这一过程遗漏风险很大,因此使用泛型可在实例化时定义类型的使用可以防止出现异常
泛型定义规范: E:集合(Element) K:关键字(Key) N:数字(Number) T:类型(Type) V:值(Value)
class 类名<T>{ }
例子:
public class Demo <T>{
//利用泛型传的类型定义对象
T name;
float fraction;
//名称
public void SetName(T newdata){
this.name = newdata ;
}
public T GetName(){
return name;
}
//分数
public void SetFraction(float newdata){
this.fraction = newdata ;
}
public Object GetFraction(){
return fraction;
}
public static void main(String[] args) {
Demo<String , Integer> d = new Demo<>();
d.SetName("Tan");
String name = d.GetName();
System.out.println("名称:"+name);
d.SetFraction(80.5F);
//向下转型
float f = (float)d.GetFraction();
System.out.println("成绩:"+f);
}
}
运行结果
名称:Tan
成绩:80.5
# 泛型的用法
# 泛型类声明多个类型
定义泛型类时声明多个类型(泛型个数要和实例化时的个数一致)
class Myclass<T, ··· >{ }
实例化时:
Myclass<String , Integer , Boolean, ··· > c = new Myclass<>();
# 泛型类声明数组类型
定义泛型类时也可以声明数组类型
class Myclass<T>{
T[] array = new T[n];
}
# 集合类声明容器的元素
定义泛型类时,使用 K 和 V 两个字符代表容器中的 键 和 值
集合定义有
集合类 | 泛型定义 |
---|---|
ArrayList | ArrayList<E> |
HashMap | HashMap<K , V> |
HashSet | HashSet<E> |
Vector | Vector<E> |
例子:(泛型常规用法)
import java.util.HashMap;
import java.util.Map;
public class Demo2 {
public static void main(String[] args) {
GenericsUse1<String , Boolean , String> grid1 = new GenericsUse1<>("Jck" , true , "22");
GenericsUse2<String> grid2 = new GenericsUse2<>();
GenericsUse3<Integer , Object> grid3 = new GenericsUse3<>();
System.out.println("泛型类声明多个类型:(变量返回)");
System.out.println(grid1.toString());
String[] array = {"成员1","成员2","成员3"};
grid2.ObtainArray(array);
grid2.outarray();
grid3.put(1 , "Sans12");
grid3.put(2 , 3.23);
grid3.put(3 , new Object());
System.out.println("\n通过键获取值:");
System.out.println("K(1):"+grid3.Getvalue(1));
System.out.println("K(2):"+grid3.Getvalue(2));
System.out.println("K(3):"+grid3.Getvalue(3));
}
}
//泛型类声明多个类型
class GenericsUse1<T , T2 , string>{
T no1;
T2 no2;
string no3;
public GenericsUse1(T no1 , T2 no2 , string no3){
this.no1 = no1;
this.no2 = no2;
this.no3 = no3;
}
@Override
public String toString() {
return "GenericsUse1{" +
"no1=" + no1 +
", no2=" + no2 +
", no3=" + no3 +
'}';
}
}
//泛型类声明数组类型
class GenericsUse2<T>{
T[] array;
public void ObtainArray(T[] array){
this.array = array;
}
public void outarray(){
System.out.println("\n遍历:");
for (T tmp : array){
System.out.println(tmp);
}
}
}
//集合类声明容器的元素
class GenericsUse3<K , V>{
private Map<K , V> hashMap = new HashMap<>();
//存入集合的方法
public void put(K k , V v ){
hashMap.put(k , v);
}
public V Getvalue(K k){
return hashMap.get(k);
}
}
运行结果
泛型类声明多个类型:(变量返回)
GenericsUse1{no1=Jck, no2=true, no3=22}
遍历:
成员1
成员2
成员3
通过键获取值:
K(1):Sans12
K(2):3.23
K(3):java.lang.Object@4d405ef7
# 泛型高级用法
# 限制泛型可用类型
默认是所有类型都可以实例化。extends关键字 可在泛型中限于指定类型及该类型的子类的使用
class 类名称<T extends List>{ } //限制于List集合及子类
# 使用类型通配符
限制泛型类型,限制泛型对象的使用 ,声明时需要 ?
表示通配符
A<?>a;
//泛型必须是List的子类,且不能增加和改写
A<? extends List>a;
//泛型必须是List的父类
A<? super List>a;
# 泛型继承
泛型类的继承
class ExtendClass<T>{ }
class SubClass<T> extends ExtendClass<T>{ }
泛型接口的继承
interface TestInterface<T>{ }
class SubClass<T> implements TestInterface<T>{ }
继承可能出现的情况: 全部继承、部分继承、实现父类泛型、不实现父类泛型
//全部继承
class Father<T1 , T2>{ }
class Child<T1 , T2 , T3> extends Father<T1 , T2>{ }
//部分继承
class Father<T1 , T2>{ }
class Child<T1 , A , B> extends Father<T1 , T2>{ }
//实现父类泛型
class Father<Integer , String>{ }
class Child<A , B> extends Father<Integer , String>{ }
//不实现父类泛型
class Father<T , String>{}
// T 则默认为 Object
class Child extends Father{}
例子:(高级泛型)
import java.util.*;
public class Demo3 {
public static void main(String[] args) {
//限制泛型可用类型
ListClass1<ArrayList> array1 = new ListClass1<>();
ListClass1<LinkedList> array2 = new ListClass1<>();
//错误调试
// ListClass<HashMap> array3 = new ListClass<>();
//使用类型通配符
List <String> list1 = new ArrayList<>();
List <? extends List> list2 = new ArrayList<ArrayList>(); //下界
List <? super List> list3 = new ArrayList<Object>(); //上界
List<?> list4 ;
//list2.add("123"); //不能被添加
//list3.add("123"); //不能被添加
list1.add("No.1");
list4 = list1;
System.out.println("list1:"+list1.get(0));
System.out.println("list4:"+list4.get(0));
list1.set(0 , "No.233");
//list4.set(0 , "No.233"); //不能修改
//list4.add("No.2"); //不能添加
System.out.println("list1:"+list1.get(0));
System.out.println("list4:"+list4.get(0));
//泛型继承
GenericsUse4<Integer , Boolean , String , Float> grid4 = new GenericsUse4<>(23 , true , "mane" , 3.14);
System.out.println();
System.out.println(grid4.toString());
}
}
//限制泛型可用类型
class ListClass1<T extends List>{ }
/*
*
* 继承泛型
*
* */
//接口
interface TestInterface<T4>{
}
//部分继承 T1、T2
class GenericsUse4<T1 , T2 , T3 , T4> GenericsUse1<T1 , T2 , String> implements TestInterface<T4>{
//T4为独有泛型
public GenericsUse4(T1 no1, T2 no2, String no3, double v) {
super(no1, no2, no3);
}
}
/**运行结果
list1:No.1
list4:No.1
list1:No.233
list4:No.233
GenericsUse1{no1=23, no2=true, no3=mane}
*/
注意:
在编译之后程序会采取去泛型化的措施 只在编译阶段有效
在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加 类型检查和类型转换的方法 泛型信息不会进入到运行时阶段
以上是个人学习后写出来的代码分享,如果有问题可在下面留言!
上次更新: 2023/03/12, 00:43:49