当前位置 : 主页 > 编程语言 > java >

Java反射:框架设计的灵魂

来源:互联网 收集:自由互联 发布时间:2022-06-23
@toc框架:半成品软件。可以在框架的基础上进行软件开发,简化编码。反射就是把Java类中的各个成员映射成一个个的Java对象。即在运行状态中,对于任意一个类,都能够知道这个类的

@toc框架:半成品软件。可以在框架的基础上进行软件开发,简化编码。反射就是把Java类中的各个成员映射成一个个的Java对象。即在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性。这种动态获取信息及动态调用对象方法的功能叫Java的反射机制。好处:

  • 可以在程序运行过程中,操作这些对象。
  • 可以解耦,提高程序的可扩展性。

    获取Class对象的方式

  • Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
  • 多用于配置文件,将类名定义在配置文件中。读取文件,加载类。

  • 类名.class:通过类名的属性class获取
  • 多用于参数的传递

  • 对象.getClass():getClass()方法在Object类中定义着。
  • 多用于对象的获取字节码的方式

    //1.Class.forName("全类名") Class cls1 = Class.forName("com.zjq.javabase.base25.domain.Person"); System.out.println(cls1); //2.类名.class Class cls2 = Person.class; System.out.println(cls2); //3.对象.getClass() Person p = new Person(); Class cls3 = p.getClass(); System.out.println(cls3);

    结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。

    Class对象功能

    测试的Person类:

    package com.zjq.javabase.base25.domain; /** * @author zjq */ public class Person { private String name; private int age; public String a; protected String b; String c; private String d; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + ", a='" + a + '\'' + ", b='" + b + '\'' + ", c='" + c + '\'' + ", d='" + d + '\'' + '}'; } public void eat(){ System.out.println("eat..."); } public void eat(String food){ System.out.println("eat..."+food); } }

    获取成员变量们

    • Field[] getFields() :获取所有public修饰的成员变量
    • Field getField(String name) 获取指定名称的 public修饰的成员变量

    • Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符
    • Field getDeclaredField(String name)

    案例:

    //0.获取Person的Class对象 Class personClass = Person.class; //1.Field[] getFields()获取所有public修饰的成员变量 Field[] fields = personClass.getFields(); for (Field field : fields) { System.out.println(field); } System.out.println("------------"); //2.Field getField(String name) Field a = personClass.getField("a"); //获取成员变量a 的值 Person p = new Person(); Object value = a.get(p); System.out.println(value); //设置a的值 a.set(p,"张三"); System.out.println(p); System.out.println("==================="); //Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符 Field[] declaredFields = personClass.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println(declaredField); } //Field getDeclaredField(String name) Field d = personClass.getDeclaredField("d"); //忽略访问权限修饰符的安全检查 d.setAccessible(true);//暴力反射 Object value2 = d.get(p); System.out.println(value2);

    获取构造方法们

    • Constructor<?>[] getConstructors()
    • Constructor<T> getConstructor(类<?>... parameterTypes)

    • Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
    • Constructor<?>[] getDeclaredConstructors() //0.获取Person的Class对象 Class personClass = Person.class;

    //Constructor<T> getConstructor(类<?>... parameterTypes)Constructor constructor = personClass.getConstructor(String.class, int.class);System.out.println(constructor);//创建对象Object person = constructor.newInstance("张三", 23);System.out.println(person);

    System.out.println("----------");

    Constructor constructor1 = personClass.getConstructor();System.out.println(constructor1);//创建对象Object person1 = constructor1.newInstance();System.out.println(person1);

    Object o = personClass.newInstance();System.out.println(o);

    ### 获取成员方法们 - Method[] getMethods() - Method getMethod(String name, 类<?>... parameterTypes) - Method[] getDeclaredMethods() - Method getDeclaredMethod(String name, 类<?>... parameterTypes) ```java //0.获取Person的Class对象 Class personClass = Person.class; //获取指定名称的方法 Method eat_method = personClass.getMethod("eat"); Person p = new Person(); //执行方法 eat_method.invoke(p); Method eat_method2 = personClass.getMethod("eat", String.class); //执行方法 eat_method2.invoke(p,"饭"); System.out.println("-----------------"); //获取所有public修饰的方法 Method[] methods = personClass.getMethods(); for (Method method : methods) { System.out.println(method); String name = method.getName(); System.out.println(name); //method.setAccessible(true); } //获取类名 String className = personClass.getName(); System.out.println(className);//com.zjq.javabase.base25.domain.Person

    获取全类名

    String getName()

    Field:成员变量

    操作:

  • 设置值
  • void set(Object obj, Object value)

  • 获取值
  • get(Object obj)

  • 忽略访问权限修饰符的安全检查
  • setAccessible(true):暴力反射

    Constructor:构造方法

    创建对象:T newInstance(Object... initargs) 如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法

    Method:方法对象

    执行方法:Object invoke(Object obj, Object... args) 获取方法名称:String getName:获取方法名

    案例:

    需求:写一个"框架",不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象,并且执行其中任意方法实现:

  • 配置文件
  • 反射步骤:
  • 将需要创建的对象的全类名和需要执行的方法定义在配置文件中
  • 在程序中加载读取配置文件
  • 使用反射技术来加载类文件进内存
  • 创建对象
  • 执行方法代码:pro.properties文件内容如下:

    className=com.zjq.javabase.base25.domain.Student methodName=sleep

    Student类:

    public class Student { public void sleep() { System.out.println("sleep..."); } }
  • 反射操作: ```java //1.加载配置文件 //1.1创建Properties对象 Properties pro = new Properties(); //1.2加载配置文件,转换为一个集合 //1.2.1获取class目录下的配置文件 ClassLoader classLoader = ReflectTest.class.getClassLoader(); InputStream is = classLoader.getResourceAsStream("pro.properties"); pro.load(is); //2.获取配置文件中定义的数据 String className = pro.getProperty("className"); String methodName = pro.getProperty("methodName"); //3.加载该类进内存 Class cls = Class.forName(className); //4.创建对象 Object obj = cls.newInstance(); //5.获取方法对象 Method method = cls.getMethod(methodName); //6.执行方法 method.invoke(obj);

    本文内容到此结束了, 如有收获欢迎点赞

    网友评论