Java反射机制是在运行状态中,对于任意一个类(class文件),都能够获得该类的所有属性和方法;并能够调用它的任意一个方法和属性。这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制;简单的说动态获取类中的信息,就是Java反射,可以理解为对类的解剖;
应用场景:如果想要对指定名称的字节码文件进行加载并获取其中的内容并调用。
Java的反射机制,在软件中有大量的应用,极大的提高了软件的扩展性。
好处: 1、提高了程序的扩展性;
2、反射应用简单、高效;
Java反射涉及到的类:
在Java中,字节码文件抽象出来的类为Class类,在该类中封装了操作字符码文件的方法。
获得字节码文件的三种方法:
方式一:
Object类中的getClass()方法;
特点: 想要通过这种方式,必须要明确具体的类,并创建对象;
public static void getClassObject_1(){
Person p = new Person();
Class clazz = p.getClass();
}
方法二:
任何数据类型,都具备一个静态的属性.class来获取对应的class对象;
特点:相对简单,还是要用到类中的静态成员;
扩展性较差,必须获得对象才能完成;
private Static void getClassObject_2(){
Class clazz = Person.class;
}
方法三:
可以使用class类中的forName方法完成;
特点:只要通过给定的字符串名称就可以获取该类,更为扩展;
这种方式只要有名称即可,获取字节码文件的方式更为灵活;扩展性更好;
private static void getClassObject_3(){
String className = "Person";
Class clazz = Class.forName(className);
}
对字节码文件的解剖:
一、获取类的构造函数:
reflect(反射包):Constructor、filed、method;
获取构造函数:getConstructor(paramterTypes);//当获取无参的构造函数,()中为空;
String name = "Person";
Class clazz = Class.forName(name);
Constructor cons = clazz.getConstructor(String.class,int.class);//获取有参的构造函数;
Object obj = clazz.newInstance("xiaoming",38);
二、获取字节码文件中的字段:
方法:class.getField()
public static void getField(){
Class<Person> clazz = (Class<Person>) Class.forName("cn.itcast.bean.Person");
// Field[] fields = clazz.getFields();//获取所有共有字段;
// for(Field field : fields){
// System.out.println(field);
// }
// Field field = clazz.getField("age");//注意:getField()获取的只能是公共的,并且不能访问字节码文件中的私有属性;
Field field = clazz.getDeclaredField("age");//只获取本类任意一个字段,无论共有私有;
// Field[] fields = clazz.getDeclaredFields();//获取所有字段;
// for(Field field : fields){
// System.out.println(field);
// }
// field.setAccessible(true);//对于私有字段,使用getDeclareField可以得到私有字段,却不能对其进行操作,此设置是对私有字段的访问取消权限检查。(暴力访问);
Object obj = clazz.newInstance();
field.set(obj,18);//为对象的字段赋值;
Object o = field.get(obj);
System.out.println(o);
}
三、获取字节码文件中的方法:
1、获取指定class中的公共函数。
public static void getMethod(){
Class clazz = Class.forName("Person");
Method[] methods = clazz.getMethods();//获取所有公有方法;
methods = clazz.getDeclaredMethods();//只获取所有方法;
for(Method method : methods){
System.out.printf(method);
}
}
2、获取无参方法;
public static void getMethod2(){
Class clazz = Class.forName("Person");
Method method = clazz.getMethod(“show”,null);//拿方法必须要指定方法名和参数;
//Object obj = clazz.newInstance();
Constructor cons = clazz.getConstructor(String.class,int.class);
Object obj = constructor.newInstance("xiaoming",38);
method.invoke(obj,null);
}
3、获取有参方法;
public static void getMethodDemo2(){
Class clazz = Class.forName("Person");
Method method = clazz.getMethod(“show”,String.class,int.class);//拿方法必须要指定方法名和参数;
Object obj = clazz.newInstance();
method.invoke(obj,"xiaoqiang",38);//调用对象中的有参方法,必须填写传递的参数;
}