泛型
泛型是一种未知的数据类型,当我们不知道使用什么数据类型的时候,就可以使用泛型。也可以把他看作是一个变量,用来接受数据类型
创建集合对象的时候就会确定泛型的数据类型,此时会把数据类型作为参数传递 将数据类型赋值给泛型
比如说ArrayList
集合在定义的时候,不知道集合中都会存储什么类型的数据,所以定义的类型使用泛型E
public class ArrayList<E>{
public boolean arr(E e){...}
public E get(int index){...}
}
此时创建集合对象ArrayList<String> list = new ArrayList<>();
的时候,会将数据类型作为参数传递,也就是说将String
赋值给泛型E
,就像这样:
public class ArrayList<String>{
public boolean arr(String e){...}
public String get(int index){...}
}
创建集合对象,不使用泛型
- 好处:
默认类型就是Object类型 可以存储任意类型数据 - 弊端:集合不安全 会引发异常,比如说
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("abc");
list.add(123);
//使用迭代器遍历list集合
//获取迭代器
Iterator it = list.iterator();
//使用迭代器中的方法hasNext和next遍历集合
while(it.hasNext()){
//因为没有使用泛型,所以他取出的元素是Object类型
Object obj = it.next();
System.out.println(obj);
//此时如果想用String类特有的方法,比如说.length()获取字符串长度,不能使用
//需要使用到多态向下转型
String s = (String)obj;
System.out.println(s.length());
}
}
运行结果见下:
创建集合对象 使用泛型
- 好处:
- 避免了类型转换的麻烦 存的是什么类型取出来的事就是什么类型
- 把运行期异常(代码运行之后会抛出的异常)提升到了编译异常,这样更早的发现错误,不至于后续改的太难受
- 弊端:
- 泛型是什么类型就只能存储什么类型的数据
注意:
- 泛型不止可以修饰类,也可以修饰方法如
public E void method(E e){...}
,修饰接口,这里要注意修饰接口有两种使用方式:- 第一种:定义接口的实现类,实现接口,指定接口的泛型,比如说
public interface Iterator<E>{
E next();
}
//Scanner实现了Iterator接口,并指定接口的泛型为String,
//所以重写的next方法泛型默认是String
public final class Scanner implements Iterator<String>{
public String next(){...}
}
- 第二种:接口使用什么泛型,实现类就使用什么泛型,就相当于有定义了一个含有泛型的类,在创建对象时确定泛型的类型
public interface List<E>{
boolean add(E e);
E get(int index);
}
public class ArrayList<E> implements List<E>{
public boolean add(E e){}
public E get(int index){}
}
泛型通配符 ?
? 代表任意的数据类型
注意:
泛型通配符不能创建对象使用ArrayList<?> list = new ArrayList<?>();//这样是不行的
,只能作为方法的参数使用
作用:
比如说有几个不同类型的ArrayList对象,想要有一个方法,能够把他们都遍历,此时就可以使用通配符?
public static void main(String[] args){
ArrayList<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(2);
ArrayList<String> list2 = new ArrayList<>();
list1.add("wo");
list1.add("ke");
list1.add("zhen");
list1.add("shi");
list1.add("ge");
list1.add("xian");
list1.add("nv");
list1.add("a");
print(list1);
print(list2);
}
public static void print(ArrayList<?> list){
Iterator<?> it = list.itertor();
while(it.hasNext()){
Object o = it.next();
System.out.println(o);
}
}
泛型总结:
- 泛型是为了解决某些容器、算法等代码的通用性而引入,并且能在编译期间做类型检查。
- 泛型利用的是 Object 是所有类的祖先类,并且父类的引用可以指向子类对象的特定而工作。
- 泛型是一种编译期间的机制,即 MyArrayList 和 MyArrayList 在运行期间是一个类型。
- 泛型是Java中的一种合法语法,标志就是<>
包装类
Object引用可以指向任意类型的对象,但是8种基本类型并不是对象,那泛型机制如何保证呢?
所以Java种引入了一种特殊的类----包装类,将8大基本数据类型包装到对象中,对应关系如下:
基本数据类型 | 对应的包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
flout | Flout |
double | Double |
char | Character |
boolean | Boolean |
为了开发方便,Java在编译期间增加了自动拆箱和自动装箱机制