什么是反射
1. JAVA反射机制是在运行状态中,对于任意一个类 (class文件),都能够知道这个类的所有属性和方法。
2. 对于任意一个对象,都能够调用它的任意一个方法和属性。
这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Class对象
Java的三大特性是继承、封装和多态。
相同的两个类之间的共性的部分可以抽取成一个父类,比如男人和女人可以抽取成父类人,因为男人和女人都有共性,吃饭,喝水这样的动作,和手脚这样的属性。
同样的不同的 .class文件中也有共性的,比如方法,字段,构造函数。
所以 .class文件向上抽取就成了 Class类
/**
* Person类
*
*/
public class Person {
public String name;
private Integer age;
Person(){
}
Person(String name,Integer age){
this.name=name;
this.age=age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public void show(){
System.out.println(this.toString());
}
private void privateMethod(){
System.out.println("我是私有的方法");
}
}
获取Class对象的三种方式
- 获取字节码对象的方式
- 根据类中的静态属性来获取
- 根据类的静态方法getClass来获取需要传入一个类的全限定名(该字符串参数的值是某个类的全限定名(必须添加完整包名))
public static void get() throws ClassNotFoundException {
/**
* 获取Class对象的三种方式
*/
/*
* 获取字节码对象的方式:
* 1,Object类中的getClass()方法的。
* 想要用这种方式,必须要明确具体的类,并创建对象。
* 麻烦 .
*
*/
Person p=new Person();
Class<? extends Person> aClass = p.getClass();
/*
* 方式二:
* 2,任何数据类型都具备一个静态的属性.class来获取其对应的Class对象。
* 相对简单,但是还是要明确用到类中的静态成员。
* 还是不够扩展。
*/
Class<Person> personClass = Person.class;
/*
* 方式三:
* 只要通过给定的类的 字符串名称就可以获取该类,更为扩展。
* 可是用Class类中的方法完成。
* 该方法就是forName.
* 这种方式只要有名称即可,更为方便,扩展性更强。
*/
Class<?> aClass1 = Class.forName("com.company.Person");
System.out.println(aClass1);
}
获取Class中的构造函数并创建对象
- 通过空参的构造器创建对象(没有空构造器会抛出异常)
- 通过获取构造器来创建对象 .getStructure()
/**
* 获取构造函数
*/
public static void getStructure() throws Exception {
//第一步要获取Class对象
Class<?> ac = Class.forName("com.company.Person");
//通过空参的构造器创造对象
// Person o = (Person) ac.newInstance();
//构造器也是一个对象,获取构造器,通过构造器获取对象
Constructor constructor = ac.getConstructor(String.class, Integer.class);
Person zyn = (Person) constructor.newInstance("zyn", 22);
System.out.println(zyn.getName());
}
获取Class中的字段
- 获取public修饰的 .getField(String name)c
- 获取本类的字段,但包含私有。 .getDeclaredField(String name); //传入的是字段名
- 对私有字段的访问取消权限检查。暴力访问。(只有对私有字段设置了取消权限检查才可以访问)
/**
* 获取字段
*/
public static void getField() throws Exception {
//第一步还是先获取Class对象
Class<?> aClass = Class.forName("com.company.Person");
//获取构造函数
Constructor<?> constructor = aClass.getConstructor(String.class, Integer.class);
//创建对象
Person p = (Person) constructor.newInstance("zhangsan",25);
//字段也是一个对象,获取字段
Field name = aClass.getField("name");
//字段的赋值,需要告诉给哪个对象,赋什么值
name.set(p,"zyn");
//字段的获取值,需要传入获取哪个字段的值
String strName = (String) name.get(p);
//获取本类中的字段,但包含私有
Field age = aClass.getDeclaredField("age");
//对私有字段的访问取消权限检查。暴力访问。,只有对私有字段设置了取消权限检查才可以访问
age.setAccessible(true);
System.out.println(age.get(p));
System.out.println(strName);
}
获取Class中的方法
- 获取所有方法
- 获取本类中的方法(包含私有)
- 方法的执行(私有的方法想要使用也是设置取消访问权限)
/**
* 获取方法
*/
public static void getMethod() throws Exception {
//第一步获取Class对象
Class<?> aClass = Class.forName("com.company.Person");
//创建对象
Constructor<?> constructor = aClass.getConstructor(String.class, Integer.class);
Person zyn = (Person) constructor.newInstance("zyn", 21);
//方法也是对象(获取所有共有的方法)
Method[] methods = aClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
//获取本类中所有的方法,包含私有
Method[] declaredMethods = aClass.getDeclaredMethods();
//获取本类中的方法
aClass.getMethod("show",null);//第一个参数串方法名,空参就传入null,非空参
//获取本类中私有的方法
Method privateMethod = aClass.getDeclaredMethod("privateMethod", null);
//私有的方法想要使用也是设置取消访问权限
privateMethod.setAccessible(true);
//执行方法也是需要知道执行哪个对象的改方法
privateMethod.invoke(zyn);//如果有参数就穿进去参数就可以了
Method show = aClass.getMethod("show", String.class);
show.invoke(zyn,"123456");
}
API使用说明
获取构造函数
//获取构造方法
/*
* 通过Class对象可以获取某个类中的:构造方法;
*
* 获取构造方法:
* 1).批量的方法:
* public Constructor[] getConstructors():所有"公有的"构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
* 2).获取单个的方法,并调用:
* public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:
* public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;
*
* 调用构造方法:
* Constructor-->newInstance(Object... initargs)
*/
获取成员函数
/*
* 获取成员方法并调用:
*
* 1.批量的:
* public Method[] getMethods():获取所有"公有方法";(包含了父类的方法也包含Object类)
* public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)
* 2.获取单个的:
* public Method getMethod(String name,Class<?>... parameterTypes):
* 参数:
* name : 方法名;
* Class ... : 形参的Class类型对象
* public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
*
* 调用方法:
* Method --> public Object invoke(Object obj,Object... args):
* 参数说明:
* obj : 要调用方法的对象;
* args:调用方式时所传递的实参;
):
*/
获取成员变量
/*
* 获取成员变量并调用:
*
* 1.批量的
* 1).Field[] getFields():获取所有的"公有字段"
* 2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
* 2.获取单个的:
* 1).public Field getField(String fieldName):获取某个"公有的"字段;
* 2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
*
* 设置字段的值:
* Field --> public void set(Object obj,Object value):
* 参数说明:
* 1.obj:要设置的字段所在的对象;
* 2.value:要为字段设置的值;
*
*/