java反射
2020-04-13 本文已影响0人
柳橙汁柳子
1.反射是java被视为动态语言的关键。
(动态语言:python,c#;静态:c/c++)
优点:实现动态创建对象和编译,体现出很大的灵活性;
缺点:对性能有影响。
2.Class类(注意区分Class和class和.class文件)
i.一个类在内存中只有一个Class对象,一个类被加载后,整个结构都会被封装在Class对象中;
ii.每个对象都记得是哪个类创建了自己,可以通过任何一个对象 反射出该对象的类;
iii.Class类的对象由系统创建,每个Class对象 对应一个被加载的 .class文件;
iv.获取Class对象的方法:
a) 已知具体类,通过类的class属性(最安全,性能最高):
Class c1 = Person.class;
b) 已知目标类的实例,通过调用该实例的getClass()方法:
Person person = new Person();
Class c2 = person.getClass();
c) 已知类的完整路径,通过Class类的静态方法forName()获得:
Class c3 = Class.forName("com.test.Person");
*注:以上c1、c2、c3实际上是同一个对象
d) 基本内置类型的包装类 都有一个TYPE属性:
Class c4 = Integer.TYPE;
e)利用ClassLoader:
v.哪些东西拥有Class对象?
类(外部类、内部类)、接口、数组(注意维度一样的数组则是同一个Class对象,否则不是,例如一维数组和二维数组不是同一Class对象)、枚举、注解、基本数据类型、void。
3.获取类的运行时结构
获取User类的Class对象:
Class c1 = Class.forName("com.test.User");
获取User类的名字:
c1.getName();
c1.getSimpleName();
获得User类的属性:
c1.getFields();
c1.getFields("name");
c1.getDeclaredFields(); // 获取包括private的全部属性
c1.getDeclaredFields("name");
获得类的方法:
c1.getMethods(); // 获得该类和父类的所有public方法
c1.getMethods("name");
c1.getDeclaredMethods();
c1.getDeclaredMethods("name"); // 还可以指定参数
获得类构造器
c1.getConstructors();
c1.getDeclaredConstructors();
有了Class对象,能干什么?
4.通过反射动态地创建对象:
Class c1 = Class.forName("com.test.User");
User user1 = (User)c1.newInstance(); // 本质上是调用了类的无参构造器
// 通过有参构造器创建对象
Constructor constructor =
c1.getDeclaredConstructors(String.class, int.class, int.class);
User user2 = (User)constructor.newInstance("柳子", 1, 18);
// 通过反射调用普通方法
User user3 = (User)c1.newInstance();
Method setName = c1.getDeclaredMethod("setName", String.class);
setName.invoke(user3, "柳子2");
// 通过反射操作属性
User user4 = (User)c1.newInstance();
Field name = c1.getDeclaredField("name");
name.setAccessible(true); // 设置私有属性修改权限(会提高效率)
name.set(user4, "柳子3");
// 通过反射获取泛型
// 通过反射获得注解(很多框架用到)