• java泛型


    总结

    • 泛型是一种模板化代码的方法,在很多语言中都有,实现的方法不同
    • java通过编译检查和编译擦除实现泛型
    • 编译期,进行泛型擦除和泛型检查
    • 编译期,能够确定泛型具体类型才可以使用(直接给泛型声明赋值)
    • java泛型在编译期间通过类型擦除实现(擦除成Object),运行期间类型已经被擦除
    • java泛型在编译期间进行类型检查
    • java的泛型只给javac(前端编译器)使用,一旦编译完成和泛型有关的类型全部擦除
    • 泛型没有多态,没有数组,只能使用在引用类型上,不能用在静态属性上
    • 泛型擦除,在使用时,继承时,实现时没有指定泛型的具体的类型,以Object进行处理,但类信息未变
    • 泛型擦除,在使用时,继承时,实现时没有指定泛型的具体的类型,以Object进行处理
    • 编译时,进行泛型擦除,按Object处理
    • 编译时,进行泛型检查
    • 运行时,泛型都被替换为Object了,类信息仍在

    通配符
    不能添加
    不能添加
    不能添加父对象
    实参类型List,形参类型List ,方法内外泛型范围大小不一致
    实参不能添加list.add(new Fruit()),形参可以添加list.add(new Fruit()),产生了二义性
    实参类型List,形参类型List
    实参能添加本类对象list.add(new Apple()),实参能添加子类对象list.add(new ShangDongApple()),形参能添加本类对象list.add(new ShangDongApple()),形参能添加子类对象list.add(new YanTaiApple())

    使用

    package com.xcrj.unified;
    
    import java.io.Serializable;
    
    /**
     * 泛型
     * 编译期,进行泛型擦除和泛型检查
     * 编译期,能够确定泛型具体类型才可以使用(直接给泛型声明赋值;传入具体类型间接赋值泛型声明)
     */
    // xcrj  对象泛型声明 对属于对象属性和方法生效
    public class Result<T> implements Serializable{
        private static final long serialVersionUID = 1L;
    
        //是否成功
        private Boolean succuss;
        //错误码
        private String code;
        //消息提示
        private String description;
        //结果对象
        private T data;
        //服务器当前时间戳
        private Long millis = System.currentTimeMillis();
    
        /**
         * 构造器私有化
         */
        private Result() {}
    
        /**
         * 构造器私有化
         */
        private Result(Boolean succuss, String code, String description, T data) {
            this.succuss = succuss;
            this.code = code;
            this.description = description;
            this.data = data;
        }
    
        //1. 成功只有无返回值,有返回值两种情况
        //2. 成功只有SUCCESS枚举,没有其他ErrorCode枚举
        public static <T> Result<T> success() {
            return new Result<T>(true,ErrorCode.SUCCESS.getCode(),ErrorCode.SUCCESS.getDescription(),null);
        }
    
        // xcrj  静态方法 泛型声明
        // 泛型声明;Result返回类型,没有指明泛型时仍然需要写T
        public static <T> Result<T> success(T data) {
            // new Result创建对象
            return new Result<T>(true,ErrorCode.SUCCESS.getCode(),ErrorCode.SUCCESS.getDescription(),data);
        }
    
        //1. 错误必须指定Errorcode,若无法确定具体错误,选择宏观错误
        //2. 错误只允许返回Errorcode,不允许返回数据data
        public static <T> Result<T> error(ErrorCode errorCode) {
            return new Result<T>(false,errorCode.getCode(),errorCode.getDescription(),null);
        }
    
        // spring mvc在序列化时需要用到setter和getter
        public Boolean getSuccuss() {
            return succuss;
        }
    
        public void setSuccuss(Boolean succuss) {
            this.succuss = succuss;
        }
    
        public String getCode() {
            return code;
        }
    
        public void setCode(String code) {
            this.code = code;
        }
    
        public String getDescription() {
            return description;
        }
    
        public void setDescription(String description) {
            this.description = description;
        }
    
        public T getData() {
            return data;
        }
    
        public void setData(T data) {
            this.data = data;
        }
    
        public Long getMillis() {
            return millis;
        }
    
        public void setMillis(Long millis) {
            this.millis = millis;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99

    问题

    泛型不能使用在静态属性上?
    答:不可以,编译期间无法确定静态属性泛型的具体类型

    泛型可以使用在静态方法上?
    答:可以,在static关键字后面 声明泛型即可

      //方式1,编译报错
      public static T demo2(T t) { 
          return t;
      }
      //方式2,可用,因为拥有泛型声明
      public static <W> void demo3(W w) {
      	System.out.println(w);
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    泛型不能使用在基本类型上?
    答:编译期间泛型擦除后都会变成Object

    泛型成员属性

    package com.xcrj.java1;
    
    // 泛型成员属性,需要在类名后面声明泛型
    public class Test1<T>{
        private T name;
        public Test1(T name){
            this.name=name;
        }
        public static void main(String[] args) {
            Test1<String> test1=new Test1<>("xcrj");
            System.out.println(test1.name);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    泛型成员方法

    package com.xcrj.java1;
    
    // 泛型成员方法,在方法返回类型前声明泛型
    public class Test2 {
        // xcrj 在返回类型后面声明泛型作用于入参类型
        public <T> void test(T name){
            System.out.println(name);
        }
    
        public static void main(String[] args) {
            Test2 test2=new Test2();
            // 显示指明泛型类型
            test2.<String>test("xcrj");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    泛型静态方法

    package com.xcrj.java1;
    
    // 泛型静态方法,在方法返回类型前声明泛型
    public class Test3 {
        // xcrj 在返回类型后面声明泛型作用于入参类型
        public static <T> void test(T name){
            System.out.println(name);
        }
        public static void main(String[] args) {
            // 显示指明泛型类型
            Test3.<String>test("xcrj");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    泛型构造方法

    package com.xcrj.java1;
    
    // 泛型构造方法,在方法返回类型前声明泛型
    public class Test4 {
        // xcrj 在返回类型后面声明泛型作用于入参类型
        public <T> Test4(T name){
            System.out.println(name instanceof String);
            System.out.println(name);
        }
        public static void main(String[] args) {
            // 显示指明泛型类型
            new <String>Test4("xcrj");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    泛型类

    package com.xcrj.java1;
    
    // 泛型类,T-type, K-Key, V-value, E-element
    public class Test5<T,K,V,E> {
        public void test(T namet,K namek,V namev,E namee){
            System.out.println(namet);
            System.out.println(namek);
            System.out.println(namev);
            System.out.println(namee);
        }
    
        public static void main(String[] args) {
            Test5<String,String,String,String> test5=new Test5<>();
            test5.test("xcrjt","xcrjk","xcrjv","xcrje");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    泛型接口

    package com.xcrj.java1;
    
    // 泛型接口
    public interface Test6<T,K,V,E> {
        // java8增强接口,default void方法
        default String test(T namet,K namek,V namev,E namee){
            System.out.println(namet);
            System.out.println(namek);
            System.out.println(namev);
            System.out.println(namee);
            return "";
        }
    
        // java8增强接口,default void方法
        public static void main(String[] args) {
            // 使用接口创建 匿名类对象
            Test6<String,String,String,String> test6=new Test6<String,String,String,String>() {};
            test6.test("xcrjt","xcrjk","xcrjv","xcrje");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    泛型继承

    package com.xcrj.java1;
    
    /**
     * 泛型类继承,指明父类的泛型,减少了父类的泛型,子类中仍然需要写未指明的泛型,当然也可以增加新的泛型
     * 指明父类泛型T, K为String
     * 继承父类泛型V, E
     * 声明更多泛型A, B
     */
    public class Test5Son1<V,E,A,B> extends Test5<String,String,V,E> {
        public void test(String nametson,String namekson,V namevson,E nameeson,A nameason,B namebson){
            System.out.println(nametson);
            System.out.println(namekson);
            System.out.println(namevson);
            System.out.println(nameeson);
            System.out.println(nameason);
            System.out.println(namebson);
        }
    
        public static void main(String[] args) {
            Test5Son1<String,String,String,String> test5Son1=new Test5Son1<String,String,String,String>();
            test5Son1.test("xcrjString","xcrjString","xcrjvson","xcrjeson","xcrjason","xcrjbson");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    泛型实现

    package com.xcrj.java1;
    
    /**
     * 泛型实现:指明接口的泛型,减少了接口的泛型,实现类中仍然需要写未指明的泛型,当然也可以增加新的泛型
     * 指明接口泛型T, K为String
     * 实现父类泛型V, E
     * 声明更多泛型A, B
     */
    public class Test6Impl1<V,E,A,B> implements Test6<String,String,V,E>  {
    
        @Override
        public String test(String nametImpl, String namekImpl, V namevImpl, E nameeImpl) {
            System.out.println(nametImpl);
            System.out.println(namekImpl);
            System.out.println(namevImpl);
            System.out.println(nameeImpl);
            return "";
        }
    
        public String test1(String nametImpl, String namekImpl, V namevImpl, E nameeImpl, A nameaImpl, B namebImpl) {
            System.out.println(nametImpl);
            System.out.println(namekImpl);
            System.out.println(namevImpl);
            System.out.println(nameeImpl);
            System.out.println(nameaImpl);
            System.out.println(namebImpl);
            return "";
        }
    
        public static void main(String[] args) {
            Test6Impl1<String,String,String,String> test6Impl1=new Test6Impl1<>();
            test6Impl1.test("xcrjString", "xcrjString", "xcrjvImpl", "xcrjeImpl");
            test6Impl1.test1("xcrjString", "xcrjString", "xcrjvImpl", "xcrjeImpl", "xcrjaImpl", "xcrjbImpl");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    泛型擦除和泛型检查

    package com.xcrj.java1;
    
    import java.util.List;
    import java.util.ArrayList;
    
    /**
     * 泛型擦除,在使用时,继承时,实现时没有指定泛型的具体的类型,以Object进行处理
     * 编译时,进行泛型擦除,按Object处理
     * 编译时,进行泛型检查
     * 运行时,泛型都被替换为Object了,类信息仍在
     */
    public class Test7 {
        public static void main(String[] args) {
            // 在使用时没有指定泛型的具体的类型,以Object进行处理
            List list=new ArrayList<String>();
            list.add("String");
            list.add(1);
            list.add(true);
    
            System.out.println("===================");
            for(Object obj:list){
                System.out.println(obj.getClass().getName());
                System.out.println(obj);
            }
    
            // 在使用时指定泛型的具体的类型,进行泛型检查
            List<String> list1=new ArrayList<String>();
            list1.add("String");
            // 泛型检查不通过
            // list1.add(1);
            // list1.add(true);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    通配符

    package com.xcrj.java1;
    
    import java.util.List;
    import java.util.ArrayList;
    
    /**
     * 通配符
     *  不能添加
     *  不能添加
     *  不能添加父对象
     * 实参类型List,形参类型List
     * 实参不能添加list.add(new Fruit()),形参可以添加list.add(new Fruit()),产生了二义性,因此extends不允许添加
     * 实参类型List,形参类型List
     * 实参能添加本类对象list.add(new Apple()),实参能添加子类对象list.add(new ShangDongApple()),形参能添加本类对象list.add(new ShangDongApple()),形参能添加子类对象list.add(new YanTaiApple())
     */
    public class Test8 {
        public static void main(String[] args) {
            // 不能添加
            List<?> list=new ArrayList<>();
            // list.add("Str");
    
            // 不能添加
            List<? extends Apple> list1=new ArrayList<>();
            // list1.add(new Fruit());
            // list1.add(new Apple());
            // list1.add(new ShangDongApple());
    
            testExtends(list1);
            // 传入更大范围
            testExtends1(list1);
    
            // 不能添加父对象
            List<? super Apple> list2=new ArrayList<>();
            // 可以添加本对象
            list2.add(new Apple());
            // 可以添加子对象
            list2.add(new ShangDongApple());
            // 不能添加父对象
            // list2.add(new Apple());
            
            testSuper(list2);
            // 传入更大范围
            testSuper1(list2);
        }
    
        public static void testExtends(List<? extends Apple> list){
    
        }
    
        // 实参类型List,形参类型List
        // 实参不能添加list.add(new Fruit()),形参可以添加list.add(new Fruit()),产生了二义性,因此extends不允许添加
        public static void testExtends1(List<? extends Fruit> list){
            // list.add(new Fruit());
        }
    
        public static void testSuper(List<? super Apple> list){
            
        }
    
        // 实参类型List,形参类型List
        // 实参能添加本类对象list.add(new Apple()),实参能添加子类对象list.add(new ShangDongApple()),形参能添加本类对象list.add(new ShangDongApple()),形参能添加子类对象list.add(new YanTaiApple())
        public static void testSuper1(List<? super ShangDongApple> list){
            list.add(new ShangDongApple());
            list.add(new YanTaiApple());
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    package com.xcrj.java1;
    
    public class Fruit {
        
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    package com.xcrj.java1;
    
    public class Apple extends Fruit{
        
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    package com.xcrj.java1;
    
    public class ShangDongApple extends Apple{
        
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    package com.xcrj.java1;
    
    public class YanTaiApple extends ShangDongApple {
        
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    SpringMVC学习笔记(三)
    openjudge 1.7.30 字符环
    【内存管理】页面分配机制
    移动WEB开发之流式布局--移动端常见布局--流式布局
    java - 序列化
    瑞芯微 | 如何固定以太口地址为指定ip?
    动态路由的主流算法
    神经网络的整个过程包括,神经网络的实现过程
    地址栏 Url 乱码问题
    【Harmony OS】【ARK UI】ets使用startAbility或startAbilityForResult方式调起Ability
  • 原文地址:https://blog.csdn.net/baidu_35805755/article/details/127948051