基本概念
①反射机制可以操作字节码文件(.class)
②反射机制在Java.lang.reflect.*包下
③反射机制相关的重要的类有哪些
java.lang.class 整个字节码
- reflect.Methed 方法
- reflect.Constructor 构造方法
- reflect.Field 属性
获取Class的三种方法
- 方法一:class.forName(“路径”)
①静态方法 ②参数是一个字符串 ③字符串必须是一个完整的类名
Class c = Class.forName("java.lang.String");
- 方法二:getClass();
String s ="abc";
Class c1 = s.getClass();
- 方法三:类型调用.class属性
Class c2 = String.class;
比较c,c1,c2
System.out.println(c1==c);//true
System.out.println(c2==c1);//true
通过反射机制实例对象
一:使用newInstance()方法
Class userclass = Class.forName("反射机制.User");//此路径是以src为根目录
Object obj = userclass.newInstance();//以反射机制创建对象会自动调用无参构造函数
二:验证反射机制的灵活性,读取配置文件来创建反射对象
①创建反射机制是会调用类的无参构造,且会先执行静态代码块里的内容
②
//通过Io读取properties文件
FileReader reader = new FileReader("src/反射机制/Proper.properties");//此处的路径为,项目名为根目录
//创建Map对象
Properties pro = new Properties();
//加载
pro.load(reader);
//通过key获取value
reader.close();
String path = pro.getProperty("ClassName");
System.out.println(path);
//通过反射机制实例化对象
Class c = Class.forName(path);
Object obj =c.newInstance();
System.out.println(obj);
配置文件properties
ClassName=反射机制.User
获取类路径(src)下的绝对路径
解释
Thread.currentThread() 获取当前线程
getContextClassLoader() 线程对象的方法,获取当前线程的类加载器
getResource("") 类加载器对象方法,默认从类的根路径加载文件
①,以字符串的形式返回
String path = Thread.currentThread().getContextClassLoader()
.getResource("反射机制/Proper.properties").getPath();
System.out.println(path);
②直接以流的形式返回
//直接以流的形式返回
InputStream in = Thread.currentThread().getContextClassLoader().
getResourceAsStream("Fans/Proper.properties");
③资源绑定器便于获取属性配置文件内容
java.util.ResourceBundle包下
简单,快捷,但是只能加载根路径下的资源
ResourceBundle bundle = ResourceBundle.getBundle("Fans/Proper");//注意此处不需要加properties后缀
String className = bundle.getString("ClassName");
获取Field (类属性)
①用法
Class userClass = Class.forName("反射机制.User");
//获取Field
Field[] fields = userClass.getFields();//只能获取public属性
System.out.println(fields[1].getName()); //获取属性名字
System.out.println(fields.length);
Field[] fields2 = userClass.getDeclaredFields();
System.out.println(fields2.length);
for(Field field:fields2){
int i = field.getModifiers();//获取修饰列表,返回值int修饰符代号
System.out.println(Modifier.toString(i));//将代号转换为String
System.out.println(field.getType());//获取属性类型
System.out.println(field.getName());
②反编译
StringBuffer s =new StringBuffer();//创建拼接字符串
Class userClass = Class.forName("java.lang.String");
s.append(Modifier.toString(userClass.getModifiers())+" class " +userClass.getSimpleName() + "{\n");
Field[] fields = userClass.getDeclaredFields();
for(Field field : fields){
s.append("\t");
s.append(Modifier.toString(field.getModifiers()));//加入修饰符
s.append(" ");
s.append(field.getType().getSimpleName());//类型名
s.append(" ");
s.append(field.getName());//变量名
s.append(";\n");
}
System.out.println(s);
访问Field属性
//获取属性
Field field =userClass.getDeclaredField("id");
//给object对象赋值
field.set(obj,1);//读取属性值
System.out.println(field.get(obj));
缺点:容易打破封装,私有属性也可以访问
获取Method(类方法)
①Method的获取
Class userClass = Class.forName("反射机制.User");
//获取所有的Method
Method[] methods = userClass.getDeclaredMethods();
//遍历methods
for(Method method:methods){
//修饰符列表
System.out.print(Modifier.toString(method.getModifiers()) + " ");
//返回值类型
System.out.print(method.getReturnType().getSimpleName() +" ");
//获取方法名
System.out.print(method.getName()+"(");
//获取参数列表类型
Class[] ParameterTypes = method.getParameterTypes();
for (Class cc :ParameterTypes){
System.out.print(cc.getSimpleName()+" ");
}
System.out.println(")");
}
②Method方法的调用
//调用Method方法
Object obj = userClass.newInstance();
//获取Method
Method method = userClass.getDeclaredMethod("doother", String.class, int.class);
Object a = method.invoke(obj,"a",3);