反射这个概念之前听说过,但却是第一次真正接触,记录下学习过程。
一、概述
框架:可以理解为半成品软件。我们可以在框架的基础上进行软件开发,简化编码。
反射概念:将类的各个组成部分封装为其他的对象,这就是反射机制
这样的概念有些抽象,不妨先了解下java代码在计算机中经历的三个阶段:
①Source源代码阶段:
//Person.java
public class Person{
private String name;
private int age;
public Person(){}
public void eat(){}
}
==>>javac编译
//Person.class
private String name; private int age; |
public Person(){} |
public void eat(){} |
==>>类加载器ClassLoader(将Person.class字节码文件加载到内存)
②Class类对象阶段:
//Class类对象
成员变量 Field[] fields |
构造方法 Constructor[] cons |
成员方法 Method[] methods |
==>>创建对象
③Runtime运行时阶段:
Person对象 new Person(); |
通常我们只关注第一和第三阶段,那么第二阶段将类的成员变量封装为Field对象,将构造方法封装为Constructor对象,将成员方法封装为Method对象就是我们说的反射机制。
那么为什么要用反射呢?
反射的好处:
1、可以在程序运行过程中,操作这些对象;
例如定义一个字符串,在运行中将String类加载到内存中,通过“.”操作其提供的方法都可直接使用。
2、可以解耦,提高程序的可扩展性。
二、获取Class类对象
方式:1、Class.forName("全类名"):将字节码文件加载进内存,返回Class对象。
多用于配置文件,将类名定义在配置文件中。读取文件,加载类。
2、类名.class:通过类名的属性class获取。
多用于参数的传递。
3、对象.getClass():getClass()方法在Object类中定义着。
多用于对象的获取字节码的方式。
结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
public class Reflectdemo{
public static void main(String[] args) throws Exception {
//1、Class.forName("全类名")
Class cls1=Class.forName("cn.itcast.demo.Person");
System.out.println(cls1);//class cn.itcast.demo.Person
//2、类名.class
Class cls2= Person.class;
System.out.println(cls2);//class cn.itcast.demo.Person
//3、对象.getClass()
Person p=new Person();
Class cls3=p.getClass();
System.out.println(cls3);//class cn.itcast.demo.Person
//比较三个对象
System.out.println(cls1==cls2);//true
System.out.println(cls1==cls3);//true
}
}
Class对象功能:
获取功能:1、获取成员变量们;
Field[] getFields() :获取所有public修饰的成员变量
Field getField(String name) :获取指定名称的public修饰的成员变量
Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符
Field getDeclaredField(String name)
2、获取构造方法们;
Constructor<?>[] getConstructors()
Constructor<T> getConstructor(类<?>... parameterTypes)
Constructor<?>[] getDeclaredConstructors():返回结果没有参数类型的过滤
Constructor<T> getDeclaredConstructor(类<?>... parameterTypes):返回指定参数类型的所有构造器
3、获取成员方法们;
Method[] getMethods()
Method getMethod(String name,类<?>... parameterTypes)
Method[] getDeclaredMethods()
Method getDeclaredMethod(String name,类<?>... parameterTypes)
4、获取类名
String getName()
Field:成员变量
操作:1、设置值 void set(Object obj,Object value)
2、获取值 get(Object obj)
3、忽略访问权限修饰符的安全检查 setAccessible(true)//暴力反射
public class Reflectdemo{
public static void main(String[] args) throws Exception {
//0.获取Person的Class对象
Class personClass=Person.class;
//1.Field[] getFields() :获取所有public修饰的成员变量
Field[] fields=personClass.getFields();
for(Field field:fields){
System.out.println(field);
}
System.out.println("------------------");
//2.Field getField(String name)
Field a=personClass.getField("a");
//获取变量a的值
Person p=new Person();
Object value=a.get(p);
System.out.println(value);
//设置a的值
a.set(p,22);
System.out.println(p);
System.out.println("------------------");
//3.Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符
Field[] declaredFields=personClass.getDeclaredFields();
for(Field declaredField:declaredFields){
System.out.println(declaredField);
}
//4.Field getDeclaredField(String name)
Field d=personClass.getDeclaredField("d");
//忽略访问权限修饰符的安全检查
d.setAccessible(true);//暴力反射
Object value2=d.get(p);
System.out.println(value2);
}
}
Constructor:构造方法
创建对象:T newInstance(Object... initargs)
如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法
public class Reflectdemo{
public static void main(String[] args) throws Exception {
Constructor constructor=personClass.getConstructor(String.class,int.class);
System.out.println(constructor);
//创建对象
Object person=constructor.newInstance("张三",13);
System.out.println(person);
System.out.println("----------------");
Constructor constructor1=personClass.getConstructor();
System.out.println(constructor1);
//创建对象
Object person1=constructor1.newInstance();
System.out.println(person1);
//等同于
Object o=personClass.newInstance();
System.out.println(o);
}
}
Method:方法对象
执行方法: Object invoke(Object obj,Object... args)
获取方法名称: String getName:获取方法名
public class Reflectdemo{
public static void main(String[] args) throws Exception {
//获取指定名称的方法
Method eat_method=personClass.getMethod("eat");
Person p=new Person();
//执行方法
eat_method.invoke(p);
System.out.println("------------------------");
Method eat_method2=personClass.getMethod("eat",String.class);
//执行方法
eat_method2.invoke(p,"饭");
System.out.println("------------------------");
//获取所有public修饰的方法
Method[] methods=personClass.getMethods();
for(Method method:methods){
System.out.println(method);
//String name=method.getName();
//System.out.println(name);
}
}
}
获取类名
//获取类名
String className=personClass.getName();
System.out.println(className);//cn.itcast.demo.Person