• 【JAVA数据结构】包装类与认识泛型


    作者主页:paper jie 的博客

    本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。

    本文录入于《javaSE》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造,将javaSE基础知识一网打尽,希望可以帮到读者们哦。

    其他专栏:《算法详解》《C语言》《javaSE》等

    内容分享:本期将会对包装类与泛型进行讲解

    包装类

    在java中,由于基本类型不是继承于Object类,为了让代码可以支持基本类型,java就给每个基本类型都对应装配了一个包装类型

    基本数据类型与对应的包装类

    基本数据类型包装类
    byteByte
    shortShort
    intInteger
    longLong
    floatFloat
    doubleBouble
    charCharacter
    booleanBoolean

    这里除了int和char不同,其他的包装类都是首字符大写即可。

    装箱和拆箱

    1. public static void main(String[] args) {
    2. int a = 10;
    3. //显示装箱
    4. Integer b = Integer.valueOf(a);
    5. //显示拆箱
    6. int c = b.intValue();
    7. int i = 10;
    8. //自动装箱
    9. Integer j = i;
    10. //自动拆箱
    11. int d = j;
    12. }

    在使用的过程中,装箱和拆箱的过程java为了减少开发者的负担就提供了自动机制,我们可以通过cmd来观察一下它的底层执行逻辑:

    一道相关的面试题

    这里有一个代码问题:输出什么?

    1. public static void main(String[] args) {
    2. Integer a = 127;
    3. Integer b = 127;
    4. Integer c = 128;
    5. Integer d = 128;
    6. System.out.println(a == b);
    7. System.out.println(c == d);
    8. }

    不观察它的源码可能就会以为是两个true,但其实答案是true,false

    这就需要我们观察上面说到的valueOf的源码了:

    通过源码我们发现当数字 >=-128 && <=127的时候就返回正常数字,越界了的话就会new一个新的对象,返回的就是地址,第一个打印没越界,第二个打印越界了,所以一个true,一个false

    泛型

    一般的类和方法,只能使用具体的类型: 要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大。----- 来源《Java编程思想》对泛型的介绍。 

    型是在JDK1.5引入的新的语法,通俗讲,泛型:就是适用于许多许多类型。从代码上讲,就是对类型实现了参数化。
     

    一个问题引入泛型

    我们需要实现一个类,类中包括一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中某个下标的值?

    1. class Myarray {
    2. public Object[] array = new Object[10];
    3. public void setArray(int pos, Object val) {
    4. this.array[pos] = val;
    5. }
    6. public Object getArray(int pos) {
    7. return this.array[pos];
    8. }
    9. }
    10. public class Test {
    11. public static void main(String[] args) {
    12. Myarray myarray = new Myarray();
    13. myarray.setArray(0, 1);
    14. myarray.setArray(1, "adsf");
    15. int a = (int)myarray.getArray(0);
    16. String b = (String)myarray.getArray(1);
    17. }

    上面的代码实现后,我们发现一些问题:

    虽然任何的数据类型是可以存放,但是如果在取出的时候不强制类型转换就会编译报错。

    虽然在这种情况下,当前数组任何数据都可以存放,但是,更多情况下,我们还是希望他只能够持有一种数据类型。而不是同时持有这么多类型。所以,泛型的主要目的:就是指定当前的容器,要持有什么类型的对象。让编译器去做检查。此时,就需要把类型,作为参数传递。需要什么类型,就传入什么类型。
     

    泛型使用形式

    1. class 泛型类名称<类型形参列表> {
    2. // 这里可以使用类型参数
    3. }
    4. class ClassName {
    5. }
    6. class 泛型类名称<类型形参列表> extends 继承类/* 这里可以使用类型参数 */ {
    7. // 这里可以使用类型参数
    8. }
    9. class ClassName extends ParentClass {
    10. // 可以只使用部分类型参数
    11. }

    泛型的使用

    这时我们就可以将上面错误的代码改进了:

    1. class Myarray {
    2. public Object[] array = new Object[10];
    3. public void setArray(int pos, T val) {
    4. this.array[pos] = val;
    5. }
    6. public T getArray(int pos) {
    7. return (T)this.array[pos];
    8. }
    9. }
    10. public class Test {
    11. public static void main(String[] args) {
    12. Myarray myarray = new Myarray();
    13. myarray.setArray(0, 1);
    14. //这时就不用向下转型了
    15. int a = myarray.getArray(0);
    16. }

    类名后的表示占位符,表示的是当前类是一个泛型类,一般类型参数都用一个大写字母表示。

    泛型的使用形式:

    1. 泛型类<类型实参> 变量名; // 定义一个泛型类引用
    2. new 泛型类<类型实参>(构造方法实参); // 实例化一个泛型类对象

    使用实例:

    MyArray list = new MyArray();

    这里得注意一点:

    泛型只能接受类,所有的基本类型必须使用包装类

    泛型如何编译的

    说到泛型编译,那就得提到一个知识点:擦除机制

    我们可以通过cmd观察一下有的底层代码:

    通过cmd观察我们发现字节码文件中,所有T都变成了Object

    在编译的过程中,将所有的T替换成Object这种机制,就叫做擦除机制。java的泛型是在编译级别实现的。编译器生产的字节码文件在运行期间是不包含泛型的类型信息的。

    泛型的上界

    在定义泛型类的时候,有的时候我们需要对传入的类型变量进行一定的约束,就可以通过类型边界来约束。

    使用形式

    1. class 泛型类名称<类型形参 extends 类型边界> {
    2. ...
    3. }

    栗子演示

    举个栗子:

    这里NUmber就是传入的类型变量的约束,不能超过了NUmber的范围,Number就是上界

    1. class Pgoneextends Number> {
    2. }
    3. public class Test {
    4. public static void main(String[] args) {
    5. Pgone pgone = new Pgone();
    6. Pgone pgone2 = new Pgone();
    7. }

    这里我们如果T没有指定边界,那么可以认为T extends Object

    这里举个一个比较复杂的栗子:

    我们写一个泛型类 求一个数组中的最大值

    1. //我们知道T一定是引用类型 T类型 一定是要可以比较的
    2. // 这里我们就要约束T 让他可以比较大小
    3. // T就要实现Comparable接口
    4. class Pigextends Comparable> {
    5. public T findmax(T[] array) {
    6. T max = array[0];
    7. for(int i = 0; i < array.length; i++) {
    8. if(max.compareTo(array[i]) < 0) {
    9. max = array[i];
    10. }
    11. }
    12. return max;
    13. }
    14. }
    15. public static void main(String[] args) {
    16. Pig pig = new Pig();
    17. }

    在实现Comparable接口后我们就可以使用里面的compareTo方法来比较了。

    这里要注意如果传入的泛型没有实现Comparable接口,需要自己去实现一下:

    1. class Person implements Comparable{
    2. @Override
    3. public int compareTo(Person o) {
    4. return 0;
    5. }
    6. }
    7. class Pigextends Comparable> {
    8. public T findmax(T[] array) {
    9. T max = array[0];
    10. for(int i = 0; i < array.length; i++) {
    11. if(max.compareTo(array[i]) < 0) {
    12. max = array[i];
    13. }
    14. }
    15. return max;
    16. }
    17. }
    18. public static void main(String[] args) {
    19. Pig pig2 = new Pig<>();
    20. }

    这里的person类就是先实现了Comparable接口,在当做类型传参到Pig类中求最大值

    泛型方法

    使用形式

    方法限定符 <类型形参列表> 返回值类型 方法名称(形参列表) { ... }

    方式实例

    我们在方法名前加上T即可。

    在调用方法的时候,它会根据传入的参数类型自动判断类型

    1. class Util {
    2. publicextends Comparable> T swap(T[] array) {
    3. T max = array[0];
    4. for(int i = 0; i < array.length; i++) {
    5. if(max.compareTo(array[i]) < 0) {
    6. max = array[i];
    7. }
    8. }
    9. return max;
    10. }
    11. }
    12. public class Test {
    13. public static void main(String[] args) {
    14. Util util = new Util();
    15. Integer[] integer = new Integer[]{1,2,3,4,5,6,7,4};
    16. util.swap(integer);
    17. }

    使用类型推导和不使用类型推导

    1. Integer[] a = { ... };
    2. intger.swap(a);
    1. Integer[] a = { ... };
    2. integer.swap(a);

  • 相关阅读:
    Spring MVC 四:Context层级
    尚硅谷尚优选项目教程发布
    LeetCode力扣刷题——指针三剑客之一:链表
    Windows下载安装Vue开发者工具(VueDevtools)
    jupyter notebook 快捷键
    NumPy 差分、最小公倍数、最大公约数、三角函数详解
    Docker 中运行的 MySQL 数据库与 Docker 外部的管理系统连接
    springboot基于微信小程序的在线办公系统+java+uinapp+Mysql+计算机毕业设计
    oracle练习03
    HTML案例-4.注册页面表单练习
  • 原文地址:https://blog.csdn.net/paperjie/article/details/132791846