反射

一、前期概要

1、 什么是反射

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

反射中的反的理解:在使用的之前,提前不知道需要使用什么类型的对象。只是在调用的时候,才知道要调用的对象类型。这种反其道而行的就是反射中反的理解。

程序执行分为编译器和运行期,编译时刻加载一个类就称为静态加载类,运行时刻加载类称为动态加载类,

核心思想 让你在写代码的时候可以更加灵活,降低耦合,提高代码的自适应能力。

反射框架提供如下常用的核心功能:

1.在运行时判断任意对象所属的类;

2.在运行时构造任意一个类的对象;

3.在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法);

4.在运行时调用任意一个对象的方法;

2、反射的主要用途

通用框架,很多框架都是配置化的(比如Spring通过xml配置Bean), 为了保证框架的通用性,可能需要根据不同的配置文件加载不同的对象或者类,调用不同的方法,这个时候就需要反射,运行时动态加载需要加载的对象。

3、缺点

  • 性能不佳 - 由于java反射动态解析类型,因此涉及扫描类路径以查找要加载的类的处理,从而导致性能降低。
  • 安全限制 - Reflection需要运行时权限,这些权限可能不适用于在安全管理器下运行的系统。由于安全管理器,这可能导致应用程序在运行时失败。
  • 安全问题 - 使用反射,我们可以访问我们不应该访问的部分代码,例如,我们可以访问类的私有字段并更改它的值。这可能是严重的安全威胁,并导致您的应用程序出现异常行为。
  • 高维护 - 反射代码很难理解和调试,在编译时也无法找到代码的任何问题,因为这些类可能不可用,使其不太灵活且难以维护。
  1. Class 对象
  2. 类名
  3. 修饰符
  4. 包信息
  5. 父类
  6. 实现的接口
  7. 构造器
  8. 方法
  9. 变量
  10. 注解

二、获得 Class 对象

在运行期间,一个类,只有一个Class对象产生

1、类的静态方法(常用) :

  1. 说明

    获取指定的类完整的路径相关联接口的Class对象。

  2. 方法

    // 掌握 public static Class<?> forName(String className) // 了解 public static Class<?> forName(String className, boolean initialize,ClassLoader loader) 
  3. 区别

    第一个默认进行初始化操作,

    第二个可以指定是否进行初始化操作。当initialize=false 不进行初始化操作,即不会执行静态代码块。

  4. 举个栗子

     Class clazz = Class.forName("com.wener.reflect.Xxx") // 或者 Class clazz = Class.forName("com.wener.reflect.Xxx",initialize,this.getClass().getClassLoader) 

2、使用 .class 静态语法。

  1. 说明

    任何数据类型(包括基本数据类型)都有一个“静态”的class属性

  2. 方法

    Class<?> cls = 类型.class;
    
  3. 举个栗子

    Class<String> cls = String.class;
    System.out.println(cls.toString());
    

3、使用类对象的 getClass()

  1. 说明

    通过对象的实例来返回Class对象

  2. 方法

    Class<?> cls = instance.getClass()
    
  3. 举个栗子

    public class User { } User user = new User(); Class<? extends User> clz = user.getClass(); 

4、总结

  1. 常用的是类的静态方法,
  2. getClass()的话一般在继承的时候用的比较多一点,比如Android里的注解框架
  3. .class 静态语法: 需要导入类的包,依赖太强,不导包就抛编译错误

三、创建实例

1.4、注意

  1. cls.newInstance()方法返回的是一个泛型T,我们要强转成自定义类

  2. cls.newInstance()默认返回的是类的无参数构造对象

  3. 被反射机制加载的类必须有无参数构造方法,否者运行会抛出异常

四、属性操作

1、说明

类的成员变量也是一个对象,它是java.lang.reflect.Field的一个对象,所以我们通过java.lang.reflect.Field里面封装的方法来获取这些信息并且操作这些属性

2、获取单个成员字段

  1. 方法
// 通过字段名,返回一个具体的具有public属性的成员变量(包括父类的) Field getField(String name) // 通过字段名所有已声明的所有成员变量(私有的 默认的 共有的),但不能得到其父类的成员变量 Field getDeclaredField(String name) 
  1. 举个栗子

    public class User { private String name; public String detail; } public static void main(String[] args) { try { Class<?> cls = Class.forName("com.wener.reflect.demo1.User"); /** * 获取类的指定名称公开的属性 */ Field detail = cls.getField("detail"); System.out.println(detail); /** * 获取类的指定名称的的属性(包括私有的属性) */ Field name = cls.getDeclaredField("name"); System.out.println(name); } catch (ClassNotFoundException | NoSuchFieldException e) { e.printStackTrace(); } } 

3、获取所有成员字段

  1. 方法

    // 获取所有的”公有字段” Field[] getFields() // 获取所有字段(私有、受保护、默认、公有) Field[] getDeclaredFields() 
  2. 举个栗子

    public class TestReflectUserField { public static void main(String[] args) { try { Class<?> cls = Class.forName("com.wener.reflect.demo1.User"); Field[] fields = cls.getFields(); for (Field field : fields) { System.out.println("类型: " + field.getType() + "方法名: " + field.getName()); } Field[] declaredFields = cls.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println("类型: " + declaredField.getType() + "方法名: " + declaredField.getName()); } } catch (ClassNotFoundException | NoSuchFieldException | InstantiationException | IllegalAccessException e) { e.printStackTrace(); } } } 

4、字段赋值

  1. 方法

    // 将指定对象参数上的此Field对象表示的字段设置为指定的新值 field.set(Object obj,Object value) 
  2. 参数说明

    • Object obj: 字段所在的类的实例对象
    • Object value : 新值
  3. 注意

    // 如果要给私有变量赋值必须取消权限的访问控制 field.setAccessible(true); 
  4. 举个栗子

     public static void main(String[] args) { try { // 1 实例化Class对象 Class<?> cls = Class.forName("com.wener.reflect.demo1.User"); /** * 获取类的指定名称公有的属性 */ Field detail = cls.getField("detail"); System.out.println(detail); /** * 获取类的所有的属性(包括私有 默认的 公有的) */ Field name = cls.getDeclaredField("name"); // 2.创建对象 Object o = cls.newInstance(); // 3 通过字段的set方法设置 name.set(o, "娇娇"); System.out.println(o.toString()); } catch (ClassNotFoundException | NoSuchFieldException | InstantiationException | IllegalAccessException e) { e.printStackTrace(); } } 

五 方法操作

1、获取单个方法

  1. 方法

    // 方法返回一个特定的方法,其中第一个参数为方法名称,后面的参数为方法的参数对应Class的对象 public Method getMethod(String name, Class<?>... parameterTypes) 
  2. 举个栗子

    public class User { private String name = "木木"; public String detail = "hello"; private int age; private BigDecimal balance; public void increment() { this.age++; System.out.println(age); } public BigDecimal getBalance() { return balance; } public void setBalance(BigDecimal balance) { this.balance = balance; } private void say(int num) { System.out.println(num + "号技师"); } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", detail='" + detail + '\'' + '}'; } } public class TestReflectUser { public static void main(String[] args) { reflectMethod(); } public static void reflectMethod() { try { // 1.实例化class对象 Class<?> cls = Class.forName("com.wener.reflect.demo1.User"); // 2.实例化User对象 Object o = cls.newInstance(); // 3.获取increment方法 Method method = cls.getMethod("increment"); // 有参数无返回值 Method setBalance = cls.getMethod("setBalance", BigDecimal.class); // 有返回值值无参数 Method methodGet = cls.getMethod("getBalance"); // 获取私有的方法 Method say = cls.getDeclaredMethod("say", int.class); } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } } } 

2、获取所有的方法

  1. 方法

    // 返回类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 public Method[] getDeclaredMethods() throws SecurityException 
    // 返回某个类的所有公用(public)方法,包括其继承类的公用方法。 public Method[] getMethods() throws SecurityException 
  2. 举个栗子

    public class TestReflectUser { public static void main(String[] args) { reflectMethod(); } public static void reflectMethod() { try { // 1.实例化class对象 Class<?> cls = Class.forName("com.wener.reflect.demo1.User"); // 2.实例化User对象 Object o = cls.newInstance(); // 获取所有的共有的方法(包括父类的方法) Method[] methods = cls.getMethods(); for (Method method1 : methods) { System.out.println(method1.getName()); } // 获取所有的方法(包括私有的,共有的,默认的) Method[] declaredMethods = cls.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println(declaredMethod.getName()); } } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } } } 

3、调用方法

  1. 方法

    Object invoke(Object obj, Object... args) 
  2. 参数说明

    • obj - 从中调用底层方法的对象,必须是实例化的对象
    • args - 用于方法调用的参数,是个Object数组,因为参数有可能有多个
  3. 返回值

    使用参数 args 在 obj 上指派该对象所表示方法的结果

  4. 举个栗子

     public class User { private String name = "木木"; public String detail = "hello"; private int age; private BigDecimal balance; public void increment() { this.age++; System.out.println(age); } public BigDecimal getBalance() { return balance; } public void setBalance(BigDecimal balance) { this.balance = balance; } private void say(int num) { System.out.println(num + "号技师"); } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", detail='" + detail + '\'' + '}'; } } public class TestReflectUser { public static void main(String[] args) { reflectMethod(); } public static void reflectMethod() { try { // 1.实例化class对象 Class<?> cls = Class.forName("com.wener.reflect.demo1.User"); // 2.实例化User对象 Object o = cls.newInstance(); // 3.获取set方法 Method method = cls.getMethod("increment"); // 4 执行方法 method.invoke(o); // 有参数无返回值 Method setBalance = cls.getMethod("setBalance", BigDecimal.class); Object methodSet = setBalance.invoke(o, new BigDecimal(100.00)); System.out.println(methodSet); // 有返回值值无参数 Method methodGet = cls.getMethod("getBalance"); Object invoke = methodGet.invoke(o); System.out.println(invoke); // 获取私有的方法 Method say = cls.getDeclaredMethod("say", int.class); // 运行时取消访问权限检测机制 say.setAccessible(true); // 执行方法 say.invoke(o, 1); } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } } } 

4、其它API

返回值 方法说明
String getName()获取方法的名称
int getModifiers()获取方法的修饰符
Class<?> getReturnType() Type getGenericReturnType返回方法的返回值类型
Class<?>[] getParameterTypes() Type[] getGenericParameterTypes()返回方法的参数(列表)
Class<?>[] getExceptionTypes() Type[] getGenericExceptionTypes()返回方法的异常信息
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值