JAVA反射调用方法

简介: JAVA反射调用方法
一、利用反射创建对象

创建对象:

1、使用 Class 对象的 newInstance()方法创建该 Class 对象的实例,此时该 Class 对象必须要有无参数的构造方法。

2、使用 Class 对象获取指定的 Constructor 对象,再调用 Constructor 的 newInstance()方法创建对象类的实例,此时可以选择使用某个构造方法。如果这个构造方法被私有化起来,那么必须先申请访问,将可以访问设置为 true;

示例代码(最简单的)

class User {  
  /*private User(){//将默认的构造方法私有化的话就不可以再创建对象,两种方法都是这样    
  }*/  
 
  public String toString() {
    return "User对象创建成功!";
  }
}
 
public class ReflectDemo {
  public static void main(String[] args) throws Exception {
    // 传统方式创建对象
    System.out.println(new User());
    // 使用反射的方式
    Class<User> c = User.class;
    User u = c.newInstance();// (直接newInstance的话必须保证默认的构造方法正常存在,也就是没有被私有化!这是前提条件)
    System.out.println(u);
  }
}

结果截图如下:

复杂点的,更强大的第二种:使用指定构造方法来创建对象:获取该类的 Class 对象。

利用 Class 对象的 getConstructor()方法来获取指定的构造方法。

调用 Constructor 的 newInstance()方法创建对象。

AccessibleObject 对象的 setAccessible(boolean flag)方法,当 flag 为 true 的时候,就会忽略访问

权限(可访问私有的成员)。

其子类有 Field, Method, Constructor;

若要访问对象 private 的成员?在调用之前使用 setAccessible(true),参考http://www.wityx.com/post/1202_1_1.html

Xxx x = getDeclaredXxxx();//才能得到私有的类字段.

总结步骤:
  1. 获取该类的 Class 对象。
  2. 利用 Class 对象的 getConstructor()方法来获取指定的构造方法。
  3. 申请访问(设置为可访问)
  4. 调用 Constructor(构造方法)的 newInstance()方法创建对象。

示例代码:

import java.lang.reflect.Constructor;
//http://www.wityx.com/post/256_1_1.html
class Per {
  private String name;
  private int age;
 
  private Per() {
  }
 
  private Per(String name) {
  }
 
  public String toString() {
    return "对象!!!";
  }
}
 
public class ReflectDemo1 {
  public static void main(String[] args) throws Exception {
    Class<Per> c = Per.class;
    // System.out.println(c.newInstance());;//证明利用无参的可以
    // 先获得需要被调用的构造器(private 修饰的构造方法)
    Constructor<Per> con = c.getDeclaredConstructor();// 调用默认的,什么都不要写
    System.out.println(con);    
    /**
     * 现在只需要执行这个构造器,T newInstance(Object... initargs) 使用此 Constructor
     * 对象表示的构造方法来创建该构造方法的声明 类的新实例,并用指定的初始化参数初始化该实例。
     */
    // 私有的成员是受保护的,不能直接访问(无法直接访问的构造器不一定是私有的),若要访问私有的成员,得先申请一下
    //http://www.wityx.com/post/935_1_1.html
    con.setAccessible(true);// 允许访问
    Per p = con.newInstance();// 成功,通过私有的受保护的构造方法创建了对象
    System.out.println("无参构造方法" + p);
    con = c.getDeclaredConstructor(String.class);//获取指定的构造方法
    System.out.println(con);
    con.setAccessible(true);// 允许访问
    p = con.newInstance("duixiang");// 成功,通过私有的受保护的构造方法创建了对象
    System.out.println("String构造方法" + p);
  }
}

备注:对于此时的话,单例模式就不再安全了!反射可破之!!

结果截图:

总结:

(1)getDeclaredConstructor()当没有参数时,它就是默认获取无参构造器,也可以获取指定的构造方法,如con = c.getDeclaredConstructor(String.class);//获取指定的构造方法

(2)T newInstance(Object… initargs) 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。

(3)私有的成员是受保护的,不能直接访问(无法直接访问的构造器不一定是私有的),若要访问私有的成员,得先申请一下,如con.setAccessible(true);// 允许访问

二、使用反射调用方法

每个 Method 的对象对应一个具体的底层方法。获得 Method 对象后,程序可以使用 Method 里面的 invoke 方法来执行该底层方法。

Object invoke(Object obj,Object … args):obj 表示调用底层方法的对象,后面的 args 表示传递

的实际参数。

如果底层方法是静态的,那么可以忽略指定的 obj 参数。该参数可以为 null,想想为什么?

如果底层方法所需的形参个数为 0,则所提供的 args 数组长度可以为 0 或 null。

不写,null,或 new Object[]{}

若底层方法返回的是数组类型,invoke 方法返回的不是底层方法的值,而是底层方法的返回类

型;

示例代码:

import java.lang.reflect.Method;
//http://www.wityx.com/post/640_1_1.html
class Dept {
  public String show(String name) {// 用反射的方法来调用正常的方法
    return name + ",您好!";
  }
 
  private void privateshow() {// 用反射来实现对私有化方法的调用
    System.out.println("私有的方法:privateshow");
  }
 
  public static void staticshow() {
    System.out.println("静态的方法:staticshow");
  }
}
 
public class InvokeDemo {
  public static void main(String[] args) throws Exception {
    //传统方式: 
    String name = new Dept().show("刘昭"); 
    System.out.println("传统方式:" + name);
    // 想要通过反射来调用Dept中的方法
    Class<Dept> c = Dept.class;
    Method m = c.getMethod("show", String.class);
    Object o = m.invoke(c.newInstance(), "刘昭");
    System.out.println("反射调用的方式:" + o);
    // 私有化的方法
    // 参考http://www.wityx.com/post/1205_1_1.html
    m = c.getDeclaredMethod("privateshow");// 无参方法
    m.setAccessible(true);
    o = m.invoke(c.newInstance());
    // 静态方法的调用
    m = c.getMethod("staticshow");
    m.invoke(null);// staticshow为静态方法,不需创建对象,所以这里会是 null
  }
}

结果截图:

注:Method getMethod(String name, Class<?>… parameterTypes)返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。name - 方法名;parameterTypes - 参数列表。

相关文章
|
10天前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
50 4
|
21天前
|
Java API
Java 对象释放与 finalize 方法
关于 Java 对象释放的疑惑解答,以及 finalize 方法的相关知识。
42 17
|
14天前
|
Java 测试技术 Maven
Java一分钟之-PowerMock:静态方法与私有方法测试
通过本文的详细介绍,您可以使用PowerMock轻松地测试Java代码中的静态方法和私有方法。PowerMock通过扩展Mockito,提供了强大的功能,帮助开发者在复杂的测试场景中保持高效和准确的单元测试。希望本文对您的Java单元测试有所帮助。
27 2
|
22天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
16 3
|
24天前
|
Java 大数据 API
别死脑筋,赶紧学起来!Java之Steam() API 常用方法使用,让开发简单起来!
分享Java Stream API的常用方法,让开发更简单。涵盖filter、map、sorted等操作,提高代码效率与可读性。关注公众号,了解更多技术内容。
|
22天前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
15 2
|
22天前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
15 1
|
22天前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
28 1
|
22天前
|
Java
在Java多线程编程中,`wait()`和`notify()`方法的相遇如同一场奇妙的邂逅
在Java多线程编程中,`wait()`和`notify()`方法的相遇如同一场奇妙的邂逅。它们用于线程间通信,使线程能够协作完成任务。通过这些方法,生产者和消费者线程可以高效地管理共享资源,确保程序的有序运行。正确使用这些方法需要遵循同步规则,避免虚假唤醒等问题。示例代码展示了如何在生产者-消费者模型中使用`wait()`和`notify()`。
23 1
|
22天前
|
安全 Java 开发者
Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用
本文深入解析了Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用。通过示例代码展示了如何正确使用这些方法,并分享了最佳实践,帮助开发者避免常见陷阱,提高多线程程序的稳定性和效率。
33 1