前言:反射机制在开发中很少使用,但是很多框架(Spring等)的实现原理是基于反射的,因此知道反射原理也很重要。
1.什么是反射机制?反射机制有什么作用?
反射机制:可以操作字节码文件。
作用:可以让程序更加灵活。
2.反射机制相关的类在哪个包下?
java.lang.reflect .*
3.反射机制相关的主要类:
java.lang.Class;
java.lang.reflect.Method;
java.lang.reflect.Constructor;
java.lang.reflect.Field;
4.在java中获取Class的三种方式
Class c = Class.forName(完整类名);
Class c = 对象.getClass();
Class c = int.class;
5.获取Class后可以调用无参数构造方法实例化对象:
Class c = Class.forName("java.util.Date");
Object obj = c.newInstance();//调用的是该类型的无参构造方法,如果没有这个无参构造方法会出现异常
6:如果只想要一个类的静态代码块执行:
Class.forName()
7:获取路径下的文件
(1):获取文件的绝对路径,该文件要求放在类路径下:也就是src下面.通用路径,不受环境影响。
String path = Thread.currentThread().getContextCalssLoader().getResource("类路径").getPath();
(2):直接以流的形式返回
InputStream reader = Thread.currentThread().getContextClassLoader().getResourceAsStream("classinfo.properties");
(3):资源绑定器:文件必须是类路径下的XXX.properties
ResourceBundle bundle = ResourceBundle.getBundle("classinfo");//文件名不加properties String className1 = bundle.getString("className");
8:获得类中的所有属性Field
Class studentClass = Class.forName("Student"); //获取类中所有的field Field[] fields = studentClass.getFields(); Field f = fields[0]; String name = f.getName(); System.out.printf(name); Field[] fieldss = studentClass.getDeclaredFields(); for(Field fs :fieldss){ System.out.printf(fs.getName());}
9:通过反射机制,反编译一个类的属性Field
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class ReflectTest02 {
public static void main(String[] args) throws Exception {
Class studentClass = Class.forName("Student");
StringBuilder s = new StringBuilder();
Field[] fs = studentClass.getDeclaredFields();
s.append(Modifier.toString(studentClass.getModifiers())+" "+"class"+" "+studentClass.getSimpleName()+"{\n");//动态获取修饰符和类名
for(Field fd :fs){
s.append("\t");
s.append(Modifier.toString(fd.getModifiers()));
s.append(" ");
s.append(fd.getType().getSimpleName());
s.append(" ");
s.append(fd.getName());
s.append(";\n");
}
s.append("}");
System.out.println(s);
}
}
10:通过反射机制访问对象属性:具有通用性,修改配置文件即可,尽管复杂,但是灵活性强。(重要!!!)
import java.lang.reflect.Field;
public class ReflectTest03 {
/*
怎么通过反射机制访问java对象的属性?
(1)给属性赋值 set
(2)获取属性的值 get
*/
public static void main(String[] args) throws Exception{
//首先获取整个class
Class studentClass = Class.forName("Student");
//实例化对象
Object obj = studentClass.newInstance();
//要给属性赋值,首先要获得这个属性,依靠名字来区分
Field no = studentClass.getDeclaredField("no");
//obj对象(Student对象)的no属性赋值
no.set(obj,2222);
System.out.println(no.get(obj));
}
}
11:通过反射机制访问私有变量,打破了封装,是反射的一个缺点。
Field nameField = studentClass.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(obj,"lucy");
System.out.println(nameField.get(obj));
12:反射Method
补充:可变长度参数:int... args【类型后跟3个点】,在参数列表中必须是最后一个,而且只能出现一个。可以被看做一个数组
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class ReflectTest04 {
public static void main(String[] args) throws Exception {
//获得类
Class studentClass = Class.forName("Student");
//获得所有的method,包括私有的
Method[] methods = studentClass.getDeclaredMethods();
//遍历methods
for(Method method :methods){
//获得修饰符列表
System.out.println(Modifier.toString(method.getModifiers()));
//获得方法得返回值类型
System.out.println(method.getReturnType().getSimpleName());
//获得方法得修饰符列表,一个方法得参数可能会有多个
Class[] parameters = method.getParameterTypes();
for(Class parameter:parameters){
System.out.println(parameter.getSimpleName());
}
}
}
}
13:通过反射机制调用方法执行(重要!!!)
import java.lang.reflect.Method;
public class ReflectTest05 {
public static void main(String[] args) throws Exception{
//获取类名
Class studentClass = Class.forName("Student");
//创建对象
Object obj = studentClass.newInstance();
//获取方法,方法名和参数列表
Method testMethod = studentClass.getDeclaredMethod("add",int.class,int.class);
// 调用方法,对象、方法名、实际参数列表、返回值
Object value = testMethod.invoke(obj,2,3);
System.out.println(value);
}
}