泛型
参数化类型:ParameterizedType
集合泛型
- 集合中泛型的应用:通过指定泛型的数据类型,限制集合存储的元素的数据类型
泛型的原理
- 泛型的绑定:
在创建类对象时,指定了泛型的具体类型;在编译时,检查数据类型是否符合泛型的要求;如果不符合,编译报错 - 泛型的擦除
当编译检查类型没问题时,编译完成后,泛型会被擦除
注意:泛型仅仅是在编译期进行类型的强制检查;但当真正运行时,泛型已经被擦除掉
自定义泛型
- 类上定义泛型
// 1. 定义一个泛型
class 类名<泛型名称> extends 父类{}
// 2. 可以定义多个泛型
class 类名<泛型1,泛型2,…> extends 父类{}
- 泛型名称:符合标识符的命名规范均可,编译运行不会报错;但是一般会通过一个大写字母,代表一个泛型;T(type) E(element) K(key) V(value)
- 如何使用该泛型?
- 可以指定属性的数据类型
- 可以作为方法的返回值数据类型
- 可以作为方法的参数列表中的数据类型
示例:
public class FXDemo1 {
public static void main(String[] args) {
Paper<String> p = new Paper<String>();
p.setContent("hello world");
System.out.println(p.getContent());
}
}
class Paper<E>{
private E content;
public E getContent() {
return content;
}
public void setContent(E content) {
this.content = content;
}
}
- 接口上定义泛型
// 1. 定义一个泛型
interface 接口名<泛型名称>{}
// 2. 可以定义多个泛型
interface 接口名<泛型1,泛型2,…>{}
- 类似于类上定义泛型
- 可以定义多个泛型
public class FXDemo2 {
public static void main(String[] args) {
// new InterImpl().method("123");
new InterImpl<String>().method("123");
}
}
interface Inter<T>{
public void method(T num);
}
// 创建类时绑定泛型
//class InterImpl implements Inter<String>{
// @Override
// public void method(String value) {
// System.out.println(value);
// }
//}
// 创建对象时绑定泛型
class InterImpl<T> implements Inter<T>{
@Override
public void method(T value) {
System.out.println(value);
}
}
- 方法上定义泛型
public <T> T method(T t){
return t;
}
示例:
public class FXDemo3 {
public static void main(String[] args) {
Demo d = new Demo();
String s = d.method("abc");
Demo1 d1 = d.method1("abc",100);
System.out.println(s+","+d1.getT1()+","+d1.getT2());
}
}
class Demo{
private String str;
public<T> T method (T t){
// public<T> T method (T t){
// 泛型的定义 返回值类型 参数类型
return t;
}
public <T1,T2> Demo1 method1 (T1 t1, T2 t2){
Demo1<T1,T2> d1= new Demo1<T1,T2>();
d1.setT1(t1);
d1.setT2(t2);
return d1;
}
}
class Demo1<T1,T2>{
private T1 t1;
private T2 t2;
public T1 getT1() {
return t1;
}
public void setT1(T1 t1) {
this.t1 = t1;
}
public T2 getT2() {
return t2;
}
public void setT2(T2 t2) {
this.t2 = t2;
}
}
泛型的通配 (很少用)
- 通过 ? 来表示泛型的类型暂时还不确定,直到具体类型传入时,会将 ? 和具体类型绑定;
public class FXDemo4 {
public static void main(String[] args) {
method(new Demo2<String>());
method(new Demo2<Integer>());
}
public static void method(Demo2<?> d){
// d.setField("abc");
// error 无法将具体类型和?绑定
System.out.println(d.getField());
// 可以绑定任意传入的类型
}
}
class Demo2<T>{
private T field;
public T getField() {
return field;
}
public void setField(T field) {
this.field = field;
}
}
泛型的上限和下限
- 泛型上限:? extends 类名 — 传递的要么是该类本身要么是该类的子类
- 泛型下限:? super 类名 — 传递的要么是该类本身要么是该类的父类
public class FXDemo5 {
public static void main(String[] args) {
method(new Demo2<Number>());
method(new Demo2<Integer>());
method2(new Demo2<B>());
method2(new Demo2<A>());
}
public static void method(Demo2<? extends Number> d){
// d.setField(100);
System.out.println(d.getField());
}
public static void method2 (Demo2<? super B> d){
d.setField(new B());
System.out.println(d.getField());
}
}
class A {}
class B extends A{}