JavaSE-16 【反射】

本文详细介绍了Java反射机制,包括反射的概念、特征和功能。通过反射,可以在运行时动态创建对象、调用方法和修改属性。文章还列举了获取类的多种方式,如通过Class对象、运行时类实例和Class的forName方法。接着,详细讲解了如何获取类的属性、构造方法,并通过反射创建对象、操作成员变量和调用成员方法。最后,提供了实际的代码示例,演示了如何使用反射进行各种操作。
摘要由CSDN通过智能技术生成

JavaSE-16 【反射】

第一章 反射介绍

1 反射的概念

反射(Reflection)机制是Java语言特性之一,是Java被视为动态(或准动态)语言的一个关键特性。

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

2 反射的特征

  • 运行时创建实例:在程序运行期间能够创建对象
  • 运行时调用方法:在程序运行期间能够调用方法
  • 运行时更改属性:在程序运行期间能够设置属性

3 反射的功能

通过Java反射可以实现以下功能:

  • 在运行时探知任意一个实例所属的类。
  • 在运行时构造任意一个类的实例。
  • 在运行时探知任意一个类所具有的方法和属性。
  • 在运行时调用任意一个实例的方法。

第二章 反射的基本操作

2.1 反射操作–常用方法

1、获取类的Class对象
	方式一:调用运行时类的属性:.class
	方式二:通过运行时类的对象,调用getClass()
	方式三:调用Class的静态方法:forName(String classPath)

2、获取类的路径和名称
--.getPackage().getName(); 获取包的名称
--.getSimpleName(); 获取类的名称
--.getName(); 获取类的全路径

3、获取类的属性
--.getFields(); 获取所有公开属性
--.getDeclaredFields(); 获取所有属性包括私有属性
--.getField(String name); 根据指定属性名获取公开的属性
--.getDeclaredField(String name);根据指定属性名获取属性包括私有属性

4、获取类的构造方法
--.getConstructor();获取公开的无参构造
--.getConstructor(Class<?>... parameterTypes);获取指定参数类型的公开的有参构造
--.getConstructors();获取所有公开的构造方法
--.getDeclaredConstructors();获取所有的构造方法,包括私有的
--.getDeclaredConstructor(Class<?>... parameterTypes);根据指定参数的类型获取指定的构造方法包括私有的

5、反射创建对象
无参构造对象
--字节码对象.newInstance();反射无参构造创建对象
有参构造对象
--字节码对象.getDeclaredConstructor(Class<?>... parameterTypes); 获取构造器对象
--构造器对象.setAccessible(true); 设置私有状态的权限为true
-- 构造器对象.newInstance(Object ... initargs); 构造创建对象

6、操作成员变量并赋值
--.getDeclaredField("username");根据指定名获取变量名
--属性名.setAccessible(true);设置其访问权限为true
--属性名.ser(Object obj,Object value);给指定的对象的属性赋值
--属性名.get(Object obj);获取指定对象的属性的属性值

7、反射调用成员方法
--getDeclaredMethods();获取所有的方法,包括私有的
--.getDeclaredMethod(String name, Class<?>... parameterTypes);根据指定方法名和参数类型获取指定的有参数的方法
--方法名.invoke(Object obj, Object... args);指定执行此方法的对象和参数

2.2 反射操作–类的字节码对象

方式一:调用运行时类的属性:.class
方式二:通过运行时类的对象,调用getClass()
方式三:调用Class的静态方法:forName(String classPath)

  • 编写模板类
package com.hx;
/*
    模板类
 */
public class User {
    //成员属性
    private String username;
    public String pwd;//公开的属性
    private int age;
    private String address;

    //成员方法
    public void work(){
        System.out.println("用户在工作!");
    }

    public String speak(String language){
        System.out.println("用户的母语是"+language);
        return language;
    }

    //公开的无参构造
    public User() {
        System.out.println("我是无参构造");
    }

    //公开的有参构造
    public User(String username, int age) {
        this.username = username;
        this.age = age;
    }

    //私有的的有参构造
    private User(String username, int age, String address) {
        this.username = username;
        this.age = age;
        this.address = address;
    }

    //私有属性的set和get方法
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
}
  • 测试
	/*
	      反射操作类的字节码对象:三种方式
	*/
	  //1、通过类名.class
	  Class<User> uClass = User.class;
	  System.out.println(uClass);
	  //2、通过运行时类的实例对象,调用getClass()
	  User u1 = new User();
	  Class<? extends User> aClass = u1.getClass();
	  //3、调用Class的静态方法:forName(String classPath)
	  Class<?> bClass = Class.forName("com.hx.User");

2.3 反射操作–类的路径和名称

        /*
            反射操作类的路径和名称
         */
        //4、获取当前类所在的包的包名称
        Package aPackage = aClass.getPackage();
        String name = aPackage.getName();
        System.out.println("当前类所在的包的包名称:" + name);

        //5、获取类的名称
        String simpleName = aClass.getSimpleName();
        System.out.println(simpleName);

        //6、获取完整的类的名称
        String name1 = aClass.getName();
        System.out.println(name1);

2.4 反射操作–类的属性

		/*
            反射操作属性
         */
        //7、获取公开的成员变量
        Field[] fields = aClass.getFields();
        System.out.println(Arrays.toString(fields));
        System.out.println("-----------------------------------");

        //8、获取包括私有在内的属性
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field field : declaredFields) {
            System.out.println(field);
        }
        System.out.println("-----------------------------------");

        //9、获取公开指定的变量名
        Field pwd = aClass.getField("pwd");
        System.out.println(pwd);
        System.out.println("-----------------------------------");

        //10、获取指定私有属性的变量的名称
        Field age = aClass.getDeclaredField("age");
        System.out.println(age);

2.5 反射操作–构造方法

         /*
            反射操作构造方法
         */
        //11、获取公开的无参构造
        Constructor<? extends User> c1 = aClass.getConstructor();
        System.out.println(c1);
        System.out.println("=======================================");

        //12、获取指定参数类型的公开的有参构造
        Constructor<? extends User> c2 = aClass.getConstructor(String.class, int.class);
        System.out.println(c2);
        System.out.println("=======================================");

        //13、获取所有公开的构造方法
        Constructor<?>[] constructors = aClass.getConstructors();
        for (Constructor<?> c : constructors) {
            System.out.println(c);
        }
        System.out.println("=======================================");

        //14、获取所有的构造方法,包括私有的
        Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
        for (Constructor<?> d : declaredConstructors) {
            System.out.println(d);
        }
        System.out.println("=======================================");

        //15、根据指定参数的类型获取指定的私有的构造方法
        Constructor<? extends User> d2 = aClass.getDeclaredConstructor(String.class, int.class, String.class);
        System.out.println(d2);
        System.out.println("=======================================");

2.7 反射操作–创建对象

        /*
            通过反射创建对象
         */
        //16、反射无参构造创建对象
        User u3 = aClass.newInstance();
        u3.setUsername("tom");
        u3.setAge(19);
        u3.setAddress("北京");
        System.out.println(u3);
        System.out.println("=======================================");

        //17、反射有参构造创建对象
        /*
            注意事项:
                1、使用有参的构造创建对象,那么模板类中构造方法可以是公开的,也可以是私有的
                2、不能使用字节码对象直接调用newInstance(),执行有参构造的操作
                3、需要使用字节码对象先获取构造器对象,如果是私有构造方法,需要设置访问权限为true
                4、再通过构造器对象调用newInstance(参数...)来创建对象
         */
        //获取指定参数类型的构造器
        Constructor<? extends User> constructor = 
        	aClass.getDeclaredConstructor(String.class, int.class, String.class);
        //设置此构造器的权限为可以被访问
        constructor.setAccessible(true);
        //构造创建对象
        User u4 = constructor.newInstance("lucy", 22, "美国");
        System.out.println(u4);
        System.out.println("=======================================");

2.7 反射操作–成员变量并赋值

        /*
            操作成员变量并赋值
         */
        //18、根据指定名获取变量名
        //私有属性的名称
        Field username = aClass.getDeclaredField("username");
        //设置其访问权限为true
        username.setAccessible(true);
        //给指定的对象的属性赋值
        username.set(u4,"Anny");
        System.out.println(u4);
        //获取指定对象的属性的属性值
        Object o = username.get(u4);
        System.out.println(o);
        System.out.println("=======================================");

2.8 反射操作–成员方法

		/*
            反射调用成员方法
         */
        //19、获取所有的方法,包括私有的
        Method[] methods = aClass.getDeclaredMethods();
        //遍历数组---自定义的成员方法、setter/getter、toString
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("=======================================");

        //20、根据指定方法名获取指定的无参数的方法
        Method work = aClass.getDeclaredMethod("work");
        //调用方法:指定对象和参数
        work.invoke(u4);

        //21、根据指定方法名和参数类型获取指定的有参数的方法
        Method speak = aClass.getDeclaredMethod("speak", String.class);
        //调用方法:指定对象和参数
        Object language = speak.invoke(u4, "法语");
        System.out.println(language);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值