java反射

1、反射相关的主要类

  1. java.lang.Class<T>:Class对象表示某个类加载后在堆中的对象(获取字节码对象),通过获取到的对象然后可以获得类的其他属性。
    ①:public Field getField(String name):获取属性对象。
    ②:public Constructor<T> getConstructor(Class<?>... parameterTypes):获取构造方法对象。
    ③:public Method getMethod(String name, Class<?>... parameterTypes): 获取指定方法对象。

  2. java.lang.reflect.Field:代表类的成员变量,Filed对象表示某个类的成员变量。
    ①:Field表示一个类中的属性,每一个属性,都是该类的一个实例。
    ②:public void set(Object obj, Object value):给指定对象obj设置值value
    ③:public Object get(Object obj):获取指定对象obj中存储的属性的值。

  3. java.lang.reflect.Constructor<T>:代表类的构造方法,Constructor对象表示构造器,泛型表示对应的实例对象类型。
    ①:public T newInstance(Object ... initargs):根据获取的构造器对象创建实例。

  4. java.lang.reflect.Method:代表类的方法,Method对象表示某个方法类的方法。
    ①:Object invoke(Object obj, Object... args)obj表示要执行的方法是哪个对象的;args表示执行方法时所需要的实际参数,没有参数时可不写;object表示方法返回值(没有时不写)。

简单的例子:

public class ReflectionQuestion {

    public static void main(String[] args) throws Exception {
        // 根据配置文件 re.properties指定的信息,创建Cat实例

        Properties properties = new Properties();
        properties.load(new FileInputStream("reflection\\src\\re.properties"));
        String clssfullpath = properties.get("classfullpath").toString();
        String methodName = properties.get("method").toString();

        //-----使用反射创建对象
        // 1. 加载类,得到Class类型的对象
        Class cls = Class.forName(clssfullpath);
        // 2. 通过加载类,得到Cat实例
        Object o = cls.newInstance();
        System.out.println(o.getClass());
        // 3.把这个方法当做一个对象,得到后返回
        Method method = cls.getMethod(methodName);
        System.out.println("===========");
        // 4.通过method调用方法:即通过方法的对象来调用方法
        method.invoke(o);  //传统调用方法  对象.方法() ,   反射机制调用方法:方法.invoke(对象)

        // 通过反射调用Cat对象的cry方法
        Method cry = cls.getMethod("cry");  //这个cry可以从配置文件中获取,达到修改配置文件调用方法
        cry.invoke(o);


    }
}

re.properties

classfullpath=com.Cat
method=hi

Cat类

public class Cat {

    private String name = "招财猫";
    public int age = 10;
	
	//setter()和getter()    
}

2、反射构造方法创建实例

  1. public Constructor<T> getConstructor(Class<?>... parameterTypes):获取构造器对象。
  2. public T newInstance(Object ... initargs):根据获取的构造器对象创建实例。
/**
 * 反射
 * 一个类型的字节码(.class)文件进入内存一次,字节码文件在内存中对应的class对象只有一个
 * 使用构造方法创建对象
 */
public static void main(String[] args) throws Exception {

        Class<?> cls1 = Class.forName("com.day25.Student");
        Class<?> cls2 = Class.forName("com.day25.Student");

        System.out.println(cls1 == cls2);  //返回为true

        Constructor<?>[] cs = cls1.getConstructors();  //获取所有public构造方法
        for (Constructor<?> c : cs) {
            System.out.println(c);
        }

        Constructor<?> c = cls1.getConstructor(String.class, int.class);  //获取指定的构造方法,这里的参数是构造方法中参数的类型
        Object o = c.newInstance("张三", 9);  //如果获取的构造方法需要参数,这里就需要按顺序写入参数
        System.out.println(o);

}

class Student {

    private String name;
    private int age;

    public Student() {
    }

    public Student(int age) {
        this.age = age;
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    //setter()和getter()  
    //toString()
}

3、反射获取方法

  1. public Method[] getMethods():获取一个类中的所有的public修饰的成员方法,返回值是一个Method类型的数组。
  2. public Method getMethod(String name, Class<?>... parameterTypes): 获取指定方法对象
    ①:name:表示方法名
    ②:parameterTypes:一个可变参数,表示方法参数的类型
  3. Method类:
    ①:Object invoke(Object obj, Object... args)obj表示要执行的方法是哪个对象的;args表示执行方法时所需要的实际参数;object表示方法返回值。

代码:

public class Demo3 {

    public static void main(String[] args) throws Exception {

        Class cls = Class.forName("com.day25.Person");
        Object o = cls.newInstance();

        Method eat = cls.getMethod("eat", String.class);  // 没有参数可以不写类型
        eat.invoke(o,"满汉全席");  // 没有参数可以不写
    }
}

person类:

public class Person {

   	public String name;
    public int age;
    public String sex;

    public Person() {
    }

    public Person(String name, int age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public void eat(String name){
        System.out.println("吃" + name);
    }

}

输出:

吃满汉全席

4、反射获取属性

  1. public Field getField(String name) :获取Field对象
  2. Field类型:
    ①:Field表示一个类中的属性,每一个属性,都是该类的一个实例
    ②:public void set(Object obj, Object value):给指定对象obj设置值value
    ③:public Object get(Object obj):获取指定对象obj中存储的属性的值
/**
 * 反射获取属性
 */
public class Demo4 {

    public static void main(String[] args) throws Exception {

        Class<?> cls = Class.forName("com.day25.Person");

        Field[] fields = cls.getFields();  //获取所有公共的属性
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("========");

        //获取指定属性
        Field name = cls.getField("name");
        System.out.println(name);

        //根据获取的属性修改属性值
        Object o = cls.newInstance();  //先获取指定的对象
        name.set(o, "张三");
        System.out.println(name.get(o));

    }
}

5、暴力反射

  1. Class对象获取私有属性:有一些getDeclared*****开头的方法,这些方法可以获取到类中的,所有的构造方法,所有的属性,所有的方法,不管是public还是private修饰的都可以获取到。
  2. AccessibleObject类:FieldConstructorMethod类都是这个类的子类。这个类有个能力,可以使该类或者其子类能够忽略调用权限检测符的能力
    ①:public void setAccessible(boolean flag):将参数设置为true,就不会再检测这个对象权限修饰符,直接能够使用,如果设置false,就会检测权限修饰符。
    ②:public boolean isAccessible():返回一个对象是否有设置取消权限检测。

例:

public class Demo6 {

    public static void main(String[] args) throws Exception {

        Class<?> cls = Class.forName("com.day25.Student");
        Constructor<?> con = cls.getDeclaredConstructor(String.class, int.class);  // 获取私有的构造方法

        con.setAccessible(true);  //取消权限检测
        Object o = con.newInstance("张三", 99);
        System.out.println(o);

    }
}

class Student {

    private String name;
    private int age;

    private Student() {
    }

    private Student(int age) {
        this.age = age;
    }

    private Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

输出:

Student{name=‘张三’, age=99}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值