• java核心(九):泛型


    一、泛型的目的

    • 泛型解决的是:向下转型时存在的安全隐患;
    • 泛型的核心是:在定义类或接口的时候,不需要显示地声明参数或属性的类型。

    二、类中使用泛型

    • 注:在类、接口或方法中,泛型可以定义多个,泛型的名称自定义;
    • 注:使用泛型中,在显示指定具体类型时,只能是引用类型,不能是基本数据类型;
    • 注:使用泛型中,如果没有显示指定具体类型,则系统默认使用Object作为具体类型;
    package com.study.Type;
    
    /**
     * 在声明类的时候,定义了两个泛型:T、A
     * @param <T>
     * @param <A>
     */
    class Fruit<T, A>{
        private T name;
        private A size;
    
        public Fruit(T name, A size) {
            this.name = name;
            this.size = size;
        }
    
        public void getInfo(){
            System.out.println("name: "+this.name+" , size: "+this.size);
        }
    
        public T getName() {
            return name;
        }
    
        public void setName(T name) {
            this.name = name;
        }
    
        public A getSize() {
            return size;
        }
    
        public void setSize(A size) {
            this.size = size;
        }
    
    }
    
    public class Test {
        public static void main(String[] args) {
            Fruit<String,Integer> f1 = new Fruit<>("苹果",10);
            f1.getInfo();                   // name: 苹果 , size: 10
            String name2 = f1.getName();
            int size2 = f1.getSize();
            System.out.println(name2);      //  "苹果"
            System.out.println(size2);      //  10
    
            Fruit<String,String> f2 = new Fruit<>("苹果","直径10公分");
            f2.getInfo();                   // name: 苹果 , size: 直径10公分
        }
    }

     三、接口中使用泛型

    package com.study.Type;
    
    /**
     * 接口使用泛型:T
     */
    interface IFruit<T>{
        public void print(T t);
    }
    
    /**
     * 实现类继续使用泛型:T
     */
    class Apple<T> implements IFruit<T>{
        @Override
        public void print(T t) {
            System.out.println(t+" , "+t.getClass());
        }
    }
    
    /**
     * 实现类不使用泛型,指定接口的泛型参数类型
     */
    class Orange implements IFruit<String>{
        @Override
        public void print(String s) {
            System.out.println(s+" , "+s.getClass());
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            IFruit<String> a1 = new Apple<String>();
            a1.print("苹果");         //  苹果 , class java.lang.String
    
            IFruit<Integer> a2 = new Apple<Integer>();
            a2.print(100);           //  100 , class java.lang.Integer
    
            IFruit<String> orange = new Orange();
            orange.print("橘子");     //  橘子 , class java.lang.String
            //orange.print(100);     //语法错误:Error:(43, 22) java: 不兼容的类型: int无法转换为java.lang.String
    
    
        }
    }

    四、方法中使用泛型

    class Test {
        public static void main(String[] args) {
            String str = print("苹果");
            System.out.println(str);    // 苹果
    
            int num = print(123);
            System.out.println(num);    //  123
        }
    
        /**
         * 
         * @param t :   入参
         * @param <T> : 声明一个泛型
         * @return
         */
        public static  <T> T print(T t){
            return t;
        }
    }

    五、通配符"?"的使用

    • 注:使用通配符,只能取出数据,不能设置数据
    package com.study.Type;
    
    import java.util.Date;
    
        class Message<T> {
       private T msg;
    
        public Message(T msg) {
            this.msg = msg;
        }
    
        public T getMsg() {
            return msg;
        }
    }
    
    
    public class Test {
        public static void main(String[] args) {
            Message<String> f1 = new Message<>("苹果");
            print(f1);      //  苹果 , class java.lang.String
    
            Message<Integer> f2 = new Message<>(100);
            print(f2);      //  100 , class java.lang.Integer
    
            Message<Date> f3 = new Message<>(new Date());
            print(f3);      //  Fri Mar 08 15:26:25 CST 2019 , class java.util.Date
        }
    
        /**
         * 使用通配符"?",来接受泛型
         * @param message
         */
        public static void print(Message<?> message){
            System.out.println(message.getMsg()+"  ,  "+message.getMsg().getClass());
        }
    }

    六、通配符的引申用法

      1、"? extends 类" : 设置泛型上限。可以在声明上和方法参数上使用。

    • 如:"? extends Number":意味着只可以设置Number或Number的子类(如:Integer、Long、Double、......)

      2、"? super 类":设置泛型下限。可以在方法参数上使用。

    • 如:"? super Number":意味着只可以设置Number和Number的父类(Object)

    七、分析:泛型

      1、Java泛型只存在于编辑期(.java文件中),在编译成字节码文件(.class文件)时,会把泛型擦除掉,替换为具体的类型

      在JAVA的虚拟机中并不存在泛型,泛型只是为了完善java体系,增加程序员编程的便捷性以及安全性而创建的一种机制,在JAVA虚拟机中对应泛型的都是确定的类型,在编写泛型代码后,java编译过程中会把这些泛型参数类型都擦除,用相应的确定类型来代替,代替的这一动作叫做类型擦除,而用于替代的类型称为原始类型,在类型擦除过程中,一般使用第一个限定的类型来替换,若无限定,则使用Object。

      2、泛型类的静态变量是共享的,于具体实例化的基本类型无关。

    class GT<T>{
        /**
         * 泛型类的静态变量是共享的
         */
        public static int var = 0;
    public void nothing(T x){} } class StaticTest{ public static void main(String[] args){ GT<Integer> g1 = new GT<Integer>(); g1.var = 1; System.out.println(g1.var); // 1 GT<String> g2 = new GT<String>(); g2.var = 2; System.out.println(g1.var); // 2 System.out.println(g2.var); // 2 GT<Date> g3 = new GT<>(); System.out.println(g1.var); // 2 System.out.println(g2.var); // 2 System.out.println(g3.var); // 2 } }

  • 相关阅读:
    为什么C++(感谢waterwalk翻译)
    容器操作笔记
    如此理解面向对象编程
    C++初学者小细节(不定时更新)
    Sales_item 专题
    10步让你成为更优秀的程序员
    C++ PRIMER 笔记
    C++ 异常处理
    透明度 rgba 和 opacity 的区别
    盒模型
  • 原文地址:https://www.cnblogs.com/newbie27/p/10496213.html
Copyright © 2020-2023  润新知