• 带你深入理解泛型


    目录

    前言:

    泛型类的使用

    擦除机制

    泛型上界

    静态泛型方法

    非静态泛型方法

    通配符

    通配符上界

    通配符下界

    小结:


    前言:

    😉Java和其他语言一样,都支持泛型,包括泛型类和泛型方法。泛型的出现使得类型参数化,Java提出了擦除机制,如果没有声明上界class Test,最终将Test类都擦除Object类。如果声明上界class Test意味着只能传递Number类或者Number的子类,最终擦除成Number类。这些动作都是在编译期间完成的,编译时会自动进行类型检查和转换,运行时没有泛型的概念。

    泛型类的使用

    1. class Test{
    2. private T[] tmp = (T[])new Object[10];
    3. public void setTmp(T tmp, int pos) {
    4. this.tmp[pos] = tmp;
    5. }
    6. public T getTmp(int pos) {
    7. return tmp[pos];
    8. }
    9. }
    10. public class Test17 {
    11. public static void main(String[] args) {
    12. Test test = new Test<>();
    13. test.setTmp(10,0);
    14. int a = test.getTmp(0);
    15. Test test2 = new Test<>();
    16. test2.setTmp("aaa",0);
    17. String b = test2.getTmp(0);
    18. System.out.println(a + " " + b);
    19. }
    20. }

    😆泛型类中是不可以直接new数组(T[] arr = new T[10]),因为在擦除机制中会将T擦成Object类,而Object数组可以存放存放多种类型数据,编译器认为这是不安全的,直接在编译期间就阻止了。T[] tmp = (T[])new Object[10]这样的写法编译器也会报警告,毕竟Object数组不是T类型的数组,除非T刚好擦除成Object。

    😆test.setTmp(10,0)   test2.setTmp("aaa",0) 在编译期间会根据Integer和String进行类型检查,直接阻挡在编译期间。int a = test.getTmp(0)   String b = test2.getTmp(0) 就是自动拆包的过程。

    擦除机制

     🎉通过javap -c查看字节码文件,可以清楚看见将T擦除为Object

    泛型上界

    1. class Testextends Number>{
    2. private T[] tmp = (T[])new Object[10];
    3. public void setTmp(T tmp, int pos) {
    4. this.tmp[pos] = tmp;
    5. }
    6. public T getTmp(int pos) {
    7. return tmp[pos];
    8. }
    9. }
    10. public class Test17 {
    11. public static void main(String[] args) {
    12. Test test = new Test<>();
    13. test.setTmp(10,0);
    14. int a = test.getTmp(0);
    15. }
    16. }

    🎄可以指定泛型类的上界,同时也就限制了传递参数的类型,只能传递Number的子类,编译时会将T擦除成Number,否则不能通过编译 。

    静态泛型方法

    1. class Test{
    2. public staticextends Comparable> void fun(T a, T b) {
    3. if(a.compareTo(b) > 0) {
    4. System.out.println(a);
    5. }else {
    6. System.out.println(b);
    7. }
    8. }
    9. }
    10. public class Test17 {
    11. public static void main(String[] args) {
    12. Integer a = 10;
    13. Integer b = 20;
    14. Test.fun(a, b);
    15. }
    16. }

    🐵静态泛型方法不依赖于对象,直接通过类名就可以调用,因此类型的传参是体现在方法中,当使用者调用方法时,在编译期间会进行类型检查和转换。擦除机制和前面擦除机制是一致的。

    非静态泛型方法

    1. class Test{
    2. public extends Comparable> void fun(T a, T b) {
    3. if(a.compareTo(b) > 0) {
    4. System.out.println(a);
    5. }else {
    6. System.out.println(b);
    7. }
    8. }
    9. }
    10. public class Test17 {
    11. public static void main(String[] args) {
    12. Integer a = 10;
    13. Integer b = 20;
    14. Test test = new Test();
    15. test.fun(a, b);
    16. }
    17. }

    🧢非静态泛型方法就得依赖对象,直接通过对象调用即可,其他和静态泛型方法一致。

    通配符

    🪖在使用泛型类实例化对象后,这个被作为参数传递时,由于泛型对象中可能会有多种不同类型,那么形参类型就无法确定。?符号就解决了这个问题,可以接收任何类型的参数。同时也可以指定通配符的下界和上界。

    通配符上界

    1. class Test {
    2. private T date;
    3. public void setDate(T date) {
    4. this.date = date;
    5. }
    6. public T getDate() {
    7. return this.date;
    8. }
    9. }
    10. public class Test17 {
    11. public static void fun(Test tmp) {
    12. Number a = tmp.getDate();
    13. System.out.println(a);
    14. }
    15. public static void main(String[] args) {
    16. Test test = new Test<>();
    17. test.setDate(10);
    18. fun(test);
    19. }
    20. }

    🎈擦除机制会将tmp类型擦除成Number,因此只能传递Number的子类。由于tmp类型会有多种,所以不可以在fun中设置成员变量的值(date)。可以获取date,它们都有一个共同的父类

    通配符下界

    1. class Test {
    2. private T date;
    3. public void setDate(T date) {
    4. this.date = date;
    5. }
    6. public T getDate() {
    7. return this.date;
    8. }
    9. }
    10. public class Test17 {
    11. public static void fun(Testsuper String> tmp) {
    12. tmp.setDate("aaa");
    13. }
    14. public static void main(String[] args) {
    15. Test test = new Test<>();
    16. fun(test);
    17. System.out.println(test.getDate());
    18. }
    19. }

    😯指定通配符下界,只能传递String类的父类,由于父类会有多种,不能获取到tmp中成员变量(date),因为获取后无法指定一个类型去接收。可以设置date,tmp是String或者String的父类

    小结:

    🐵泛型概念是在Java5后出现,使得代码更加灵活,需深入理解,使我们写代码更加有设计感。

  • 相关阅读:
    Nginx配置整合:基本概念、命令、反向代理、负载均衡、动静分离、高可用
    重大技术问题,iPhone 15 Pro Max面临“烧屏门”风波 | 百能云芯
    https认证过程/加密解密
    高效数据传输:Java通过绑定快速将数据导出至Excel
    设计模式-07-装饰器模式
    npm常用命令详解
    C语言初学习——易错点合集(持续更新中)
    Java 8 Stream API可以怎么玩?
    数据结构记录(一)
    计算机网络【CN】介质访问控制
  • 原文地址:https://blog.csdn.net/weixin_62353436/article/details/126797565