Java核心反射機制:
基本反射:
反射是一種動態類的處理機制,通過Class類
來實現反射機制;
Class類的基本資訊:
Module java.base
Package java.lang
Class Class<T>
java.lang.Object
java.lang.Class<T>
以下三種方式獲得類的反射,三者都非常重要,牢牢掌握。
- 利用Object類中提供getClass()方法獲取例項化物件
class Member {}
public class JavaReflectDemo {
public static void main(String[] args) throws Exception {
// 【操作特點】需要獲取一個類的例項化物件之後才可以獲取Class類例項
Member member = new Member() ; // 例項化Member類物件
Class<?> clazz = member.getClass() ; // 獲取Class類例項化物件
System.out.println(clazz);
}
}
- 使用“類.class”形式
class Member {}
public class JavaReflectDemo {
public static void main(String[] args) throws Exception {
// 【操作特點】直接通過一個類的完整名稱可以獲取Class類例項,需要編寫import或編寫完整類名稱
Class<?> clazz = Member.class ; // 獲取Class類例項化物件
System.out.println(clazz);
}
}
- 使用Class類內部提供的forName()方法根據類的完整名稱獲取例項化物件
class Member {}
public class JavaReflectDemo {
public static void main(String[] args) throws Exception {
// 【操作特點】通過名稱字串(包.類)可以獲取Class類例項,可以不使用import匯入
// 獲取Class類例項化物件
Class<?> clazz = Class.forName("cn.xbhog.demo.Member");
System.out.println(clazz);
}
}
反射獲取例項化物件:
package com.xbhog.反射機制;
class Member{
public Member() { // 構造方法
System.out.println("【構造方法】例項化Member類物件.");
}
@Override
public String toString() {
return "【toString()覆寫】部落格地址:http://www.cnblogs.com/xbhog";
}
}
public class 反射獲取物件 {
public static void main(String[] args) throws Exception {
// 獲取Class類例項化物件
Class<?> clazz = Class.forName("com.xbhog.反射機制.Member");
// 反射機制可以獲取任意類例項化物件(等價於關鍵字“new”),所以返回的型別為Object
Object obj = clazz.getDeclaredConstructor().newInstance() ;// 例項化物件
System.out.println(obj);
}
}
反射的機制可以更加方便開發者實現解耦和設計;
反射與類操作:
在反射機制下,可以自動獲取並呼叫任意一個類中的組成結構(成員屬性、方法),使得程式碼的編寫更加靈活。
反射獲取類結構:
package com.xbhog.反射機制;
interface IMessage{
public void send();
}
interface IChannelService{
public Boolean connect();
}
abstract class AbstractBase{}
public class Mail extends AbstractBase implements IMessage,IChannelService{
@Override
public void send() {
if(this.connect()){
System.out.println("傳送資訊成功");
}
}
@Override
public Boolean connect() {
return true;
}
}
package com.xbhog.反射機制;
public class MailTest {
public static void main(String[] args) {
Class<Mail> aClass = Mail.class;
System.out.println(aClass.getPackage()); //獲取類的包名
Class<? super Mail> superclass = aClass.getSuperclass(); //獲取父類物件資訊
System.out.println(superclass.getName()); //獲取父類名字
System.out.println(superclass.getSuperclass().getName()); //獲取父類的父類的名字
/*獲取介面資訊*/
Class<?>[] interfaces = aClass.getInterfaces();
for (Class<?> anInterface : interfaces) {
System.out.println(anInterface.getName());
}
}
}
反射呼叫構造方法:
反射還可以呼叫構造方法,構造方法是類中的重要組成部分,也是例項化物件時必須呼叫的方法。
例項:
import java.lang.reflect.Constructor;
class Mail {
private String msg ;
public Mail() {}// 無參構造
public Mail(String msg) {// 單參構造
System.out.println("【構造方法】呼叫Mail類單參構造方法,例項化物件");
this.msg = msg ;
}
@Override
public String toString() { // 物件資訊
return "【toString()覆寫】訊息內容:" + this.msg;
}
}
public class JavaReflectDemo {
public static void main(String[] args) throws Exception {
Class<?> cls = Mail.class ; // 獲取指定類的Class物件
Constructor<?>[] constructors = cls.getDeclaredConstructors() ; // 獲取全部構造
for (Constructor<?> cons : constructors) {
System.out.println(cons);
}
// 獲取單參構造並且引數型別為String的構造方法物件例項
Constructor<?> cons = cls.getDeclaredConstructor(String.class) ;
Object obj = cons.newInstance("www.cnblog.cn/xbhog") ;// 呼叫單參構造例項化物件
System.out.println(obj);
}
}
反射呼叫方法:
反射機制中除了獲取類中的方法定義外,最為重要的功能就是可以利用Method類中的invoke()方法並結合例項化物件(Object型別即可)實現放射的呼叫。
反射呼叫類中的setter、getter方法(重點)
package com.xbhog.反射機制.方法;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
class Member{
private String name;
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
public class getter_Setter {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<?> cls = Member.class;
String value = "xbhog";
//例項化Member物件
Object obj = cls.getDeclaredConstructor().newInstance();
//反射呼叫方法需要明確的知道方法的名稱以及方法中的引數型別
String setMethodName ="setName";
Method setmethod = cls.getDeclaredMethod(setMethodName, String.class); //獲取指定方法
setmethod.invoke(obj,value); //物件.setName(value)
String getMethodName = "getName";
Method getMethod = cls.getDeclaredMethod(getMethodName); //get沒有引數
System.out.println(getMethod.invoke(obj));//物件.getName();
}
}
通過放射實現的方法呼叫的最大的特點是可以直接利用Object型別的例項化物件進行呼叫的,但是在獲取物件時需要明確的知道方法名稱以及方法的引數型別。
Field類的作用:
在實際開發中,Field中的getType()方法使用的較多,可以通過其來確定屬性的型別
示例:
import java.lang.reflect.Field;
class Member{
private String name;
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
public class FIeldDemo {
public static void main(String[] args) throws Exception {
//獲取Member類
Class<?> cls = Member.class;
//例項化
Object obj = cls.getDeclaredConstructor().newInstance();
//成員屬性name的型別
Field name = cls.getDeclaredField("name");
//獲取詳細資訊
System.out.println(name.getType().getName());
//獲取簡略資訊
System.out.println(name.getType().getSimpleName());
}
}
結果:
java.lang.String
String