简单了解泛型

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

在Java中, 基本数据类型不是继承自Object, 为了在泛型代码中可以支持基本类型, Java给每个基本类型都对应了一个包装类型.

简单来说就是让基本数据类型也能面向对象.基本数据类型可以使用很多方法, 这就必须让它变成类.

基本数据类型对定的包装类

基本数据类型       包装类

byte                      Byte

short                    Short

int                        Integer

long                     Long

float                     Float

double                 Double

char                    Character

boolean              Boolean

除了Integer 和 Character ,其余基本类型的包装类都是首字母大写

装包(箱)和拆包(箱)

把基本类型变为包装类型, 叫做装箱

把包装类型变为基本类型, 叫做拆箱

    public static void main(String[] args) {
        //自动装包, 内部其实是调用了 valueOf 方法来实现的
        Integer a = 10;
        int i = 99;
        Integer b = i;
        //基本类型 转变为 包装类型, 都是可以直接打印的
        System.out.println(a);
        System.out.println(b);
        //显示装箱
        Integer aa = Integer.valueOf(10);
    }
    public static void main(String[] args) {
        Integer a = 10;
        //自动拆箱, 内部调用了 intValue() 方法;
        int i = a;
        //拆包
        int aa = a.intValue();
        double b = a.doubleValue();
    }

Java 包装类提供了很多方法, 可以自动调用很方便

    public static void main(String[] args) {
        Integer a = 100;
        Integer b = 100;
        System.out.println(a == b);

        Integer a1 = 200;
        Integer b1 = 200;
        System.out.println(a1 == b1);
    }
    //代码上述的输出结果为: true   和    false

为什么呢?

如果出现这个错误第一时间想到了什么呢? 我想可以看一下 Integer 出现了什么错误, 然后呢? 在赋值的过程中出现了自动装箱, 自动装箱的函数是 valueOf , 所以可以在valueOf中寻找出错的点在哪里, 现在找到 valueOf 的源码, 看装包的过程哪一点出错了

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

这个源码, 如果 i 在范围内就返回一个数组里面的值, 如果不在范围就返回 new Integer(i)

我们在源码中可以得到 low的大小为 -128, high 的大小为 127;

也就是 i 的范围在 -128 到 127 之间的话返回这个数组的某一个值

这个数组大小是多少呢? 范围是 [-128, 127], 共 256 个数字, 可以得出 下图 这个数组的样子

当 i 的范围在其之间可以返回相同的值, 如果超过了就返回一个 new 的值. 由此可出上述结果为什么是这样.

泛型

是Java中一种很难的语法

举个例子, 写一个类, 类包含一个数组成员, 让数组中可以存放任意类型的数据, 也能根据成员方法返回数组某个下标的值.

class MyArray {
    Object[] array = new Object[10];
    void setValue(int i, Object val) {
        array[i] = val;
    }
    Object getValue(int i) {
        return array[i];
    }
}
public class Main {
    public static void main(String[] args) {
        MyArray myArray = new MyArray();
        myArray.setValue(0, 1);
        myArray.setValue(1, "hello");
        //下面这一行代码报错, 因为返回值是 Object 类型,
        //需要强转为 String 类型才可以
        //String str = myArray.getValue(0);  <---报错
        String str = (String)myArray.getVlaue(0);
    }
}

这我们就想了, 不能让什么数据类型都能放到这个数组中, 我们可以指定一个数据, 这样我们在接受数据的时候也不用看每一个接收的数据是什么类型了. 我们就引入了泛型.

泛型的语法

1>

class 泛型类名称 <类型形参列表> {

    //可以使用类型参数

}

示例:

class ClassName<T1, T2, .... Tn>{

}

2>

class 泛型类名称<类型形参列表> extends 继承类 {

         //可以使用类型参数

}

示例:

class ClassName<T1, T2, .... Tn> extends ParentClass<T1> {

        //可以使用类型参数

}

类型形参列表可以用 T , E , K , V 等字母表示 其中<T, E, K, V...> 表示什么呢?

表示当前类 是一个泛型类 它只是一个占位符.

下面将上述代码改一下:

class MyArray <T>{
    Object[] array = new Object[10];
    void setValue(int i, T val) {
        array[i] = val;
    }
    T getValue(int i) {
        return (T)array[i]; // 把返回的类型,强转为指定类型
    }
}
public class Main {
    public static void main(String[] args) {
        //这行代码强制了数据类型为Integer, <>里面只能放入包装类
        MyArray<Integer> myArray = new MyArray<>();
        myArray.setValue(0, 1);
        //myArray.setValue(1, "hello");  <----当前代码报错了
        //如果我们想要放入其它类型的数据怎么做呢? 在创建一个新对象就好了
        MyArray<String> myArray1 = new MyArray<>();
        int i = myArray.getValue(0);
        System.out.println(i);
    }
}

 注意:

1> 因为使用了泛型, 在编译的时候 帮我们进行了类型的检查, 取数据也不需要进行类型转换

2> 在尖括号 <> 里面必须是引用类型.

3> 创建的一个数组的时候 不能写成 T[] array = new T[];

泛型的上界

语法:

class 泛型类名称  <类型形参 extends 类型边界>{

...

}

示例:

public class MyArray<T extends Number> {

...

}

其中的 T 必须是 Number 或者 Number的子类, 这就叫做泛型的上界

在创建对象时:

MyArray<Integer> a1 = new MyArray<>();   可以

MyArray<Double> a1 = new MyArray<>();   可以

MyArray<String> a1 = new MyArray<>();   不可以

举例: 写一个泛型类, 求一个数组中的最大值

class Alg<T> {
    public T findMaxValue(T[] array) {
        T max = array[0];
        for (int i = 1; i < array.length; i++) {
            if(max < array[i]) {
                max = array[i];
            }
        }
        return max;
    }
}

这段代码的 if 中的判断条件会出现报错, 为什么呢?

因为 T 是引用数据类型, 最终是被擦除为了 Object 类型, Object 没有实现了Comparable 接口, 所以不能直接比较大小, 要想能够比较大小, 就得让 T 实现 Comparable 接口, 实现了 Comparable接口后, 以后创建对象时, 只有实现了 Comparable 接口的才能创建

就比如: 

MyArray<Integer> a1 = new MyArray<>();   可以, 因为Integer 实现 Comparable 接口

class Preson { ... }

MyArray<Person> a1 = new MyArray<>();   不可以 , 因为Person 没有实现 Comparable 接口

所以上述代码应该写成:

class Alg<T extends Comparable> {
    public T findMaxValue(T[] array) {
        T max = array[0];
        for (int i = 1; i < array.length; i++) {
            if(max.compareTo(array[i]) < 0) {
                max = array[i];
            }
        }
        return max;
    }
}
public class Main {
    public static void main(String[] args) {
        Alg<Integer> alg = new Alg<>();
        Integer[] integers = {1, 2, 3, 4, 5, 6};
        Integer ret = alg.findMaxValue(integers);
        System.out.println(ret);
    }
}

写一个泛型方法:

如下列代码:

在这种情况下会出现 类型推导, 根据实参传值, 来推导出此时的类型.

class Alg2 {
    public <T extends Comparable>T findMaxValue(T[] array) {
        T max = array[0];
        for (int i = 1; i < array.length; i++) {
            if(max.compareTo(array[i]) < 0) {
                max = array[i];
            }
        }
        return max;
    }
}
public class Main {
    public static void main(String[] args) {
        Alg2 alg2 = new Alg2();
        Integer[] integers = {1, 2, 3, 4, 5, 6};
        Integer ret2 = alg2.findMaxValue(integers);
        System.out.println(ret2);
    }
}

下列代码将泛型方法改为静态的, 可以通过类名直接调用该泛型方法, 不用实例化对象了

class Alg3 {
    public static <T extends Comparable>T findMaxValue(T[] array) {
        T max = array[0];
        for (int i = 1; i < array.length; i++) {
            if(max.compareTo(array[i]) < 0) {
                max = array[i];
            }
        }
        return max;
    }
}

public class Main {
    public static void main(String[] args) {
        Integer[] integers = {1, 2, 3, 4, 5, 6};
        Integer ret3 = Alg3.findMaxValue(integers);
        System.out.println(ret3);
    }
}

小结

学会泛型的含义, 泛型的目的, 泛型的语法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/601424.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

免费思维13招之一:体验型思维

思维01:体验型思维 第一大战略:体验型思维。 体验型思维是免费思维中最简单的思维,我们先从最简单的讲起,由简入繁,简单的我们少讲,复杂的我们多讲。 那么,什么是体验型思维呢? 很简单,就是先让客户进行体验,再进行成交的方式。这一种思维,具体的可以分为两种:…

yolo world 瑞芯微芯片rknn部署、地平线芯片Horizon部署、TensorRT部署

特别说明&#xff1a;参考官方开源的 yoloworld 代码、瑞芯微官方文档、地平线的官方文档&#xff0c;如有侵权告知删&#xff0c;谢谢。 模型和完整仿真测试代码&#xff0c;放在github上参考链接 模型和代码。 yoloworld出来的有一段时间了&#xff0c;还没有盘到板端上玩一玩…

IJCAI 2024:吉林大学、中国科学院计算技术研究所和自动化研究所等揭示数据增强在开放场景下的“两面性”

吉林大学人工智能学院研究员高一星、中国科学院计算技术研究所副研究员唐帆、中国科学院自动化研究所研究员董未名等在人工智能领域的CCF-A类顶级国际会议IJCAI上发表的工作&#xff0c;揭示并分析基于样本混合的数据增强方法在开放场景下存在的问题&#xff0c;提出了基于非对…

《安富莱嵌入式周报》第336期:开源计算器,交流欧姆表,高性能开源BLDC控制器,Matlab2024a,操作系统漏洞排名,微软开源MS-DOS V4.0

周报汇总地址&#xff1a;嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 本周更新一期视频教程&#xff1a; BSP视频教程第30期&#xff1a;UDS ISO14229统一诊断服务CAN总线专题&#xff0c;常…

C++:多态-虚函数

C 中的多态性是面向对象编程中的一个重要概念&#xff0c;它允许在运行时选择不同的函数实现&#xff0c;以适应不同类型的对象。 多态的种类 编译时多态性&#xff08;Compile-time Polymorphism&#xff09;&#xff1a;也称为静态多态性或早期绑定&#xff0c;指在编译时确…

java.lang.Exception: Test class should have exactly one public zero-

1.原因 Test方法所在类中,不能存在有参数构造函数,无参构造可以存在。JUnit在运行测试之前&#xff0c;会对测试类做一些初始化和验证工作。对于普通的非参数化测试&#xff0c;JUnit期望测试类有一个无参的公共构造函数&#xff0c;这样它才能够实例化测试类并执行其中的测试方…

K8S快速入门

K8S快速入门 在学习k8s的过程&#xff0c;虽然官网给出的示例教程很简单&#xff0c;但是由于网络和环境的差异&#xff0c;导致实际操作的时候踩了很多坑&#xff0c;下面记录一下自己的操作步骤&#xff0c;方便需要的人参考&#xff0c;也方便以后的自己。 参考官网的资料…

uni-app+vue3 +uni.connectSocket 使用websocket

前言 最近在uni-appvue3websocket实现聊天功能&#xff0c;在使用websocket还是遇到很多问题 这次因为是app手机应用&#xff0c;就没有使用websocket对象&#xff0c;使用的是uni-app的uni.connectSocket 为了方便测试这次用的是node.js一个简单的dom&#xff0c;来联调模拟…

五分钟解决Springboot整合Mybaties

SpringBoot整合Mybaties 创建maven工程整合mybaties逆向代码生成 创建maven工程 1.通过idea创建maven工程如下图 2.生成的工程如下 以上我们就完成了一个maven工程&#xff0c;接下来我们改造成springboot项目。 这里主要分为三步&#xff1a;添加依赖&#xff0c;增加配置&…

Spring_概述

Spring 官网Spring Framework&#xff08;Spring&#xff09;文档位置重点内容Overview 官网 Spring官网 Spring Framework&#xff08;Spring&#xff09; 文档位置 重点 IoC容器AOP&#xff1a;面向切面编程AOT&#xff1a;ahead of time&#xff0c;提前编译Web 框架&…

20240507 ubuntu20.04+ros noetic 跑通lioslam

任务&#xff1a;跑通lioslam 主要参考博客 IMU激光雷达融合使用LIO-SAM建图学习笔记——详细、长文、多图、全流程_ubuntu_AIDE回归线-GitCode 开源社区 (csdn.net) 1.不要用这一句 wget -O ~/Downloads/gtsam.zip https://github.com/borglab/gtsam/archive/4.0.0-alpha2…

电商大数据的采集||电商大数据关键技术【基于Python】

.电商大数据采集API 什么是大数据&#xff1f; 1.大数据的概念 大数据即字面意思&#xff0c;大量数据。那么这个数据量大到多少才算大数据喃&#xff1f;通常&#xff0c;当数据量达到TB乃至PB级别时&#xff0c;传统的关系型数据库在处理能力、存储效率或查询性能上可能会遇…

Mac idea gradle解决异常: SSL peer shut down incorrectly

系统&#xff1a;mac 软件&#xff1a;idea 解决异常: SSL peer shut down incorrectly 查看有没有安装 gradle -v安装 根据项目gradle提示安装版本 brew install gradle7idea的配置 在settings搜索gradle&#xff0c;配置Local installation&#xff0c;选择自己的安装目录…

c++编程(10)——string

欢迎来到博主的专栏——c编程 博主ID&#xff1a;代码小豪 文章目录 <string>string类的接口构造、析构、与赋值重载构造函数赋值重载运算符 元素访问operator[] 容量修改器对string对象的操作迭代器 std::string是定义在c标准的一个类&#xff0c;定义在标准库<strin…

【SAP ME 34】POD操作面板打开内部异常500内部异常

解决方案&#xff1a; 切换到configtool目录&#xff0c;打开configtool可执行文件

win10使用问题

ThinkPad进入bios一种方式是F1 win10有了一个BitLocker&#xff0c;所以在更改bios里面的一些设置&#xff0c;会要求输入恢复密钥&#xff0c;才能生效。 恢复密钥在Microsoft账户里可以找到。 1. 坑爹的Secure Boot设置 坑爹的Secure Boot设置 - 简书 2. 在安装昆仑通态…

小程序搜索排名优化 三步操作提升

搜索排名优化最直接的一个目的就是为了提升小程序的排名和流量&#xff0c;获取用户的信任度。当用户在搜索关键词的时候&#xff0c;能让用户看到小程序&#xff0c;增加被发现和点击的机会。 一、关键词优化&#xff1a; 1.选择合适的关键词&#xff1a;选择与小程序内容高…

昂科烧录器支持Infineon英飞凌的三相电机驱动器TLE9877QXA40

芯片烧录行业领导者-昂科技术近日发布最新的烧录软件更新及新增支持的芯片型号列表&#xff0c;其中Infineon英飞凌的三相电机驱动器TLE9877QXA40已经被昂科的通用烧录平台AP8000所支持。 TLE9877QXA40是一款单芯片三相电机驱动器&#xff0c;集成了行业标准的ARMCortex™M3 内…

Poisson_Image-Editing

1.算法介绍 快速泊松图像编辑&#xff08;Fast Poisson Image Editing&#xff09;是一种图像处理算法&#xff0c;用于将源图像的某个区域无缝地嵌入到目标图像中。它基于泊松方程的性质&#xff0c;通过求解离散化的泊松方程来实现图像的融合。该算法的核心思想是&#xff0c…

[Linux][网络][TCP][四][流量控制][拥塞控制]详细讲解

目录 1.流量控制2.拥塞控制0.为什么要有拥塞控制&#xff0c;不是有流量控制么&#xff1f;1.什么是拥塞窗口&#xff1f;和发送窗口有什么关系呢&#xff1f;2.怎么知道当前网络是否出现了拥塞呢&#xff1f;3.拥塞控制有哪些算法&#xff1f;4.慢启动5.拥塞避免6.拥塞发生7.快…