zoukankan      html  css  js  c++  java
  • 在Java泛型

    1,泛型的定义以及存在意义

    泛型,即“参数化类型”。就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
    例如:GenericClass<T>{}

    一些常用的泛型类型变量:
    E:元素(Element),多用于java集合框架
    K:关键字(Key)
    N:数字(Number)
    T:类型(Type)
    V:值(Value)

    如果要实现不同类型的加法,每种类型都需要重载一个add方法

    package com.jay.java.泛型.needGeneric;
    
    /**
     * Author:Jay On 2019/5/9 16:06
     * <p>
     * Description: 为什么使用泛型
     */
    public class NeedGeneric1 {
    
        private static int add(int a, int b) {
            System.out.println(a + "+" + b + "=" + (a + b));
            return a + b;
        }
    
        private static float add(float a, float b) {
            System.out.println(a + "+" + b + "=" + (a + b));
            return a + b;
        }
    
        private static double add(double a, double b) {
            System.out.println(a + "+" + b + "=" + (a + b));
            return a + b;
        }
    
        private static <T extends Number> double add(T a, T b) {
            System.out.println(a + "+" + b + "=" + (a.doubleValue() + b.doubleValue()));
            return a.doubleValue() + b.doubleValue();
        }
    
        public static void main(String[] args) {
            NeedGeneric1.add(1, 2);
            NeedGeneric1.add(1f, 2f);
            NeedGeneric1.add(1d, 2d);
            NeedGeneric1.add(Integer.valueOf(1), Integer.valueOf(2));
            NeedGeneric1.add(Float.valueOf(1), Float.valueOf(2));
            NeedGeneric1.add(Double.valueOf(1), Double.valueOf(2));
        }
    }

    取出集合元素时需要人为的强制类型转化到具体的目标类型,且很容易现“java.lang. ClassCast Exception”异常。

    package com.jay.java.泛型.needGeneric;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Author:Jay On 2019/5/9 16:23
     * <p>
     * Description: 为什么要使用泛型
     */
    public class NeedGeneric2 {
        static class C{
    
        }
        public static void main(String[] args) {
            List list=new ArrayList();
            list.add("A");
            list.add("B");
            list.add(new C());
            list.add(100);
            //1.当我们将一个对象放入集合中,集合不会记住此对象的类型,当再次从集合中取出此对象时,改对象的编译类型变成了Object类型,但其运行时类型任然为其本身类型。
            //2.因此,//1处取出集合元素时需要人为的强制类型转化到具体的目标类型,且很容易出现“java.lang.ClassCastException”异常。
            for (int i = 0; i < list.size(); i++) {
    //            System.out.println(list.get(i));
                String value= (String) list.get(i);
                System.out.println(value);
            }
        }
    }

    所以使用泛型的意义在于
    1,适用于多种数据类型执行相同的代码(代码复用)
    2, 泛型中的类型在使用时指定,不需要强制类型转换(类型安全,编译器会检查类型)

    2,泛型类的使用

    定义一个泛型类:public class GenericClass<T>{}

    package com.jay.java.泛型.DefineGeneric;
    
    /**
     * Author:Jay On 2019/5/9 16:49
     * <p>
     * Description: 泛型类
     */
    public class GenericClass<T> {
        private T data;
    
        public T getData() {
            return data;
        }
    
        public void setData(T data) {
            this.data = data;
        }
    
        public static void main(String[] args) {
            GenericClass<String> genericClass=new GenericClass<>();
            genericClass.setData("Generic Class");
            System.out.println(genericClass.getData());
        }
    }

    3,泛型接口的使用

    定义一个泛型接口:public interface GenericIntercace<T>{}

    /**
     * Author:Jay On 2019/5/9 16:57
     * <p>
     * Description: 泛型接口
     */
    public interface GenericIntercace<T> {
         T getData();
    }

    实现泛型接口方式一:public class ImplGenericInterface1<T> implements GenericIntercace<T>

    /**
     * Author:Jay On 2019/5/9 16:59
     * <p>
     * Description: 泛型接口实现类-泛型类实现方式
     */
    public class ImplGenericInterface1<T> implements GenericIntercace<T> {
        private T data;
    
        private void setData(T data) {
            this.data = data;
        }
    
        @Override
        public T getData() {
            return data;
        }
    
        public static void main(String[] args) {
            ImplGenericInterface1<String> implGenericInterface1 = new ImplGenericInterface1<>();
            implGenericInterface1.setData("Generic Interface1");
            System.out.println(implGenericInterface1.getData());
        }
    }

    实现泛型接口方式二:public class ImplGenericInterface2 implements GenericIntercace<String> {}

    /**
     * Author:Jay On 2019/5/9 17:01
     * <p>
     * Description: 泛型接口实现类-指定具体类型实现方式
     */
    public class ImplGenericInterface2 implements GenericIntercace<String> {
        @Override
        public String getData() {
            return "Generic Interface2";
        }
    
        public static void main(String[] args) {
            ImplGenericInterface2 implGenericInterface2 = new ImplGenericInterface2();
            System.out.println(implGenericInterface2.getData());
        }
    }

    4,泛型方法的使用

    定义一个泛型方法: private static<T> TgenericAdd(T a, T b) {}

    /**
     * Author:Jay On 2019/5/10 10:46
     * <p>
     * Description: 泛型方法
     */
    public class GenericMethod1 {
        private static int add(int a, int b) {
            System.out.println(a + "+" + b + "=" + (a + b));
            return a + b;
        }
    
        private static <T> T genericAdd(T a, T b) {
            System.out.println(a + "+" + b + "="+a+b);
            return a;
        }
    
        public static void main(String[] args) {
            GenericMethod1.add(1, 2);
            GenericMethod1.<String>genericAdd("a", "b");
        }
    }
    /**
     * Author:Jay On 2019/5/10 16:22
     * <p>
     * Description: 泛型方法
     */
    public class GenericMethod3 {
    
        static class Animal {
            @Override
            public String toString() {
                return "Animal";
            }
        }
    
        static class Dog extends Animal {
            @Override
            public String toString() {
                return "Dog";
            }
        }
    
        static class Fruit {
            @Override
            public String toString() {
                return "Fruit";
            }
        }
    
        static class GenericClass<T> {
    
            public void show01(T t) {
                System.out.println(t.toString());
            }
    
            public <T> void show02(T t) {
                System.out.println(t.toString());
            }
    
            public <K> void show03(K k) {
                System.out.println(k.toString());
            }
        }
    
        public static void main(String[] args) {
            Animal animal = new Animal();
            Dog dog = new Dog();
            Fruit fruit = new Fruit();
            GenericClass<Animal> genericClass = new GenericClass<>();
            //泛型类在初始化时限制了参数类型
            genericClass.show01(dog);
    //        genericClass.show01(fruit);
    
            //泛型方法的参数类型在使用时指定
            genericClass.show02(dog);
            genericClass.show02(fruit);
    
            genericClass.<Animal>show03(animal);
            genericClass.<Animal>show03(dog);
            genericClass.show03(fruit);
    //        genericClass.<Dog>show03(animal);
        }
    }

    5,限定泛型类型变量

    1,对类的限定:public class TypeLimitForClass<T extends List & Serializable>{}
    2,对方法的限定:public static<T extends Comparable<T>>T getMin(T a, T b) {}

    /**
     * Author:Jay On 2019/5/10 16:38
     * <p>
     * Description: 类型变量的限定-方法
     */
    public class TypeLimitForMethod {
    
        /**
         * 计算最小值
         * 如果要实现这样的功能就需要对泛型方法的类型做出限定
         */
    //    private static <T> T getMin(T a, T b) {
    //        return (a.compareTo(b) > 0) ? a : b;
    //    }
    
        /**
         * 限定类型使用extends关键字指定
         * 可以使类,接口,类放在前面接口放在后面用&符号分割
         * 例如:<T extends ArrayList & Comparable<T> & Serializable>
         */
        public static <T extends Comparable<T>> T getMin(T a, T b) {
            return (a.compareTo(b) < 0) ? a : b;
        }
    
        public static void main(String[] args) {
            System.out.println(TypeLimitForMethod.getMin(2, 4));
            System.out.println(TypeLimitForMethod.getMin("a", "r"));
        }
    }
    /**
     * Author:Jay On 2019/5/10 17:02
     * <p>
     * Description: 类型变量的限定-类
     */
    public class TypeLimitForClass<T extends List & Serializable> {
        private T data;
    
        public T getData() {
            return data;
        }
    
        public void setData(T data) {
            this.data = data;
        }
    
        public static void main(String[] args) {
            ArrayList<String> stringArrayList = new ArrayList<>();
            stringArrayList.add("A");
            stringArrayList.add("B");
            ArrayList<Integer> integerArrayList = new ArrayList<>();
            integerArrayList.add(1);
            integerArrayList.add(2);
            integerArrayList.add(3);
            TypeLimitForClass<ArrayList> typeLimitForClass01 = new TypeLimitForClass<>();
            typeLimitForClass01.setData(stringArrayList);
            TypeLimitForClass<ArrayList> typeLimitForClass02 = new TypeLimitForClass<>();
            typeLimitForClass02.setData(integerArrayList);
    
            System.out.println(getMinListSize(typeLimitForClass01.getData().size(), typeLimitForClass02.getData().size()));
    
        }
    
        public static <T extends Comparable<T>> T getMinListSize(T a, T b) {
            return (a.compareTo(b) < 0) ? a : b;
        }

    6,泛型中的约束和局限性

    1,不能实例化泛型类
    2,静态变量或方法不能引用泛型类型变量,但是静态泛型方法是可以的
    3,基本类型无法作为泛型类型
    4,无法使用instanceof关键字或==判断泛型类的类型
    5,泛型类的原生类型与所传递的泛型无关,无论传递什么类型,原生类是一样的
    6,泛型数组可以声明但无法实例化
    7,泛型类不能继承Exception或者Throwable
    8,不能捕获泛型类型限定的异常但可以将泛型限定的异常抛出

    /**
     * Author:Jay On 2019/5/10 17:41
     * <p>
     * Description: 泛型的约束和局限性
     */
    public class GenericRestrict1<T> {
        static class NormalClass {
    
        }
    
        private T data;
    
        /**
         * 不能实例化泛型类
         * Type parameter 'T' cannot be instantiated directly
         */
        public void setData() {
            //this.data = new T();
        }
    
        /**
         * 静态变量或方法不能引用泛型类型变量
         * 'com.jay.java.泛型.restrict.GenericRestrict1.this' cannot be referenced from a static context
         */
    //    private static T result;
    
    //    private static T getResult() {
    //        return result;
    //    }
    
        /**
         * 静态泛型方法是可以的
         */
        private static <K> K getKey(K k) {
            return k;
        }
    
        public static void main(String[] args) {
            NormalClass normalClassA = new NormalClass();
            NormalClass normalClassB = new NormalClass();
            /**
             * 基本类型无法作为泛型类型
             */
    //        GenericRestrict1<int> genericRestrictInt = new GenericRestrict1<>();
            GenericRestrict1<Integer> genericRestrictInteger = new GenericRestrict1<>();
            GenericRestrict1<String> genericRestrictString = new GenericRestrict1<>();
            /**
             * 无法使用instanceof关键字判断泛型类的类型
             * Illegal generic type for instanceof
             */
    //        if(genericRestrictInteger instanceof GenericRestrict1<Integer>){
    //            return;
    //        }
    
            /**
             * 无法使用“==”判断两个泛型类的实例
             * Operator '==' cannot be applied to this two instance
             */
    //        if (genericRestrictInteger == genericRestrictString) {
    //            return;
    //        }
    
            /**
             * 泛型类的原生类型与所传递的泛型无关,无论传递什么类型,原生类是一样的
             */
            System.out.println(normalClassA == normalClassB);//false
            System.out.println(genericRestrictInteger == genericRestrictInteger);//
            System.out.println(genericRestrictInteger.getClass() == genericRestrictString.getClass()); //true
            System.out.println(genericRestrictInteger.getClass());//com.jay.java.泛型.restrict.GenericRestrict1
            System.out.println(genericRestrictString.getClass());//com.jay.java.泛型.restrict.GenericRestrict1
    
            /**
             * 泛型数组可以声明但无法实例化
             * Generic array creation
             */
            GenericRestrict1<String>[] genericRestrict1s;
    //        genericRestrict1s = new GenericRestrict1<String>[10];
            genericRestrict1s = new GenericRestrict1[10];
            genericRestrict1s[0]=genericRestrictString;
        }
    
    }
    /**
     * Author:Jay On 2019/5/10 18:45
     * <p>
     * Description: 泛型和异常
     */
    public class GenericRestrict2 {
    
        private class MyException extends Exception {
        }
    
        /**
         * 泛型类不能继承Exception或者Throwable
         * Generic class may not extend 'java.lang.Throwable'
         */
    //    private class MyGenericException<T> extends Exception {
    //    }
    //
    //    private class MyGenericThrowable<T> extends Throwable {
    //    }
    
        /**
         * 不能捕获泛型类型限定的异常
         * Cannot catch type parameters
         */
        public <T extends Exception> void getException(T t) {
    //        try {
    //
    //        } catch (T e) {
    //
    //        }
        }
    
        /**
         *可以将泛型限定的异常抛出
         */
        public <T extends Throwable> void getException(T t) throws T {
            try {
    
            } catch (Exception e) {
                throw t;
            }
        }
    }

    7,泛型类型继承规则

    1,对于泛型参数是继承关系的泛型类之间是没有继承关系的
    2,泛型类可以继承其它泛型类,例如: public class ArrayList<E> extends AbstractList<E>
    3,泛型类的继承关系在使用中同样会受到泛型类型的影响

    /**
     * Author:Jay On 2019/5/10 19:13
     * <p>
     * Description: 泛型继承规则测试类
     */
    public class GenericInherit<T> {
        private T data1;
        private T data2;
    
        public T getData1() {
            return data1;
        }
    
        public void setData1(T data1) {
            this.data1 = data1;
        }
    
        public T getData2() {
            return data2;
        }
    
        public void setData2(T data2) {
            this.data2 = data2;
        }
    
        public static <V> void setData2(GenericInherit<Father> data2) {
    
        }
    
        public static void main(String[] args) {
    //        Son 继承自 Father
            Father father = new Father();
            Son son = new Son();
            GenericInherit<Father> fatherGenericInherit = new GenericInherit<>();
            GenericInherit<Son> sonGenericInherit = new GenericInherit<>();
            SubGenericInherit<Father> fatherSubGenericInherit = new SubGenericInherit<>();
            SubGenericInherit<Son> sonSubGenericInherit = new SubGenericInherit<>();
    
            /**
             * 对于传递的泛型类型是继承关系的泛型类之间是没有继承关系的
             * GenericInherit<Father> 与GenericInherit<Son> 没有继承关系
             * Incompatible types.
             */
            father = new Son();
    //        fatherGenericInherit=new GenericInherit<Son>();
    
            /**
             * 泛型类可以继承其它泛型类,例如: public class ArrayList<E> extends AbstractList<E>
             */
            fatherGenericInherit=new SubGenericInherit<Father>();
    
            /**
             *泛型类的继承关系在使用中同样会受到泛型类型的影响
             */
            setData2(fatherGenericInherit);
    //        setData2(sonGenericInherit);
            setData2(fatherSubGenericInherit);
    //        setData2(sonSubGenericInherit);
    
        }
    
        private static class SubGenericInherit<T> extends GenericInherit<T> {
    
        }

    8,通配符类型

    1,<? extends Parent> 指定了泛型类型的上届
    2,<? super Child> 指定了泛型类型的下届
    3, <?> 指定了没有限制的泛型类型

    /**
     * Author:Jay On 2019/5/10 19:51
     * <p>
     * Description: 泛型通配符测试类
     */
    public class GenericByWildcard {
        private static void print(GenericClass<Fruit> fruitGenericClass) {
            System.out.println(fruitGenericClass.getData().getColor());
        }
    
        private static void use() {
            GenericClass<Fruit> fruitGenericClass = new GenericClass<>();
            print(fruitGenericClass);
            GenericClass<Orange> orangeGenericClass = new GenericClass<>();
            //类型不匹配,可以使用<? extends Parent> 来解决
    //        print(orangeGenericClass);
        }
    
        /**
         * <? extends Parent> 指定了泛型类型的上届
         */
        private static void printExtends(GenericClass<? extends Fruit> genericClass) {
            System.out.println(genericClass.getData().getColor());
        }
    
        public static void useExtend() {
            GenericClass<Fruit> fruitGenericClass = new GenericClass<>();
            printExtends(fruitGenericClass);
            GenericClass<Orange> orangeGenericClass = new GenericClass<>();
            printExtends(orangeGenericClass);
    
            GenericClass<Food> foodGenericClass = new GenericClass<>();
            //Food是Fruit的父类,超过了泛型上届范围,类型不匹配
    //        printExtends(foodGenericClass);
    
            //表示GenericClass的类型参数的上届是Fruit
            GenericClass<? extends Fruit> extendFruitGenericClass = new GenericClass<>();
            Apple apple = new Apple();
            Fruit fruit = new Fruit();
            /*
             * 道理很简单,? extends X  表示类型的上界,类型参数是X的子类,那么可以肯定的说,
             * get方法返回的一定是个X(不管是X或者X的子类)编译器是可以确定知道的。
             * 但是set方法只知道传入的是个X,至于具体是X的那个子类,不知道。
             * 总结:主要用于安全地访问数据,可以访问X及其子类型,并且不能写入非null的数据。
             */
    //        extendFruitGenericClass.setData(apple);
    //        extendFruitGenericClass.setData(fruit);
    
            fruit = extendFruitGenericClass.getData();
    
        }
    
        /**
         * <? super Child> 指定了泛型类型的下届
         */
        public static void printSuper(GenericClass<? super Apple> genericClass) {
            System.out.println(genericClass.getData());
        }
    
        public static void useSuper() {
            GenericClass<Food> foodGenericClass = new GenericClass<>();
            printSuper(foodGenericClass);
    
            GenericClass<Fruit> fruitGenericClass = new GenericClass<>();
            printSuper(fruitGenericClass);
    
            GenericClass<Apple> appleGenericClass = new GenericClass<>();
            printSuper(appleGenericClass);
    
            GenericClass<HongFuShiApple> hongFuShiAppleGenericClass = new GenericClass<>();
            // HongFuShiApple 是Apple的子类,达不到泛型下届,类型不匹配
    //        printSuper(hongFuShiAppleGenericClass);
    
            GenericClass<Orange> orangeGenericClass = new GenericClass<>();
            // Orange和Apple是兄弟关系,没有继承关系,类型不匹配
    //        printSuper(orangeGenericClass);
    
            //表示GenericClass的类型参数的下界是Apple
            GenericClass<? super Apple> supperAppleGenericClass = new GenericClass<>();
            supperAppleGenericClass.setData(new Apple());
            supperAppleGenericClass.setData(new HongFuShiApple());
            /*
             * ? super  X  表示类型的下界,类型参数是X的超类(包括X本身),
             * 那么可以肯定的说,get方法返回的一定是个X的超类,那么到底是哪个超类?不知道,
             * 但是可以肯定的说,Object一定是它的超类,所以get方法返回Object。
             * 编译器是可以确定知道的。对于set方法来说,编译器不知道它需要的确切类型,但是X和X的子类可以安全的转型为X。
             * 总结:主要用于安全地写入数据,可以写入X及其子类型。
             */
    //        supperAppleGenericClass.setData(new Fruit());
    
            //get方法只会返回一个Object类型的值。
            Object data = supperAppleGenericClass.getData();
        }
    
        /**
         * <?> 指定了没有限定的通配符
         */
        public static void printNonLimit(GenericClass<?> genericClass) {
            System.out.println(genericClass.getData());
        }
    
        public static void useNonLimit() {
            GenericClass<Food> foodGenericClass = new GenericClass<>();
            printNonLimit(foodGenericClass);
            GenericClass<Fruit> fruitGenericClass = new GenericClass<>();
            printNonLimit(fruitGenericClass);
            GenericClass<Apple> appleGenericClass = new GenericClass<>();
            printNonLimit(appleGenericClass);
    
            GenericClass<?> genericClass = new GenericClass<>();
            //setData 方法不能被调用, 甚至不能用 Object 调用;
    //        genericClass.setData(foodGenericClass);
    //        genericClass.setData(new Object());
            //返回值只能赋给 Object
            Object object = genericClass.getData();
    
        }
    
    }

    9,获取泛型的参数类型

    Type是什么
    这里的Type指java.lang.reflect.Type, 是Java中所有类型的公共高级接口, 代表了Java中的所有类型. Type体系中类型的包括:数组类型(GenericArrayType)、参数化类型(ParameterizedType)、类型变量(TypeVariable)、通配符类型(WildcardType)、原始类型(Class)、基本类型(Class), 以上这些类型都实现Type接口.

    参数化类型,就是我们平常所用到的泛型List、Map;
    数组类型,并不是我们工作中所使用的数组String[] 、byte[],而是带有泛型的数组,即T[] ;
    通配符类型, 指的是<?>, <? extends T>等等
    原始类型, 不仅仅包含我们平常所指的类,还包括枚举、数组、注解等;
    基本类型, 也就是我们所说的java的基本类型,即int,float,double等
    public interface ParameterizedType extends Type {
        // 返回确切的泛型参数, 如Map<String, Integer>返回[String, Integer]
        Type[] getActualTypeArguments();
        
        //返回当前class或interface声明的类型, 如List<?>返回List
        Type getRawType();
        
        //返回所属类型. 如,当前类型为O<T>.I<S>, 则返回O<T>. 顶级类型将返回null 
        Type getOwnerType();
    }
    /**
     * Author:Jay On 2019/5/11 22:41
     * <p>
     * Description: 获取泛型类型测试类
     */
    public class GenericType<T> {
        private T data;
    
        public T getData() {
            return data;
        }
    
        public void setData(T data) {
            this.data = data;
        }
    
        public static void main(String[] args) {
            GenericType<String> genericType = new GenericType<String>() {};
            Type superclass = genericType.getClass().getGenericSuperclass();
            //getActualTypeArguments 返回确切的泛型参数, 如Map<String, Integer>返回[String, Integer]
            Type type = ((ParameterizedType) superclass).getActualTypeArguments()[0]; 
            System.out.println(type);//class java.lang.String
        }
    }
  • 相关阅读:
    大三寒假第十四天
    大三寒假第十一天
    大三寒假第十二天
    SparkSQL 通过jdbc连接数据库/通过hive读写数据
    bootstrapfileinput上传控件
    信用卡评分模型(五)
    “元宇宙”是什么?它到底有哪些大招?
    如何学习游戏引擎?
    Web开发的26项基本概念和技术总结
    游戏引擎开发和游戏客户端开发有什么区别?
  • 原文地址:https://www.cnblogs.com/deityjian/p/11370166.html
Copyright © 2011-2022 走看看