反射
框架设计的灵魂
## 什么是框架?
半成品软件
可以在框架的基础上进行软件的开发,简化编码
其实如果自己学框架并不需要框架,但如果以后要自己写框架,则需要对反射理解特别深!
反射的概念
将类的各个组成部分封装为其他对象,这就是反射机制
先说一说java代码运行的三个步骤
### 1,编码阶段
这个时候还是硬盘上,没有进入虚拟机
名字叫Junit.java的文件的代码如下:
public class Junit { //属性 private String name; private String a1; //构造方法 public Junit(String name, String a1) { this.name = name; this.a1 = a1; } public Junit() { } //普通方法 public String getName() { return name; } public void setName(String name) { this.name = name; } }
然后通过javac编译后
变成Junit.class的二进制字节码文件,
private String name; private String a1; public Junit(String name, String a1) { this.name = name; this.a1 = a1; } public Junit() { } public String getName() { return name; } public void setName(String name) { this.name = name; }
就会分为三个部分
然后进入第二阶段
2,将字节码文件加载进内存
使用的是类加载器
对应的java里面的一个对象,叫作ClassLoader
在java里面有一个Class类(名字叫Class的类)
可以用来描述字节码文件的共同的行为!
在上面我把字节码文件写成了三个部分,这三个部分就是字节码文件的三个共同部分
1,三个成员变量(类里面的属性)
2,构造方法
3,成员方法
在Class类里面,把成员变量用:Field数组描述 fields 构造方法用:Constructor数组描述 constructors 成员方法:Method数组描述 methods
3,创建对象运行阶段
反射的好处
1,可以在程序运行过程中,可以操作这些对象
2,可以解耦,降低程序的耦合性,提高程序的可扩展性
获取Class对象(字节码对象)的方式
有三种方式,分别对象java代码的三个阶段
1,Class.forName("全类名") 全类名就是包名加类名 将字节码文件加载进内存,生成Class对象 Class c1=Class.forName("com.java1201.xiawu.ceshi.Ren"); 因为使用的是全类名,所以需要用字符串,一般多用于配置文件。 将类名定义在配置文件中,通过读取配置文件,然后用反射创建字节码对象。 避免重复使用!
2,类名.class 类默认的class属性 通过类名属性获取Class对象 Class c2 = Ren.class; 多用于参数的传递
3,对象.getclass() 通过方法获取Class对象 Class c3=new Ren().getClass(); 多用于对象调取字节码文件 通过这三种方式获取的字节码对象都是一个 Class c1=Class.forName("com.java1201.xiawu.ceshi.Ren"); Class c2 = Ren.class; Class c3=new Ren().getClass(); System.out.println(c1==c2&&c2==c3); 控制台运行结果: ture
Class对象(字节码对象)的使用
1,获取成员变量们 ``` 方法: 获取public修饰和父类继承来的成员变量:getFields() 返回值 Field[] 获取指定public修饰和父类继承来的成员变量:getFiled(String name) 返回值 Field 获取所有的成员变量:getDeclaredFields() 返回值 Field[] 获取指定的成员变量:getDeclaredField(String name) 返回值 Field 如果找不到指定的成员变量会抛出一个空异常 ```
2,获取构造方法们 其实和上面成员变量的方法差不多 ``` 方法: 获取public修饰和父类继承来的构造方法:getConstructors() 返回值 Constructor<?>[] 获取指定public修饰和父类继承来的构造方法:getConstructor(String name) 返回值 Constructor<?> 获取所有的构造方法:getDeclaredConstructors() 返回值 Constructor<?>[] 获取指定的构造方法:getDeclaredConstructor(String name) 返回值 Constructor<?> 如果找不到指定的成员变量会抛出一个空异常 ```
3,获取成员方法们 ``` 方法: 获取public修饰和父类继承来的成员方法:getMethod 返回值 Constructor<?>[] 获取指定public修饰和父类继承来的成员方法:getMethods(String name, Class<?>... parameterTypes) 返回值 Method 获取所有的成员方法:getDeclaredMethods() 返回值 Method[] 获取指定的成员方法:getDeclaredMethod(String name,Class<?>... parameterTypes) 返回值 Method ```
4,获取类名 • 获取类名: getName 返回值 String • 获取包名: getPackage() 返回值 Package
Class c2 = Ren.class;
Field f=c2.getField("a2"); //获取指定的声明的属性对象
Ren r=(Ren) c2.getDeclaredConstructor().newInstance(); //获取一个操作对象,这里是用了获取字节码对象无参构造的一个方法,用来创建新的对象
赋值成员变量:set(Object obj, Object value) , 前面这个obj是对象,后面的是需要赋入的值 f.set(r,"zp"); //给,r对象,的f属性,赋值"zp" 获取成员变量的值 f.get(r); //获取,r对象的f属性值, 调用无参成员方法:invoke(Object obj, Object... args) 返回值:Object Method m1=c2.getMethod("getNme") //获取指定的声明的成员对象 m1.invoke(r); 调用有参且只有一个参数的成员方法: Method m2=c2.getMethod("setNme",方法参数类型.Class); //大基本类型的话,要用对应的包装类型 m1.invoke(r,值); 调用多个参数的成员方法: Method m3=c2.getMethod("add",方法参数类型.Class,方法参数类型.Class…………) //有几个参数写几个 m1.invoke(r,值,值…………); 构造方法那个和成员方法类似,
上面的方法,对私有属性都是没办法操作的 想操作私有犯法或属性,可以用暴力反射 使用方法: 获取的对象.setAccessible(true); 这个获取的对象指的是Method,Field这些
标签:反射,String,认识,public,获取,关于,返回值,Class,name From: https://www.cnblogs.com/fssnjcl/p/16942229.html