一、 泛型的由来即使用
泛型的由来
泛型的由来:通过Object转型问题引入
早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有
类型转换的问题。也就存在这隐患,所以Java提供了泛型来解决这个安全问题。
泛型的使用
把泛型定义在类上
格式:public class 类名<泛型类型1,…>
注意事项:泛型类型必须是引用类型
当使用类去创建对象时,指定泛型。那么传入的是什么就是什么泛型
public class Tool<Q> {
private Q q;
public Q getObj() {
return q;
}
public void setObj(Q q) {
this.q = q;
}
public void show(Q q) {
System.out.println(q);
}
}
public static void main(String[] args) {
Tool<String> tool =new Tool<String>();
//创建工具类对象
tool.show("abc");
}
结果打印出:abc
把泛型定义在方法上
定义格式:public <泛型类型> 返回类型 方法名(泛型类型 变量名)
public class Tool<Q> {
private Q q;
public Q getObj() {
return q;
}
public void setObj(Q q) {
this.q = q;
} //注意此处区别,参数括号里面为T
public<T> void show(T q) {
//方法泛型最好与类的泛型一致
System.out.println(q);
//如果不一致,需要在方法上声明该泛型
}
}
Tool<String> tool =new Tool<String>();
//创建工具类对象
//tool.show("abc");
tool.show(true);
打印结果为true。
tips:如果此处方法改为静态方法,则返回值表示错误值。静态方法是随着类的加载而加载的。静态方法必须声明自己的泛型。即public
static void Printable(W w) 。类中的泛型,在创建对象的时候被赋值,static在调用静态方法(W
w)的时候被赋值。
把泛型定义在接口上
定义格式:public interface 接口名<泛型类型>
方式一:(推荐)
interface Inter<T>{
public void show(T t);
}
//当我们规定接口泛型为String的时候,那么我们的方法也是String
class Demo implements Inter<String>{
@Override
public void show(String t) {
System.out.println(t);
}
}
方式二:
//该方法主要是为了实现功能,没必要给自己类加上泛型。这样我们去创建对象时都需要指定一个泛型。
class Demo<T> implements Inter<T>{
@Override
public void show(T t) {
System.out.println(t);
}
}
二、 泛型高级之通配符
泛型通配符:<?>
任意类型,如果没有明确,那么就是Object以及任意的Java类了
在做开发时,后面不确定接受什么类型,后面可能调用一个方法,返回一个集合或者对象,数据类型不确定。这时我们前面可以来一个?代表任意类型
当右边的泛型,是不确定时,左边可以指定为?
List<?> list =new ArrayList<String>();
- ? extends E
向下限定,E及其子类 ?表示子类 E表示父类
ArrayList<Person> list1 =new ArrayList<Person>();
list1.add(new Person("张三", 12));
list1.add(new Person("李四", 13));
list1.add(new Person("王五", 14));
//这样可以放进去的原因时,Student必须是继承Person才能放进去。
//此时Student往上提升,调用Person类中的toString方法
ArrayList<Student> list2 =new ArrayList<Student>();
list2.add(new Student("赵六", 15));
list2.add(new Student("周七", 16));
list1.addAll(list2);
System.out.println(list1);
效果如下:
- ? super E
向上限定,E及其父类
该方法会在TreeSet集合中进行介绍