泛型
概述
泛型:参数化类型
泛型声明的格式
1.泛型类 2.泛型接口 3.泛型方法。
1.泛型类:
格式:
[权限修饰符] class 类名<标识符,标识符>{}
代码
package com.demo;
/**
1.泛型类:
格式:
[权限修饰符] class 类名<标识符,标识符>{}
*/
public class 泛型<M> {
public static void main(String[] args) {
fun(5);
泛型<Double> k = new 泛型<>();
泛型<Integer> k1 = new 泛型<>();
}
public static void fun(int a){}
/* public static void add(int a,int b){}
public static void add(double a,double b){}
public static void add(float a,int b){}*/
public void add(M a, M b){}
}
泛型接口
格式
[权限修饰符] interface 接口名称<标识符,标识符>{ }
代码
package com.demo;
/**
1.格式:
[权限修饰符] interface 接口名称<标识符,标识符>{
}
*/
public class 泛型 {
public static void main(String[] args) {
T<String> t = new T<String>() {
@Override
public void fun(String s) {
}
};
T<Integer> t1 = new T<Integer>() {
@Override
public void fun(Integer integer) {
}
};
}
}
interface T<M>{
public void fun(M m);
}
泛型方法
概述
接口或类上的泛型可以给类/接口的成员使用,方法也算是成员,所以接口或类上的泛型可以给方法使用。
引入泛型方法的原因:(使用场景)
① 当类或接口上的泛型不够该方法使用时,可以将该方法声明成泛型方法。
② 静态方法必须使用泛型方法。(静态方法随着类的加载而加载,当类出现时,未必有对象,泛型也可能没有被指定)
泛型方法声明的格式
[权限修饰符][修饰符] <标识符,标识符>返回值类型 方法名称 (参数列表 泛型){}
泛型方法的泛型的确定
随着方法的调用而确定
代码
package com.demo;
/**
1.泛型方法:
*/
public class 泛型方法 {
public static void main(String[] args) {
F<String> f = new F<>();
f.fun("abc", 12);
f.fun("abc", "abc");
}
}
class F<N>{
public <K>void fun(N n,K k){
}
public void fun1(N n){
}
//返回值类型前面声明泛型。 泛型方法
public static <B>void sf(B b){}
}
泛型的特点
可擦除技术:只存在编译期,在class文件中不存在。
菱形技术:<> 1.7有类型推断,可以进行直接推断,在new后面的可以省略数据类型不写
泛型的好处
可以将运行期的异常转换成编译期的异常,减少了类型转换异常的发生。
避免了向下转型。
泛型的继承时的注意问题
子类继承时
如果父类有泛型,在子类中没有指定任何泛型时,为Object类型
如果子类中使用泛型时
当泛型的值不确定时,子类与父类都要有泛型
当泛型的值确定时,父类后面指定泛型的具体类型
代码
package com.demo;
public class 泛型关于子类继承问题 {
public static void main(String[] args) {
ZiP<Integer> zp = new ZiP<>();
ZiP<Integer> zp1 = new ZiP();
ZiP<Integer> zp2 = new ZiP<>();
ZiP<String> zp3= new ZiP<>();
Zip1 zp4 = new Zip1();
zp4.fun("abc");
}
}
class P<T1>{
public void fun(T1 t1){}
}
//当泛型的值不确定时,子类与父类都要有泛型
class ZiP<T1> extends P<T1>{}
//当泛型的值确定时,父类后面指定泛型的具体类型
class Zip1 extends P<String>{}
泛型的通配符
概述
1.泛型的通配符:
? 代表可以接收任意数据类型。表示有泛型。
注意:具体类型的操作,就不能使用。
2.泛型通配符的限定:
? extends T 上限限定
? super T 下限限定
3.泛型的命名:
原则上泛型起名是标识符,但是一般起名用字母代替,Java中常见字母
E T K V 用法上没区别,含义有区别
E :Element 元素
T :Type 类型
K: key 键
V: value 值
代码
package com.demo;
import java.util.ArrayList;
import java.util.Iterator;
/**
1.泛型的通配符:
? 代表可以接收任意数据类型。表示有泛型。
注意:具体类型的操作,就不能使用。
2.泛型通配符的限定:
? extends T 上限限定
? super T 下限限定
3.泛型的命名:
原则上泛型起名是标识符,但是一般起名用字母代替,Java中常见字母
E T K V 用法上没区别,含义有区别
E :Element 元素
T :Type 类型
K: key 键
V: value 值
*/
public class 泛型的通配符 {
public static void main(String[] args) {
/*ArrayList<Integer> list = new ArrayList();
fun(list);
ArrayList<String> list1 = new ArrayList();
fun(list1);*/
ArrayList<Person> list2 = new ArrayList<>();
fun1(list2);
}
public static void fun(ArrayList<?> list){
Iterator<?> it = list.iterator();
while (it.hasNext()){
Object value = it.next();
}
}
public static void fun1(ArrayList<? super Student> list){}
}
class Person{
}
class Student extends Person{}
class MiddleStudent extends Student{}