什么是反射
- java反射就是通过Class类(反射入口),在程序运行状态下获得类的名称、package信息、所有属性、方法、注解、类型、类加载器并可对其进行操作的一种机制。
什么是Class类
- java.lang.Class类是提供java反射机制的核心类之一,它是java程序在初始化(initialization)后存放在堆区的一个储存了对应类所有属性、方法、构造器等信息的类(class类就像它所对应的java类在镜子中的倒影一样将java类所有的信息以对象的形式储存下来,由此来提供一个接口供程序员访问方法区中的Class数据)。
反射存在的意义
- 我们利用传统的new关键字进行类的实例化时,需要写明需要实例化的类,此时如果需要实例化的类名有所变化,我们就不得不去修改源码。如果应用反射机制,就可以靠读入配置文件进行对象的实例化,而需要实例化的类发生变化时,只需要修改配置文件即可。降低了代码的耦合,充分体现了java的动态特性。
例子:
import java.io.FileInputStream;
import java.lang.reflect.Method;
import java.util.Properties;
public class Test {
public static void main(String[] args) throws Exception {
//读取配置文件
Properties properties=new Properties();
properties.load(new FileInputStream("src\\classInfo.property"));
String classPath = properties.get("classPath").toString();
String classMethod = properties.get("classMethod").toString();
//获取类对应的Class文件
Class clazz=Class.forName(classPath);
//利用反射加载对象实例
Object obj= clazz.newInstance();
}
}
配置文件classInfo.property:
classPath=com.per.lander.Animal
classMethod=cry
获取Class类的常用方式
1)Class.forname("全类名")
条件:在全类名可知的情况下,且该类在类路径下
2)类名.class
条件:在已知类名的情况下的情况下,且该类在类路径下
3)实例名.getClass() 条件:有一个已经实例化的类
Class类的常用方法
当我们拿到一个类的class对象是就可以通过class获取其对应类的各种信息
获取类名:
1) getName:获取全类名
2) getSimpleName:获取简单类名
获取属性:
1) getField(“String fieldName”):以Field类型返回public修饰指定的属性,包含本类以及父类的
2) getDeclaredField(“String fieldName”):以Field类型返回本类中指定的属性
3) getFields():以Field[]返回所有public修饰的属性,包含本类以及父类的
4) getDeclaredFields():以Field[]返回本类中所有方法
获取方法:
1) getMethod(“String methodName”,方法参数列表的class对象):以Method类型返回指定public修饰的方法,包含本类以及父类的
2) getDeclaredMethod(“String methodName”,方法参数列表的class对象):以Method类型返回本类中指定的方法(包括非public)
3) getMethods():以Method[]返回所有public修饰的方法,包含本类以及父类的
4) getDeclaredMethods():以Method[]返回本类中所有方法
获取构造器:
1) getConstructor(“参数列表的class对象”,构造器参数列表的class对象):以Constructor返回本类中public修饰的构造器
2) getDeclaredConstructor(“参数列表的class对象”,构造器参数列表的class对象):以Constructor返回本类中指定的构造器
3) getConstructors():以Constructor[]返回本类中所有public修饰的构造器
4) getDeclaredConstructors():以Constructor[]返回本类中所有的构造器
获取其他:
1) getPackage():以Package形式返回包信息
2)getSuperClass():以Class形式返回父类信息
3)getInterfaces():以Class[]形式返回接口信息
4)getAnnotations():以Annotation[]形式返回注解信息
通过反射创建实例对象
使用类的public无参构造器创建对象:
步骤:
1)获取类的class对象
2)调用class的newInstance()方法即可
示例代码:
Class clazz2=Class.forName("com.per.lander.Animal"); //获取类的Class对象
Object o=clazz2.newInstance(); //利用newInstance()方法获取类的Class对象
使用类的public有参构造函数创建对象:
步骤:
1)获取类的Class对象
2)通过Class对象的getConstructor获取class对象对应的类的构造器对象
3)通过获得的构造器对象的newInstance(''参数列表的class对象'')方法创建有参构造器的类对象
示例代码:
Class clazz3=Class.forName("com.per.lander.Animal");//获取类的Class对象
//利用类的class对象获取类的类的有参构造器
Constructor<?> constructor=clazz3.getConstructor(String.class);//获取类的有参构造器(参数列表中传入和有参构造器对应的参数的class对象)
Object o1=constructor.newInstance("mammal");//利用有参构造器创建类的实例对象参数列表中传入实参
使用类的private有参构造函数创建对象:
步骤:
1)获取类的Class对象
2)通过Class对象的getDeclearConstructor获取class对象对应的类的私有构造器对象
3)调用构造器对象的setAccessible(true)使反射可以访问私有构造器
4)通过获得的构造器对象的newInstance(''参数列表的class对象'')方法创建有参构造器的类对象
示例代码:
Class clazz4=Class.forName("com.per.lander.Animal");//获取类的class对象
Constructor<?> constructorPte=clazz4.getDeclaredConstructor(int.class);//获取类的有参构造器(参数列表中传入和有参构造器对应的参数的class对象)
constructorPte.setAccessible(true);//爆破使反射可以访问private构造器
Object o2=constructorPte.newInstance(32);//利用有参构造器创建类的实例对象参数列表中传入实
其他反射相关的类及其方法
java.lang.reflect.Field类
1)getModifiers():以int形式返回属性修饰符
2)getType():以Class形式返回类型
3)getName():返回属性名
4)set(Object 属性所属的类实例对象名,value)
5)get(Object 属性所属的类实例对象名)
通过反射访问对象属性:
Class clazz5 =Class.forName("com.per.lander.Animal");//创建类的Class对象
Object o3=clazz5.newInstance();//通过Class对象创建类的实例对象
//当属性为public时
Field field=clazz5.getDeclaredField("name");//通过Class对象获得类的指定Public的Field对象
field.set(o,“Dog”);//通过field对象的set方法设置属性值
field.get(o);//通过Field对象的get方法获得属性值
//当属性为private时
Field field=clazz5.getField("weight");//通过Class对象获得类的指定Private的Field对象
field.setAccessible(true);//将私有Field设置为反射可操作
field.set(o,53);//通过field对象的set方法设置属性值
field.get(o);//通过Field对象的get方法获得属性值
//当属性为static时可以不将类实例化直接操作属性
Field field=clazz5.getDeclaredField("name");//通过Class对象获得类的指定Static的Field对象
field.set(null,"StaticN")//设置static属性的值
field.get(null)//获取static属性的值
java.lang.reflect.Method类
1)getModifiers():以int形式返回修饰符
2)getReturnType():以Class形式获取返回值
3)getName():返回方法名
4)getParameterTypes():以Class[]返回参数类型数组
4)invoke(Object 属性所属的类实例对象名,参数列表):以Class[]返回参数类型数组
通过反射访问对象方法:
Class clazz6 =Class.forName("com.per.lander.Animal");//创建类的Class对象
Object o4=clazz6.newInstance();//通过Class对象创建类的实例对象
//当方法为public且无形参
Method method1=clazz6.getMethod("cry");//利用class对象获取method对象
method1.invoke(o4);//执行方法
//当方法为private且有参数时
Method method1=clazz6.getDeclaredMethod("run",String.class);//利用class对象获取method对象
method1.setAccessible(true);//将私有method设置为反射可操作
method1.invoke(o4,"fly");//执行方法
//当方法为static方法时可不用将方法所属的类实例化(此处run方法为static方法)
Object reVal=method1.invoke(null,"fly");//执行static方法
Object reVal=method1.invoke(null,"fly");//返回值为一个运行对象为实际返回类型的Object对象
java.lang.reflect.Constructor类
1)getModifiers:以int形式返回修饰符
2)getName:返回构造器名(全类名)
3)getParameterTypes:以Class[]返回参数类型数组