一篇文章带你读懂反射(五)

95 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的10天,点击查看活动详情

五.通过反射创建对象

1.方式一:调用类中的oublic修饰的无参构造器 2.方式二:调用类中的指定构造器

3.Class类相关方法

  • newInstance:调用类中的无参构造器,获取对应类的对象
  • getConstructor(Class...clazz):根据参数列表,获取对应的public构造器对象
  • getDecalaredConstructor((Class...clazz):根据参数列表,获取对应的所有构造器对象

4.Constructor类相关方法

  • setAccessible:暴破
  • newlnstance(Object...obj):调用构造器

5.1通过反射访问类中的成员

  • 访问属性

1.根据属性名获取Field对象

Field f=clazz对象.getDeclaredField(属性名):

2.暴破:f.setAccessible(true);//f是Field

3.访问

f.set(o,值); syso(f.get(o));

4.如果是静态属性,则set和get中的参数o,可以写成null

/**
 * @author LeeZhi
 * @version 1.0
 */
public class ReflectAccessProperty {
​
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        //1.得到Student类对应的Class对象
        Class<?> stuClass = Class.forName("com.gbx.reflection.Student");
        //2.创建对象
        Object o = stuClass.newInstance();//o 得运行类型就是Student
        //3.使用反射得到 age属性对象
        Field age = stuClass.getField("age");
        age.set(o,18);//通过反射设置属性
        System.out.println(o);
​
        //4.使用反射操作name属性
        Field name = stuClass.getDeclaredField("name");
        //对name进行暴破
        name.setAccessible(true);
        name.set(o,"小黄");//
        name.set(null,"子");//因为name是static属性,因此o也可以写出nulL
        System.out.println(o);
    }
}
class Student{
    public int age;
    private static String name;
​
    public Student() {
    }
​
    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                '}';
    }
  • 访问方法

1.根据方法名和参数列表获取Method方法对象:Method m= clazz.getMethod(方法名,XX.class);

2.获取对象:Object o=clazz.newInstance();

3.暴破:m.setAccessible(true):

4.访问:Object returnValue=m.invoke(o,实参列表)://o就是对象

5.注意:如果是静态方法,则invoke的参数o,可以写成null!

public class ReflectAccessMethod {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //1.得到Boss类对应的Class对象
        Class<?> bossCls = Class.forName("com.gbx.reflection.Boss");
        //2.创建对象
        Object o = bossCls.newInstance();
        //3.调用public的hi方法
        //Method hi = bossCls.getMethod("hi");
        //3.1得到hi方法对象
        Method hi1 = bossCls.getDeclaredMethod("hi",String.class);
        //3.2调用
        hi1.invoke(o,"Lee");
​
        //4.调用 private static 方法
        //4.1得到 say 方法对象
        Method say = bossCls.getDeclaredMethod("say", int.class, String.class, char.class);
        say.setAccessible(true);
        System.out.println(say.invoke(100, "小黄", "女"));
        //4.3因为say方法是static的,还可以这样调用,可以传入null
        System.out.println(say.invoke(null,200,"李四",'女'));
        //5.在反射中,如果方法有返回值,统一返回0bjct,但是他运行类型和方法定义的返回类型一致
        Object reVal=say.invoke(null,300,"王五",'男');
        System.out.println("reVal的运行类型="+reVal.getClass());//String
    }
​
}
class Boss{
    public int age;
    private static String name;
​
    private static String say(int n,String s,char c){
        return n +" "+s +" "+c;
    }
    public void hi(String s){
        System.out.println("hi" + s);
    }
}