JAVA基础 反射技术学习笔记 2

简介: JAVA基础 反射技术学习笔记

4.3 通过类的字节文件对象获取类的成员变量

方法介绍

image.png

package cn.it.bz.Reflect;
public class User {
    private String name;
    public int age;
   ……
}
package cn.it.bz.Reflect;
import java.lang.reflect.Field;
public class GetField {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        //获取类的字节文件对象
         Class<?> userClass = Class.forName("cn.it.bz.Reflect.User");
         //获取被public修饰的成员变量
         Field[] fields = userClass.getFields();
         for (Field field : fields) {
            System.out.println(field);
         }
        System.out.println("-----------------");
         //获取类中全部的成员变量
        Field[] declaredFields = userClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        System.out.println("-----------------");
        //根据成员变量的名称返回被public修饰的成员变量
        Field name = userClass.getField("age");
        System.out.println(name);
        System.out.println("---------------------");
        //根据成员变量的名称返回成员变量,忽略修饰符
        Field name1 = userClass.getDeclaredField("name");
        System.out.println(name1);
    }
}

42ccd62b0ad0403aa951e7528c08dd87.png

4.4 操作成员变量

package cn.it.bz.Reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class GetField2 {
    public static void main(String[] args) throws Exception {
        Class<User> userClass = User.class;
        //获取public修饰的叫age的成员变量
        Field age = userClass.getField("age");
        //向User的实例user的age赋值
        User user = new User();
        age.set(user,123);
        //向User的实例user1的age赋值
        Constructor<User> constructor = userClass.getConstructor(null);//获取无参数构造方法
        User user1 = constructor.newInstance();
        age.set(user1,18);
        //获取成员变量的值
        System.out.println("user:"+user.getAge());
        System.out.println("user1:"+user1.getAge());
        System.out.println("-------或者---------");
        System.out.println(age.get(user));
        System.out.println(age.get(user1));
    }
}

4.5 通过类的字节文件对象获取类的方法

image.png

package cn.it.bz.Reflect;
import java.lang.reflect.Method;
public class GetMethod {
    public static void main(String[] args) throws Exception {
        User user = new User();
        Class<? extends User> aClass = user.getClass();
        //获取全部的方法(包含当前User类的全部方法和其继承父类的公共方法)
        Method[] methods = aClass.getMethods();
        for (Method method: methods) {
            System.out.println(method);
        }
        System.out.println("----------------------");
        //根据方法名和参数获得指定方法
         Method setName = aClass.getMethod("setName", String.class);
         System.out.println(setName);
        System.out.println("----------------------");
        //获取私有方法
        Method getName = aClass.getDeclaredMethod("suibian");
        System.out.println(getName);
    }
}

4.6 调用方法

package cn.it.bz.Reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class GetMethod2 {
    public static void main(String[] args) throws Exception {
         Class<User> userClass = User.class;
         //获取方法区(也是字节文件对象)中的方法
         Method setName = userClass.getMethod("setName", String.class);
         //获取无参构造
         Constructor<User> constructor = userClass.getConstructor(null);
         //实例化User类
         User user = constructor.newInstance();
        //执行setName方法,第一个参数表示是哪个实例的setName方法,第二个参数表示执行该方法需要的参数。
        setName.invoke(user, "小明");
        //获取成员变量的值
        Method getName = userClass.getMethod("getName");
        Object invoke = getName.invoke(user);//表示执行user实例的getName方法,返回值是Object实际上是String类型
        System.out.println(invoke);
    }
}

4.7 获取类的其他信息

package cn.it.bz.Reflect;
public class GetClassInfo {
    public static void main(String[] args) {
        Class<User> userClass = User.class;
        //获取类的类名
        String name = userClass.getName();
        System.out.println("类的名称:"+name);
        //获取该类的包名
        Package aPackage = userClass.getPackage();
        String packageName = aPackage.getName();
        System.out.println("该类所在的包名:"+packageName);
        //获取该类的父类(Java不支持多继承,只有一个父类)
        Class superclass = userClass.getSuperclass();
        String superName = superclass.getName();
        System.out.println("该类的父类:"+superName);
        //获取该类实现的接口(一个类可以实现多个接口)
        Class[] interfaces = userClass.getInterfaces();
        for (Class anInterface: interfaces) {
            System.out.println("该类实现的接口:"+anInterface.getName());
        }
    }
}

五、小案例

需求:根据给定的方法名顺序来决定方法的执行顺序。

向main方法中String数组中传递参数:

package cn.it.bz.Reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
class Reflect{
    public void method1(){
        System.out.println("method1执行");
    }
    public void method2(){
        System.out.println("method2执行");
    }
    public void method3(){
        System.out.println("method3执行");
    }
}
public class ReflectDemo {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
       Reflect reflect = new Reflect();
       if (args.length > 0) {
           //获取Reflect类的字节文件对象
           Class<Reflect> reflectClass = Reflect.class;
           // 获取Reflect的所有方法
           Method[] methods = reflectClass.getMethods();
           for (String arg : args) {
               for (int i = 0; i < methods.length; i++) {
                   if(arg.equalsIgnoreCase(methods[i].getName())){
                       methods[i].invoke(reflect); //没有参数就不给
                   }
               }
           }
       }else {
           reflect.method1();
           reflect.method2();
           reflect.method3();
       }
    }
}

六、反射机制的效率

由于Java反射是要解析字节码,将内存中的对象进行解析,包括了一些动态类型,而JVM无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多!

反射机制的效率测试

package cn.it.bz.Reflect;
import java.lang.reflect.Method;
public class Test {
    public static void main(String[] args) throws Exception {
        //获取当前时间毫秒数
        long l = System.currentTimeMillis();
        //实例化对象
        User user  = new User();
        //获取类字节文件对象
        Class<? extends User> aClass = user.getClass();
        //获取setName方法
        Method setNameMethod = aClass.getMethod("setName", String.class);
        //执行1000次
        for (int i = 0; i < 1000000000 ; i++) {
                setNameMethod.invoke(user, "name");
        }
        long l1 = System.currentTimeMillis();
        System.out.println("反射耗时::"+(l1-l));
        System.out.println("----------------------");
        long l2 = System.currentTimeMillis();
        User user1 = new User();
        for (int i = 0; i <1000000000;i++ ) {
            user1.setName("哈哈哈");
       }
        long l3 = System.currentTimeMillis();
        System.out.println("非反射射耗时::"+(l3-l2));
    }
}

七、setAccessible方法

setAccessible是启用和禁用访问安全检查的开关。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查;默认值为false。

由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的。

7.1 默认情况下获取private修饰的成员变量

package cn.it.bz.Reflect;
import java.lang.reflect.Field;
public class Test2 {
    public static void main(String[] args) throws Exception {
        User user = new User();
        Class<? extends User> aClass = user.getClass();
        //获取private修饰的成员变量name
        Field name = aClass.getDeclaredField("name");
        //向成员变量赋值
        name.set(user, "张三");
        //返回user对象的name属性
        String o =(String) name.get(user);
        System.out.println(o);
    }
}

7.2  忽略JDK安全检查

package cn.it.bz.Reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test2 {
    public static void main(String[] args) throws Exception {
        User user = new User();
        Class<? extends User> aClass = user.getClass();
        //获取private修饰的成员变量name
        Field name = aClass.getDeclaredField("name");
        //忽略安全检查
        name.setAccessible(true);
        //向成员变量赋值
        name.set(user, "张三");
        //返回user对象的name属性
        String o =(String) name.get(user);
        System.out.println(o);
        System.out.println("----------------------");
        Method suibianMethod = aClass.getDeclaredMethod("suibian");
        //忽略安全检查
        suibianMethod.setAccessible(true);
        //执行suibianM方法
        suibianMethod.invoke(user);
    }
}

4f68923b5fa349ba9cd63e728f617d47.png

相关文章
|
9天前
|
JSON 前端开发 JavaScript
java-ajax技术详解!!!
本文介绍了Ajax技术及其工作原理,包括其核心XMLHttpRequest对象的属性和方法。Ajax通过异步通信技术,实现在不重新加载整个页面的情况下更新部分网页内容。文章还详细描述了使用原生JavaScript实现Ajax的基本步骤,以及利用jQuery简化Ajax操作的方法。最后,介绍了JSON作为轻量级数据交换格式在Ajax应用中的使用,包括Java中JSON与对象的相互转换。
19 1
|
17天前
|
SQL 监控 Java
技术前沿:Java连接池技术的最新发展与应用
本文探讨了Java连接池技术的最新发展与应用,包括高性能与低延迟、智能化管理和监控、扩展性与兼容性等方面。同时,结合最佳实践,介绍了如何选择合适的连接池库、合理配置参数、使用监控工具及优化数据库操作,为开发者提供了一份详尽的技术指南。
23 7
|
19天前
|
移动开发 前端开发 Java
过时的Java技术盘点:避免在这些领域浪费时间
【10月更文挑战第14天】 在快速发展的Java生态系统中,新技术层出不穷,而一些旧技术则逐渐被淘汰。对于Java开发者来说,了解哪些技术已经过时是至关重要的,这可以帮助他们避免在这些领域浪费时间,并将精力集中在更有前景的技术上。本文将盘点一些已经或即将被淘汰的Java技术,为开发者提供指导。
48 7
|
15天前
|
SQL Java 数据库连接
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率。本文介绍了连接池的工作原理、优势及实现方法,并提供了HikariCP的示例代码。
30 3
|
15天前
|
SQL 监控 Java
Java连接池技术的最新发展,包括高性能与低延迟、智能化管理与监控、扩展性与兼容性等方面
本文探讨了Java连接池技术的最新发展,包括高性能与低延迟、智能化管理与监控、扩展性与兼容性等方面。同时,结合最佳实践,介绍了如何选择合适的连接池库、合理配置参数、使用监控工具及优化数据库操作,以实现高效稳定的数据库访问。示例代码展示了如何使用HikariCP连接池。
9 2
|
17天前
|
Java 数据库连接 数据库
优化之路:Java连接池技术助力数据库性能飞跃
在Java应用开发中,数据库操作常成为性能瓶颈。频繁的数据库连接建立和断开增加了系统开销,导致性能下降。本文通过问题解答形式,深入探讨Java连接池技术如何通过复用数据库连接,显著减少连接开销,提升系统性能。文章详细介绍了连接池的优势、选择标准、使用方法及优化策略,帮助开发者实现数据库性能的飞跃。
24 4
|
15天前
|
Java 数据库连接 数据库
深入探讨Java连接池技术如何通过复用数据库连接、减少连接建立和断开的开销,从而显著提升系统性能
在Java应用开发中,数据库操作常成为性能瓶颈。本文通过问题解答形式,深入探讨Java连接池技术如何通过复用数据库连接、减少连接建立和断开的开销,从而显著提升系统性能。文章介绍了连接池的优势、选择和使用方法,以及优化配置的技巧。
16 1
|
15天前
|
算法 Java 数据库连接
Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性
本文详细介绍了Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性。连接池通过复用数据库连接,显著提升了应用的性能和稳定性。文章还展示了使用HikariCP连接池的示例代码,帮助读者更好地理解和应用这一技术。
30 1
|
17天前
|
SQL Java 数据库连接
打破瓶颈:利用Java连接池技术提升数据库访问效率
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,避免了频繁的连接建立和断开,显著提升了数据库访问效率。常见的连接池库包括HikariCP、C3P0和DBCP,它们提供了丰富的配置选项和强大的功能,帮助优化应用性能。
36 2
|
19天前
|
前端开发 Java API
过时Java技术的退役:这些技能你不再需要掌握!
【10月更文挑战第22天】 在快速变化的技术领域,一些曾经流行的Java技术已经逐渐被淘汰,不再适用于现代软件开发。了解这些过时的技术对于新手开发者来说尤为重要,以避免浪费时间和精力学习不再被行业所需的技能。本文将探讨一些已经或即将被淘汰的Java技术,帮助你调整学习路径,专注于那些更有价值的技术。
30 1