在运行时,获取在Java中传递给方法的参数/参数的数量(带或不带varargs)

在运行时,获取在Java中传递给方法的参数/参数的数量(带或不带varargs),java,parameters,arguments,optional-parameters,optional-arguments,Java,Parameters,Arguments,Optional Parameters,Optional Arguments,背景: 我正在移植另一种语言的代码。在该语言中,尾随参数始终是可选的。像:doIt(字符串x、整数y、UUID z)这样的方法可以通过传递零、一、二或三个参数来调用 因此,该语言提供了一个countArguments函数。当将代码从该语言转换为Java时,我需要一个Java函数来替换每次出现的countArguments 对于现代Java,是否有某种方法可以获得传递给方法的参数或参数的计数 函数重载 我们有,每个人都有不同数量的论点。例如: doIt(字符串x) doIt(字符串x,整数y)

背景:

我正在移植另一种语言的代码。在该语言中,尾随参数始终是可选的。像:
doIt(字符串x、整数y、UUID z)
这样的方法可以通过传递零、一、二或三个参数来调用

因此,该语言提供了一个
countArguments
函数。当将代码从该语言转换为Java时,我需要一个Java函数来替换每次出现的
countArguments


对于现代Java,是否有某种方法可以获得传递给方法的参数或参数的计数

函数重载 我们有,每个人都有不同数量的论点。例如:

  • doIt(字符串x)
  • doIt(字符串x,整数y)
  • doIt(字符串x,整数y,UUID z)
可变参数 我们有:

  • doIt(字符串x、整数y、UUID z、BigDecimal…)
获取参数的计数 ➥ 如何获取运行时传递的实际参数数

例如:

public void doIt( String x ) {
    int countArguments = … ;  // Returns `1`. 
}

public void doIt( String x , Integer y ) {
    int countArguments = … ;  // Returns `2`.
}

public void doIt( String x , Integer y , UUID z , BigDecimal... ) {
    int countArguments = … ;  // Returns `3`, `4`, `5`, `6`, `7`, or more.
}

如果您谈论的是从JavaScript转换,例如,函数参数未定义,并且您只有一个具有给定名称的函数,因此您必须检查实际传递的参数数量,以确定调用了函数的哪个“重载”,那么您的方法应转换为:

doIt(Object... args)
数组的长度是参数的数量

当然,在JavaScript中就是这样做的,因为参数是未定义的,并且没有重载

在Java中,您应该创建具有不同参数列表的实际重载方法,如您在问题中所示。在这些方法中,不需要检查参数的数量,因为参数列表是固定的

在方法确切知道参数的数量时(因为它们是固定的),使用代码检查参数的数量是荒谬的,因此在非varargs Java上下文中,这个问题毫无意义

最终答案:
如果方法有varargs,则检查数组的长度。

如果方法没有varargs,那么检查参数计数是愚蠢的,代码不应该这样做。

使用
AspectJ
,并在
周围或
前面添加
建议。
您将得到一个
JoinPoint
,只需调用
JoinPoint#getArgs()


旧答案。

我正在用这个特性移植另一种语言的代码。我需要一个 模拟此“计数参数”函数的方法。我需要一个函数 Java来替代对此类函数的调用

这不值得。你要做的是让它完全自动化

  • 获取堆栈跟踪(
    Thread.currentThread().getStackTrace()
  • 获取调用方法名称、一级和行号
  • 使用字节码操作工具(如
    ByteBuddy
    ASM
    )解析类,以查找实际的方法参数
  • 当varargs存在时,将其作为输入传递给此方法(我实际上正在描述的方法)
  • 使用varargs长度对通过解析.class找到的参数求和

  • 没有别的办法。但这是自杀性的

    部分可以通过反射来实现。使用:


    但请注意,由于varargs是一个数组,因此它将被视为1个参数。要获取此数组的长度,需要获取值。但使用反射无法获得任何值。在这种情况下,按照@LppEdd

    Mmmh的建议使用可能更好,我不完全确定我是否理解了这个问题。你想把这张支票放在哪里?我的意思是,它不像Javascript那样,基本上你可以输入你想要的东西。这是Java 11独有的吗?@BasilBourque每个方法都有一个定义良好的参数数量。对于varargs one,它只是一个数组,因此请查找length属性。例如,计数将为3+varargs.length如果您正在翻译代码,那么您已经解析了代码,并且知道您使用的是什么方法。如果该方法没有varargs,请用声明的参数数替换
    countArguments
    。如果方法有一个varargs,那么用公式
    (N+VARARG.length)
    替换
    countArguments
    ,其中N是声明参数的数量减去1,而
    VARARG
    是varargs参数的名称。我想他想要的是完全自动化的,而不必显式传递参数
    final Object[] arguments = joinPoint.getArgs();
    final int count = arguments.length;
    
    public void doIt(String x, Integer y, BigDecimal... decimals) {
        int count = new Object(){}.getClass().getEnclosingMethod().getParameterCount();  // 3
    }