• [JavaCore]JAVA中的泛型


    JAVA中的泛型

    【更新总结】

    泛型就是定义在类里面的一个类型,这个类型在编写类的时候是不确定的,而在初始化对象时,必须确定该类型;这个类型可以在一个在里定义多个;在一旦使用某种类型,在类方法中,那么统一都必须使用该类型(比如出现T的,所有类方法都必须以T为一种类型);类和方法可以使用不同的类型(比如类中定义R,而方法可以定义S,两者类型可以不一致)。但是在接口中定义泛型方法时,类型必须通过类进行传递至方法,就是说方法声明的类型必须与接口声明一致。

    [写在开始]

    以前在博彦给微软做外包的时候,做的是浏览器的测试,接触到C#相关知识点比较多,经常学习相关知识,对泛型有略微了解,但不深入,只知道方法的参数可以为任意类型,前天看了篇文章,总结的比较好,一直都觉得泛型这东西很好,今天再对JAVA中的泛型总结总结。

    [扫盲]

    Java泛型(Generics)是JDK5开始引入的一个新特性,允许在定义类和接口的时候使用类型参数(Type Parameter)。声明的类型参数在使用时用具体的类型来替换,现在泛型最主要的应用是在JDK5中的新集合类框架中,Map, List均有用到。其中的优点不言而喻,我们可以横向扩展更多的类,缺点呢,其实也就是他的优点,因为这需要我们在使用泛型类的时候,要很清楚自己的代码目地,不能使用错误的类型。

    [看例子学习]

    最基本的泛型类

    package com.garinzhang.javabase.generic.e1;
    /**
     * 最基本的泛型类,类型由自己定义
     * @author Garin Zhang
     *
     * @param <T>
     */
    public class Point<T> {
        private T var;
        public T getVar() {
            return var;
        }
        public void setVar(T var) {
            this.var = var;
        }
    }
    package com.garinzhang.javabase.generic.e1;
    public class GenericExample {
        /**
         * @param args
         */
        public static void main(String[] args) {
            Point<String> p = new Point<String> ();
            p.setVar("coder");
            System.out.println(p.getVar());
        }
    }

    多个泛型类型

    package com.garinzhang.javabase.generic.e2;
    /**
     * 多个泛型类型,一般多个最好是以靠近T的字母,如S,R等
     * @author Garin Zhang
     *
     * @param <T>
     * @param <S>
     */
    public class Notepad<T, S> {
        private T key;
        private S value;
    
        public T getKey() {
            return this.key;
        }
        public S getValue() {
            return this.value;
        }
        public void setKey(T key) {
            this.key = key;
        }
        public void setValue(S value) {
            this.value = value;
        }
    }
    package com.garinzhang.javabase.generic.e2;
    public class GenericExample {
        /**
         * @param args
         */
        public static void main(String[] args) {
            Notepad<String, Integer> p = new Notepad<String, Integer> ();
            p.setKey("coder");
            p.setValue(99999);
            System.out.println("key: " + p.getKey());
            System.out.println("value: " + p.getValue());
        }
    }

    在方法参数中使用通配符"?"

     
    package com.garinzhang.javabase.generic.e3;
    /**
     * 该例子关键在main方法里
     * @author Garin Zhang
     *
     * @param <T>
     */
    public class Info<T> {
        private T key;
        public T getKey() {
            return this.key;
        }
        public void setKey(T key) {
            this.key = key;
        }
        @Override
        public String toString() {
            return this.key.toString();
        }
    }
    package com.garinzhang.javabase.generic.e3;
    /**
     * 在方法参数中使用通配符
     * @author Garin Zhang
     *
     */
    public class GenericExample {
        /**
         * @param args
         */
        public static void main(String[] args) {
            Info<String> i =  new Info<String>();
            i.setKey("coder");
            fun(i);
            Info<Integer> j = new Info<Integer>();
            j.setKey(9999);
            fun(j);
        }
        public static void fun(Info<?> temp) {
            System.out.println("Content: " + temp);
        }
    }

    向上转型失败

    package com.garinzhang.javabase.generic.e4;
    /**
     * 该例子关键在main方法里
     * @author Garin Zhang
     *
     * @param <T>
     */
    public class Info<T> {
        private T key;
        public T getKey() {
            return this.key;
        }
        public void setKey(T key) {
            this.key = key;
        }
        @Override
        public String toString() {
            return this.key.toString();
        }
    }
    package com.garinzhang.javabase.generic.e4;
    public class GenericExample {
        /**
         * @param args
         */
        public static void main(String[] args) {
            Info<String> strEg = new Info<String>();
            Info<Object> objEg;
            // 编译错误"Type mismatch: cannot convert from Info<String> to Info<Object>"
            // 向上转型失败,String -> Object
            // objEg = strEg;
        }
    }
    泛型在接口中的使用
    package com.garinzhang.javabase.generic.e5;
    /**
     * 该例子关键在main方法里
     * @author Garin Zhang
     *
     * @param <T>
     */
    interface Info<T> {
        public T getVar();
    }
    package com.garinzhang.javabase.generic.e5;
    /**
     * 泛型类
     * @author Garin Zhang
     *
     * @param <T>
     */
    public class InfoImpl<T> implements Info<T> {
        private T var;
        public InfoImpl(T var) {
            this.setVar(var);
        }
        public void setVar(T var) {
            this.var = var;
        }
        public T getVar() {
            return this.var;
        }
    }
    package com.garinzhang.javabase.generic.e5;
    /**
     * 非泛型类
     * @author Garin Zhang
     *
     * @param <T>
     */
    public class InfoImpl1 implements Info<String> {
        private String var;
        public InfoImpl1(String var) {
            this.setVar(var);
        }
        public void setVar(String var) {
            this.var = var;
        }
        public String getVar() {
            return this.var;
        }
    }
    package com.garinzhang.javabase.generic.e5;
    public class GenericExample {
        /**
         * @param args
         */
        public static void main(String[] args) {
            Info<String> strEg = new InfoImpl<String>("coder");
            System.out.println("Content: " + strEg.getVar());
    
            Info<String> strEg1 = new InfoImpl1("coder1");
            System.out.println("Content: " + strEg1.getVar());
        }
    }

    通配符和extends, super的使用

    package com.garinzhang.javabase.generic.e6;
    /**
     * 该例子关键在main方法里
     * @author Garin Zhang
     *
     * @param <T>
     */
    public class Info<T> {
        private T key;
        public T getKey() {
            return this.key;
        }
        public void setKey(T key) {
            this.key = key;
        }
        @Override
        public String toString() {
            return this.key.toString();
        }
    }
    package com.garinzhang.javabase.generic.e6;
    public class GenericExample {
        /**
         * @param args
         */
        public static void main(String[] args) {
            Info<String> strEg =  new Info<String>();
            strEg.setKey("coder");
            // 编译报错"The method fun(Info<? extends Number>) in the type GenericExample is not applicable for the arguments (Info<String>)"
            // upTypeLimit(i);
    
            // 使用Integer,Number类型均可以
            Info<Integer> intEg = new Info<Integer>();
            intEg.setKey(9999);
            upTypeLimit(intEg);
    
            // 编译报错"The method downTypeLimit(Info<? super String>) in the type GenericExample is not applicable for the arguments (Info<Integer>)"
            // downTypeLimit(intEg);
    
            // 由于使用的是super,downTypeLimit只能接收String本身和Object
            // 查看了String的继承关系,没有继承其他类,只有Object
            downTypeLimit(strEg);
    
            Info<Object> objEg = new Info<Object>();
            objEg.setKey(999);
            downTypeLimit(objEg);
        }
        /**
         * <? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类
         * @param temp
         */
        public static void upTypeLimit(Info<? extends Number> temp) {
            System.out.println("Content: " + temp);
        }
    
        /**
         * <? super T> 表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object
         * 在此例中,表示T只能为Object或String,因为String只继承于Object
         * @param temp
         */
        public static void downTypeLimit(Info<? super String> temp) {
            System.out.println("Content: " + temp);
        }
    }
    方法泛型,方法里面多个泛型
    package com.garinzhang.javabase.generic.e7;
    /**
     * 方法泛型,方法里面多个泛型
     * @author Garin Zhang
     *
     * @param <T>
     */
    public class Info {
        /**
         * 格式:方法修饰付 <以逗号隔开的类型列表> 返回值类型 方法名(参数列表)
         * 例如:public <T, S> T fun(T t, S s)
         * @param t
         * @param s
         * @return
         */
        public <T, S> T fun(T t, S s) {
            System.out.println(s.toString());
            return t;
        }
    }
    package com.garinzhang.javabase.generic.e7;
    public class GenericExample {
        /**
         * @param args
         */
        public static void main(String[] args) {
            Info info = new Info();
            String str = info.fun("coder", "print second generic param");
            System.out.println(str);
    
            int i = info.fun(30, "print second param again");
            System.out.println(i);
        }
    }

     方法中传入或返回的泛型类型由调用方法时所设置的参数类型决定

    package com.garinzhang.javabase.generic.e8;
    /**
     * extends
     * @author Garin Zhang
     *
     * @param <T>
     */
    public class Info<T extends Number> {
        private T var;
        public T getVar() {
            return this.var;
        }
        public void setVar(T var) {
            this.var = var;
        }
        @Override
        public String toString() {
            return this.var.toString();
        }
    }
    package com.garinzhang.javabase.generic.e8;
    public class GenericExample {
        /**
         * @param args
         */
        public static void main(String[] args) {
            Info<Integer> intEg = fun(30); // 这里类型已经确定为Integer
            System.out.println(intEg.getVar());
        }
        /**
         * 方法中传入或返回的泛型类型由调用方法时所设置的参数类型决定
         * @param param
         * @return
         */
        public static <T extends Number> Info<T> fun(T param) {
            Info<T> temp = new Info<T>();
            temp.setVar(param);
            return temp;
        }
    }

     让方法中传入两个参数类型保持一致

    package com.garinzhang.javabase.generic.e9;
    /**
     * 查看main
     * @author Garin Zhang
     *
     * @param <T>
     */
    public class Info<T> {
        private T var;
        public T getVar() {
            return this.var;
        }
        public void setVar(T var) {
            this.var = var;
        }
        @Override
        public String toString() {
            return this.var.toString();
        }
    }
    package com.garinzhang.javabase.generic.e9;
    public class GenericExample {
        /**
         * @param args
         */
        public static void main(String[] args) {
            Info<String> i1 = new Info<String>();
            i1.setVar("Hello");
    
            Info<String> i2 = new Info<String>();
            i2.setVar("Coder");
    
            Info<Integer> i3 = new Info<Integer>();
            i3.setVar(999);
    
            add(i1, i2);
    
            //编译错误“The method add(Info<T>, Info<T>) in the type GenericExample is not applicable for the arguments (Info<String>, Info<Integer>)”
            // add(i1, i3);
        }
        /**
         * 方法中传入两个参数类型必须一致
         * @param param
         * @return
         */
        public static <T> void add(Info<T> i1, Info<T> i2) {
            System.out.println(i1.getVar() + ":" + i2.getVar());
        }
    }
    泛型,可变参数,类似于javascript里的Arguments对象
    package com.garinzhang.javabase.generic.e10;
    public class GenericExample {
        /**
         * @param args
         */
        public static void main(String[] args) {
            Integer i[] = fun(1, 2, 3, 4, 5, 6);
            fun2(i);
        }
        public static <T> T[] fun(T... arg) {
            return arg;
        }
        public static <T> void fun2(T param[]) {
            System.out.println("generic array: ");
            for(T t : param) {
                System.out.println(t + " ,");
            }
        }
    }

    泛型嵌套:使用泛型类做为参数;根据返回值类型确定返回值

    package com.garinzhang.javabase.generic.e11;
    /**
     * 接受两个泛型类型
     * @author Garin Zhang
     *
     * @param <T>
     */
    public class Info<T, V> {
        private T var;
        private V value;
    
        public T getVar() {
            return this.var;
        }
        public void setVar(T var) {
            this.var = var;
        }
    
        public V getValue(){
            return this.value;
        }
        public void setValue(V value) {
            this.value = value;
        }
        @Override
        public String toString() {
            return this.var.toString();
        }
    }
    package com.garinzhang.javabase.generic.e11;
    /**
     * 接受1个泛型类型
     * @author Garin Zhang
     *
     * @param <T>
     */
    public class Demo<S> {
        private S info;
        public Demo(S info) {
            this.setInfo(info);
        }
        public void setInfo(S info) {
            this.info = info;
        }
        public S getInfo() {
            return this.info;
        }
    }
    package com.garinzhang.javabase.generic.e11;
    import java.util.List;
    import com.google.common.collect.Lists;
    public class GenericExample {
        /**
         * @param args
         */
        public static void main(String[] args) {
            Demo<Info<String, Integer>> d;
            Info<String, Integer> i;
            i = new Info<String, Integer>();
            i.setVar("Coder");
            i.setValue(999);
            d = new Demo<Info<String,Integer>>(i);
            System.out.println("Content: " + d.getInfo().getVar());
            System.out.println("Content: " + d.getInfo().getValue());
    
    
            System.out.println(query(1, 2, 3, 4, 5).toString());            // [1, 2, 3, 4, 5]
            // 警告"Type safety: A generic array of Object&Comparable<?>&Serializable is created for a varargs parameter"
            System.out.println(query(1, 2, 3, "StringType").toString());    // [1, 2, 3, StringType]
            System.out.println(query("I ", "am ", "a ", "coder").toString());// [I , am , a , coder]
    
            List<String> list = Lists.newArrayList("I ", "am ", "a ", "coder");
            System.out.println(list.toString());        // [I , am , a , coder]
        }
        /**
         * 通过返回值确定泛型类型,这个方法里面的返回值类型,是由方法的定义自动生成的
         * @param elements
         * @return
         */
        public static <E> List<E> query(E... elements) {
            // https://github.com/exitsoft/exit-web-framework/commit/1d2f1098a2a4b6abab175b793e2308aa8bd0ea16.
            // import com.google.common.collect.Lists;
            //        <dependency>
            //            <groupId>com.google.guava</groupId>
            //            <artifactId>guava</artifactId>
            //            <version>16.0.1</version>
            //        </dependency>
            return Lists.newArrayList(elements);
        }
     }

     

    参考资料:

    http://www.cnblogs.com/sharpxiajun/archive/2013/05/19/3087179.html

    http://blog.csdn.net/jinuxwu/article/details/6771121

    http://luckykapok918.blog.163.com/blog/static/2058650432012102341548827/

    http://sharewind.iteye.com/blog/1622164

    http://love-love-l.blog.163.com/blog/static/21078304201081312858230/

    http://www.cnblogs.com/panjun-Donet/archive/2008/09/27/1300609.html

    Thinking in Java

  • 相关阅读:
    循环冗余检验 (CRC) 算法原理
    工具分享——将C#文档注释生成.chm帮助文档
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/garinzhang/p/3696115.html
Copyright © 2020-2023  润新知