成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java反射機制應用實踐

開發 后端
Java反射機制是一個非常強大的功能,在很多大型項目比如Spring, Mybatis都可以看見反射的身影。通過反射機制我們可以在運行期間獲取對象的類型信息,利用這一特性我們可以實現工廠模式和代理模式等設計模式,同時也可以解決Java泛型擦除等令人苦惱的問題。

引言

Java反射機制是一個非常強大的功能,在很多大型項目比如Spring, Mybatis都可以看見反射的身影。通過反射機制我們可以在運行期間獲取對象的類型信息,利用這一特性我們可以實現工廠模式和代理模式等設計模式,同時也可以解決Java泛型擦除等令人苦惱的問題。本文我們就從實際應用的角度出發,來應用一下Java的反射機制。

反射基礎

p.s: 本文需要讀者對反射機制的API有一定程度的了解,如果之前沒有接觸過的話,建議先看一下官方文檔的Quick Start

在應用反射機制之前,首先我們先來看一下如何獲取一個對象對應的反射類Class,在Java中我們有三種方法可以獲取一個對象的反射類。

通過getClass方法

在Java中,每一個Object都有一個getClass方法,通過getClass方法我們可以獲取到這個對象對應的反射類:

String s = "ziwenxie";
Class<?> c = s.getClass();

通過forName方法

我們也可以調用Class類的靜態方法forName

Class<?> c = Class.forName("java.lang.String");

使用.class

或者我們也可以直接使用.class

Class<?> c = String.class;

獲取類型信息

在文章開頭我們就提到反射的一大好處就是可以允許我們在運行期間獲取對象的類型信息,下面我們通過一個例子來具體看一下。

首先我們在typeinfo.interfacea包下面新建一個接口A

package typeinfo.interfacea;
public interface A { void f(); }

接著我們在typeinfo.packageaccess包下面新建一個接口C,接口C繼承自接口A,并且我們還另外創建了幾個用于測試的方法,注意下面幾個方法的權限都是不同的。

package typeinfo.packageaccess;
import typeinfo.interfacea.A;
class C implements A {
    public void f() { System.out.println("public C.f()"); }
    public void g() { System.out.println("public C.g()"); }
    protected void v () { System.out.println("protected C.v()"); }
    void u() { System.out.println("package C.u()"); }
    private void w() { System.out.println("private C.w()"); }
}
public class HiddenC {
    public static A makeA() { return new C(); }
}

callHiddenMethod()方法中我們用到了幾個新的API,其中getDeclaredMethod()根據方法名用于獲取Class類指代對象的某個方法,然后我們通過調用invoke()方法傳入實際的對象就可以觸發對象的相關方法:

package typeinfo;
import typeinfo.interfacea.A;
import typeinfo.packageaccess.HiddenC;
import java.lang.reflect.Method;
public class HiddenImplementation {
    public static void main(String[] args) throws Exception {
        A a = HiddenC.makeA();
        a.f();
        System.out.println(a.getClass().getName());
        // Oops! Reflection still allows us to call g():
        callHiddenMethod(a, "g");
        // And even methods that are less accessible!
        callHiddenMethod(a, "u");
        callHiddenMethod(a, "v");
        callHiddenMethod(a, "w");
    }
    static void callHiddenMethod(Object a, String methodName) throws Exception {
        Method g = a.getClass().getDeclaredMethod(methodName);
        g.setAccessible(true);
        g.invoke(a);
    }
}

從輸出結果我們可以看出來,不管是publicdefaultprotect還是pricate方法,通過反射類我們都可以自由調用。當然這里我們只是為了顯示反射的強大威力,在實際開發中這種技巧還是不提倡。

public C.f()
typeinfo.packageaccess.C
public C.g()
package C.u()
protected C.v()
private C.w()

應用實踐

我們有下面這樣一個業務場景,我們有一個泛型集合類List<Class<? extends Pet>>,我們需要統計出這個集合類中每種具體的Pet有多少個。由于Java的泛型擦除,注意類似List<? extends Pet>的做法肯定是不行的,因為編譯器做了靜態類型檢查之后,到了運行期間JVM會將集合中的對象都視為Pet,但是并不會知道Pet代表的究竟是Cat還是Dog,所以到了運行期間對象的類型信息其實全部丟失了。p.s: 關于泛型擦除:我在上一篇文章里面有詳細解釋,感興趣的朋友可以看一看。

為了實現我們上面的例子,我們先來定義幾個類:

public class Pet extends Individual {
    public Pet(String name) { super(name); }
    public Pet() { super(); }
}
public class Cat extends Pet {
    public Cat(String name) { super(name); }
    public Cat() { super(); }
}
public class Dog extends Pet {
    public Dog(String name) { super(name); }
    public Dog() { super(); }
}
public class EgyptianMau extends Cat {
    public EgyptianMau(String name) { super(name); }
    public EgyptianMau() { super(); }
}
public class Mutt extends Dog {
    public Mutt(String name) { super(name); }
    public Mutt() { super(); }
}

上面的Pet類繼承自IndividualIndividual類的的實現稍微復雜一點,我們實現了Comparable接口,重新自定義了類的比較規則,如果不是很明白的話,也沒有關系,我們已經將它抽象出來了,所以不理解實現原理也沒有關系。

public class Individual implements Comparable<Individual> {
    private static long counter = 0;
    private final long id = counter++;
    private String name; // name is optional
    public Individual(String name) { this.name = name; }
    public Individual() {}
    public String toString() {
        return getClass().getSimpleName() + (name == null ? "" : " " + name);
    }
    public long id() { return id; }
    public boolean equals(Object o) {
        return o instanceof Individual && id == ((Individual)o).id;
    }
    public int hashCode() {
        int result = 17;
        if (name != null) {
            result = 37 * result + name.hashCode();
        }
        result = 37 * result + (int) id;
        return result;
    }
    public int compareTo(Individual arg) {
        // Compare by class name first:
        String first = getClass().getSimpleName();
        String argFirst = arg.getClass().getSimpleName();
        int firstCompare = first.compareTo(argFirst);
        if (firstCompare != 0) {
            return firstCompare;
        }
        if (name != null && arg.name != null) {
            int secendCompare = name.compareTo(arg.name);
            if (secendCompare != 0) {
                return secendCompare;
            }
        }
        return (arg.id < id ? -1 : (arg.id == id ? 0 : 1));
    }
}

下面創建了一個抽象類PetCreator,以后我們通過調用arrayList()方法便可以直接獲取相關Pet類的集合。這里使用到了我們上面沒有提及的newInstance()方法,它會返回Class類所真正指代的類的實例,這是什么意思呢?比如說聲明new Dog().getClass().newInstance()和直接new Dog()是等價的。

public abstract class PetCreator {
    private Random rand = new Random(47);
    // The List of the different getTypes of Pet to create:
    public abstract List<Class<? extends Pet>> getTypes();
    public Pet randomPet() {
        // Create one random Pet
        int n = rand.nextInt(getTypes().size());
        try {
            return getTypes().get(n).newInstance();
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
    public Pet[] createArray(int size) {
        Pet[] result = new Pet[size];
        for (int i = 0; i < size; i++) {
           result[i] = randomPet();
        }
        return result;
    }
    public ArrayList<Pet> arrayList(int size) {
        ArrayList<Pet> result = new ArrayList<Pet>();
        Collections.addAll(result, createArray(size));
        return result;
    }
}

接下來我們來實現上面這一個抽象類,解釋一下下面的代碼,在下面的代碼中,我們聲明了兩個集合類,allTypestypes,其中allTypes中包含了我們呢上面所聲明的所有類,但是我們具體的類型實際上只有兩種即MuttEgypianMau,所以我們真正需要new出來的寵物只是types中所包含的類型,以后我們通過調用getTypes()便可以得到types中所包含的所喲類型。

public class LiteralPetCreator extends PetCreator {
    @SuppressWarnings("unchecked")
    public static final List<Class<? extends Pet>> allTypes = Collections.unmodifiableList(
        Arrays.asList(Pet.class, Dog.class, Cat.class, Mutt.class, EgyptianMau.class));
    private static final List<Class<? extends Pet>> types = allTypes.subList(
        allTypes.indexOf(Mutt.class), allTypes.size());
    public List<Class<? extends Pet>> getTypes() {
        return types;
    }
}

總體的邏輯已經完成了,***我們實現用來統計集合中相關Pet類個數的TypeCounter類。解釋一下isAssignalbeFrom()方法,它可以判斷一個反射類是某個反射類的子類或者間接子類。而getSuperclass()顧名思義就是得到某個反射類的父類了。

public class TypeCounter extends HashMap<Class<?>, Integer> {
    private Class<?> baseType;
    public TypeCounter(Class<?> baseType) {
        this.baseType = baseType;
    }
    public void count(Object obj) {
        Class<?> type = obj.getClass();
        if (!baseType.isAssignableFrom(type)) {
            throw new RuntimeException(
                obj + " incorrect type " + type + ", should be type or subtype of " + baseType);
        }
        countClass(type);
    }
    private void countClass(Class<?> type) {
        Integer quantity = get(type);
        put(type, quantity == null ? 1 : quantity + 1);
        Class<?> superClass = type.getSuperclass();
        if (superClass != null && baseType.isAssignableFrom(superClass)) {
            countClass(superClass);
        }
    }
    @Override
    public String toString() {
        StringBuilder result = new StringBuilder("{");
        for (Map.Entry<Class<?>, Integer> pair : entrySet()) {
            result.append(pair.getKey().getSimpleName());
            result.append("=");
            result.append(pair.getValue());
            result.append(", ");
        }
        result.delete(result.length() - 2, result.length());
        result.append("} ");
        return result.toString();
    }
}
責任編輯:張燕妮 來源: ziwenxie
相關推薦

2017-05-17 15:28:15

Java反射機制

2012-04-05 13:50:38

Java

2015-09-23 09:08:38

java反射

2010-04-01 09:22:38

代理模式Java反射機制

2011-03-09 09:11:52

java反射機制

2011-09-27 10:23:24

Java反射機制

2011-04-01 14:50:56

Java的反射機制

2009-06-17 13:57:54

java實例Reflection

2022-10-21 14:12:06

2012-02-08 09:44:52

Java反射

2010-09-17 13:02:11

JAVA反射機制

2010-09-17 12:39:51

JAVA反射機制

2010-08-11 09:40:44

LINQ

2011-05-26 15:23:34

JavaReflection

2012-02-08 09:53:25

Java反射

2023-11-01 13:48:00

反射java

2012-02-08 10:12:19

Java反射

2021-02-23 08:18:04

Java 反射機制

2009-06-19 13:59:41

Java反射機制

2023-06-27 08:37:35

Java反射動態代理機制
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久久久久免费观看 | 亚洲精品久久久蜜桃网站 | 国产精品久久久久久久久久了 | 91中文字幕在线 | 亚洲午夜精品在线观看 | 国产精品一区二区福利视频 | 黄色大片毛片 | 一区二区三区电影在线观看 | 美女亚洲一区 | 日日摸日日碰夜夜爽亚洲精品蜜乳 | 久久一区二区av | 超黄毛片 | 免费在线成人 | 一级毛片色一级 | 91麻豆精品国产91久久久资源速度 | 日本欧美在线观看视频 | 亚洲精品一区二区冲田杏梨 | 视频一区在线观看 | 日韩成人在线看 | 性一交一乱一透一a级 | 中文视频在线 | 色视频网站免费 | 欧美一区视频 | 国产一卡二卡三卡 | 91精品国产综合久久精品 | 精品一二区 | 日韩精品久久一区二区三区 | 日韩一及片 | 中文字幕 视频一区 | 九九九国产 | 91久久精品一区二区二区 | 欧美精品欧美精品系列 | 另类视频在线 | 国产成人精品999在线观看 | 欧美偷偷 | 国产欧美一区二区三区日本久久久 | 波多野结衣一区二区三区 | 久久鲁视频| 国外成人免费视频 | 色婷婷久久久久swag精品 | 亚洲精品乱码久久久久v最新版 |