泛型详解.
创始人
2024-05-28 20:14:09
0

1 泛型的引入
问题:我们之前实现过的顺序表,只能保存 int 类型的元素,如果现在需要保存 指向 Person 类型对象的引用的顺序表,请问应该如何解决?如果又需要保存指向 Book 对象类型的引用呢?

之前写的顺序表代码示例:

import java.util.Arrays;public class MyArrayList {private int[] elem;private int usedSize;private static int capacity = 10;public MyArrayList() {this.elem = new int[capacity];}public boolean isFull() {if (this.usedSize == capacity) {return true;}return false;}public void add(int pos, int data) {if (pos < 0 || pos > this.usedSize) {System.out.println("pos位置不合法");return;}if (isFull()) {this.elem = Arrays.copyOf(this.elem, 2 * capacity);capacity *= 2;}for (int i = this.usedSize - 1; i >= pos; i--) {this.elem[i + 1] = this.elem[i];}this.elem[pos] = data;this.usedSize++;}public void display() {for (int i = 0; i < this.usedSize; i++) {System.out.print(this.elem[i] + " ");}System.out.println();}public boolean isEmpty() {if (this.usedSize == 0) {return true;}return false;}public boolean contains(int toFind) {if (isEmpty()) {return false;}for (int i = 0; i < this.usedSize; i++) {if (this.elem[i] == toFind) {return true;}}return false;}public int search(int toFind) {if (isEmpty()) {return -1;}for (int i = 0; i < this.usedSize; i++) {if (this.elem[i] == toFind) {return i;}}return -1;}public int getPos(int pos) {if (isEmpty()) {throw new RuntimeException("顺序表为空!");}if (pos < 0 || pos >= this.usedSize) {throw new RuntimeException("pos不合法");}return this.elem[pos];}public int size() {return this.usedSize;}public void setPos(int pos, int value) {if (pos < 0 || pos >= this.usedSize) {System.out.println("pos位置不合法!");return;}this.elem[pos] = value;}public void remove(int toRemove) {if (isEmpty()) {return;}int index = search(toRemove);if (index == -1) {System.out.println("没有你要删除的数字!");}for (int i = index; i < this.usedSize - 1; i++) {this.elem[i] = this.elem[i + 1];}this.usedSize--;}public void clear() {for (int i = 0; i < this.usedSize; i++) {this.elem[i] = 0;}this.usedSize = 0;}public static void main(String[] args) {MyArrayList myArrayList = new MyArrayList();myArrayList.add(0, 1);myArrayList.add(1, 2);myArrayList.add(2, 3);myArrayList.add(3, 4);System.out.println(myArrayList.size());myArrayList.display();System.out.println(myArrayList.contains(3));System.out.println(myArrayList.contains(2));System.out.println(myArrayList.search(5));System.out.println(myArrayList.search(2));System.out.println(myArrayList.getPos(0));System.out.println(myArrayList.usedSize);myArrayList.display();myArrayList.remove(1);myArrayList.remove(2);myArrayList.display();myArrayList.remove(4);myArrayList.display();myArrayList.clear();System.out.println("==============");myArrayList.display();}
}
  • 首先,我们在学习多态过程中已知一个前提,父类的引用可以指向子类的对象。
  • 其次,我们也已知 Object 是 java 中所有类的祖先类
     

那么,要解决上述问题,我们很自然的想到一个解决办法,将我们的顺序表的元素类型定义成 Object 类型,这样我们的 Object 类型的引用可以指向 Person 类型的对象或者指向 Book 类型的对象了。

因为代码改动较多,现在指出主要代码:

这样,我们可以就可以很自由的存储指向任意类型对象的引用到我们的顺序表了。
 

改编后的代码: 

 

package test1;import java.util.Arrays;public class MyArrayList {private Object[] elem;private int usedSize;private static int capacity = 10;public MyArrayList() {this.elem = new Object[capacity];}public boolean isFull() {if (this.usedSize == capacity) {return true;}return false;}public void add(int pos, Object data) {if (pos < 0 || pos > this.usedSize) {System.out.println("pos位置不合法");return;}if (isFull()) {this.elem = Arrays.copyOf(this.elem, 2 * capacity);capacity *= 2;}for (int i = this.usedSize - 1; i >= pos; i--) {this.elem[i + 1] = this.elem[i];}this.elem[pos] = data;this.usedSize++;}public void display() {for (int i = 0; i < this.usedSize; i++) {System.out.print(this.elem[i] + " ");System.out.println();}System.out.println();}public boolean isEmpty() {if (this.usedSize == 0) {return true;}return false;}public boolean contains(Object toFind) {if (isEmpty()) {return false;}for (int i = 0; i < this.usedSize; i++) {if (this.elem[i] == toFind) {return true;}}return false;}public int search(Object toFind) {if (isEmpty()) {return -1;}for (int i = 0; i < this.usedSize; i++) {if (this.elem[i] == toFind) {return i;}}return -1;}public Object getPos(int pos) {if (isEmpty()) {throw new RuntimeException("顺序表为空!");}if (pos < 0 || pos >= this.usedSize) {throw new RuntimeException("pos不合法");}return this.elem[pos];}public int size() {return this.usedSize;}public void setPos(int pos, int value) {if (pos < 0 || pos >= this.usedSize) {System.out.println("pos位置不合法!");return;}this.elem[pos] = value;}public void remove(int toRemove) {if (isEmpty()) {return;}int index = search(toRemove);if (index == -1) {System.out.println("没有你要删除的数字!");}for (int i = index; i < this.usedSize - 1; i++) {this.elem[i] = this.elem[i + 1];}this.usedSize--;}public void clear() {for (int i = 0; i < this.usedSize; i++) {this.elem[i] = 0;}this.usedSize = 0;}public static void main(String[] args) {MyArrayList books = new MyArrayList();for (int i = 0; i < 10; i++) {books.add(i,new Book("三国演义", "罗贯中", 15));}books.display();
//        MyArrayList myArrayList = new MyArrayList();
//        myArrayList.add(0, 1);
//        myArrayList.add(1, 2);
//        myArrayList.add(2, 3);
//        myArrayList.add(3, 4);
//        System.out.println(myArrayList.size());
//        myArrayList.display();
//        System.out.println(myArrayList.contains(3));
//        System.out.println(myArrayList.contains(2));
//        System.out.println(myArrayList.search(5));
//        System.out.println(myArrayList.search(2));
//        System.out.println(myArrayList.getPos(0));
//        System.out.println(myArrayList.usedSize);
//        myArrayList.display();
//        myArrayList.remove(1);
//        myArrayList.remove(2);
//        myArrayList.display();
//        myArrayList.remove(4);
//        myArrayList.display();
//        myArrayList.clear();
//        System.out.println("==============");
//        myArrayList.display();}
}


遗留问题:现在的 MyArrayList 虽然可以做到添加任意类型的引用到其中了,但遇到以下代码就会产生问题。

写一个Person类:

 接下来我称之为牛马操作:

编译竟然正确,没有报红,我们运行一下看看:

 

运行时会抛出了异常
 

提示:问题暴露的越早,影响越小。编译期间的问题只会让开发者感觉到,运行期间的错误会让所有的软件使用者承受错误风险。

所以我们需要一种机制,可以 1. 增加编译期间的类型检查 2. 取消类型转换的使用 泛型就此诞生!
 

2.泛型的分类

  • 1. 泛型类
  • 2. 泛型方法

3 泛型类的定义的简单演示


 注意: 泛型类可以一次有多个类型变量,用逗号分割。
 

4 泛型背后作用时期和背后的简单原理

  • 1. 泛型是作用在编译期间的一种机制,即运行期间没有泛型的概念。
  • 2. 泛型代码在运行期间,就是我们上面提到的,利用 Object 达到的效果(这里不是很准确,以后会做说明)。
     

5 泛型类的使用


 

通过以上代码,我们可以看到泛型类的一个使用方式:只需要在所有类型后边跟尖括号,并且尖括号内是真正的类型,即 E 可以看作的最后的类型。
 

看具体代码:

package test1;import java.util.Arrays;public class MyArrayList {private Object[] elem;private int usedSize;private static int capacity = 10;private E e;public MyArrayList() {this.elem = new Object[capacity];this.e = e;}public boolean isFull() {if (this.usedSize == capacity) {return true;}return false;}public void add(int pos, E data) {if (pos < 0 || pos > this.usedSize) {System.out.println("pos位置不合法");return;}if (isFull()) {this.elem = Arrays.copyOf(this.elem, 2 * capacity);capacity *= 2;}for (int i = this.usedSize - 1; i >= pos; i--) {this.elem[i + 1] = this.elem[i];}this.elem[pos] = data;this.usedSize++;}public void display() {for (int i = 0; i < this.usedSize; i++) {System.out.print(this.elem[i] + " ");System.out.println();}System.out.println();}public boolean isEmpty() {if (this.usedSize == 0) {return true;}return false;}public boolean contains(E toFind) {if (isEmpty()) {return false;}for (int i = 0; i < this.usedSize; i++) {if (this.elem[i] == toFind) {return true;}}return false;}public int search(E toFind) {if (isEmpty()) {return -1;}for (int i = 0; i < this.usedSize; i++) {if (this.elem[i] == toFind) {return i;}}return -1;}public Object getPos(int pos) {if (isEmpty()) {throw new RuntimeException("顺序表为空!");}if (pos < 0 || pos >= this.usedSize) {throw new RuntimeException("pos不合法");}return this.elem[pos];}public int size() {return this.usedSize;}public void setPos(int pos, int value) {if (pos < 0 || pos >= this.usedSize) {System.out.println("pos位置不合法!");return;}this.elem[pos] = value;}public void remove(E toRemove) {if (isEmpty()) {return;}int index = search(toRemove);if (index == -1) {System.out.println("没有你要删除的数字!");}for (int i = index; i < this.usedSize - 1; i++) {this.elem[i] = this.elem[i + 1];}this.usedSize--;}public void clear() {for (int i = 0; i < this.usedSize; i++) {this.elem[i] = 0;}this.usedSize = 0;}public static void main(String[] args) {MyArrayList books = new MyArrayList();books.add(0, new Book("红楼梦", "曹雪芹", 18));books.add(2, new Person("lisi", "lll"));//        Book book1 = new Book("红楼梦", "曹雪芹", 18);
//        for (int i = 0; i < 10; i++) {
//            if (i == 0) {
//                books.add(i, book1);
//            } else {
//                books.add(i, new Book("三国演义", "罗贯中", 15));
//            }
//        }
//        books.display();
//        Person person = (Person) books.getPos(0);
//        MyArrayList myArrayList = new MyArrayList();
//        myArrayList.add(0, 1);
//        myArrayList.add(1, 2);
//        myArrayList.add(2, 3);
//        myArrayList.add(3, 4);
//        System.out.println(myArrayList.size());
//        myArrayList.display();
//        System.out.println(myArrayList.contains(3));
//        System.out.println(myArrayList.contains(2));
//        System.out.println(myArrayList.search(5));
//        System.out.println(myArrayList.search(2));
//        System.out.println(myArrayList.getPos(0));
//        System.out.println(myArrayList.usedSize);
//        myArrayList.display();
//        myArrayList.remove(1);
//        myArrayList.remove(2);
//        myArrayList.display();
//        myArrayList.remove(4);
//        myArrayList.display();
//        myArrayList.clear();
//        System.out.println("==============");
//        myArrayList.display();}
}

 

那么现在就会出现编译错误 ,这就是泛型的作用!

注意: Book 只能想象成 E 的类型,但实际上 E 的类型还是 Object。
 

6 泛型总结

  • 1. 泛型是为了解决某些容器、算法等代码的通用性而引入,并且能在编译期间做类型检查。
  • 2. 泛型利用的是 Object 是所有类的祖先类,并且父类的引用可以指向子类对象的特定而工作。
  • 3. 泛型是一种编译期间的机制,即 MyArrayList 和 MyArrayList 在运行期间是一个类型。
  • 4. 泛型是 java 中的一种合法语法,标志就是尖括号 <>
     

相关内容

热门资讯

小学中秋节的作文【优选3篇】 小学中秋节的作文 篇一中秋节是中国传统的节日之一,也是我最喜欢的节日。在这一天,我和家人一起庆祝,品...
梦里清江小学作文【优质3篇】 梦里清江小学作文 篇一我爱梦里清江小学梦里清江小学是我上学的地方,它位于美丽的梦里清江边。每当我踏进...
难忘的秋游小学作文450字(... 难忘的秋游小学作文450字 篇一难忘的秋游今天,我们全班去郊游了,这是我度过的一个最难忘的秋天。我们...
可怜的骆驼作文(优质3篇) 可怜的骆驼作文 篇一骆驼是一种生活在沙漠中的动物,它们背上长着一座座驼峰,可以存储大量的水分,帮助它...
倔老头作文【优选3篇】 倔老头作文 篇一倔老头的坚持倔老头是我家附近的一位老先生,他已经七十多岁了,但他的身体和精神状态一直...
小学生一年级的作文400字(... 小学生一年级的作文400字 篇一我的暑假计划暑假就要来了,我有很多计划,让我来给大家说说吧!首先,我...
师爱温暖我的心小学作文【优秀... 师爱温暖我的心小学作文 篇一师爱温暖我的心作为一名小学生,我有幸遇到了一位非常特别的老师,她就是我的...
可爱的金毛小学作文【优秀3篇... 可爱的金毛小学作文 篇一我家的金毛小狗我家有一只可爱的金毛小狗,它的名字叫做小黄。小黄是一只非常聪明...
四年级上册三单元作文【优秀3... 四年级上册三单元作文 篇一我的家乡我是一个四年级的学生,我想给大家介绍一下我的家乡。我的家乡是一个美...
约定的作文【优秀3篇】 约定的作文 篇一约定的作文可以是一种非常有趣的写作形式,它让人们可以事先约定一个共同的主题或要求,然...
山不过来我就过去作文【优秀3... 山不过来我就过去作文 篇一山不过来我就过去小时候,我曾听过这样一个故事:有一位终身未婚的老人,住在山...
游趵突泉【精选3篇】 游趵突泉 篇一:探寻自然奇迹的乐园趵突泉,位于中国山东省济南市市中心,是中国历史最为悠久的泉眼之一。...
有关四年级写粗心的我的作文【... 有关四年级写粗心的我的作文 篇一我是一个四年级的学生,经常因为自己的粗心而给自己带来麻烦。我想通过写...
春天的味道作文【通用6篇】 春天的味道作文 篇一春天的味道总是令人难以忘怀,每当春天来临,大自然的芬芳气息就扑面而来。春天的味道...
小学生作文开学啦四年级14篇... 小学生作文开学啦四年级14篇篇一:开学第一天的收获开学啦!四年级的我充满了期待和憧憬。我迫不及待地穿...
龟兔赛跑新编小学四年级作文5... 篇一:龟兔赛跑新编小学四年级作文500字昔日的龟兔赛跑,我们都知道龟兔最终以发挥自己绝对的优势,一步...
四年级消防安全征文【优秀5篇... 四年级消防安全征文 篇一消防安全是我们生活中非常重要的一部分,它关系到我们的生命安全和财产安全。作为...
四年级写景作文【优秀6篇】 四年级写景作文 篇一春天的校园春天到了,整个校园都变得生机勃勃,充满了活力。我喜欢在春天的校园里漫步...
有趣的象棋四年级作文【优秀3... 有趣的象棋四年级作文 篇一在我们的学校,有一个特别有趣的活动,那就是象棋比赛。作为一个四年级的学生,...
300字描写菜园作文四年级【... 300字描写菜园作文四年级 篇一我的菜园今天,我们四年级的同学来到了学校的菜园。这是一个有着绿油油蔬...