將類的各個組成部分封裝為其他對象,就是反射機制

image.png
反射的好處:
- 在程序的運行過程中,操作這些對象
- 可以解耦,提高程序的可擴展性
獲取class對象(對應(yīng)三個階段)
- class.forName("全類名"):將字節(jié)碼文件加載進內(nèi)存
- 類名.class:通過類名的屬性class獲取
- 對象.getClass():getClass()方法在Object類中定義著
class Person{
private int age;
private String name;
public String a;
protected String b;
String c;
public Person(){
}
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public void eat(){
System.out.println("eating");
}
public void eat(String food){
System.out.println("eating:" + food);
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
", a='" + a + '\'' +
", b='" + b + '\'' +
", c='" + c + '\'' +
'}';
}
}
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Class cls1 = Class.forName("Person");
System.out.println(cls1);
Class cls2 = Person.class;
System.out.println(cls2);
Person p = new Person();
Class cls3 = p.getClass();
System.out.println(cls3);
// 比較三個對象的內(nèi)存地址
System.out.println(cls1 == cls2); // true
System.out.println(cls1 == cls3); // true
}
}
結(jié)論:
同一個字節(jié)碼文件(*.class)在一次程序運行過程中,只會被加載一次,不論通過哪一種方式獲取的Class對象都是同一個
class對象功能:
1.獲取功能
獲取成員變量們
Field[] getFields():獲取所有public修飾的成員變量
Field getField(String name):獲取指定名稱的public修飾的成員變量
Field[] getDeclaredFields():獲取所有成員變量,不考慮修飾符(對于private,需設(shè)置setAccessible=true)
Field getDeclaredField(String name):獲取指定名稱的成員變量獲取構(gòu)造方法們
獲取成員方法們
獲取類名
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Class cls = Person.class;
Field[] fields = cls.getFields();
for(Field f: fields){
System.out.println(f);
} // 只打印 public java.lang.String Person.a
Field a = cls.getField("a");
Person p = new Person();
Object value = a.get(p);
System.out.println(value); // null
// 設(shè)置a的值
a.set(p, "張三");
System.out.println(p); // Person{age=0, name='null', a='張三', b='null', c='null'}
}
}
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Class cls = Person.class;
Field f2 = cls.getDeclaredField("name");
f2.setAccessible(true); // 沒有這句話會報錯
Person p = new Person();
Object value = f2.get(p);
System.out.println(value);
}
}
構(gòu)造方法
獲取到構(gòu)造器的最主要的目的就是創(chuàng)建對象
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Class cls = Person.class;
// 帶參的構(gòu)造器使用
Constructor constructor = cls.getConstructor(int.class, String.class);
System.out.println(constructor); // public Person(int,java.lang.String)
// 創(chuàng)建對象
Object person = constructor.newInstance(18, "張三");
System.out.println(person); // Person{age=18, name='張三', a='null', b='null', c='null'}
// 無參構(gòu)造器的使用
Constructor constructor1 = cls.getConstructor();
Object person1 = constructor1.newInstance();
System.out.println(person1);
// 等價于上面的無參構(gòu)造
Object o = cls.newInstance();
System.out.println(o);
}
}
獲取成員方法
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Class cls = Person.class;
Method method = cls.getMethod("eat");
Person p = new Person();
method.invoke(p);
Method method1 = cls.getMethod("eat", String.class);
method1.invoke(p, "fish");
Method[] method2 = cls.getMethods();
for(Method m: method2){
// m.setAccessible(true);
String name = m.getName();
System.out.println(m);
}
}
}