JAVA泛型概述和基本使用
一、概述
泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。
在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add(true);
Iterator iterator = arrayList.iterator();
while(iterator.hasNext())
{
Person p =(Person)iterator.next();
}
}
//Exception in thread "main" java.lang.ClassCastException
泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,以提高代码的重用率。
public static void main(String[] args) {
ArrayList<Boolean> arrayList = new ArrayList<>();
arrayList.add(true);
Iterator<Boolean> iterator = arrayList.iterator();
while(iterator.hasNext())
{
Person p =(Person)iterator.next(); //编译出现错误
}
}
二、好处
1.提高安全性(将运行期的错误转换到编译期)
概述中已经进行阐述
2.省去强转的麻烦
public static void main(String[] args) {
ArrayList<Person> list = new ArrayList<Person>();
list.add(new Person("张三", 23));
list.add(new Person("李四", 24));
Iterator<Person> it = list.iterator();
while(it.hasNext()) {
Person p = it.next(); //不需要进行强转
System.out.println(p.getName() + "..." + p.getAge());
}
}
三、基本使用与注意事项
1.存储字符串
public static void demo1() {
ArrayList<String> list = new ArrayList<>(); //创建集合对象
list.add("a");
list.add("b");
list.add("c");
list.add("d");
Iterator<String> it = list.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
2.存储自定义类型
public static void main(String[] args) {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("张三", 23));
list.add(new Person("李四", 24));
list.add(new Person("王五", 25));
list.add(new Person("赵六", 26));
Iterator<Person> it = list.iterator();
while(it.hasNext()) {
Person p = it.next();
System.out.println(p.getName() + "..." + p.getAge());
}
}
3.注意事项
- <>中放的必须是引用数据类型
- 集合的泛型要保证前后的数据类型一致
- 1.7版本的新特性(菱形泛型):前面的泛型定义了数据类型,后面的泛型可以省略只写<>
- 泛型最好不用定义成Object,没有意义
四、泛型方法的概述和使用
1.概述
将泛型定义在方法上
2.定义格式
public [<泛型类型>] 返回类型 方法名(泛型类型 变量名)
[ ]为可选项
public class Tool<Q> {
private Q q;
public Q getObj() {
return q;
}
public void setObj(Q q) {
this.q = q;
}
public void show(Q t) { //方法泛型最好与类的泛型一致
System.out.println(t);
}
}
注意事项:
1.方法泛型最好与累的泛型一致,如果该方法需要自己的泛型,如下
public<T> void show(T t) { //方法泛型最好与类的泛型一致
System.out.println(t); //如果不一致,需要在方法上声明该泛型
}
2.静态方法必须声明自己的泛型,因为静态方法是随着类的加载而加载,此时没有创建对象,所以类的泛型没有具体的数据类型。因此必须声明自己的泛型,在调用静态方法时泛型被赋值。
public static<W> void print(W w) { //静态方法必须声明自己的泛型
System.out.println(w);
}
五、泛型接口的概述和使用
1.概述
将泛型定义在接口上
2.定义格式
public interface 接口名<泛型类型>
interface Inter<T> {
public void show(T t);
}
class Demo implements Inter<String> {
@Override
public void show(String t) {
System.out.println(t);
}
}
六、泛型高级之通配符
1.泛型通配符<?>
任意类型,如果没有明确,那么就是Object以及任意的JAVA类
List<?> list = new ArrayList<Integer>(); //当右边的泛型是不确定时,左边可以指定为?
2.? extends E
向下限定,E及其子类
//Collection接口中的一个方法
//E为Collection的泛型
//说明这里的参数必须是E类型或者是E类型的子类,父类指针指向子类对象,反之不可以
boolean addAll(Collection<? extends E> c);
3.? super E
向上限定,E及其父类