框架:半成品软件,可以在框架上开发软件,简化代码
反射机制
将类的各个组成部分封装为其他对象,这就是反射机制
- 第一部分
Source源代码阶段
:源代码对象中有变量,构造方法,成员方法等内容。(代码->字节码文件) - 第二部分
Class对象阶段
,把不同的部分封装成对象。 (加载入内存)封装成Field[]、Constructor[]、Method[]
三个数组对象 - 第三部分
运行阶段
:才是声明对象。
反射好处:
- 在程序的执行中操作第二部分的这些对象
使用IDEA会自动弹出该对象的方法,是因为IDEA通过反射机制将对象的字节码文件加载入内存,获取了所有的方法数组
Method[]
,并进行打印提示。
- 可以解耦,提高程序的可扩展性
获取第二阶段字节码对象Class
的方式
三个阶段,三种不同获取方式
- 第一阶段:
Class.forName("全类名“)
:将字节码对象加载进内存返回Class对象。多用于配置文件,将类名定义在配置文件中。 - 第二阶段:通过类名的属性获取
类名.Class
。多用于传参 - 第三阶段:
对象.getClass()
public static void main(String[] args) throws ClassNotFoundException {
//1.静态方法forName获取
Class<?> c1 = Class.forName("object.Person");
System.out.println(c1);
//2.类名获取
Class<Person> c2 = Person.class;
System.out.println(c2);
//3.对象获取
Person p = new Person();
Class c3 = p.getClass();
System.out.println(p.getClass());
System.out.println(c1==c2);
System.out.println(c1==c3);
}
//输出
class object.Person
class object.Person
class object.Person
true
true
两个true表示三个对象相同,同一个字节码文件(*.class)再一次执行过程中,只会被加载一次,不同方式获取的Class
对象相同。
Field:成员变量
getField
只能获取用public修饰的变量
getDeclaredMethod
获取所有的变量
//获取Person的Class对象
Class personClass = Person.class;
Field f = personClass.getField("name");
//获取name的值
Person p = new Person();//person中有变量 name
Object value = f.get(name);
System.out.println(value);//可以打印出变量name的值
f.set(p,"张三");//改变对象变量
//假设age是私有变量
Field f = personClass.getDeclaredField(age);
//忽略访问权限修饰符
f.setAccessible(true);//暴力反射
f.get(p);//获取年龄
f.set(p,20);//只是age变量的field,所以直接设置age变量
获取到变量后不是特指哪个具体对象的变量,而是声明对象后,在通过变量获取对象的具体变量值。
反射可以获取所有类型变量,并且改变变量通过field
的setAccessible(true)
方法忽略访问权限修饰符安全检查。
获取成员变量之后的操作:
- 设置值
Field中的set()方法
- 获取值
Field中的get()方法
构造方法constructor
- 用来构造该字节码文件中的对象
Class pClass= Person.class;
//无参构造器
Constructor con1=pClass.getConstructor();
System.out.println(con1);
//输出 public object.Person()
//有参构造器
Constructor con2=pClass.getConstructor(String.class,int.class,int.class);
System.out.println(con2);
//输出 public object.Person(java.lang.String,int,int)
- 使用constructor的方法创建对象
Object person=con2.newInstance("a",10,100);
System.out.println(person);
//输出object.Person{name='a', age=10, weight=100}
Method成员方法
获取单个方法
Class<Person> personClass = Person.class;
Method getName = personClass.getMethod("getName");
//创建空对象返回 null,传入参数返回参数
Person p =new Person();
//调用方法需要传入 对象和参数
Object name= getName.invoke(p);
System.out.println(name);
//输出null
获取所有方法
Method[] methods = personClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
输出: 获取所有方法包括 自己写的方法 和继承的父类Object
类的所有方法
public java.lang.String object.Person.toString()
public java.lang.String object.Person.getName()
public void object.Person.setName(java.lang.String)
public int object.Person.getAge()
public void object.Person.setAge(int)
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()```