反射
类的加载
- 加载:类的加载器将class文件加载到内存中,加载到方法区(.class,常量、静态方法、常量池、共享区域)
- 连接:校验的功能,校验数据的完整性和正确性。
- 初始化:给静态方法和静态变赋值。
- 加载完成后:虚拟机会自动创建这个class文件的对应的对象(Class对象用来描述class文件)。
类的初始化时机
什么时间会创建Class对象?
在方法去中创建 类.class文件。
- 创建类的实例
- 类的静态变量(存在共享区域),或者为静态变量赋值
- 类的静态方法
- 使用反射方式来强制创建某个类或者接口对应的java.lang.Class对象
- 初始化某个类的子类(创建父类的.class文件 和自己的.class文件)
- 直接使用java.exe命令来运行某个主类
反射
什么是反射
在类的Class运行期间,可以动态(在运行期间)的访问类中的变量和方法,或者修改变量的方法,这种机制叫反射。
在知道类的.class文件的情况下,通过Class对象操作类中的变量和方法,这种机制叫反射
为什么要用反射
有些时候我们知道一个类的完整路径,需要获得这个类里的属性、方法等,可以通过反射来获得。
- 静态编译:在编译时确定类型,绑定对象
- 动态编译:运行时确定类型,绑定对象。动态编译发挥了java的灵活性,体现了多态,降低类之间的耦合。
反射的作用
- Class类
- Constructor 构造
- Method 方法
- Field 字段 变量
- instance 实例
- invoke 执行 方法
获得Class对象的方式
- 类名.class;实例:Class c =Student.class
- 类名 对象=new 类名();对象.getClass();
- Class.forName(“类的完整路径”)
获得构造方法 Constructor
特别注意的是获取构造方法
- Constructor getDeclaredConstructor(Class
获得class文件的方法 Method
- 获得Class对象
- 获得普通方法 Class对象的 XXXMethod()方法
- Method getDeclaredMethod(String name, Class
获得Class文件里的变量 Feild 字段
- Field getField(String name)
- Field[] getFields()
- Field getDeclaredField(String name)
-Field[] getDeclaredFields()
获取实例
T newInstance()
在使用获得私有的构造方法、私有的普通发送、私有的成员变量后 要设置可访问性
void setAccessible(boolean flag)
这个方法是 java.lang.reflect
类 AccessibleObject;
AccessibleObject 类是 Field、Method 和 Constructor 对象的基类。
- 在调用静态的方法(被static修饰的方法 )时,传入的参数是null; invoke(null)
反射类的方法调用
Student对象
public class Student {
private String name;
private int age;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getname() {
return name;
}
public void setname(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
private String eat(){
return name+"吃";
}
public static void sleep(String name){
System.out.println(name+"睡睡睡");
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
测试类
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Demo {
public static void main(String[] args)throws Exception {
//利用反射获取 Student.class类
Class<?> c=Class.forName("com.text.demo01.Student");
//创建对象
Object obj = c.newInstance();
Student stu=(Student)obj;
System.out.println(stu);
//获取类的构造方法
Constructor<?>[] cons = c.getConstructors();
for (Constructor<?> con : cons) {
System.out.println(con.getName()+" "+con.getParameterCount());
}
//获得单个无参构造方法
Constructor<?> con = c.getConstructor();
System.out.println(con);
//获取类的实例
Object stu1 = con.newInstance();
System.out.println(stu1);
//获得单个有参构造方法
Constructor<?> con1 = c.getConstructor(String.class,int.class);
System.out.println(con1);
Student stu2 = (Student)con1.newInstance("小明",23);
System.out.println(stu2);
System.out.println("=======================");
//获得普通方法
Method[] methods = c.getMethods();
for (Method method : methods) {
System.out.println(method);
}
Method setAge = c.getMethod("setAge", int.class);
setAge.invoke(stu2, 33);
System.out.println(stu2);
//获得被private 修饰的方法
Method eat = c.getDeclaredMethod("eat");
//设置权限
eat.setAccessible(true);
Object stringName = eat.invoke(stu2);
System.out.println(stringName);
//获得静态的方法
Method sleep = c.getMethod("sleep", String.class);
sleep.invoke(null, "穆宁");
System.out.println("========获取字段 即为对象的属性名称============");
//获取的是没有被private修饰的属性
Field[] fields = c.getFields();
for (Field field : fields) {
System.out.println(field);
}
Field[] Fields = c.getDeclaredFields();
for (Field field : Fields) {
System.out.println(field);
}
//给私有的属性设一个值,读取出来
Field fieldName = c.getDeclaredField("name");
fieldName.setAccessible(true);
fieldName.set(stu2, "小明大宝贝");
System.out.println(stu2.getname());
}
}
利用反射初始化用户
- data.properties文件内容
id=001
username=jack
password=123
User类
public class User {
private String id;
private String username;
private String password;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
}
}
ReflectDemo类 反射
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;
import java.util.Set;
public class RuflectDemo {
public static void main(String[] args) throws Exception {
//通过反射得到User对象
Class<?> c = Class.forName("com.text.demo.User");
User user = (User)c.newInstance();
//读取配置文件
Properties pro=getProperties();
//设置User属性
// user.setId(pro.getProperty("uid"));
// user.setUsername(pro.getProperty("username"));
// user.setPassword(pro.getProperty("password"));
setFieldValue(c,user,pro);
System.out.println(user);
}
private static void setFieldValue(Class<?> c, User user, Properties pro)throws Exception {
//得到配置文件的信息
Set<Object> keySet = pro.keySet();
for (Object key : keySet) {
String keyStr=(String) key;
String value = pro.getProperty(keyStr);
//根据key 拼接set方法
String firstStr=keyStr.substring(0, 1).toUpperCase();//得到key的第一个字符,转成大写
String otherStr=keyStr.substring(1);
String methodName="set"+firstStr+otherStr;
Field field = c.getDeclaredField(keyStr);
field.setAccessible(true);
Class<?> type = field.getType();
if(type.getName().equals("int")){
Method declaredMethod = c.getDeclaredMethod(methodName, int.class);
declaredMethod.invoke(user, Integer.parseInt(value));
}
if(type.getName().equals("java.lang.String")){
Method declaredMethod = c.getDeclaredMethod(methodName, String.class);
declaredMethod.invoke(user, value);
}
}
}
private static Properties getProperties()throws Exception{
//读取配置文件
Properties pro=new Properties();
pro.load(new FileInputStream("data.properties"));
return pro;
}
}