Class對象
虛擬機在class文件的載入階段,把類信息保存在方法區數據結構中,並在Java堆中生成一個Class對象,作為類信息的入口。
聲明兩個類,Cat.java 和 Dog.java
class Cat {
private String name;
private int age;
static {
System.out.println("Cat is load");
}
}
class Dog {
private String name;
private int age;
static {
System.out.println("Dog is load");
}
}
獲取Class對象一般有三種方式:
通過實例變數方式
public class test {
public static void main(String args) {
Dog dog = new Dog;
Class clazz = dog.getClass;
}
}
public class test {
public static void main(String args) {
Dog dog = new Dog;
Class clazz = dog.getClass;
}
}
通過類名方式
public class test {
public static void main(String args) {
Class clazz = Dog.class;
}
}
public class test {
public static void main(String args) {
Class clazz = Dog.class;
}
}
通過這種方式時,只會載入Dog類,並不會觸發其類構造器的初始化。
通過Class.forName(String classname)方式
public class ClassTest {
public static void main(String args) {
try {
Class clazz = Class.forName("zzzzzz.Dog");
} catch (ClassNotFoundException e) {}
}
}
public class ClassTest {
public static void main(String args) {
try {
Class clazz = Class.forName("zzzzzz.Dog");
} catch (ClassNotFoundException e) {}
}
}
在JDK源碼實現中,forName方法會調用Native方法forName0,它在JVM中調用findClassFromClassLoader載入Dog類,其原理和ClassLoader一樣,將會觸發Dog類的類構造器初始化,forName0方法聲明如下:
private static native Class<?> forName0(String name, boolean initialize, ClassLoader loader, Class> caller)
1
private static native Class<?> forName0(String name, boolean initialize, ClassLoader loader, Class> caller)
其中initialize參數,用來告訴虛擬機是否需要對載入的類進行初始化,如果initialize為false,則不會進行初始化Dog類。
Class clazz = Class.forName("zzzzzz.Dog", false, Dog.class.getClassLoader);
1
Class clazz = Class.forName("zzzzzz.Dog", false, Dog.class.getClassLoader);
反射機制
反射機制reflect可以在運行期間獲取類的欄位、方法、父類和介面等信息。
1、獲取類欄位
Class class_dog = Dog.class;
Field fields = class_dog.getDeclaredFields;
for (Field field : fields) {
System.out.println(field.getName);
}
1 Class class_dog = Dog.class;
2 Field fields = class_dog.getDeclaredFields;
3 for (Field field : fields) {
4 System.out.println(field.getName);
5 }
2、獲取類方法
Class class_dog = Dog.class;
Method methods = class_dog.getDeclaredMethods;
for (Method method : methods) {
System.out.println(method);
}
Class class_dog = Dog.class;
Method methods = class_dog.getDeclaredMethods;
for (Method method : methods) {
System.out.println(method);
}
通過method.invoke(obj, ...args)可以調用obj實例的method方法。
3、獲取對應的實例構造器,並生成類實例
public class ClassTest {
public static void main(String args) throws NoSuchMethodException {
Class class_dog = Dog.class;
Constructor constructor = class_dog.getConstructor(String.class, int.class);
constructor.newInstance("Tom", 10);
}
}
class Dog {
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
}
public class ClassTest {
public static void main(String args) throws NoSuchMethodException {
Class class_dog = Dog.class;
Constructor constructor = class_dog.getConstructor(String.class, int.class);
constructor.newInstance("Tom", 10);
}
}
class Dog {
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
}
如果沒有顯示的聲明默認構造器,class_dog.getConstructor會拋出NoSuchMethodException異常。
4、通過newInstance方法生成類實例
Class class_dog = Dog.class;
Dog dog = class_dog.newInstance;
Class class_dog = Dog.class;
Dog dog = class_dog.newInstance;
5、設置私有變數
Class class_dog = Dog.class;
Field name = class_dog.getDeclaredField("name");
name.setAccessible(true);
Dog dog = (Dog) class_dog.newInstance;
name.set(dog, "Tom");
Class class_dog = Dog.class;
Field name = class_dog.getDeclaredField("name");
name.setAccessible(true);
Dog dog = (Dog) class_dog.newInstance;
name.set(dog, "Tom");
6、獲取私有變數
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
return (Unsafe)f.get(null);
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
return (Unsafe)f.get(null);
這種方式在使用Unsafe類進行黑魔法時經常用到。
反射的性能問題
Stackoverflow上,很多人覺得使用反射reflect會影響系統性能,主要有以下幾點看法:
1、代碼的驗證防禦邏輯過於複雜,本來這塊驗證時在鏈接階段實現的,使用反射reflect時需要在運行時進行;
2、產生過多的臨時對象,影響GC的消耗;
3、由於缺少上下文,導致不能進行更多的優化,如JIT;
不過現代JVM已經運行的足夠快,我們應該把主要重心放在複雜的代碼邏輯上,而不是一開始就進行各種性能優化。
小編團隊開發群,你想要的都在這裡哦!學習,交流,源碼,開發工具 616 959 444
應有盡有!小編先在這裡代表團隊謝過各位,歡迎學習Java各個階段的小夥伴們加入我們!