JAVA泛型详解 --- 学习笔记

来源:互联网 发布:问道1.52服务端源码 编辑:程序博客网 时间:2024/06/15 21:29

原文请戳此处!!!


1. 普通泛型

class Point<T>{                  //此处可以随便写标识符号,T只是Type的简称    private T var;               // var的类型由T指定,也就是:由外部指定    public T getVar(){           //返回值得类型也是由外部决定的        return var;    }    public void setVar(T var){    //设置的类型也由外部决定        this.var = var;    }}public class GenericsDemo01{    public static void main(String args[]){        Point<String> p = new Point<String>();   //此处决定了类Point<T>里面的var类型为String类型        p.setVar("forfan06");      //设置字符串        System.out.println(p.getVar().length());  //此处分两步,一是取得字符串;二是获得字符串长度    }}

-----------------------------------------------------------------------------------------------------------

class Notepad<K, V>{    //指定了两个泛型类型T和V,当然,此处的T和V可以换成其他字符。但是为了方便识别,一般取一个有意义单词的大写首字母    private K key;      // 此处的T和V均是由外部决定的    private V value;    public K getKey(){        return this.key;    }    public V getValue(){        return this.value;    }    public void setKey(K key){        this.key = key;    }    public void setValue(V value){        this.value = value;    }}public class GenericsDemo02{    public static void main(String args[]){        Notepad<String, Integer> t = null;        //定义了两个泛型类型的对象。        t = new Notepad<String, Integer>();       //里面的key和value分别为String和Integer类型。        t.setKey("饭饭");                          //设置对象t的内容        t.setValue(20);                System.out.print("姓名:" + t.getKey());      //获取对象t的属性        System.out.println(", 年龄:" + t.getValue());    }}

2. 通配符

class Info<T>{    private T var;     //定义泛型变量,由外部决定    public void setVar(T var){        this.var = var;    }    public T getVar(){        return this.var;    }    public String toString(){   //直接打印        return this.var.toString();    }}public class GenericsDemo03{    public static void main(String args[]){        Info<String> i = new Info<String>();  //使用String类型为泛型类型        i.setVar("forfan06");        fun(i);    }    public static void fun(Info<?> info){    //此处Info<?>里面没有明确指明泛型类型,说明可以接受任意的泛型对象。        System.out.println("内容是:" + info);    }}

更好的验证通配符的作用:增加Info<Integer>如下代码:也可以正常运行!!!

class Info<T>{    private T var;     //定义泛型变量,由外部决定    public void setVar(T var){        this.var = var;    }    public T getVar(){        return this.var;    }    public String toString(){   //直接打印        return this.var.toString();    }}public class GenericsDemo03{    public static void main(String args[]){        Info<String> i = new Info<String>();  //使用String类型为泛型类型        i.setVar("forfan06");        fun(i);        Info<Integer> s = new Info<Integer>();        s.setVar(28);        fun(s);    }    public static void fun(Info<?> info){    //此处Info<?>里面没有明确指明泛型类型,说明可以接受任意的泛型对象。        System.out.println("内容是:" + info);    }}

上面程序若修改为:

class Info<T>{    private T var;     //定义泛型变量,由外部决定    public void setVar(T var){        this.var = var;    }    public T getVar(){        return this.var;    }    public String toString(){   //直接打印        return this.var.toString();    }}public class GenericsDemo03{    public static void main(String args[]){        Info<String> i = new Info<String>();  //使用String类型为泛型类型        i.setVar("forfan06");        fun(i);        Info<Integer> s = new Info<Integer>();        s.setVar(28);        fun(s);    }    public static void fun(Info<T> info){    //此处Info<?>里面没有明确指明泛型类型,说明可以接受任意的泛型对象。        System.out.println("内容是:" + info);    }}

则会出现编译错误!!!!!!!!!!!!

GenericsDemo03.java:22: error: cannot find symbol    public static void fun(Info info){                                    ^  symbol:   class T  location: class GenericsDemo031 error编译错误


3. 受限泛型

上限:

class Info<T>{    private T var;    public void setVar(T var){        this.var = var;    }    public T getVar(){        return this.var;    }    public String toString(){        return this.var.toString();    }}public class GenericsDemo04{    public static void main(String args[]){        Info<Integer> i1 = new Info<Integer>();          //声明Integer类的泛型对象        Info<Float> i2 = new Info<Float>();              //声明Float类的泛型对象        i1.setVar(27);                                   //设置整数(小数), 自动装箱!!        i2.setVar(10.53f);        fun(i1);        fun(i2);    }    public static void fun(Info<? extends Number> temp){   //只能接受Number类及其子类的实例!!!!        System.out.print(temp + "、");    }}

下限:

class Info<T>{    private T var;    public void setVar(T var){        this.var = var;    }    public T getVar(){        return this.var;    }    public String toString(){        return this.var.toString();    }}public class GenericsDemo04{    public static void main(String args[]){        Info<String> i1 = new Info<String>();        Info<Object> i2 = new Info<Object>();        i1.setVar("forfan06");        i2.setVar(new Object());                fun(i1);        fun(i2);    }    public static void fun(Info<? super String> temp){     //只能接收String类或其父类(Object类)类型的泛型        System.out.print(temp + "、");    }}


4. 泛型无法向上转型

class Info<T>{    private T var;    public void setVar(T var){        this.var = var;    }    public T getVar(){        return this.var;    }    public String toString(){        return this.var.toString();    }}public class GenericsDemo05{    public static void main(String args[]){        Info<String> i1 = new Info<String>();        Info<Object> i2 = null;        i2 = i1;   //此句会出错:error: incompatible types    }}

运行得到错误:

GenericsDemo05.java:17: error: incompatible types        i2 = i1;   //此句会出错:incompatible types             ^  required: Info  found:    Info1 error编译错误

  • 此时Info<String> i1, Info<Object> i2中,i2已经不是i1的基类了!!!所以不存在向上转型这一说法!!!!!

5. 泛型接口

interface Info<T>{          //在接口中定义泛型    public T getVar();      //定义抽象方法,抽象方法的返回值就是泛型类型}class InfoImpl<T> implements Info<T>{   //定义泛型接口的子类    private T var;    public InfoImpl(T var){             //通过构造方法设置属性内容        this.var = var;    }    public T getVar(){        return this.var;    }    public void setVar(T var){        this.var = var;    }}public class GenericsDemo06{    public static void main(String args[]){        Info<String> i = null;         //声明接口对象,泛型T此时为String类型        i = new InfoImpl<String>("forfan06");     //通过子类实例化对象        System.out.println("内容:" + i.getVar());    }}

interface Info<T>{          //在接口中定义泛型    public T getVar();      //定义抽象方法,抽象方法的返回值就是泛型类型}class InfoImpl implements Info<String>{   //定义泛型接口的子类    private String var;    public InfoImpl(String var){             //通过构造方法设置属性内容        this.var = var;    }    public String getVar(){        return this.var;    }    public void setVar(String var){        this.var = var;    }}public class GenericsDemo06{    public static void main(String args[]){        Info i = null;   //声明接口对象        i = new InfoImpl("forfan06");  //通过子类实例化对象        System.out.println("内容:" + i.getVar());    }}

6. 泛型方法

声明格式:

[访问权限] <泛型标识>  泛型标识 方法名称([泛型标识 参数名称])

class Demo{    public <T> T fun(T t){       //可以接收任意类型的数据        return t;                //直接把参数返回    }}public class GenericsDemo07{    public static void main(String args[]){        Demo d= new Demo();        String str = d.fun("forfan06");        int i = d.fun(28);    //传递数字,自动装箱        System.out.println(str);        System.out.println(i);    }}

7. 通过泛型方法返回泛型类型实例

class Info<T extends Number>{    //指定上限,只能是数字类型。(只能是Number类的子类)    private T var;    public T getVar(){        return this.var;    }    public void setVar(T var){        this.var = var;    }    public String toString(){   //覆写Object类中的toString()方法        return this.var.toString();    }}public class GenericsDemo08{    public static void main(String args[]){        Info<Integer> i = fun(30);        System.out.println(i.getVar());    }    public static <T extends Number> Info<T> fun(T param){      //方法中传入或返回的泛型类型由调用方法时所设置的参数类型决定        Info<T> temp = new Info<T>();    //根据传入的数据类型实例化Info        temp.setVar(param);              //将传递的内容设置到Info对象的var属性中        return temp;       //返回实例化对象    }}

8. 使用泛型统一传入的参数类型

class Info<T>{    private T var;    public T getVar(){        return this.var;    }    public void setVar(T var){        this.var = var;    }    public String toString(){        return this.var.toString();    }}public class GenericsDemo09{    public static void main(String args[]){        Info<String> i1 = new Info<String>();        Info<String> i2 = new Info<String>();        i1.setVar("forfan06");        i2.setVar("你好!");        add(i1,i2);    }    public static <T> void add(Info<T> i1, Info<T> i2){        System.out.println(i1.getVar() + " " + i2.getVar());    }}

9. 泛型数组

public class GenericsDemo10{    public static void main(String args[]){        Integer i[] = fun1(1, 2, 3, 4, 5, 6);  //返回泛型数组        fun2(i);    }    public static <T> T[] fun1(T...arg){   //接收可变参数        return arg;                        //返回泛型数组     }    public static <T> void fun2(T param[]){    //输出        System.out.println("接收泛型数组:");        for(T t:param){            System.out.print(t + "、");        }    }}

此时运行会得到以下警告:

GenericsDemo10.java uses unchecked or unsafe operations.Note: Recompile with -Xlint:unchecked for details.

出现上面警告是因为用到了JAVA5.0的泛型,而5.0的泛型不做类型检查,例如ArrayList = a new ArrayList(); a.add("hello");这样会出现警告!解决方法有以下几种:

  1. 在方法的前面加上@SuppressWarnings("unchecked")
  2. 声明泛型类型,例如ArrayList<Object> a = new ArrayList<Object>();
  3. 使用1.4兼容JDK来编译, javac -source 1.4 Test.java
  4. 也可以查看警告信息,javac Xlint:unchecked Test.java。这样会显示详细的警告信息。

10. 泛型的嵌套设置

class Info<T, V>{    private T var;    private V value;    public Info(T var, V value){        this.setVar(var);        this.setValue(value);    }    public void setVar(T var){        this.var = var;    }    public void setValue(V value){        this.value = value;    }    public T getVar(){        return this.var;    }    public V getValue(){        return this.value;    }}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;    }}public class GenericsDemo11{    public static void main(String args[]){        Demo<Info<String, Integer>> d = null;      //将Info作为Demo的泛型类型        Info<String, Integer> i = null;            //Info指定两个泛型类型        i = new Info<String, Integer>("forfan06", 30);    //实例化Info对象        d = new Demo<Info<String, Integer>>(i);           //在Demo类中设置Info类的对象        System.out.println("内容一:" + d.getInfo().getVar());        System.out.println("内容二:" + d.getInfo().getValue());    }}

泛型方法不一定要通过参数来确定泛型准确类型,可以只通过返回值,比如:

public static <E> ArrayList<E> new ArrayList(){     return new ArrayList<E>();}public List<PrepaidHistory> queryHistories(Long skyid, PrepaidHistoryType type, Date from, Date end){     ...     return Lists.newArrayList();}

这样Lists.newArrayList();

智能的知道返回类型为PrepaidHistory


0 0