JavaSE學習筆記 - 反射技術
阿新 • • 發佈:2020-08-27
概述
- 反射是一種強大的工具,可以用來編寫能夠動態操縱 Java 程式碼的程式,通過反射機制我們可以操作位元組碼檔案。反射機制將類的各個部分封裝成了物件,在程式執行的過程中我們可以操作這些物件(在操作一個類物件的時候我們可以操作其方法成員變數等)。這樣可以使得程式解耦,提高了程式的可擴充套件性。
Java 程式碼的三個階段
- 原始碼階段:編寫類檔案,然後新增成員變數,成員方法等,程式碼編譯後生成位元組碼檔案,此時程式碼還未被載入進記憶體。
- Class 類物件階段:Class 類物件使用類載入器將位元組碼檔案載入進記憶體,此時記憶體中就會產生一個唯一的 Class 類物件來標識這個類中的各項資訊,Class 類物件中又包含了描述成員變數的 Field 物件、描述構造方法的 Constructor 物件和描述成員方法的 Method 物件。
- 執行時階段:new 一個新的類物件。
Class
- 在程式執行的時候,系統始終為所有的物件維護一個執行時的型別標識,這個資訊會跟蹤每一個物件所屬的類,我們使用 Java 中的 Class 類就可以訪問這些被記錄的資訊。
獲取 Class 物件的三種方式
- Class.forName("全類名"):將位元組碼檔案載入進記憶體,配置檔案常用
public class Main { public static void main(String[] args) throws ClassNotFoundException { Class cls = Class.forName("java.lang.String"); System.out.println(cls);//class java.lang.String } }
- 類名.class:常用於引數的傳遞
public class Main { public static void main(String[] args) throws ClassNotFoundException { Class cls = Class.forName("java.lang.String"); Class cls1 = String.class; System.out.println(cls.hashCode());//460141958 System.out.println(cls1);//class java.lang.String } }
- 物件.getClass():常用於獲取物件位元組碼
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
Class cls = Class.forName("java.lang.String");
Class cls1 = String.class;
String str = "";
Class cls2 = str.getClass();
//位元組碼檔案在記憶體中只被載入一次
//不管使用什麼方式獲取到的Class物件都是同一個
System.out.println(cls.hashCode());//460141958
System.out.println(cls1.hashCode());//460141958
System.out.println(cls2);//class java.lang.String
}
}
Class 類常用 API
- 獲取 public 修飾的成員變數
//獲取 public 修飾的成員變數
public class Main {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class cls = Class.forName("java.lang.String");
Field[] fields = cls.getFields();
for (Field field : fields) {
System.out.println(field.getName());
}
Field field = cls.getField("CASE_INSENSITIVE_ORDER");
System.out.println(field.getName());
}
}
//獲取所有的成員變數
public class Main {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class cls = Class.forName("java.lang.String");
Field[] fields = cls.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName());
}
Field field = cls.getDeclaredField("hash");
System.out.println(field.getName());
}
}
- 獲取建構函式
public class Main {
public static void main(String[] args) throws Exception {
Class cls = Class.forName("java.lang.String");
//得到所有公共的建構函式物件
Constructor[] constructors = cls.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
//得到特定的公共建構函式物件
Constructor constructor = cls.getConstructor(String.class);
System.out.println(constructor);
}
}
public class Main {
public static void main(String[] args) throws Exception {
Class cls = Class.forName("java.lang.String");
//得到所有的建構函式物件
Constructor[] constructors = cls.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
//得到特定的建構函式物件
Constructor constructor = cls.getDeclaredConstructor(String.class);
System.out.println(constructor);
}
}
- 獲取成員方法
public class Main {
public static void main(String[] args) throws Exception {
Class cls = Class.forName("java.lang.String");
//獲取所有公共的成員方法
Method[] methods = cls.getMethods();
for (Method method : methods) {
System.out.println(method);
}
//獲取特定的公共的成員方法
System.out.println("-------");
Method method = cls.getMethod("toLowerCase", Locale.class);
System.out.println(method);
}
}
public class Main {
public static void main(String[] args) throws Exception {
Class cls = Class.forName("java.lang.String");
//獲取所有的成員方法
Method[] methods = cls.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
//獲取特定的成員方法
System.out.println("-------");
Method method = cls.getDeclaredMethod("lastIndexOfSupplementary", int.class, int.class);
System.out.println(method);
}
}
- 有關 Class 類的 API
public class Main {
public static void main(String[] args) throws Exception {
Class cls = Class.forName("java.lang.String");
System.out.println(cls.getName());//java.lang.String
System.out.println(cls.getSimpleName());//String
//獲取父類
Class superclass = cls.getSuperclass();
System.out.println(superclass);//class java.lang.Object
System.out.println(superclass.isInterface());//false
//獲取包物件
Package aPackage = cls.getPackage();
System.out.println(aPackage.getName());//java.lang
}
}
Constructor
public class Main {
public static void main(String[] args) throws Exception {
Class cls = Class.forName("java.lang.String");
//得到所有的建構函式物件
Constructor[] constructors = cls.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
//方法名
System.out.println(constructor.getName());
//修飾符
System.out.println(Modifier.toString(constructor.getModifiers()));
//引數型別
Class[] parameterTypes = constructor.getParameterTypes();
for (Class parameterType : parameterTypes) {
System.out.print(parameterType.getName() + " ");
}
System.out.println();
System.out.println("-------------------------------------");
}
}
}
//建立物件
public class Main {
public static void main(String[] args) throws Exception {
Class cls = String.class;
String str = (String) cls.newInstance();
}
}
Field
public class Main {
public static void main(String[] args) throws Exception {
String str = "1111";
Class cls = Class.forName("java.lang.String");
Field[] fields = cls.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
System.out.println(Modifier.toString(field.getModifiers()));
System.out.println(field.getType().getSimpleName());
System.out.println(field.getName());
//System.out.println(field.get(str));
System.out.println("-----------------------------------------------");
}
}
}
//為物件的成員變數設定值
public class Main {
public static void main(String[] args) throws Exception {
Class cls = String.class;
String str = (String) cls.newInstance();
Field field = cls.getDeclaredField("value");
//不是公共的成員變數是需要暴力反射,預設只能修改非公共成員變數
field.setAccessible(true);
System.out.println(field);
System.out.println(field.get(str));//[C@4554617c
System.out.println(str);//
field.set(str, new char[]{'1', '1'});
System.out.println(field.get(str));//[C@74a14482
System.out.println(str);//11
}
}
Method
public class Main {
public static void main(String[] args) throws Exception {
Class cls = Class.forName("java.lang.String");
//獲取所有的成員方法
Method[] methods = cls.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
System.out.println(Modifier.toString(method.getModifiers()));
System.out.println(method.getReturnType().getSimpleName());
Class<?>[] parameterTypes = method.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println(parameterType.getSimpleName());
}
//是否有可變引數
System.out.println(method.isVarArgs());
System.out.println(method.getName());
System.out.println("-------------------------");
}
}
}
//執行類方法
public class Main {
public static void main(String[] args) throws Exception {
Class cls = String.class;
String str = (String) cls.newInstance();
Field field = cls.getDeclaredField("value");
field.setAccessible(true);
field.set(str, new char[]{'1', '1'});
Method method = cls.getDeclaredMethod("length");
System.out.println(method.invoke(str));
}
}
配置檔案操作類
配置檔案
className = java.lang.String
methodName = length
fieldName = value
Properties + IO + 反射
public class Main {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
//方式一:利用當前類獲取流,配置檔案需要在src目錄下
ClassLoader classLoader = Main.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream("pro.properties");
properties.load(is); //要記得關閉流
//方式二:首先獲取檔案路徑,然後根據路徑建立輸入流
//配置檔案需要在根路徑下
// String path = Thread.currentThread().getContextClassLoader().getResource("pro.properties").getPath();
// //System.out.println(path);
// FileReader reader = new FileReader(path);
// properties.load(reader);
Class cls = Class.forName(properties.getProperty("className"));
Object o = cls.newInstance();
Field field = cls.getDeclaredField(properties.getProperty("fieldName"));
field.setAccessible(true);
field.set(o, new char[]{'a', 'b'});
System.out.println(field.get(o));
Method method = cls.getDeclaredMethod(properties.getProperty("methodName"));
System.out.println(method.invoke(o));
}
}
ResourceBundle + 反射
public class Main {
public static void main(String[] args) throws Exception {
//資源繫結器,配置檔案需要放在根路徑下
ResourceBundle bundle = ResourceBundle.getBundle("pro");
Class cls = Class.forName(bundle.getString("className"));
Object o = cls.newInstance();
Field field = cls.getDeclaredField(bundle.getString("fieldName"));
field.setAccessible(true);
field.set(o, new char[]{'a', 'b'});
System.out.println(field.get(o));
Method method = cls.getDeclaredMethod(bundle.getString("methodName"));
System.out.println(method.invoke(o));
}
}
反射方式反編譯類框架
配置檔案
className = java.util.ResourceBundle
測試程式碼
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
//資源繫結器,配置檔案需要放在根路徑下
ResourceBundle bundle = ResourceBundle.getBundle("pro");
Class<?> cls = Class.forName(bundle.getString("className"));
Package aPackage = cls.getPackage();
//包
if (aPackage != null) System.out.println("package " + aPackage.getName());
System.out.println();
//修飾符
System.out.print(Modifier.toString(cls.getModifiers()) + " ");
//類名
System.out.print(cls.getSimpleName() + " ");
//父類
Class<?> superclass = cls.getSuperclass();
if (!superclass.equals(Object.class)) {
System.out.print( "extends " + superclass.getSimpleName() + " ");
}
//介面
Class<?>[] interfaces = cls.getInterfaces();
StringBuilder _interfaces = new StringBuilder();
if(interfaces.length == 0) {
_interfaces.append("");
} else {
_interfaces.append(" implements ");
}
for (int i = 0; i < interfaces.length; i++) {
_interfaces.append(interfaces[i].getSimpleName());
if (i != interfaces.length - 1) {
_interfaces.append(", ");
} else {
_interfaces.append(" ");
}
}
System.out.println(_interfaces + "{");
System.out.println();
//獲取成員變數
getDeclaredFields(cls);
//獲取構造方法
getDeclaredConstructors(cls);
//獲取成員方法
getMethods(cls);
System.out.println("}");
}
private static void getDeclaredFields(Class<?> cls) {
Field[] fields = cls.getDeclaredFields();
for (Field field : fields) {
System.out.print("\t");
//修飾符
System.out.print(Modifier.toString(field.getModifiers()) + " ");
//資料型別
System.out.print(field.getType().getSimpleName() + " ");
//變數名
System.out.println(field.getName() + ";");
//System.out.println(field);
//System.out.println("----------------");
}
System.out.println();
}
private static void getDeclaredConstructors(Class<?> cls) {
Constructor<?>[] constructors = cls.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
//修飾符
System.out.print("\t");
if (constructor.getModifiers() != 0)
System.out.print(Modifier.toString(constructor.getModifiers()) + " ");
//方法名
System.out.print(cls.getSimpleName() + "(");
//引數
Class<?>[] typeParameters = constructor.getParameterTypes();
StringBuilder _typeParameters = new StringBuilder();
for (int i = 0; i < typeParameters.length; i++) {
if (i != 0) {
_typeParameters.append(", ");
}
_typeParameters.append(typeParameters[i].getSimpleName());
}
System.out.println(_typeParameters + "){};");
//System.out.println(constructor);
//System.out.println("---------------------------");
}
System.out.println();
}
private static void getMethods(Class<?> cls) {
Method[] methods = cls.getMethods();
for (Method method : methods) {
System.out.print("\t");
//修飾符
System.out.print(Modifier.toString(method.getModifiers()) + " ");
//返回值
System.out.print(method.getReturnType().getSimpleName() + " ");
//方法名
System.out.print(method.getName() + "(");
//引數
Class<?>[] parameterTypes = method.getParameterTypes();
StringBuilder _parameterTypes = new StringBuilder();
for (int i = 0; i < parameterTypes.length; i++) {
if (i != 0) {
_parameterTypes.append(", ");
}
_parameterTypes.append(parameterTypes[i].getSimpleName());
}
System.out.println(_parameterTypes + "){};");
//System.out.println(method);
//System.out.println("------------------------");
}
System.out.println();
}
}