用Java如何从另一个类获取命令行参数

14
假设我有一个 Java 包...
它有一个主类和主方法,以及一堆其他类......
我的问题是,是否可以从这些不是主类但在同一个包中的其他类中获取传递给主方法的 args 参数...

请注意:此处有一个带有额外信息的重复问题:https://dev59.com/KFgR5IYBdhLWcg3wJqi7 - Brad Parks
5个回答

11
不,从可移携性来看不行,可能基于JVM实现有一些巧妙的方法,但我从未见过,即使存在这种方法,依赖它也是个非常糟糕的想法。
如果你想在其他地方使用这些值,`main`函数需要以某种方式使它们可用。
一个简单的方法(不一定是最好的方法)是将字符串作为`main`函数的第一件事存储起来,并提供一种获取它们的方式: Scratch2.java:
public class Scratch2 {
    // Arguments and accessor for them.

    private static String[] savedArgs;
    public static String[] getArgs() {
        return savedArgs;
    }

    public static void main(String[] args) {
        // Save them away for later.

        savedArgs = args;

        // Test that other classes can get them.

        CmdLineArgs cla = new CmdLineArgs();
        cla.printArgs();
    }
}

CmdLineArgs.java:

public class CmdLineArgs {
    public void printArgs() {
        String[] args = Scratch2.getArgs();
        System.out.println ("Arg count is [" + args.length + "]");
        for (int i = 0; i < args.length; i++) {
            System.out.println ("Arg[" + i + "] is [" + args[i] + "]");
        }
    }
}

当使用参数 a b c 运行时,这会输出:

Arg count is [3]
Arg[0] is [a]
Arg[1] is [b]
Arg[2] is [c]

为什么调用getArgs()方法不需要Scratch2类的对象? - Kasun Siyambalapitiya
查找错误时出现了一个错误,提示“通过返回数组来暴露内部表示”。我克隆了该数组,但仍然出现相同的错误。 - Kasun Siyambalapitiya
如果mylib.jar被main.jar(包含主类)使用,并且mylib.jar由另一个不想依赖于common.jar的组开发(可能会被main.jar和mylib.jar用于包含由main.jar中的Main类设置的args的Util类),那该怎么办呢?即这个解决方案不能泛化。 - yerlilbilgin
@yerlilbilgin:你也可以问“如果你的编码标准禁止在主函数之外访问参数怎么办?”或者“如果你的同事都不接受这样的变化,你该怎么办?”我的回答解决了获取参数的技术方面,这也是问题所问的。如果你想解决技术上的任意限制问题,可能应该单独提出一个问题,并且可能需要在与编码本身无关的工作场所关系网站上提问。 - paxdiablo

9

在一些JRE实现中,system-properties提供了system-property "sun.java.command"来获取启动程序时使用的程序名称和参数,例如:"myjar.jar param1 param2 ..."。

虽然该值甚至不属于文档中提到的属性集之一,但它存在于Oracle-JRE v1.8和OpenJRE v1.8(经过测试)。

我找不到任何文档说明是否默认支持此值(最好能找到的是System#getProperties()文档中的列表)。 欢迎任何关于此事的澄清。请谨慎处理!


@yerlilbilgin,很高兴你喜欢我的回答:D。然而,这种解决问题的方法相当不安全,因为它没有标准化(据我所知),在大多数情况下可能有效,但不一定。如果你更愿意保险起见,我的建议是使用@paxdiablos的答案。不过,这是一个不错的技巧:) - user4668606
不,我仍然更喜欢你的答案。有些情况下,我需要读取命令行参数,但它在一个被主库使用的库中。我不想创建一个“通用实用类”,让两个库都使用并在那里设置参数。所以只要我不太多地涉及多操作系统(当前项目仅限于Windows),我还是更喜欢你的答案。 - yerlilbilgin

6

1
如paxdiablo所说,您的主类将需要存储这些参数,然后分发或使需要这些参数的人可以使用。通常一个好的想法是让另一个类来解析这些参数,并提供这个类的对象而不是原始命令行给需要它的人。

0

我在这方面有点新手,但你应该能够将 string[] args 存储到一个私有实例变量中,然后为其创建一个访问器方法。 例如,

public class test {
private String[] myArgs = new String[10];
public static void main(String[] args) {
myArgs = args;
}
public String[] getArgs() {
return myArgs;
}
}

不确定它是否有效,但这是想法。


唯一可移植的方法是控制主类,并能够设置运行时使用它。 - Dragas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接