Basil Bourque
Basil Bourque

Reputation: 338386

At runtime, get number of parameters/arguments passed to a method, with or without varargs, in Java

Background:

I am porting code from another language. In that language, trailing arguments are always optional. A method like: doIt( String x , Integer y , UUID z ) may be called with zero, one, two, or three arguments passed.

So that language offers a countArguments function. When translating code from that language to Java, I need a function in Java to substitute every occurrence of countArguments.


With modern Java, is there some way to get a count of parameters or arguments passed to a method?

Method overloading

We have method overloading, each taking a different number of arguments. Example:

Varargs

And we have varargs:

Get count of arguments

➥ How to get the actual number of arguments passed at runtime?

Example:

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.
}

Upvotes: 1

Views: 1021

Answers (3)

Ruslan
Ruslan

Reputation: 6290

Partly it can be done using reflection. Using getEnclosingMethod():

public void doIt(String x, Integer y, BigDecimal... decimals) {
    int count = new Object(){}.getClass().getEnclosingMethod().getParameterCount();  // 3
}

But note, since varargs is an array it will be considered as 1 argument. To get length of this array you need to get value. But you can't get any values using reflection. In this case probably better to use AOP as suggested by @LppEdd

Upvotes: 1

LppEdd
LppEdd

Reputation: 21124

Use AspectJ with an Around or Before advice.
You'll get a JoinPoint, simply call JoinPoint#getArgs();.

final Object[] arguments = joinPoint.getArgs();
final int count = arguments.length;

Voilà.


Old answer.

I am porting code from another language with this feature. I need a way to emulate this "count arguments" function. I need a function in Java to substitute for calls made to such a function

This is not worth it. What you'd have to do to make this totally automatic is

  1. Get Stack trace (Thread.currentThread().getStackTrace())
  2. Get calling method name, one level up, and line number
  3. Parse the class with a bytecode manipulation tool such as ByteBuddy or ASM to find the actual method arguments.
  4. Pass the varargs, when they're present, as input to this method (the method I'm actually describing).
  5. Sum the arguments found via parsing the .class with the varargs length.

No other ways. But this is suicidal

Upvotes: 0

Andreas
Andreas

Reputation: 159086

If you are talking about converting from e.g. JavaScript, where function arguments are undefined, and you only have 1 function with a given name, so you have to check the number of arguments actually passed to figure out which "overload" of the function is called, then your method should be translated to:

doIt(Object... args)

The length of the array is the number of arguments.

Of course, that's how you do it in JavaScript, because the arguments are undefined, and there is no overload.

In Java, you should create actually overloaded methods, with different argument lists, as you showed in the question. In those methods, there is no need to check the number of arguments, because the argument list is fixed.

Having code that checks the number of arguments when the method knows exactly how many there are (because they are fixed), is ridiculous, so the question makes no sense, in a non-varargs Java context.

Final Answer:
If method has varargs, then check the length of the array.
If method doesn't have varargs, then a check of argument count is idiotic, and the code shouldn't do it.

Upvotes: 0

Related Questions