1:什么是反射?
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
2:三种拿取字节码文件的方式
Person person = new Person();//原来创建对象的方式
//拿取字节码文件对象(第一种)
Class alz = person.getClass();
//拿取字节码文件对象(第二种)
Class alzs =Person.class;
//数据库里拿字节码文件,通过反射(第三种)
Class aClass = Class.forName("com.pp.Person");
Person 实例类代码如下图所示:
package com.pp;
public class Person {
//成员变量
public String name;
public int age;
private String address;
//构造方法
public Person() {
System.out.println("空参数构造方法");
}
public Person(String name) {
this.name = name;
System.out.println("带有String的构造方法");
}
//私有的构造方法
private Person(String name, int age){
this.name = name;
this.age = age;
System.out.println("带有String,int的构造方法");
}
public Person(String name, int age, String address){
this.name = name;
this.age = age;
this.address = address;
System.out.println("带有String, int, String的构造方法");
}
//成员方法
//没有返回值没有参数的方法
public void method1(){
System.out.println("没有返回值没有参数的方法");
}
//没有返回值,有参数的方法
public void method2(String name){
System.out.println("没有返回值,有参数的方法 name= "+ name);
}
//有返回值,没有参数
public int method3(){
System.out.println("有返回值,没有参数的方法");
return 123;
}
//有返回值,有参数的方法
public String method4(String name){
System.out.println("有返回值,有参数的方法");
return "哈哈" + name;
}
//私有方法
private void method5(){
System.out.println("私有方法");
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", address=" + address+ "]";
}
}
3:通过反射拿构造方法
a:拿取所有
Class c = Class.forName("com.pp.Person");//称C为字节码对象
//拿取多个构造方法
Constructor[] cons = c.getDeclaredConstructors();
//遍历每一个构造方法
for(Constructor con :cons){
System.out.println(con);
四个构造方法如下图所示:
public com.pp.Person(java.lang.String,int,java.lang.String)
private com.pp.Person(java.lang.String,int)
public com.pp.Person(java.lang.String)
public com.pp.Person()
b:只拿其中一个构造方法(比如拿取上面第一条)
Class c = Class.forName("com.pp.Person");
Constructor con = c.getDeclaredConstructor(String.class,int.class,String.class);
System.out.println(con);
结果如下:
public com.pp.Person(java.lang.String,int,java.lang.String)
4:创建对象(Public)
Class c = Class.forName("com.pp.Person");
Constructor con = c.getDeclaredConstructor(String.class,int.class,String.class);
Object instance = con.newInstance("张三", 12,"北京");
System.out.println(instance);
运行结果如下:
带有String, int, String的构造方法
Person [name=张三, age=12, address=北京]
5:私有构造方法创建对象
Class c = Class.forName("com.pp.Person");
Constructor con = c.getDeclaredConstructor(String.class,int.class);
//暴力反射
con.setAccessible(true);//取消语言检查
Object instance = con.newInstance("李四", 22);
System.out.println(instance);
运行结果:
带有String,int的构造方法
Person [name=李四, age=22, address=null]
6:拿取成员变量
A:拿取所有公开字段
Class c = Class.forName("com.pp.Person");
Field[] fields = c.getFields();
for(Field field:fields){
System.out.println(field);
运行结果如下图:
只可以拿到公开字段name和age,因为address是私有的,所以看不到。
public java.lang.String com.pp.Person.name
public int com.pp.Person.age
B:拿取一个字段
Class c = Class.forName("com.pp.Person");
Field age= c.getField("age");
System.out.println(age);
结果如下:
public int com.pp.Person.age
7:通过反射创建对象获取指定成员变量进行赋值操作
a:public字段
Class c = Class.forName("com.pp.Person");
Constructor declaredConstructor = c.getDeclaredConstructor(String.class);
Object instance = declaredConstructor.newInstance("王五");
Field age= c.getField("age");//public
//获取值
age.get(instance);
//赋值
age.set(instance,12);
System.out.println( age.get(instance));
运行结果:
12
b:private字段
强制暴力反射拿到private字段
Class c = Class.forName("com.pp.Person");
Constructor Constructor = c.getDeclaredConstructor(String.class);
Object instance = Constructor.newInstance("王五");
Field address= c.getDeclaredField("address");//public
address.setAccessible(true);//跳过访问权限
address.set(instance,"北京");
System.out.println( address.get(instance));
运行结果:
带有String的构造方法
北京
8:通过反射拿方法
a:public
Class c = Class.forName("com.pp.Person");
Constructor con= c.getDeclaredConstructor(String.class);//获取单个构造方法
Object instance = con.newInstance("lisi");
Method method = c.getMethod("method4", String.class);
Object invoke = method.invoke(instance,"王芝洋");
System.out.println(invoke);
运行结果如下图所示:
带有String的构造方法
有返回值,有参数的方法
哈哈王芝洋
b:private
Class c = Class.forName("com.pp.Person");
Constructor con= c.getDeclaredConstructor(String.class);//获取单个构造方法
Object instance = con.newInstance("lisi");
Method method= c.getDeclaredMethod("method5");
method.setAccessible(true);//跳过访问权限
Object invoke = method.invoke(instance,null);
System.out.println(invoke);
运行结果如下图:
带有String的构造方法
私有方法
null