反射:在运行状态下就可以获得类的信息。
反射获取类的属性:
1.获取.class文件:有三种方法
(1) Class class1 = Class.forName('包名.类名');
(2) Class class2 = 包名.类名.class;
(3)由于过程有点繁琐可能用的不多(以类User为例)
User user = new User();
Class class3 = user.getClass();
如果将class都打印出来得到的是一个地址,由于获取的都是同一个.class文件所以它们的地址是相等的
即class1==class2;class1==class3返回的都是true.
不同的就是第一种方法会动态的通过jvm去加载类,所以执行的时候就会执行静态代码块,
而第二种是一种静态的获取不会去加载类,
第三种方法不仅会加载类,还生成了对象,会执行静态代码块和构造代码块.
2.通过得到的Class去创建对象
Object obj = class1.newInstance();
这里很神奇没有调用构造函数又是怎么生成对象的呢?
其实这里是底层调用了我们默认的一个无参构造,如果我们显示的定义一个有参构造且不显示的定义无参构造,最后运行就会报错.
所以:我们在定义构造函数时建议最好加上无参构造.
3.通过反射拿到类的信息:
(1)得到类:
Class class1 = Class.forName("包名.类名");
(2)得到属性:在java中定义了一个类来表示属性Field,通过以下方法获取的都是 修饰符+类型 +属性名称
例如属性名是id: public java.lang.Integer keke24.User.id
获取属性有三种方式:
第一种:Field[] fields = class1.getField();
不过比较可惜的是这一种方法只能够获取公开的属性名要想获得所有的属性名还得使用后两种方法.
第二种:Filed[] filelds = class1.getDeclareFields();
第三种Filed field = class1.getDeclareFileld(''属性名");
4.给属性赋值
(1)先创建一个对象:
Object obj = class1.newInstanbce();
(2)获取属性
Filed field = class1.getDeclareFileld(''id");
(3)赋值:
field.set(obj,233);
不过要注意的是这样设置属性值只能是可以访问的属性,要想设置私有属性值只能加一句:
field.setAccessible(true);
这样设置之后也是有风险的该属性就变得公开了,没有了安全性.
(4)获取设置的属性值
field.get(obj);
5.获取所有修饰符
int num = field.getModifiers();//这里获得的是一个int类型的值
String string = Modifier.toString(num);//将获取到的int类型的值转换为修饰符的字符串
6.获取属性类型
Class type = field.getType();
String string2 = type.getName();
7.获取属性的名称
field.getName();