一、泛型
1.泛型的引入
我们知道一个顺序表中可以存放int型的对象,那么如果要存入指向 Person 类型对象的引用的顺序表,请问应该如何解决?
首先我们可以想到基类的引用可以指向子类的对象,因为Object是所有类的祖先类,所以我们将顺序表的元素类型定义成 Object 类型,这样我们的 Object 类型的引用可以指向 Person 类型的对象
看这样一段代码:
class Book{
}
class Person{
}
public class MyArrayList {
private Object[] array; // 保存顺序表的元素,即 Object 类型的引用
private int size; // 保存顺序表内数据个数
public void add(Object o) { 尾插 }
public Object get(int index) { 获取 index 位置的元素 }
...
}
这样,我们可以就可以很自由的存储指向任意类型对象的引用到我们的顺序表了。
虽然此时的MyArrayList可以添加任意类型的引用到其中,但是也有可能出现错误,如下:
MyArrayList books = new MyArrayList();
//可以添加Book类型
books.add(new Book());
// 将 Object 类型转换为 Person 类型,需要类型转换才能成功
// 这里编译正确,但运行时会抛出异常 ClassCastException
// 因为get方法获取到的是一个Object对象,强制类型转换报错
Person person = (Person)books.get(0);
遇到向下转型可能会出错。因此我们需要一种机制,可以实现:
1.增加编译期间的类型检查
2. 取消类型转换的使用 泛型就此诞生!
2.泛型的分类
1.泛型类
2.泛型方法
3.泛型类的使用
定义了一个元素是 Book 引用的 MyArrayList
MyArrayList<Book> books = new MyArrayList<>();
// 不需要做类型转换
Book book = book.get(0);
在这里后边的**<>中可以不用书写类型,编译器会根据前边<>**中的类型自动转化。
4.泛型背后作用时期
泛型是作用在编译期间的一种机制,即运行期间没有泛型的概念。
5.总结
1.泛型是为了解决某些容器、算法等代码的通用性而引入,并且能在编译期间做类型检查。
2. 泛型利用的是 Object 是所有类的祖先类,并且父类的引用可以指向子类对象的特定而工作。
3. 泛型是一种编译期间的机制,即 MyArrayList<>类型是Person和类型是Book在运行期间是一个类型。
4. 泛型是 java 中的一种合法语法,标志就是尖括号 <>。
二、包装类
1.包装类的引入
Object 引用可以指向任意类型的对象,但8 种基本数据类型不是对象,那岂不是刚才的泛型机制要失效了?
实际上也确实如此,为了解决这个问题,java 引入了一类特殊的类,即这 8 种基本数据类型的包装类,在使用过程中,会将类似 int 这样的值包装到一个对象中去。
2.包装类的使用
ArrayList<int> list = new ArrayList<>(); //错误的
ArrayList<Integer> list = new ArrayList<>(); //正确的
int类型不是对象,直接写入泛型的数据类型中是错误的,需要使用它的包装类Integer。
基本数据类型和包装类的对应关系:
其中除了int和char类型,其余6种基本数据类型的包装类就是它本身,只是首字母大写。int对应的包装类是Integer,char是Character。