【问题标题】:Get the number of variable arguments of a method in java获取java中方法的变量参数个数
【发布时间】:2017-01-31 14:52:27
【问题描述】:

当心以下可能是愚蠢的问题:

我有一个方法使用 String.format() 方法来格式化一些文本。目前,它接收两个参数,所以我有两个“%s”参数来创建我想要的任何文本。

但是有人可能想在我的方法中使用 3 个参数,或者 4 个,或者 100 个。如何将传递给 String.format() 方法的参数的长度作为可变参数,以便在有 3 个参数传递给它的情况下,将有 3 个“%s”而不是当前的 2 个;或 4,或 100。

如何获取传递给 String.format() 方法的参数数量,以便其中的文本根据需要自动添加“%s”?因为参数只是作为常规参数传递,而不是作为数组或类似的东西传递。如何获取参数数组的长度?

PS。这很重要 - 我不是在谈论获取(字符串...参数) - 没有这样的事情 - 当有人调用您的方法时,它使用实际参数,“字符串...参数”不可用于抓取和获取它的长度。

我意识到这是一个糟糕的问题,因为我面前没有代码可以进一步解释,但这一直困扰着我很长一段时间 - 你如何获得传递给方法的参数数量?

对于这样的事情:

String.format(SomeObject.SomeString, param1, param2,...,param 100)

编辑:SomeObject.SomeString 声明如下:

String SomeString = "Blah blah %s blah blah blah %s";

所以它有两个被硬编码的参数。

当有人使用它时,您如何自定义SomeObject.SomeString 以便它“知道”有多少参数已传递给 String.format() 方法(以便 SomeObject.SomeString 知道要动态添加多少 %s) ?

【问题讨论】:

  • 知道传递给String.format 的参数数量有什么用处?如果您的格式字符串的参数数量不正确,您将获得MissingFormatArgumentException;如果你有太多,你无论如何都不会看到额外的。您唯一能做的就是将args.length 作为显式参数传递给String.format 调用。

标签: java variadic-functions string.format


【解决方案1】:

因为参数只是作为常规参数传递,而不是作为数组传递。

不,值作为数组传递,因此您可以编写

public String myVarags(String... args) {
    String s = "";
    for(int i = 0;i < args.length; i++)
        s += "%s ";
    return String.format(s, args);
}

它将为每个参数生成一个String 和一个%s,然后使用给定的值格式化字符串。这也是一种非常愚蠢和无用的方法。

可变参数符号只是语法糖,它在运行时是一个数组。

【讨论】:

  • 这正是我想说的,它不会发生。当有人使用它时,它只是说String.format(SomeObject.SomeString, param1) 或者它可以说String.format(SomeObject.SomeString, param1, param2),实际数组永远不可用,因此您可以获得它的长度 - 只有常规参数。您如何获得方法的参数数量,保存这些参数的数组的“名称”是什么?请记住,我们只是使用方法,而不是声明它或其他任何东西。
  • 我不确定这如何回答这个问题。他特别说“PS。这很重要 - 我不是在谈论获取(字符串...参数) - 没有这样的事情 - 当有人调用你的方法时,它使用实际参数”。他想根据传递给String.format 的其他参数修改SomeObject.SomeString
  • 完全正确。我想获取传递给String.format()方法的参数个数比如修改SomeObject.SomeString,并使其适应传递给String.format()方法的参数个数。
  • @RobertRuxandrescu 有什么用?这听起来不像是使用String.format() 的正常方式。
  • @Adam 不,不会。然而,这看起来像是一个经典的 XY 问题。我只能想象他真正想要做什么,以及他到底是如何认为这将是一个很好的解决方案。
【解决方案2】:

听起来您想访问传递给不同方法的参数数量,该方法将可变参数作为参数(String.format() 方法)。

如果您无法更改方法内部的代码,则无法知道将多少参数传递到方法中。而String 参数肯定不知道传入了多少参数。它是一个完全独立的对象。

你唯一能做的就是创建一个包装方法。您可以采用相同的可变参数,然后将它们传递给 String.format() 方法,进行任何您想做的更改。

那么任何调用String.format()的代码都需要调用你的包装方法。

例子:

public String StringFormatWrapper(String...args) {
    //perform actions on the args
    if (args.length > 1) 
        args[1] = "Hello World";

    //call the String.format() method
    return String.format(args)
}

如果您无法访问调用 String.format() 的内容,那么您想要做的就是不可能的。

【讨论】:

  • 我的预感正朝着“不可能”的方向发展。
  • @RobertRuxandrescu 我仍然站在“你不知道自己在做什么”的一边。如果你能清楚地解释自己就好了。
  • 那只是因为我面前没有代码。我看了一会儿,我只是在这里复制我能记住的任何东西。主要思想是声明了一个 String 并使用要创建的 String.format() 方法,其第一个参数是为 2 个参数硬编码的 SomeObject.SomeString,然后是 @ 中其余参数的可变参数987654328@ 方法。所以最终的字符串将是硬编码字符串作为第一个参数和硬编码字符串使用的所有其他后续参数的结果。
【解决方案3】:

我认为您的要求是不可能的,因为您的 SomeObject.SomeString 只是一个论点,它对其他论点一无所知。您可以做的是将您的参数转换为可变参数数组并在SomeObject 上创建一个方法以生成正确的字符串:

String[] args = ...
String.format(SomeObject.createSomeString(args.length), args);

【讨论】:

  • 是的,这是一个非常奇怪的情况,我也想知道这是否可能。我的问题是 - 有没有办法“计算”某人传递给方法的参数数量?例如,假设您有方法 A(param1, param2, param3) - Java 中有什么方法可以获取该方法调用了三个参数的信息吗?方法在任何地方都“存储”了多少参数?
  • @RobertRuxandrescu 是的,您可以在可变参数上调用 .length。它只是一个数组。
  • 是的,但是那个数组的名字是什么?对于方法A(param1, param2, param3),包含参数的参数数组的名称是什么?
  • 是的,所有这些都存储在 Method 对象上。您可以通过多种方式获取Method 对象的句柄,请查看反射文档:docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html。你可以做Method m = ... ; m.getParameterTypes().length();
  • 当然,如果该方法采用可变参数参数,它将计为一个参数,因为它是一个数组。进行反思不会为您提供比您已经知道的更多的信息。
【解决方案4】:

我想了很多,我想出了一个解决方案,这个解决方案是一个非常简单的解决方案。其实我5分钟就写好了。

事情是这样的:

主类:

public class Main {

    SomeObject someObject = new SomeObject();

    public static void main(String[] args) {

        Main main = new Main();
        main.formatString("a","b","c","D","efesfs");

    }

    public void formatString(String...varargs){
        String formattedString = String.format(someObject.returnFormattedString(varargs.length), varargs);
        System.out.println(formattedString);
    }
}

某些对象类:

public class SomeObject {

    public String someString = "Blah blah blah";

    public String returnFormattedString(int numberOfArguments){
        for (int i = 0; i<numberOfArguments; i++){
            someString += "%s";
        }

        return someString;
    }
}

换句话说,我将所有这些东西包装在一个方法中,该方法可以访问作为参数传递的参数数量,并且我会将它们的数量(作为 varargs.length)传递给 SomeObject 中的方法将长度作为 int 变量并使用 for 循环的类将根据需要添加尽可能多的“%s”。

它就像一个魅力。

我知道有些人批评我说这不是“正确的”,“这不是正确的问题”等等,但至少它有一个简单的解决方案,就像我认为它应该有的那样,而不是“不可能”,你不需要在运行时分解字节码或任何疯狂的事情。

【讨论】:

  • “您的”解决方案正是这里所有其他答案中向您提出的建议。
  • 是和不是。从技术上讲,你是对的,这与我得到的解决方案相同。但我最初的问题是,我是否可以从方法的实际调用中确定参数的数量,而无需像你和我那样编写新的并调用那个。所以,是的。
猜你喜欢
  • 2020-03-21
  • 2011-01-20
  • 1970-01-01
  • 2014-07-29
  • 1970-01-01
  • 1970-01-01
  • 2021-10-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多