首頁  >  文章  >  Java  >  12.Java 基礎 - 通配符

12.Java 基礎 - 通配符

黄舟
黄舟原創
2017-02-27 10:46:041396瀏覽


基本概念


#通配符(Wildcard) ,使用一個問號表示類型參數, 是一種表示【未知類型】的【類型限制】的方法

泛型將資料型別定義為一個參數,我們可以在用到的使用再指定具體的型別。但是如果在用到的時候還不能確定具體的類型,就需要依賴通配符來解決。

抽象的講,因為泛型不支援協變,所以才引入了通配符,使得將泛型類型變成協變的。


通配符作用

下面透過兩個例子來探究下通配符的作用。

1.不使用通配符

ArrayList<Object> list_obj = null;
ArrayList<String> list_str = new ArrayList<String>();
// ArrayList 的元素支持  String -> Object 的强制转换list_str.add("hello");
System.out.println((Object)list_str.get(0));// 编译错误,泛型不支持协变list_obj = list_str;

觀察程式碼,發現:

  • 存放在ArrayList 中的元素卻支持從String -> Object 的向上轉型,因為String 是Object 的子類別。

  • 當 ArrayList 的參數類型從 String -> Object 轉換的時候出現了編譯錯誤,因為泛型不支援協變。


2.使用萬用字元

ArrayList<String> list_str = new ArrayList<String>();
list_str.add("hello");

ArrayList<Integer> list_int = new ArrayList<Integer>();
list_int.add(100);

ArrayList<?> list = null;
list = list_str;
System.out.println(list.get(0));    // hellolist = list_int;
System.out.println(list.get(0));    // 100//编译错误list.add("hello");
list.add(100);

觀察程式碼,發現:

  • ##在使用了通配符之後,它允許其接受任意類型的轉變,正好解決了泛型不支援協變的限制。

  • 但是同時也失去了向其中加入任何類型物件的權利。


通配符類型

通配符的形式有三種,分別是:

//1、无限定通配符 Demo<?>//2、上边界限定通配符 Demo< ? extends Number>   

//3、下边界限定通配符    Demo< ? super Number>


1.上邊界限定通配符

觀察下面的例子:定義了三個帶有繼承關係的類,分別是Person -> Man -> Worker。

class Person{    void print(){
    }
}

class Man extends Person{    void paly(){
    }
}

class Worker extends Man{    void say(){
    }
}public class Test {
    public static void main(String[] args)  {        
    // 创建了三个 ArrayList 数组
        ArrayList<Person> personList = new ArrayList<Person>();
        ArrayList<Man> manList= new ArrayList<Man>();
        ArrayList<Worker> workerList = new ArrayList<Worker>();        
        // 限定了上界, ? 代表 Man 以及继承 Man 的类
        ArrayList<? extends Man> list  = null;

        list = manList;
        list = workerList;        // 编译错误,因为 Person 是 Man 的父类
        list = personList;        // 编译错误,因为使用了通配符就不能添加对象
        list.add(new Man());
        list.add(new Worker());        for(Man man : list){
            man.print();
            man.paly();
        }        for(Person per : list){
            per.print();
        }        // 编译错误,因为 ? 也可以代表 Man
        // 从继承我们可以知道 Worker 肯定是 Man,但 Man 不一定是 Worker。
        // for(Worker worker : list);
    }
}


2.下邊界限定通配符
// 省略相同代码...public class Test {
    public static void main(String[] args)  {
        ArrayList<Person> personList = new ArrayList<Person>();
        ArrayList<Man> manList= new ArrayList<Man>();
        ArrayList<Worker> workList = new ArrayList<Worker>();        
        // 限定了下届, ? 代表 Man 以及 Man 的父类
        ArrayList<? super Man> list  = null;

        list = personList;
        list = manList;        // 编译错误,因为 Worker 是 Man 的子类
        list = workList;        // 编译错误,无法确定其父类对象
        // Person 继承子 Cell 类,那么用 Person 遍历就是错误的
        // for(Man man : list);
        // for(Person per : list);

        // 因为 Object 是所有类的根类,所以可以用Object来遍历
        // for(Object obj : list);
    }
}


3.無邊界通配符
// 省略相同代码...public class Test {
    public static void main(String[] args)  {
        ArrayList<Person> personList = new ArrayList<Person>();
        ArrayList<Man> manList= new ArrayList<Man>();
        ArrayList<Worker> workList = new ArrayList<Worker>();        //无边界通配符
        ArrayList<?> list  = null;        //可以代表一切类型
        list = personList;
        list = manList;
        list = workList;        //为了避免类型混淆,只允许使用 Object 遍历
        for(Object obj : list); 
    }
}

以上就是12.Java 基礎- 通配符的內容,更多相關內容請關注PHP中文網(www.php.cn)!



#

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn