[JavaCore]JAVA中的泛型

JAVA中的泛型

[写在开始]

以前在博彦给微软做外包的时候,做的是浏览器的测试,接触到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

你可能感兴趣的:(javac)