1.获取字节码文件对象(3种)
//1)用对象名调用类名p1.getclass()
Person p1 = new Person();
Class<? extends Person> c1 = p1.getClass();
//2)用类调用class,注意此时class相当于数组的length属性
Class<Person> c2 = Person.class;
System.out.println(c1 == c2);//结果显示为TRUE(类只被加载一次,因此c1和c2用的同一个类)
System.out.println("++++++++++++++++++++++");
//3)用Class调forname(获取目标类的地址,注意要带双引号!!!!!),
// 因此反射的优点之一就是解耦合因为它可以精确的指向它所要指向的类
Class<?> c3 = Class.forName("leipackage.Person");
System.out.println(c3 == c2);
System.out.println("++++++++++++++++++++++++++++++++++");2.用字节码调构造函数(4种) Constractor
//2.用字节码对象调构造函数(4种),
// 获取的构造函数输出值为构造函数的详细信息即 访问权限修饰符.包名.类名;
// 且获取多个类时要进行判断和遍历
//1)用字节码对象获取指定单个公共构造函数,若有参则用形参数据类型.class设置映射构造的形参
//若无参则不用管
//总结:输出结果为 public leipackage.Person() public 包名.类名()
Constructor<?> con1 = c3.getConstructor();
System.out.println(con1);
System.out.println("+++++++++++++++++++++++++++++++++++++++");
//2)getConstructors获取所有公共构造函数,先判断在进行遍历!
Constructor<?>[] con2 = c3.getConstructors();
//需要判断
if (con2 != null) {
//遍历
for (Constructor con : con2) {
System.out.println(con);
System.out.println("++++++++++++++++++++++++++++");
}
}
//3)getDeclaredConstructors()获取所有的(公共的 私有的 保护的 默认的)
Constructor<?>[] con3 = c3.getDeclaredConstructors();
//判断
if(con3 != null){
//遍历
for (Constructor co:con3) {
System.out.println(co);
System.out.println("+++++++++++++++++++++++++++++++++");
}
}
//4)获取指定构造函数
Constructor<?> con4 = c3.getDeclaredConstructor(String.class,int.class);//默认两参
System.out.println(con4);
System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++");3. 用构造函数对象创建对象newInstance(2种只能用指定公共构造函数或者指定单个构造函数进行创建)
3.用构造函数创建对象
//1)用公共无参创建
Object o = con1.newInstance();
System.out.println(o);
System.out.println("+++++++++++++++++++++++++++++++++++");
//2)用默认两参创建,传入实参
//除过公共的构造函数,其余的都要进行压制检查 构造函数.set
con4.setAccessible(true);
Object o1 = con4.newInstance("张三",20);//数字直接写数字就行
System.out.println(o1);
System.out.println("++++++++++++++++++++++++++++++++");4.通过字节码对象给成员变量赋值 Field()
4.通过字节码对象给成员变量赋值(2步:先获取成员变量(字节码对象.getField() 再为成员变量赋值(nameField.set()))
//一次获取多个属性对象时要进行判断和进行遍历,且所有的属性输出结果是:访问权限修饰符 全限定包名.属性名
//1)getFields()通过字节码对象获取所有公共成员变量
Field[] f1 = c1.getFields();
if (f1 !=null){
for (Field file:f1) {
System.out.println(file);
}
System.out.println("++++++++++++++++++++++");
}
//2)getDeclaredFields()获取所有类型的成员变量
Field[] f2 = c1.getDeclaredFields();
if (f2 != null){
for (Field fi:f2) {
System.out.println(fi);
}
System.out.println("++++++++++++++++++++++++++++++++");
}
//通过getDeclaredField("成员变量名")获取指定(公共 私有 默认)成员变量,并通过所创建的对象为其赋值
//对于无参公共构造函数可以用字节码对象直接创建对象
Person person = c1.newInstance();
Field name1 = c1.getDeclaredField("name");
Field age = c1.getDeclaredField("age");
Field address = c1.getDeclaredField("address");
//对于私有属性要压制检查
age.setAccessible(true);
address.setAccessible(true);
address.set(person,"中国广东");
age.set(person,20);
name1.set(person,"李小龙");
Field name = c1.getField("name");
//可以改值,对于同一个对象
name.set(person,"张三丰");
System.out.println(person);总结:
1)对于无参公共构造函数可以直接通过字节码对象.newinstance进行创建
2)getField用于获取属性对象,后面直接用双引号写入成员变量的名字
3)set用于赋值,且用set对属性进行赋值时其参数有两个,一参为该类创建的对象且当其类中有公共无参构造函数时可以用字节码对象直接newinstance进行创建.
5通过字节码文件对象调方法Method
5.用字节码文件对象调方法Method
//1)通过字节码对象调getMethods()获取所有公共方法对象
Method[] method1 = c3.getMethods();
if (method1 != null){
for (Method me:method1) {
System.out.println(me);
}
System.out.println("+++++++++++++++++++++++++++++++++");
}
//2)通过字节码对象调取getDeclaredMethods()所有方法(公共 私有 默认 受保护)对象不含Object的方法
Method[] methods2 = c3.getDeclaredMethods();
if (methods2 != null){
for (Method m2:methods2) {
System.out.println(m2);
}
}
//3)通过字节码对象调取c3.getMethod()获得指定公共方法
Method method3 = c3.getMethod("show");
//4)tog字节码对象调取getDeclaredMethod()指定方法(公共 私有 默认 受保护)
Method method4 = c3.getDeclaredMethod("method", String.class);
//通过方法对象为方法设置实参
method4.setAccessible(true);
method4.invoke(person,"hello,刘亦菲!");总结:
1)与给成员变量赋值一样,分两步
先获取方法对象getMethod 再用方法对象.invoke
2)赋值时与给成员变量赋值的方法一致,一参为对象,二参为方法的实参.没有则不写
版权声明:本文为HeiManBa_8原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。