利用反射技术提升Java应用的灵活性和可扩展性

简介: 利用反射技术提升Java应用的灵活性和可扩展性

前言


反射:将类的各个组成部分封装为其他对象,这就是反射机制。

好处:

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





获取Class对象的方式


  1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象

多用于配置文件,将类名定义在配置文件中。读取文件,加载类

  1. 类名.class:通过类名的属性class获取

多用于参数的传递


  1. 对象.getClass():getClass()方法在Object类中定义着。

多用于对象的获取字节码的方式


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


示例:

public class Person {
    private String name;
    private int age;
    private static String city="上海";
    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 void eat(){
        System.out.println("吃饭。。。。");
    }
    public void sleep(){
        System.out.println("睡觉。。。。");
    }
}
public class Reflectyby6Demo1 {
    public static void main(String[] args) {
        /*
        1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
        - 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
        2. 类名.class:通过类名的属性class获取
        - 多用于参数的传递
        3. 对象.getClass():getClass()方法在Object类中定义着。
        - 多用于对象的获取字节码的方式
         */
        //1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
        try {
            Class<?> aClass = Class.forName("com.tuling.domain.Person");
            //类名.class:通过类名的属性class获取
            Class<Person> personClass = Person.class;
            //3. 对象.getClass():getClass()方法在Object类中定义着。
            Person person = new Person();
            Class<? extends Person> aClass2 = person.getClass();
            System.out.println("aClass==personClass:"+(aClass==personClass));
            System.out.println("aClass2==personClass:"+(aClass==personClass));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}





Class对象功能


获取成员变量

  • Field[] getFields() :获取所有public修饰的成员变量
  • Field getField(String name)   获取指定名称的 public修饰的成员变量
  • Field[] getDeclaredFields()  获取所有的成员变量,不考虑修饰符
  • Field getDeclaredField(String name)  




Field:成员变量


  1. 设置值  void set(Object obj, Object value)  
  2. 获取值 get(Object obj)
  3. 忽略访问权限修饰符的安全检查(暴力反射) setAccessible(true)

示例:

public class ReflectYby6Demo2 {
    @Test
    public void test1() throws Exception {
        /*
        - Field[] getFields() :获取所有public修饰的成员变量
        - Field getField(String name)   获取指定名称的 public修饰的成员变量
        - Field[] getDeclaredFields()  获取所有的成员变量,不考虑修饰符
        - Field getDeclaredField(String name)
         */
        Class<Person> personClass = Person.class;
        //
        Field[] fields = personClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("-----------");
        Field[] declaredFields = personClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        /*
        1. 设置值
        - void set(Object obj, Object value)
        2. 获取值
        - get(Object obj)
        3. 忽略访问权限修饰符的安全检查
        - setAccessible(true):暴力反射
         */
        System.out.println("------------------");
        Field a = personClass.getField("a");
        Person p = new Person();
        a.set(p,"zhongguo");
        //获取值
        Object o = a.get(p);
        System.out.println("o:"+o);
        //a.setAccessible(true);
        Field name = personClass.getDeclaredField("name");
        /*
        Class com.qf.reflect.ReflectDemo2 can not access a member of class com.qf.domain.Person with modifiers "private"
         */
        System.out.println("name:"+name.get(p));
    }
}




获取构造方法

  • Constructor<?>[] getConstructors()  
  • Constructor<T> getConstructor(Class<?>... parameterTypes)  
  • Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)  
  • Constructor<?>[] getDeclaredConstructors()  




Constructor:构造方法

创建对象:T newInstance(Object... initargs)  

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

示例:

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ReflectDemo3 {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        /*
        2. 获取构造方法们
        - Constructor<?>[] getConstructors()
        - Constructor<T> getConstructor(类<?>... parameterTypes)
        - Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
        - Constructor<?>[] getDeclaredConstructors()
         */
        Class<Person> personClass = Person.class;
        //获取有参的构造方法
        Constructor<Person> constructor = personClass.getConstructor(String.class, int.class);
        System.out.println(constructor);
        //创建对象1
        Person person1 = constructor.newInstance("张三", 23);
        System.out.println(person1);
        //获取无参的构造方法
        Constructor<Person> constructor2 = personClass.getConstructor();
        System.out.println("constructor2:"+constructor2);
        //创建对象2
        Person person2 = constructor2.newInstance();
        System.out.println("person2:"+person2);
        //创建对象3
        Person person3 = personClass.newInstance();
        System.out.println("person3:"+person3);
        System.out.println("------------");
        Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        System.out.println("-------------");
        //构造器暴力访问
        //constructor2.setAccessible(true);
    }
}



获取成员方法

  • Method[] getMethods()  :获取类里面所有的public方法,包括父类里面的public方法
  • Method getMethod(String name, 类<?>... parameterTypes)  
  • Method[] getDeclaredMethods()  :获取类里面声明的所有的方法,不包括父类的方法
  • Method getDeclaredMethod(String name, 类<?>... parameterTypes)  




Method:方法对象

执行方法:Object invoke(Object obj, Object... args)  

获取方法名称:String getName

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Reflectyby6Demo4 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        /*
        获取成员方法:
        Method[] getMethods()
        Method getMethod(String name, 类<?>... parameterTypes)
        Method[] getDeclaredMethods()
        Method getDeclaredMethod(String name, 类<?>... parameterTypes)
         */
        Class<Person> personClass = Person.class;
        //获取指定名称的方法
        Method eat = personClass.getMethod("eat");
        //
        Person p = new Person();
        //执行方法
        eat.invoke(p);
        //获取指定名称,并且带参数的方法
        Method eat2 = personClass.getMethod("eat", String.class);
        //执行带参数的方法
        eat2.invoke(p,"wowo");
        System.out.println("--------------");
        //获取所有public修饰的方法
        Method[] methods = personClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
            //方法名
            System.out.println(method.getName());
        }
        System.out.println("-----------------");
        //获取类名
        String name = personClass.getName();
        System.out.println("类名:"+name);
    }
}




在程序使用(解析)注解


在程序使用(解析)注解:获取注解中定义的属性值


1获取注解定义的位置的对象  (Class,Method,Field)


2判断注解是否存在

isAnnotationPresent(Class)


3获取指定的注解

getAnnotation(Class)


4调用注解中的抽象方法获取配置的属性值

示例:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno4 {
    int age() default 0;
}
import java.lang.reflect.Method;
public class Annotationyby6Demo3 {
    public static void main(String[] args) throws NoSuchMethodException {
        /*
        - 在程序使用(解析)注解:获取注解中定义的属性值
        1. 获取注解定义的位置的对象  (Class,Method,Field)
        - isAnnotationPresent(Class)
        1. 获取指定的注解
        - getAnnotation(Class)
        3. 调用注解中的抽象方法获取配置的属性值
         */
        Class<Person> personClass = Person.class;
        System.out.println("------------");
        Method test = personClass.getMethod("test");
        System.out.println(test.isAnnotationPresent(MyAnno4.class));
        //获取方法上定义的注解
        if(test.isAnnotationPresent(MyAnno4.class)){
            System.out.println("test方法有定义注解");
            MyAnno4 annotation2 = test.getAnnotation(MyAnno4.class);
            int age2 = annotation2.age();
            System.out.println("age2:"+age2);
        }
    }
}





最后


本期结束咱们下次再见👋~

🌊 关注我不迷路,如果本篇文章对你有所帮助,或者你有什么疑问,欢迎在评论区留言,我一般看到都会回复的。大家点赞支持一下哟~ 💗

相关文章
|
6天前
|
JSON Java Apache
非常实用的Http应用框架,杜绝Java Http 接口对接繁琐编程
UniHttp 是一个声明式的 HTTP 接口对接框架,帮助开发者快速对接第三方 HTTP 接口。通过 @HttpApi 注解定义接口,使用 @GetHttpInterface 和 @PostHttpInterface 等注解配置请求方法和参数。支持自定义代理逻辑、全局请求参数、错误处理和连接池配置,提高代码的内聚性和可读性。
|
15天前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
基于开源框架Spring AI Alibaba快速构建Java应用
|
8天前
|
SQL Java 数据库连接
从理论到实践:Hibernate与JPA在Java项目中的实际应用
本文介绍了Java持久层框架Hibernate和JPA的基本概念及其在具体项目中的应用。通过一个在线书店系统的实例,展示了如何使用@Entity注解定义实体类、通过Spring Data JPA定义仓库接口、在服务层调用方法进行数据库操作,以及使用JPQL编写自定义查询和管理事务。这些技术不仅简化了数据库操作,还显著提升了开发效率。
20 3
|
11天前
|
JSON 前端开发 JavaScript
java-ajax技术详解!!!
本文介绍了Ajax技术及其工作原理,包括其核心XMLHttpRequest对象的属性和方法。Ajax通过异步通信技术,实现在不重新加载整个页面的情况下更新部分网页内容。文章还详细描述了使用原生JavaScript实现Ajax的基本步骤,以及利用jQuery简化Ajax操作的方法。最后,介绍了JSON作为轻量级数据交换格式在Ajax应用中的使用,包括Java中JSON与对象的相互转换。
25 1
|
16天前
|
SQL Java 数据库连接
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率。本文介绍了连接池的工作原理、优势及实现方法,并提供了HikariCP的示例代码。
30 3
|
16天前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
33 2
|
16天前
|
SQL 监控 Java
Java连接池技术的最新发展,包括高性能与低延迟、智能化管理与监控、扩展性与兼容性等方面
本文探讨了Java连接池技术的最新发展,包括高性能与低延迟、智能化管理与监控、扩展性与兼容性等方面。同时,结合最佳实践,介绍了如何选择合适的连接池库、合理配置参数、使用监控工具及优化数据库操作,以实现高效稳定的数据库访问。示例代码展示了如何使用HikariCP连接池。
10 2
|
16天前
|
Java 数据库连接 数据库
深入探讨Java连接池技术如何通过复用数据库连接、减少连接建立和断开的开销,从而显著提升系统性能
在Java应用开发中,数据库操作常成为性能瓶颈。本文通过问题解答形式,深入探讨Java连接池技术如何通过复用数据库连接、减少连接建立和断开的开销,从而显著提升系统性能。文章介绍了连接池的优势、选择和使用方法,以及优化配置的技巧。
16 1
|
16天前
|
算法 Java 数据库连接
Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性
本文详细介绍了Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性。连接池通过复用数据库连接,显著提升了应用的性能和稳定性。文章还展示了使用HikariCP连接池的示例代码,帮助读者更好地理解和应用这一技术。
31 1
|
SQL 存储 Java
Java 应用与数据库的关系| 学习笔记
快速学习 Java 应用与数据库的关系。
203 0
Java 应用与数据库的关系| 学习笔记