java反射

一、定义

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

二、常用方法总结

##########属性方法构造方法注解
获得公共,指定名字/类型 单个getField(String name)getMethod(String name, Class…<?> parameterTypes)getConstructor(Class…<?> parameterTypes)getAnnotation(Class annotationClass)
获得公共,所有getClasses()getFields()getMethods()getConstructors()getAnnotations()
获得指定名字/类型单个 (包括私有)getDeclaredField(String name)getDeclaredMethod(String name, Class…<?> parameterTypes)getDeclaredConstructor(Class…<?> parameterTypes)getDeclaredAnnotation(Class annotationClass)
获得所有 (包括私有)getDeclaredClasses()getDeclaredFields()getDeclaredMethods()getDeclaredConstructors()getDeclaredAnnotations()
其他forName(String className)根据类名返回类的对象set(Object obj, Object value)设置obj中对应属性值;get(Object obj)获得obj中对应的属性值invoke(Object obj, Object… args) 传递object对象及参数调用该对象对应的方法newInstance(Object… initargs)根据传递的参数创建类的对象isAnnotation(),isAnnotationPresent(Class<? extends Annotation> annotationClass)

二、反射使用

1.获取类对象有3种方式
  • Class.forName()(常用)
  • Hero.class, 需要导入类, 有依赖
  • new Hero().getClass(), 能拿到对象,就无需用反射了
    在ClassLoader下,一种类只有一个类对象。所以三种结果是一样的
   @Test
    public void test_reflect() throws ClassNotFoundException {
        Object obj = Class.forName("com.learning.reflect.Person");
        Class obj2 = Person.class;
        Class obj3 = new Person().getClass();
        System.out.println(obj == obj2);//true
        System.out.println(obj == obj3);//true
    }
2. 利用反射创建对象

步骤
1)获取类对象
2)获取构造对象
3)获取对象
以下是使用有参构造器实例对象的例子:

   @Test
    public void test_reflect_new_object_with_parameter() throws Exception {
        //1)获取类对象
        Class<?> pClass = Class.forName("com.learning.reflect.Person");
        //2)获取构造对象
        Constructor<?> con = pClass.getDeclaredConstructor(String.class);// 调用了Person的有参构造器, 参数为String name
        //3)获取对象'
        Person o = (Person) con.newInstance("Vivi");
        System.out.println(o.toString());//Person{name='Vivi', age=0}
    }

    @Test
    public void test_reflect_new_object_with_parameter_pravite() throws Exception {
        //1)获取类对象
        Class<?> pClass = Class.forName("com.learning.reflect.Person");
        //2)获取构造对象
        Constructor<?> con = pClass.getDeclaredConstructor(int.class);//调用了Person的有参构造器, 参数为int age
        //3)获取对象'
        con.setAccessible(true); //如果方法/属性是私有的,则需要设置Accessible为true
        Person o = (Person) con.newInstance(18);
        System.out.println(o.toString());//Person{name='null', age=18}
    }


    @Test
    public void test_reflect_new_object_no_parameter() throws Exception {
        //1)获取类对象
        Class<?> pClass = Class.forName("com.learning.reflect.Person");
        //2)获取构造对象
        Constructor<?> con = pClass.getDeclaredConstructor();//调用了Person的无参构造器
        //3)获取对象'
        Person o = (Person) con.newInstance();
        System.out.println(o.toString());//Person{name='null', age=0}
        
        //与以下写法一样, 如果使用无参构造,则可省略2), 直接用类对象pClass.newInstance()
        Person person = (Person) pClass.newInstance();//调用了Person的无参构造器
        System.out.println(person.toString());//Person{name='null', age=0}
    }

注意:

  • 用无参构造实例对象。可省略2), 直接用类对象pClass.newInstance()
  • 如果方法/属性是私有的,则需要设置Accessible为true con.setAccessible(true);
3. 利用反射获得并设置属性
    @Test
    public void test_reflect_set_private_field() throws Exception {
        //获得类对象
       Class pClass =  Class.forName("com.learning.reflect.Person");
        //通过无参构造器获得对象
        Person person = (Person)pClass.newInstance();//调用了Person的无参构造器
        //得到属性
       Field pName = pClass.getDeclaredField("name");
       //私有属性,需要设置Accessible为true
       pName.setAccessible(true);
        //设置属性
       pName.set(person, "Vivi");
        System.out.println(person);//Person{name='Vivi', age=0}
    }
4. 获得方法并使用
    @Test
    public void test_reflect_set_private_method() throws Exception {
        //获得类对象
        Class pClass =  Class.forName("com.learning.reflect.Person");
        //通过无参构造器获得对象
        Person person = (Person)pClass.newInstance();//调用了Person的无参构造器
        //得到方法
        Method pMethod = pClass.getDeclaredMethod("play",java.lang.String.class);
        //私有方法,需要设置Accessible为true
        pMethod.setAccessible(true);
        //方法调用
        pMethod.invoke(person, "Shanghai");//playing in Shanghai
    }

测试的Person类:

public class Person {

    private String name;
    private int age;

    private void play(String city){
        System.out.println("playing in " + city);
    }
    public Person(String name, int age) {
        System.out.println("调用了Person的有参构造器, 参数为String name, int age");
        this.name = name;
        this.age = age;
    }

    public Person(String name) {
        System.out.println("调用了Person的有参构造器, 参数为String name");
        this.name = name;
    }

    private Person(int age) {
        System.out.println("调用了Person的有参构造器, 参数为int age");
        this.age = age;
    }

    public Person() {
        System.out.println("调用了Person的无参构造器");
    }
	...set/get/toString...
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值