将类的各个组成部分封装为其他对象,就是反射机制
![](https://img.haomeiwen.com/i6853111/852acb21a30fefe5.png)
反射的好处:
- 在程序的运行过程中,操作这些对象
- 可以解耦,提高程序的可扩展性
获取class对象(对应三个阶段)
- class.forName("全类名"):将字节码文件加载进内存
- 类名.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);
// 比较三个对象的内存地址
System.out.println(cls1 == cls2); // true
System.out.println(cls1 == cls3); // true
}
}
结论:
同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个
class对象功能:
1.获取功能
-
获取成员变量们
Field[] getFields():获取所有public修饰的成员变量
Field getField(String name):获取指定名称的public修饰的成员变量
Field[] getDeclaredFields():获取所有成员变量,不考虑修饰符(对于private,需设置setAccessible=true)
Field getDeclaredField(String name):获取指定名称的成员变量 -
获取构造方法们
-
获取成员方法们
-
获取类名
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
// 设置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);
}
}
构造方法
获取到构造器的最主要的目的就是创建对象
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Class cls = Person.class;
// 带参的构造器使用
Constructor constructor = cls.getConstructor(int.class, String.class);
System.out.println(constructor); // public Person(int,java.lang.String)
// 创建对象
Object person = constructor.newInstance(18, "张三");
System.out.println(person); // Person{age=18, name='张三', a='null', b='null', c='null'}
// 无参构造器的使用
Constructor constructor1 = cls.getConstructor();
Object person1 = constructor1.newInstance();
System.out.println(person1);
// 等价于上面的无参构造
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);
}
}
}
网友评论