Java的反射机制是在运行状态中,对于任意一个类,都能知道这个类的属性和方法,对于任意一个对象,都能使用该类的成员与方法,这种动态获取的以及动态调用方法的功能称为反射机制。
通过反射技术, 我们可以拿到该字节码文件中所有的东西, 例如成员变量, 成员方法, 构造方法, 而且还包括私有的。
1 字节码文件获取的三种方式
1.1 对象.getClass() 此方法用于在Object对象已经存在的情况下,可使用
1.2 类名.class() 类名.class是一个静态的属性,可直接访问
1.3 Class.forName(全类名) 通过Class类中的静态方法, 指定字符串, 该字符串是类的全类名(包名+类名) ,此方法需要处理异常
例子如下:
package cn.itcast_03;
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
//对象名.getClass()
Student s = new Student();
Class cls = s.getClass();
System.out.println(cls); //class cn.itcast_03.Student
//类名.class
Class cls1 = Student.class;
System.out.println(cls1);//class cn.itcast_03.Student
//Class.forName(全类名)方法
//此方法需要处理异常 ClassNotFoundException
Class cls2 = Class.forName("cn.itcast_03.Student");
System.out.println(cls2);//class cn.itcast_03.Student
}
}
2 字节码对象是描述.class文件的
面向对象的构造:
成员变量
构造方法
成员方法
2.1 反射构造方法创造对象
步骤:
1 取得class对象
2 取得class构造
3 创建实例
package cn.itcast_03;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ConstructorDemo {
public static void main(String[] args) throws ClassNotFoundException,
NoSuchMethodException, SecurityException, InstantiationException,
IllegalAccessException, IllegalArgumentException,
InvocationTargetException {
//通过类.newInstance()
Class cls = Class.forName("cn.itcast_03.Student");
Object obj = cls.newInstance();
System.out.println(obj); // cn.itcast_03.Student@47abfd68
//取得构造方法后再创建实例
Class cls1 = Class.forName("cn.itcast_03.Student");
Constructor con = cls1.getConstructor();
Object obj1 = con.newInstance();
System.out.println(obj1);//cn.itcast_03.Student@2d7fc1e7
}
}
newInstance() 与getConstructor()的区别:
newInstance()只能创建无参构造
getConstructor()可取得所有构造,根据传入参数取得对应构造参数实例
- 获得类成员
3.1 获取公有成员
Field f = 类.getField()
获取私有成员需要使用: 类.getDeclaredFields();
若需要设置私有成员的值,则需要设置属性.setAccessible(true)
package cn.itcast_03;
import java.lang.reflect.Field;
public class FieldDemo {
public static void main(String[] args) throws ClassNotFoundException,
InstantiationException, IllegalAccessException,
NoSuchFieldException, SecurityException {
// 获取字节码对象
Class cls = Class.forName("cn.itcast_03.Student");
// 创建对象
Object obj = cls.newInstance();
//获取所有成员
Field[] f = cls.getDeclaredFields();// 访问该类的所有公有成员方法
for (Field field : f) {
System.out.println(field);
}
Field name = cls.getDeclaredField("name");
System.out.println(name);
Field age = cls.getDeclaredField("age");
System.out.println(age);
//设置可访问
name.setAccessible(true);
age.setAccessible(true);
name.set(obj, "lilizhou");
age.set(obj, 6);
System.out.println(obj);
}
}
- 获取成员方法
公有单个成员方法: cls.getMethod(name, parameterTypes)
公有所有方法:cls.getMethods()
私有单个成员方法:getDeclaredMethod(name, parameterTypes)
package cn.itcast_03;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MethodDemo {
public static void main(String[] args) throws InstantiationException,
IllegalAccessException, ClassNotFoundException,
NoSuchMethodException, SecurityException, IllegalArgumentException,
InvocationTargetException {
Class cls = Class.forName("cn.itcast_03.Student");
Object obj = cls.newInstance();
Method[] mes = cls.getMethods();
for (Method m : mes) {
System.out.println(m);
}
//cls.getDeclaredMethod(name, parameterTypes)
//私有方法
Method me = cls.getDeclaredMethod("show");
me.setAccessible(true);//需要设置访问标识才可以访问
me.invoke(obj);
Method me1 = cls.getMethod("toString");
me1.invoke(obj);
}
}