原文出处:https://blog.csdn.net/sinat_38259539/article/details/71799078
java反射机制的定义:
在java反射机制是在运行状态中,对于任意一个类,都能知道他的属性和方法。对于任意一个对象,都能够调用他的任意一个方法,这种动态获取的信息以及动态调用对象的方法的功能,称作为java语言的反射机制。
动态:指的就是非编译时处理,运行时处理。
Java类的加载顺序:
每一个Java类在加载进内存时一定会产生一个class对象,在里面有关于类的信息
这时候就需要去了解一下Class类:
Class类的实例表示正在运行中的Java类或者接口。
Class没有公共构造方法。Class对象是在jvm加载类的时候自动创建的。、
Jvm中运行的每一个Java类都对应一个Class类的实例。
/**
* 获取Class对象的三种方式
* 1 Object ——> getClass();
* 2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
* 3 通过Class类的静态方法:forName(String className)(常用)
*
*/
public class Fanshe {
public static void main(String[] args) {
//第一种方式获取Class对象
Student stu1 = new Student();//这一new 产生一个Student对象,一个Class对象。
Class stuClass = stu1.getClass();//获取Class对象
System.out.println(stuClass.getName());
//第二种方式获取Class对象
Class stuClass2 = Student.class;
System.out.println(stuClass == stuClass2);//判断第一种方式获取的Class对象和第二种方式获取的是否是同一个
//第三种方式获取Class对象
try {
Class stuClass3 = Class.forName("fanshe.Student");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
System.out.println(stuClass3 == stuClass2);//判断三种方式是否获取的是同一个Class对象
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
一般都是用第三种方法,因为它对于原来的Java类的依赖最少,不需要导包
Java的反射一般用在运行时读取配置文件:
public class Student2 {
public void show2(){
System.out.println("is show2()");
}
}
className = cn.fanshe.Student
methodName = show
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Properties;
/*
* 我们利用反射和配置文件,可以使:应用程序更新时,对源码无需进行任何修改
* 我们只需要将新类发送给客户端,并修改配置文件即可
*/
public class Demo {
public static void main(String[] args) throws Exception {
//通过反射获取Class对象
Class stuClass = Class.forName(getValue("className"));//"cn.fanshe.Student"
//2获取show()方法
Method m = stuClass.getMethod(getValue("methodName"));//show
//3.调用show()方法
m.invoke(stuClass.getConstructor().newInstance());
}
//此方法接收一个key,在配置文件中获取相应的value
public static String getValue(String key) throws IOException{
Properties pro = new Properties();//获取配置文件的对象
FileReader in = new FileReader("pro.txt");//获取输入流
pro.load(in);//将流加载到配置文件对象中
in.close();
return pro.getProperty(key);//返回根据key获取的value值
}
}
自己写的一个
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Properties;
public class TestReflect {
public static void main(String[] args) {
try {
Class cls = Class.forName(getClassName("ClassName"));
Method m = cls.getMethod(getClassName("MethodName"));
Constructor[] cons = cls.getDeclaredConstructors();
for(Constructor con : cons){
System.out.println(con);
m.invoke(con.newInstance("anna","19"));
}
Constructor con = cls.getConstructor(String.class,String.class);
con.newInstance("anna","19");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static String getClassName(String key) {
// TODO Auto-generated method stub
try {
Properties pro = new Properties();
FileInputStream fis = new FileInputStream("D:\\workspace\\Test\\src\\day01\\config.properties");
pro.load(fis);
fis.close();
String classname = pro.getProperty(key);
/* String teachername = pro.getProperty("TeacherName");
String teacherage = pro.getProperty("TeacherAge");
String classmethod = pro.getProperty("ClassMethod");
HashMap<String, String> map = new HashMap<String, String>();
map.put(arg0, arg1);*/
return classname;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
class Teacher{
public String name;
public String age;
public Teacher(String name, String age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public void print(){
System.out.println("this is print method");
System.out.println("name = "+name+" age = "+age);
}
}
此时通过反射读取配置文件内容,运行方法。
Java反射还有一个比较普遍的使用的地方:Spring中BeanUtils.copy 方法:
之前做过一个项目,在VO与PO的属性赋值上大量使用了get/set方法;代码冗余
使用copy方法简单快捷,不过因为反射机制效率较低,所以最好少使用。
Java反射机制其实破坏了封装性
setAccess(True)这个方法,可以使本来私有的,无法访问的属性/方法变成可以访问的