• Java集合框架-------泛型


    JAVA自动装箱和自动拆箱:

    装箱:将一个值封装称为一个对象的过程

    举例:

    Integer number=new Integer(100);
    
    • 1

    拆箱:从一个类型包装器中提取值的过程
    举例:

    int i=number.intValue();
    
    • 1

    装箱和拆箱是Java最初的版本中就存在的,他并不是Java1.5的新特性,自动拆装箱,当编译器编译时若发现是基本类型与包装类型之间相互赋值,将自动补充代码来完成转换工作,这个过程称为自动拆装箱。

    自动拆箱和装箱:

    自动装箱:当我们需要某个类型的对象时,该基本类型的数据类型自动被封装到与它相同类型的包装器中

    举例:

    Integer number=100;//直接将基本数据类型的值赋值给类包装器
    
    • 1

    自动拆箱与自动装箱相反,当我们需要一个值时,这个被装箱到对象中的值就会被自动的提取出来,不需要我们手动的去调用xxxvalue()方法。

    举例:

    int i=number;//直接将这个对象引用赋值给一个基本的变量即可
    
    • 1

    那么为什么要自动装箱和自动拆箱操作呢?

    原因是可以大大简化基本类型变量和包装类对象之间的转换过程。

    包装类:

    通常情况下基本的数据类型,它只是一个类型而不是一个对象,JAVA是一个面向对象的编程语言,那么就需要将基本类型打包封装成对象,而将这些基本类型进行对象化的相关类就是包装类。

    java定义了8个包装类,包括:Integer、Character、Byte、Short、Long、Float、Double、Boolean,其中Character和Boolean是直接继承自Object的,而其余6个包装类继承自java.lang.Number类

    即为了解决基本类型不能直接参与面向对象开发的问题,使得基本类型可以通过包装类的形式存在。## 泛型:
    泛型是JDK5.0的新特征泛型的本质是参数化类型,即程序中所操作的数据类型被指定为一个参数

    Java语言引入泛型的好处是安全简单,可以避免强制类型转换而产生的ClassCastException,在JDK5.0之前,在没有泛型的情况下,通过对类型Object的引用来实现参数的“任意化”。

    泛型可以用在类,接口和方法的创建中,分别称为泛型类,泛型接口,泛型方法。

    泛型头部定义格式如下:

    [修饰符] class 类名<T>
    [public] interface 接口名<T>
    [public][static]<T> 返回值类型 方法名(T参数)
    
    • 1
    • 2
    • 3

    泛型类的定义和创建:

    一般情况下,我们使用K,T,E,V等字母表示泛型类型参数,泛型类在命名上仍然要符合标识符的命名规则。

    [public] class 泛型类名<形式类型参数1,形式类型参数1>
    //形式类型参数列表用于指明当前泛型可接受的类型参数占位符的个数,参数是任意的,不同参数之间我们使用逗号隔开
    {
    类体
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    注:泛型的类型参数只能是引用数据类型,不能是基本数据类型

    普通类在创建对象的过程中,都是直接进行创建的,但是泛型类在创建对象时,需要使用实际的参数类型去代替泛型类中的参数类型

    举例:

    person <String> name=new person<String>();//这里的String即为实际参数类型
    
    • 1

    泛型类的简单使用:

    package generics;
    
    public class generics<T> {
        private  T obj;
        public generics(T obj) {
            this.obj = obj;
        }
        public T getObj() {
            return obj;
        }
        public void setObj(T obj) {
            this.obj = obj;
        }
        public void showObj(){
            System.out.println("T的实际类型为:"+obj.getClass().getName());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    package generics;
    public class generics1 {
        public static void main(String[]args){
        //定义泛型类generics的一个Integer类型
            generics<Integer> number=new generics<Integer>(67);
            number.showObj();
            int number1=number.getObj();
            System.out.println("数字为:"+number1);
            //定义泛型类generics的一个String类型
            generics<String> str=new generics<String>("hello,java");
            str.showObj();
            String str1=str.getObj();
            System.out.println("字符串为:"+str1);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    输出:

    T的实际类型为:java.lang.Integer
    数字为:67
    T的实际类型为:java.lang.String
    字符串为:hello,java
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    泛型接口:

    定义如下:

    [public] interface 接口名<T>
    {
    抽象方法
    }
    
    • 1
    • 2
    • 3
    • 4

    泛型接口的实现必须通过泛型类

    泛型接口的简单使用:

    package generics;
    
    public class generics<T> implements text1<T>{//通过泛型类去实现泛型接口
        @Override
        public void show(T t) {
            System.out.println(t);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    package generics;
    
    public interface text1<T> {
        void show(T t);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    package generics;
    public class generics1 {
        public static void main(String[]args){
           generics<String> inter1=new generics<String>();//传递String类型
           inter1.show("我爱中国");
           generics<Double> inter2=new generics<Double>();//传递double类型
           inter2.show(99.0);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    输出:

    我爱中国
    99.0
    
    • 1
    • 2

    泛型的优点:

    泛型对程序带来的主要优点有两部分:

    1:类型安全,泛型的主要目标是提高Java程序的类型安全。

    2:消除强制转换类型,采用了泛型后,所有强制转换类型都是自动地和隐式的,这样就提高了代码的重用率。

    package generics;
    public class generics1 {
      private Object obj;
      public generics1(Object obj){
          this.obj=obj;
      }
      public Object getObj(){
          return obj;
      }
      public void showType(){
          System.out.println("实际类型是:"+obj.getClass().getName());
          //getClass()会获得对象执行时的Class实例,调用getName() 可以获取类的名称
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    不强制转化:

    generics1 grade=new generics1(90.3);
    grade.showType();
    double i=grade.getObj();
    System.out.println("成绩="+i);
    
    • 1
    • 2
    • 3
    • 4

    报错:

    在这里插入图片描述不使用泛型的情况下,必须进行强制类型转换!

    package generics;
    
    public class generics{
       public static void main(String[]args){
            generics1 grade=new generics1(90.3);
           grade.showType();
           double i=(double)grade.getObj();
           System.out.println("成绩="+i);
           generics1 name= new generics1("张三");
           name.showType();
           String name1=(String)name.getObj();
           System.out.println("名字是"+name1);
           generics1 number=new generics1(100);
           number.showType();
           int number1=(int)number.getObj();
           System.out.println("数字是"+number1);
           generics1 height=new generics1(180.2f);
           height.showType();
           Float weight1=(Float)height.getObj();
           System.out.println("身高是"+weight1);
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    输出:

    实际类型是:java.lang.Float
    成绩=90.3
    实际类型是:java.lang.String
    名字是张三
    实际类型是:java.lang.Integer
    数字是100
    实际类型是:java.lang.Float
    身高是180.2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    提醒:float的f是必须要加的,不加就编译出错!

    float类型末尾加f(必须加) :

    例如 float f = 90.3f
    90.3是浮点数,默认是double类型,如果不加f去标记的话,那这个浮点数就是从double类型转换成了float类型,属于向下转型,必须得加小括号进行强制转换

    通用符与受限的泛型类型:

    泛型的类型通配符是"?“,使用”?"作为类型参数,代表任何可能的类型。

    例如: Set<?>
    
    • 1

    它表示Set集合中可以存放任意一种类型的对象,泛型Set是任何泛型Set的父类,Set类型的变量在调用方法时是受到限制的;凡是必须知道具体类型参数的操作都不能执行。

    package generics;
    
    import java.util.Date;
    import java.util.HashSet;
    import java.util.Set;
    import java.util.Vector;
    
    public class generics{
       public static void main(String[]args){
           Set<String> set=new HashSet<String>();
           set.add("王俊凯");
           set.add("王源");
           set.add("易烊千玺");
       }
       public static void showELement(Set<?> v){
           v.add(new Date());//尝试创建具体参数类型!报错
           for(int i=0;i<v.size();i++){
               Object obj=v.elementAt(i);
               System.out.println(obj);
           }
           v.clear();
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    报错:

    在这里插入图片描述原因为:形参v是通配符类型的Set对象,此处明确要添加的类型为Date,所以编译器阻止该操作,上文我们说到凡是必须知道具体类型参数的操作都不能执行。

    在定义泛型类时,默认可以使用任何类型来实例化一个泛型类的对象,但也可以在用泛型类创建对象时对数据做出限制。

    举例:

    class ClassName<T extends anyClass>
    
    • 1

    其中anyClass是某个类或者接口,他表示泛型类型只能是anyClass的子类或者子接口,使用通配符"?"创建泛型类对象,通配符的主要作用是在创建一个泛型类对象时限制这个泛型类的类型是某个或者是继承该类的子类或者是实现某个接口的类.

    举例:

    ArrayList<? extends Number>
    
    • 1

    表示泛型类型只能是Number的子类。

    受限泛型的简单使用:

    package generics;
    
    import java.util.Date;
    import java.util.HashSet;
    import java.util.Set;
    import java.util.Vector;
    
    public class generics<T extends Number>{//该泛型只能是Number的子类或者子接口
       private T obj;
       public generics(T obj){
           this.obj=obj;
       }
       public T getObj(){
           return obj;
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    package generics;
    public class generics1 {
    public static void main(String[]args){
        generics<Integer> num1=new generics<Integer>(5);
        System.out.println("给出的参数是"+num1.getObj());
        generics<Double> num2=new generics<Double>(8.8);
        System.out.println("给出的参数是"+num2.getObj());
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    输出:

    给出的参数是5
    给出的参数是8.8
    
    • 1
    • 2

    但如果参数传递的类型为如下所示的String类型,编译则不通过,原因为String并不是Number的子类。

    generics<String> s=generics<String>("hello");
    
    • 1

    泛型的局限性:

    1:泛型的参数不能被实例化
    
    2:不能声明参数化类型的数组
    
    3:不能用基本类型替换引用类型参数
    
    4:不能定义带泛型的异常,不允许定义Throwable的泛型子类
    
    5:不能在静态变量或者静态方法中引用类中声明的类型参数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Java泛型的主要作用是建立在具有类型安全的数据结构,它在集合框架中的应用非常广泛

  • 相关阅读:
    【复盘】主从延迟以及 Waiting for tablemetadata lock 线上问题
    C语言——指针进阶
    iOS脱壳之frida-ios-dump
    库存预占架构升级方案设计-交易库存中心
    代码随想录算法训练营第六天|字符串 & 栈 & 队列
    TeamTalk中对一条连接收发消息的封装。
    Java多线程-线程同步简述
    【数据结构第2.5讲(栈和队列)】
    Steam通过短信验证来遏制带有恶意软件的更新
    跳表和散列表
  • 原文地址:https://blog.csdn.net/m0_64365419/article/details/127776467