Class 類(lèi)的使用
在 Java 面向?qū)ο蟮氖澜缋?萬(wàn)事萬(wàn)物皆對(duì)象惩淳!
- 但是注意 Java 語(yǔ)言中惫撰,靜態(tài)成員然眼、普通數(shù)據(jù)類(lèi)型都不是對(duì)象(封裝類(lèi)彌補(bǔ)了普通數(shù)據(jù)類(lèi)型的不足)
- 我們所編寫(xiě)的每一個(gè)類(lèi)都是對(duì)象甘邀,類(lèi)是 java.lang.Class 類(lèi)的實(shí)例對(duì)象。 There is a class named Class 即這里有一個(gè)名稱(chēng)為 Class 的類(lèi)昔字,我們所寫(xiě)的每一個(gè)對(duì)象所屬的類(lèi)都是它的實(shí)例
Class 類(lèi)的實(shí)例對(duì)象如何獲缺邸?
有以下代碼中的三種方式:
package com.fy.reflect;
public class Test01 {
public static void main(String[] args) throws ClassNotFoundException {
// 類(lèi) A 的實(shí)例對(duì)象如何表示
A a = new A();
/* 類(lèi) A 也是 Class 類(lèi)一個(gè)實(shí)例對(duì)象,因?yàn)槿魏我粋€(gè)類(lèi)都是 Class 類(lèi)的實(shí)例對(duì)象螃宙,
* 官網(wǎng)稱(chēng)之為類(lèi)類(lèi)型蛮瞄,有如下三種表示方法
*/
// 第一種表示方法:任何一個(gè)類(lèi)都有一個(gè)隱藏的靜態(tài)成員方法去獲取 Class 實(shí)例
Class c1 = A.class;
// 第二種表示方法:利用某一個(gè)類(lèi)的對(duì)象的 getClass()方法
Class c2 = a.getClass();
// Class 動(dòng)態(tài)加載一個(gè)類(lèi)
Class c3 = Class.forName("com.fy.reflect.A");
// 一個(gè)類(lèi)只可能是 Class 類(lèi)的一個(gè)實(shí)例對(duì)象,所以下面的輸出都為 true
System.out.println(c1 == c2); //輸出 true
System.out.println(c1 == c3); //輸出 true
}
}
class A{
}
如何理解動(dòng)態(tài)加載類(lèi)?
Class.forName("類(lèi)的全稱(chēng)")
- 不僅表示了類(lèi)的類(lèi)類(lèi)型谆扎,還代表了動(dòng)態(tài)加載類(lèi)
- 一定區(qū)分編譯和運(yùn)行
如何理解編譯時(shí)刻加載類(lèi)是靜態(tài)加載類(lèi)挂捅,運(yùn)行時(shí)刻加載類(lèi)是動(dòng)態(tài)加載類(lèi)
舉個(gè)例子,我們 Java 開(kāi)發(fā)者一般選擇的 IDE 工具都是 Eclipse 或者 MyEclipse堂湖,比如以下代碼闲先,我創(chuàng)建了 Eclipse,沒(méi)創(chuàng)建 MyEclipse 類(lèi)无蜂,書(shū)寫(xiě)代碼時(shí)就會(huì)出現(xiàn)錯(cuò)誤(即編譯出錯(cuò))伺糠,導(dǎo)致程序無(wú)法運(yùn)行。也就是即使有了 Eclipse斥季,沒(méi)有 MyElicpse 也不能開(kāi)發(fā)训桶。但我們實(shí)際開(kāi)發(fā)中,只有一個(gè) IDE 工具給我們就能進(jìn)行開(kāi)發(fā)酣倾,不管有沒(méi)有另外一個(gè)舵揭。再聯(lián)想下,某個(gè)項(xiàng)目中有幾十個(gè)功能躁锡,若是某個(gè)功能有問(wèn)題其他功能就不能使用么午绳?顯然不合理。
public class JavaIDE {
public static void main(String[] args) {
//new 是靜態(tài)加載類(lèi)映之,在編譯時(shí)都會(huì)加載所用到的類(lèi)
Eclipse e = new Eclipse();
e.coding();
MyEclipse m = new MyEclipse();
m.coding();
}
}
class Eclipse {
public static void coding() {
System.out.println("This is Eclipse");
}
}
因此我們想到拦焚,用到某個(gè)功能就去加載某個(gè)類(lèi),即動(dòng)態(tài)加載類(lèi)杠输。
為了更好的演示效果赎败,希望大家在這里用文本編輯器編寫(xiě)代碼,在 cmd 中利用 javac 命令編譯抬伺、 java 命令運(yùn)行代碼
public class JavaIDE {
public static void main(String[] args) throws Exception {
// 動(dòng)態(tài)加載螟够,在運(yùn)行時(shí)加載類(lèi)
Class c = Class.forName(args[0]);
// 通過(guò)類(lèi)類(lèi)型,創(chuàng)建該對(duì)象
IdeAble ia = (IdeAble)c.newInstance();
ia.coding();
}
}
在這里峡钓,我們通過(guò)類(lèi)類(lèi)型創(chuàng)建對(duì)象時(shí),傳統(tǒng)理念是
Eclipse e = (Eclipse)c.newInstance();
但是當(dāng)我們需要的工具是 MyEclipse 時(shí)若河,這樣則不滿(mǎn)足功能要求能岩。因此選擇一個(gè)標(biāo)準(zhǔn)接口,所有功能類(lèi)都去實(shí)現(xiàn)它萧福,創(chuàng)建對(duì)象時(shí)只需創(chuàng)建接口對(duì)象就行拉鹃。
這樣需要什么功能,就去加載某個(gè)功能類(lèi)就行。
interface IdeAble{
public void coding();
}
class Eclipse implements IdeAble{
public void coding() {
System.out.println("This is Eclipse");
}
}
class MyEclipse implements IdeAble{
public void coding() {
System.out.println("This is MyEclipse");
}
}
再在cmd下膏燕,編譯 JavaIDE 和 Eclipse钥屈,在運(yùn)行。
當(dāng)我們需要使用 Eclipse 功能時(shí)再去編寫(xiě)相應(yīng)的代碼坝辫,只要滿(mǎn)足 IdeAble 接口標(biāo)準(zhǔn)就行篷就,再運(yùn)行即可
方法的反射
//獲取類(lèi)的所有方法
public static void getMethods(Object obj) {
Class c = obj.getClass();
// 獲取類(lèi)所有的方法,包括從父類(lèi)繼承而來(lái)的
Method[] methods = c.getMethods();
for (Method method : methods) {
// 獲取方法的返回類(lèi)類(lèi)型
Class returnType = method.getReturnType();
System.out.print(returnType.getName() + " ");
// 獲取方法的名稱(chēng)
System.out.print(method.getName() + "(");
// 獲取參數(shù)類(lèi)型近忙,得到的是參數(shù)列表的類(lèi)型的類(lèi)類(lèi)型
Class[] paramTypes = method.getParameterTypes();
int i = 0;
for (Class class1 : paramTypes) {
if (i == paramTypes.length - 1) {
System.out.print(class1.getName());
} else {
System.out.print(class1.getName() + ",");
}
i++;
}
System.out.println(")");
}
}
成員變量的反射
//獲取類(lèi)的所有成員屬性
public static void getField(Object obj) {
Class c = obj.getClass();
Field[] fields = c.getFields();
for (Field field : fields) {
System.out.println(field.getName());
}
}
構(gòu)造函數(shù)的反射
//獲取類(lèi)的所有構(gòu)造方法
public static void getConstructor(Object obj) {
Class c = obj.getClass();
Constructor[] constructors= c.getConstructors();
for (Constructor constructor : constructors) {
System.out.print(constructor.getName()+" (");
Class[] conParams= constructor.getParameterTypes();
int i=0;
for (Class class1 : conParams) {
if (i == conParams.length-1) {
System.out.print(class1.getName());
}else{
System.out.print(class1.getName()+",");
}
i++;
}
System.out.println(")");
}
}