/*
泛型的好处: 1.避免强制类型转换的麻烦
2.将运行时异常,提前到了编译时期,降低了程序员的工作量
3.一旦指定泛型,数据类型将被统一
4.实现代码的模板化,把数据类型当做参数传递
泛型是不存在多态的,左侧<>中写的类型必须和右侧<>中的类型保持一致
泛型可以定义在哪些地方?
1.可以定义在类 和方法(静态方法/非静态方法)上 和接口上
*/
//创建集合,指定存储数据的类型String
ArrayList<String> list = new ArrayList<>();
//2.将运行时异常,提前到了编译时期,降低了程序员的工作量
list.add(new Student("zs",18));
//创建集合全部按照Object类型处理,不指定存储数据的类型String
ArrayList list2 = new ArrayList();
//增强for进行遍历
for (Object obj : list2) {
//把String提升为Object,不能调用String的特有方法
//必须进行强制类型转换
System.out.println(obj+"的长度: "+((String)obj).length());
}
泛型类定义
/* 泛型类: 定义的类上有属于类自己的泛型
定义类时,该类中需要处理某种类型的数据,但是什么类型,不确定,所以定义成泛型
泛型变量一般用大写字母表示:
T(Type),E(Element),K(Key),V(Value)
泛型类的定义格式: public class 类名<泛型变量><T> { }
泛型类上定义的泛型,什么时间确定具体的类型呢?
创建该类的对象时,<>中写的是什么类型,泛型就代表什么类型
泛型类中可以把泛型当成某种具体的类型提前使用
方法上定义的泛型,什么时间确定具体的类型呢? 调用方法时,根据方法参数的类型,确定方法上定义的泛型的具体类型
*/
public class MyClass03<T> {
//定义变量
private T t;
//空参构造方法
public MyClass03() {
}
//满参构造方法
public MyClass03(T t) {
this.t = t;
}
//set和get方法
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
//测试泛型类
public class Demo04GenericClass {
public static void main(String[] args) {
//空参构造创建对象 //确定泛型T的类型: String
MyClass03<String> mc = new MyClass03<>();//右侧<>中可以不写东西,但是需要保留<>
//set方法给成员变量赋值 /只能传String
mc.setT("hello");
//创建对象时,确定泛型为String 只能传String
//mc.setT(100);//错误
//get方法获取成员变量的值
String str = mc.getT();
System.out.println(str);
}
}
非静态泛型方法
//泛型方法的定义
/* 不知道怎么处理就定义泛型方法
T: 属于类上定义的泛型,该类中所有非静态方法中都可以直接使用
*/
非静态泛型方法: 定义的方法上有属于方法自己的泛型
非静态泛型方法的定义格式:
修饰符 <泛型变> <T> 返回值类型 方法名称(泛型变量 变量名称)(T t) {
...
}
静态方法不能使用类上的泛型,必须自己定义 多了修饰符 static <泛型变>
修饰符 static <泛型变> <T> 返回值类型 方法名称(泛型变量 变量名称) (T t){
...
}
public class MyClass04<T> {
//不叫泛型方法 叫使用类上泛型的方法,因为泛型T不属于方法本身
public void method(T t) {
System.out.println(t);
}
//叫 非静态泛型方法 /泛型E只属于方法show自己
public <E> void show(E e) {
System.out.println(e);
}
/*
静态方法: 不能使用类上定义的泛型
静态方法直接有类名调用,此时没有对象,
而类上的泛型,必须在创建对象时确定,
既然没有对象,类上的泛型没有确定
*/
/*public static void method(T t) {
}*/
静态泛型方法
public static <E> void fun(E e) {
System.out.println(e);
}
}
//测试类
public class Demo05GenericMethod {
public static void main(String[] args) {
//创建对象,类上的泛型T被确定为: String
MyClass04<String> mc = new MyClass04<>();
mc.method("hello");
//使用类上的泛型,只能传递String
//mc.method(200);
//show方法上有自己的泛型 根据传递的参数,确定泛型的具体类型 使用更灵活
mc.show("java");
mc.show(100);可传除字符串之外的类型
mc.show(new Student("zs",18));
}
MyClass04.fun("Hello");
MyClass04.fun(200);
MyClass04.fun(new Student("ls",28));
}
##泛型接口
定义接口的定义格式:定义接口时,该接口中不确定 什么类型就定义成泛型
public interface 接口名称<泛型变量><T> { ... }
接口中的所有非静态方法,都可以使用该泛型
接口上定义的泛型,什么时间确定具体的类型呢?
1.实现类实现接口时,确定接口上泛型的具体类型的话, 直接指定具体类型
2.定义实现类时,也不确定接口上的泛型 该实现类必须定义为泛型类
而且实现类上的泛型和接口上的泛型要保持一致
创建实现类对象时,确定具体的类型
public interface MyInter<T> {
//抽象方法
public abstract void method(T t);
}
/*
实现类实现接口时,确定接口上泛型的具体类型的话,
直接指定具体类型
*/
public class MyInterImplA implements MyInter<String> {
@Override
public void method(String s) {
System.out.println(s);
}
}
/*
定义实现类时,也不确定接口上的泛型
该实现类必须定义为泛型类
*/
public class MyInterImplB<T> implements MyInter<T> {
@Override
public void method(T t) {
System.out.println(t);
}
}
//测试类
public class Demo04GenericInterface {
public static void main(String[] args) {
MyInterImplA mia = new MyInterImplA();
mia.method("hello");
MyInterImplB<Student> mib = new MyInterImplB<>();
mib.method(new Student("ww",38));
//泛型被确定为Student
//mib.method(100);
}
}
泛型通配符--泛型通配符: ? 用来匹配泛型的,但是不能使用?定义泛型
使用泛型通配符,定义变量: List<?> list 可以接收哪些对象? (创建对象时,只要在<>中写上一种引用类型就可以)都可以
public class Demo05TongPeiFu {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("AAA");
list.add("BBB");
list.add("CCC");
Set<Integer> list2 = new HashSet<>();
list2.add(111);
list2.add(222);
list2.add(333);
//调用方法
print(list);
print(list2);
System.out.println("-------------");
//调用方法
print2(list);
print2(list2);
}
/* 定义一个方法,完成以上两个集合的遍历String Integer 使用了泛型统配符? */
不存在多态不能使用object
public static void print(Collection<?> coll) {
for (Object s : coll) {
System.out.println(s);
}
}
/*
定义泛型方法 */
public static <E> void print2(Collection<E> coll) {
for (E e : coll) {
System.out.println(e);
}
}
}
List<Object> list2 = new ArrayList<Object>();
泛型的上限
父类: Person 子类: Worker 子类: Teacher 子类: JavaTeacher
泛型的上限: ? extends E : 表示Person类型或者Person类型的任意子类型
//调用方法
print(list3);
不管是Worker类还是Teacher类还是JavaTeacher类,都是Person的子类
? extends Person: Person类型或者Person类型的任意子类型
//print(list4);//错误,因为String不是Person的子类
//print(list5);//错误,因为Integer不是Person的子类
/*
定义一个方法,只能完成以上3个集合的遍历
ArrayList<Person>/ArrayList<Worker>/ArrayList<Teacher>
*/
public static void print(ArrayList<? extends Person> list) {
for (Person p : list) {
System.out.println(p);
}
}
泛型的下限
//使用3.7中定义的Person/Worker/Teacher/JavaTeacher类
子类: JavaTeacher 父类: Teacher 父类: Worker 父类: Person
一个子类的父类可以有任意多个
如何表示出一个子类的任意父类呢?
?: 任意一种引用类型
? super E: 表示E类型或者E类型的任意父类型
ArrayList<String> list4 = new ArrayList<>();
ArrayList<Integer> list5 = new ArrayList<>();
print(list3);
//print(list4);//错误,因为String不是Teacher的父类
//print(list5);//错误,因为Integer不是Teacher的父类
*
定义一个方法,只能完成以上3个集合的遍历
ArrayList<Person>/ArrayList<Worker>/ArrayList<Teacher>
不管是Person类还是Worker类都是Teacher类的父类
? super Teacher: Teacher类型或者Teacher类型的任意父类型
public static void print(ArrayList<? super Teacher> list) {
for (Object o : list) {
System.out.println(o);
}
}