• Java泛型拾遗


          先上百度百科的解释

          泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。
    在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。

    好吧,我知道这如果初次解除泛型直接就懵掉了,这都是些什么???
    理解泛型第一步理解类型信息擦除。

    1.简单泛型
    类型信息擦除,举两个例子

    @Test
    public void testGeneric() {
        List<String> list1 = new ArrayList<String>();
        List<Integer> list2 = new ArrayList<Integer>();
        System.out.println("list1类型" + list1.getClass());
        System.out.println("list2类型" + list2.getClass());
    }
    
    list1类型class java.util.ArrayList
    list2类型class java.util.ArrayList
    
    @Test
    public void testGeneric1() {
        List list = new ArrayList();
        list.add("xyz");
        list.add(100);
        for (int i = 0; i < list.size(); i++) {
            String name = (String) list.get(i);
            System.out.println("name:" + name);
        }
    }
    
    name:xyz
    java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

    这个例子很明显编译阶段没问题,执行阶段挂掉了。
    关于这个举个不恰当的例子:鱼和猫不能放到一个篮子里, 放进去没事, 拿出来还想拿到鱼的话,那就是太单纯了。
    所以当时就要避免这情况发生,如果篮子里有个猫,就不放往里放鱼,如果有鱼也就让猫远点,这是不是解释了泛型。

    具体的看下List接口的定义就了解了。

    2.泛型接口

    这个就拿上面List接口为例

    public interface List<E> extends Collection<E> {...}

    public class ArrayList<E> extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    {...}

    这样的泛型接口很合适于工厂模式,这个留个坑在这,设计模式我已经放那了,我希望能写完那个系列...(拖延症患者伤不起, 设计模式我绝对写完,给自己点信心,总要有点坚持)

    3.泛型方法
          先对泛型方法做一个声明,拥有泛型方法的类可以是泛型类,也可以不是泛型类,其实就是跟类没啥关系喽
    就是那句流行的话,你强任你强...

    public class GenericTest {
        public <T> void printClassInfo(T t) {
            System.out.println(t.getClass().getName());
        }
    }
    
    @Test
    public void testGeneric2() {
        GenericTest genericTest = new GenericTest();
        genericTest.printClassInfo("String");
        genericTest.printClassInfo(new Integer("123"));
        genericTest.printClassInfo(genericTest);
    }
    
    java.lang.String
    java.lang.Integer
    com.test.GenericTest

    这样一个类既可以传入String Integer 还有自定义的类型 好神奇的方法重载有没有

    4.泛型类

    public class GenericClass<T> {
        public T getObj() {
            return obj;
        }
    
        public void setObj(T obj) {
            this.obj = obj;
        }
    
        private T obj;
    }
    
    @Test
    public void testGeneric3() {
        GenericClass genericClassTest = new GenericClass();
        genericTest.printClassInfo("String");
        genericTest.printClassInfo(new Integer("123"));
        genericTest.printClassInfo(genericTest);
    }
    
    testGeneric

    泛型边界
         可以用无界泛型调用的方法, 就是可以用Object调用的方法
    不限制边界,那就是Object

          Java泛型编程中使用extends关键字指定泛型参数类型的上边界(后面还会讲到使用super关键字指定泛型的下边界),即泛型只能适用于extends关键字后面类或接口的子类。
    Java泛型编程的边界可以是多个,使用如<T extends A & B & C>语法来声明,其中只能有一个是类,并且只能是extends后面的第一个为类,其他的均只能为接口(和类/接口中的extends意义不同)。
    使用了泛型边界之后,泛型对象就可以使用边界对象中公共的成员变量和方法。

    @Test
    public void testGeneric4() {
        GenerateAnimal dog = new GenerateAnimal(new Dog());
        dog.getName();
    }
    
    public class Dog implements Animal {
        @Override
        public String getName() {
            System.out.println("dog");
            return "dog";
        }
    }
    
    public interface Animal {
        String getName();
    }
    
    public class GenerateAnimal<T extends Animal> {
        private T t;
        GenerateAnimal(T t){
            this.t = t;
        }
    
        public String getName() {
            return t.getName();
        }
    }

    泛型通配符

    @Test
    public void testGeneric5() {
        Fruit<String> f1 = new Fruit<>("平凡如我");
        Fruit<Integer> f2 = new Fruit<>(77);
        Fruit<Double> f3 = new Fruit<>(22.1);
        getData(f1);
        getData(f2);
        getData(f3);
    
        // getFruitData(f1); 编译问题
        getFruitData(f2);
        getFruitData(f3);
    }
    
    private void getData(Fruit<?> f) {
        System.out.println("Fruit :"  + f.getData());
    }
    
    private void getFruitData(Fruit<? extends Number> f) {
        System.out.println("Fruit :"  + f.getData());
    }
    
    Fruit :平凡如我
    Fruit :77
    Fruit :22.1
    Fruit :77
    Fruit :22.1
    
    @Test
    public void testGeneric6() {
        Fruit<String> f1 = new Fruit<>("平凡如我");
        Fruit<Integer> f2 = new Fruit<>(77);
        Fruit<Double> f3 = new Fruit<>(22.1);
        //getFruitSupperData(f1); // 编译问题
        //getFruitSupperData(f3); // 编译问题
        getFruitSupperData(f2);
    
    }
    
    private void getFruitSupperData(Fruit<? super Integer> f) {
        System.out.println("Fruit :"  + f.getData());
    }

    总结

        关于泛型这些也差不多了,在我理解,Java是一种强类型语言,而泛型,使参数类型是可变化的,当然上面的例子与泛型的实际应用还差比较远,希望之后能更融会贯通的应用泛型。

  • 相关阅读:
    html5-移动端布局模板
    html5-figure和figcaption元素
    html5-hgroup和address元素
    html5-新元素新布局模板-完善中
    数据库操作符
    数据库操作,复制表
    数据库基本sql语句
    反射+工厂模型+Properties
    java :动态代理
    java 反射
  • 原文地址:https://www.cnblogs.com/daily-note/p/6958945.html
Copyright © 2020-2023  润新知