Is there an easier alternative to mimicking the sp

2019-04-29 03:54发布

问题:

I've found it's available in Ruby, but I recognize it from what I've done in Python; the "splat" operator. Long story short, I'm wondering if there's a simpler way to accomplish what I currently am, mimicking what the "splat" operator does.

I made a central method that the rest can call because I realized I have several very similar ones, and they were all doing the same except for a few minor things. Here's the method signature:

private String callScript(String scriptLocation, String... extraArgs) throws Exception {

I want to require at least one argument (the scriptLocation), and then allow any number of extra arguments. What I end up doing with this is creating a ProcessBuilder. My desire is to do something like this:

ProcessBuilder pb = new ProcessBuilder("something", scriptLocation, /* extraArgs */);

But of course, the ProcessBuilder constructor only accepts things like:

  • List<String>
  • String[]
  • String...

So my approach obviously wouldn't work.

My current workaround, which works fine as far as I know, is:

List<String> finalArgs = new ArrayList<String>();
finalArgs.add("something");
finalArgs.add(scriptLocation);
finalArgs.addAll(Arrays.asList(extraArgs));
ProcessBuilder pb = new ProcessBuilder(finalArgs);

(yes, I understand I don't have to use List and could just make a String[])

(and yes, I understand I could loop through extraArgs and add them to finalArgs individually, instead of having to use addAll and Arrays.asList())

(and yes, I know I can make a function that effectively accomplishes my workaround by returning certain arguments combined with variable arguments)

So I guess outside of these last three statements, is there anything that can achieve this?

回答1:

It depends on your definition of simpler, but you could write a class utilizing the Builder pattern:

public class MyProcessBuilder {
    List<String> args;

    MyProcessBuilder( String text, String location ) {
        args = new ArrayList<String>();
        args.add( text );
        args.add( location );
    }

    MyProcessBuilder arg( String arg ) {
        args.add( arg );
        return this;
    }

    MyProcessBuilder args( String... args ) {
        this.args.addAll( Arrays.asList( args ) );
        return this;
    }

    public ProcessBuilder go() {
        return new ProcessBuilder( args );
    }

    public static MyProcessBuilder callScript( String location ) {
        return new MyProcessBuilder( "something", location );
    }

    public static void main( String[] args ) {
        callScript( "/tmp/bla" ).arg( "something else" ).arg( "more" ).go();
    }
}


回答2:

Write a utility splat() and publish it?:)

This might look more uniform:

List<String> finalArgs = new ArrayList<String>();

finalArgs.addAll(Arrays.asList( "something" ));
finalArgs.addAll(Arrays.asList( scriptLocation ));
finalArgs.addAll(Arrays.asList( extraArgs )));

ProcessBuilder pb = new ProcessBuilder(finalArgs);


回答3:

When you call

ProcessBuilder pb = new ProcessBuilder("something", scriptLocation, /* extraArgs */);

If you have

public ProcessBuilder(String something, String scriptLocation, String... extraArgs);

Then you can call this method in many ways:

ProcessBuilder pb = new ProcessBuilder("something", "/tmp/script.sh");

ProcessBuilder pb = new ProcessBuilder("something", "/tmp/script.sh","someArg");

ProcessBuilder pb = new ProcessBuilder("something", "/tmp/script.sh","someArg","someArg2");



ProcessBuilder pb = new ProcessBuilder("something", "/tmp/script.sh");

ProcessBuilder pb = new ProcessBuilder("something", "/tmp/script.sh",new String[]{});

ProcessBuilder pb = new ProcessBuilder("something", "/tmp/script.sh",new String[]{"someArg"});

ProcessBuilder pb = new ProcessBuilder("something", "/tmp/script.sh",new String[]{"someArg","someArg2"});



ArrayList<String> someStringList = new ArrayList<String>();
someStringList .add("SomeArg");
someStringList .add("SomeArg2");
String[] extraArgs = someStringList .toArray(new String[someStringList .size()]);
ProcessBuilder pb = new ProcessBuilder("something", "/tmp/script.sh",extraArgs);