反射机制概述
1.反射的作用
通过java语言中的反射机制可以操作字节码文件(可以读和修改字节码文件)
2.反射机制的相关类在java.lang.reflect.*;
反射机制相关的类(重要的类):
java.lang.Class; //代表字节码文件
java.lang.reflect.Method; //代表字节码中的方法字节码
java.lang.reflect.Constructor; //代表字节码中的构造方法字节码
java.lang.reflect.Filed //代表字节码中的属性字节码
3.要操作一个字节码需要先获取到这个类的字节码,有三种方式获取:
(1)Class.forName()
静态方法,方法的参数是一个字符串,字符串需要的是一个完整类名,完整类名必须带有包名.
(2)java中任何一个对象都有一个方法:getClass()
示例:
String s = “abc”;
Class x = s.getClass();//代表xString.class字节码文件,s代表String类型
(3)java语言中任何一种类型,包括基本数据类型,它都有.class属性
Class z = String.class
4.获取类路径下的绝对路径
src是类的根路径
资源绑定器
1.java.util包下提供了一个资源绑定器,便于获取属性配置文件中的内容,使用这种方式时,属性配置文件xxx.properties必须放到类路径下(即src下)
代码示例:
ResourceBundle bundle = ResourceBundle.getBundle("文件名");//文件名不需要后缀
String className = bundle.getString("className");
2.获取Field(Field译为字段,其实就是属性/成员)
使用反射机制获取
代码示例:
//获取整个类
Class studentClass = Class.forName("完整类名");
//获取类中所有的Field(public修饰的)
Field[] fields = studentClass.getFields();
//获取类中所有的Field(包括public、protected、private等都可以)
Field[] fields = studentClass.getDeclareFields();
//获取属性的类型
field.getType();
//获取属性的修饰符列表
field.getModifiers();//返回的修饰符是一个数字,每个数字是修饰符的代号
//将这个“代号”数字转换成“字符串”
String modifierString = Modifier.toString(i);
反编译Field(通过反射机制反编译一个类的属性Field)
代码示例:
/*
java.lang.reflect.Field;类中的属性
*/
import java.lang.reflect.*;
public class Test09
{
public static void main(String[] args) throws Exception{
//获取整个类
Class c = Class.forName("java.lang.String");
//获取所有的属性
Field[] fs = c.getDeclaredFields();
StringBuffer sb = new StringBuffer();
sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() + "{\n");
for(Field field:fs){
sb.append("\t");
sb.append(Modifier.toString(field.getModifiers()) + " ");
sb.append(field.getType().getSimpleName() + " ");
sb.append(field.getName() + ";\n");
}
sb.append("}");
System.out.println(sb);
}
}
通过反射机制访问对象属性(给属性赋值set,获取get)
代码示例:
Class studentClass = Class.forName("完整类名");
Objcet obj = studentClass.newInsrance();
//obj就是Student对象,底层调用无参数构造方法
//获取指定属性
Field noField = studentClass.getDeclareField("属性名");
//给obj对象(student对象)的属性赋值
noField.set(obj,111);//给obj对象的属性赋值111
//可以访问私有属性:打破封装
nameField.setAccessible(true);
//这样设置以后在外部可以访问private了
反射机制的缺点:打破封装,可能会给不法分子留机会
可变长度参数
1.int…cargs,这就是可变长度参数
2.可变长度参数要求的个数是0~N个,可变长度参数在参数列表中必须在最后一个位置上,而且可变长度参数只能有1个
3.可变长度参数可以当做一个数组来看待
反射机制调用方法
代码示例:
//获取类
Class studentClass = Class.forName("完整类名");
//创建对象
Object obj = userService.newInstance();
//获取Method
Method loginMethod = userServiceClass.getDeclareMethod("login",String.class,String.class);
//调用方法
Object reValue = loginMethod.invoke(obj,"admin","123");
反射机制让代码具有通用性,可变化的内容都是写到配置文件中,将来修改配置后,创建的对象不一样,调用方法不同,但java代码无需做任何改动。
反射机制调用构造方法
1.先获取到这个有参数的构造方法
Class c = Class.forName(“完整类名”);
Constructor con = c.getDeclaredConstructor(参数类型.class);
2.调用构造方法new对象
con.newInstance(实际参数);
//获取无参构造方法
Constructor con = c.getDeclaredConstructor();
Object newObj2 = con2.newInstance();