天天看點

JAVA之旅(二十一)——泛型的概述以及使用,泛型類,泛型方法,靜态泛型方法,泛型接口,泛型限定,通配符

JAVA之旅(二十一)——泛型的概述以及使用,泛型類,泛型方法,靜态泛型方法,泛型接口,泛型限定,通配符

不知不覺JAVA之旅已經寫到21篇了,不得不感歎當初自己堅持要重學一遍JAVA的信念,中途也算是非常的痛苦吧,不過熬到現在,已經算是有點效果了,繼續加油,估計三十來篇就能結束自己的JAVA之旅了,go,go!

一.泛型的概述

什麼是泛型,我們可以用一個很典型的例子來說明
package com.lgl.hellojava;

import java.util.ArrayList;
import java.util.Iterator;

//公共的   類   類名
public class HelloJJAVA {
    public static void main(String[] args) {
        /**
         * 泛型
         */
        ArrayList al = new ArrayList();
        al.add("hello 1");
        al.add("hello 02");
        al.add("hello 0300");
        al.add("hello 084");
        //添加int
        al.add(5);
        Iterator iterator = al.iterator();
        while (iterator.hasNext()) {
            String s = (String) iterator.next();
            // 列印長度
            sop(s.length());
        }
    }

    // 輸出
    public static void sop(Object obj) {
        System.out.println(obj);

    }
}      
這裡,我們用一個arraylist存儲的資料有String也有int,輸出的結果
JAVA之旅(二十一)——泛型的概述以及使用,泛型類,泛型方法,靜态泛型方法,泛型接口,泛型限定,通配符
不會發現,他報的就是類型的異常,我們要怎麼去解決?這裡就牽扯出泛型來了
  • 泛型:JDK1.5版本之後出現的新特性,用于解決安全問題,是一個安全機制;
我們要怎麼使用?
ArrayList<String> al = new ArrayList<String>();      
我定義了一個容器,容器的參數是String類型,規範了資料類型,就不能存其他的資料了,安全性提高了!
  • 好處:講運作時期出現的問題轉移到了編譯時期,友善程式員解決問題,讓運作時期問題減少,安全

二.泛型的使用

泛型的格式:通過<>來定義要操作的引用資料類型,在使用JAVA提供的對象時,什麼時候寫泛型呢,通常在集合架構中很常見,隻要見到<>就是定義泛型!

其實<>就是用來接收類型的,當使用集合時,将集合中要存儲的資料類型,作為參數,傳遞到<>一樣 ,我們來個小例子

package com.lgl.hellojava;

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

//公共的   類   類名
public class HelloJJAVA {
    public static void main(String[] args) {
        TreeSet<String> tr = new TreeSet<String>(new LenComp());
        tr.add("hello 01");
        tr.add("hello 012");
        tr.add("hello 013");
        tr.add("hello 014");

        Iterator<String> iterator = tr.iterator();
        while (iterator.hasNext()) {
            String string = iterator.next();
            sop(string);
        }
    }

    // 輸出
    public static void sop(Object obj) {
        System.out.println(obj);

    }
}

// 比較器
class LenComp implements Comparator<String> {

    @Override
    public int compare(String o1, String o2) {
        String s1 = o1;
        int num = new Integer(o1.length()).compareTo(new Integer(o2.length()));
        if (num == 0) {
            return o1.compareTo(o2);
        }
        return num;
    }

}      
你可以仔細的看看裡面是怎麼用泛型的,就是一些小技巧

三.泛型類

這是我們優化代碼比較常見的一種方式,我們可以看這塊代碼
package com.lgl.hellojava;

//公共的   類   類名
public class HelloJJAVA {
    public static void main(String[] args) {
        Tool t = new Tool();
        t.setW(new Worker());
        t.getW();
    }

    // 輸出
    public static void sop(Object obj) {
        System.out.println(obj);

    }
}
//操作勞工的工具類
class Tool {
    private Worker w;

    public Worker getW() {
        return w;
    }

    public void setW(Worker w) {
        this.w = w;
    }

}

class Worker {

}      
這裡,有一個勞工的類,我們定義一個工具類去操作,對吧,這個邏輯就是這麼的簡單,但是你回發現,如果我在定義一個學生的類,就又得需要一個學生的工具類了,我們為什麼不去合并這個工具類,抽調共有的方法呢?你會說可以用Object?
//操作勞工的工具類
class Tool {
    private Object obj;

    public Object getObj() {
        return obj;
    }

    public void setObj(Object obj) {
        this.obj = obj;
    }

}      
這樣的話,你如果傳遞的話,還是要定義床底類型,不然會報類型異常的,我們泛型的用法
class Utils<T> {

    private T t;

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }
}      
由你來指定傳遞進來的參數,這樣就可以為所欲為了
  • 什麼時候定義泛型類
當類中要操作的引用資料類型不确定的時候,早起定義Object來完成擴充,現在定義泛型來完成擴充

四.泛型方法

泛型除了定義在類中,還是可以定義在方法上的,我們來看一下
package com.lgl.hellojava;

//公共的   類   類名
public class HelloJJAVA {
    public static void main(String[] args) {
        Demo<String> d = new Demo<String>();
        d.show("hh");
        d.print("aa");
    }
}

class Demo<T> {
    public void show(T t) {
        System.out.println("show:" + t);
    }

    public void print(T t) {
        System.out.println("print:" + t);
    }
}      
泛型類定義的泛型,在整個類中有效,如果被方面使用,那麼泛型類的對象明确要操作的具體類型後,所有要操作的類型就已經固定了。
  • 為了讓不同的方法可以操作不同的類型,而且類型不确定,那麼可以将泛型定義在方法上
仔細看
class Demo {
    public <T> void show(T t) {

    }
    public <T>void print(T t){

    }
}      
這樣就可以傳遞泛型參數了

五.靜态泛型方法

這個倒不是什麼大知識點,就是注意一下,泛型方法不能使用靜态的,也可以說靜态方法不可以通路類上定義的泛型,如果靜态方法操作的應用資料類型不确定,可以将泛型定義在方法上,就可以了
class Demo<T> {
    public <T> void show(T t) {

    }

    public <T> void print(T t) {

    }

    public static <T> void method(T t) {

    }
}      
要放在static後面哦!

六.泛型接口

你類和方法都有了,怎麼能少得了接口呢?
package com.lgl.hellojava;


//公共的   類   類名
public class HelloJJAVA {
    public static void main(String[] args) {
        InterImpl<Integer> i = new InterImpl<Integer>();
        i.show(55);
    }
}

class InterImpl<T> implements Inter<T> {

    @Override
    public void show(T t) {
        System.out.println("show:" + t);
    }

}

interface Inter<T> {
    void show(T t);
}      
結構也差不多,傳參數就行,但是這種情況是不多見的

七.泛型限定

我們來玩玩泛型的進階用法,go

先從例子切入正題

package com.lgl.hellojava;

import java.util.ArrayList;
import java.util.Iterator;

//公共的   類   類名
public class HelloJJAVA {
    public static void main(String[] args) {
        ArrayList<String> al = new ArrayList<String>();

        al.add("hello 01");
        al.add("hello 02");
        al.add("hello 03");
        al.add("hello 04");

        ArrayList<Integer> all = new ArrayList<Integer>();
        all.add(9);
        all.add(596);
        all.add(98);
        all.add(97);

        printColl(all);
    }
    //内容不明确
    public static void printColl(ArrayList<?> als) {
        Iterator<?> iterator = als.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}      
問号是占位符,上面的邏輯就是我們有兩個arrayList,但是我們需要公用一個方法,内容不明确,是以用問号占位,其實實作的方式還有很多種,還有一種需求使用不到?的,因為?是列印任何的資料,但是我隻需要列印限定的幾種類型,這個時候該怎麼做?
package com.lgl.hellojava;

import java.util.ArrayList;
import java.util.Iterator;

//公共的   類   類名
public class HelloJJAVA {

    public static void main(String[] args) {
        ArrayList<Person> al = new ArrayList<Person>();
        al.add(new Person("zhangsan"));
        al.add(new Person("lisi"));
        al.add(new Person("wangwu"));

        ArrayList<Student> al1 = new ArrayList<Student>();
        al1.add(new Student("zhangsan -- 1"));
        al1.add(new Student("lisi -- 2"));
        al1.add(new Student("wangwu -- 3"));

        // ArrayList
        printColl(al1);
    }

    // 内容不明确
    public static void printColl(ArrayList<? extends Person> als) {
        Iterator<? extends Person> iterator = als.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next().getName());
        }
    }
}

class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

class Student extends Person {

    public Student(String name) {
        super(name);
    }
}      
這裡,就能列印出學生和人類,而不列印其他類型的參數了,這就叫泛型限定
  • ?叫通配符,也可以了解為占位符
  • 泛型的限定 ? extends E:E類型和E的子類型。這叫上限
  • ? super E:可以接受E類型和E的父類,這叫下限
下限我就不示範了,有機會的同學可以自己試試看,還是挺好玩的

歡迎加群:555974449