views:

1787

answers:

11

I'm coming from a .net background and want to know the accepted way of creating a method that returns a boolean and modifies a string that was passed in via parameter. I understand Strings are immutable in Java so the below snippet will always produce an empty string. I am constrained to return boolean only. Exceptions can't be thrown. If I need to wrap the String class in, say, a StringHolder, what package could I find this in.

public static void DoStuff()
{
    String msg = "";
    if (GetMessage(msg))
    {
       System.out.println(msg);
    }
}
+7  A: 

Use a java.lang.StringBuilder - basically a mutable String. However, it would be safer and more "Java style" to return the modified String.

Michael Borgwardt
+1  A: 

You can't use a string as an output parameter. The way to do it would be to use a StringBuilder class instead or return null for a failure.

Discussion Here

KiwiBastard
+1  A: 

Strings are immutable, so yes, you will need to wrap the String in a StringHolder. You can write your own as simply as

  class StringHolder
  {
     String msg;
  }

  StringHolder sMsg = new StringHolder();
  sMsg.msg = "";
  if (GetMessage(sMsg))
  {
     System.out.println(sMsg.msg);
  }
Paul Tomblin
+1  A: 

A trivial StringHolder would be a String[1].


bool GetMessage(String[] output)
{
     if(output.length < 1)
          throw new Exception("Output must be a String[1]");
     output[0] = "You win!";
}

public static void DoStuff()
{
      String[] msg = new String[1];
      if(GetMessage(msg))
      {
          System.out.println(msg[0]);
      }
}

StringBuilder is probably the canonical way to do it, though.

Stobor
+1  A: 

That is some strange requirement.

Why don't do it the right way ( or at least the java way ) ? Is like trying to get two results from a function. Like subtract( 2 , 2 ) returns 0 and "Good morning sir".

Well anyway, you can try these two options.

1st. StringBuilder Not the best thing to use, since you're not "building" an String.

public static void doStuff(){
    String msg = "";
    StringBuilder sb = new StringBuilder();
    if ( getMessage( sb ) ) {
        System.out.println( sb );
    }
}

public static boolean getMessage( StringBuilder sb ) {
    if ( "".equals( sb.toString() )) {
        sb.delete( 0, sb.length() );
        sb.append("It was empty");
        return true;
    } else {
        return false;
    }
}

2nd StringHolder ( anything holder for that matter ) Not too java style either but do the work. This would be the one used by most java developer I know.

public static void doStuff(){
    String msg = "";
    String [] holder = { msg };
    if ( getMessage( holder ) ){
        System.out.println( holder[0]  );
    }
}
public static boolean getMessage( String [] holder ) {
    if ( "".equals(  holder[0] )) {
        holder[0] = "It was empty";
        return true;
    } else {
        return false;
    }
}

3rd. Option. not what you asked but what I would do. Unfortunately violates the "return boolean" condition.

public void doStuff() { 
    String msg = "";
    String result = getMessage( msg );
    if ( result != msg ) {
        System.out.println( result );
    }
}
public static String getMessage( String msg ) {
    if ( "".equals(msg){
        return "It was empty";
    }
    return msg
}

Choose one.

Note

Although not everyone likes this ( Jon Skeet would say "Is not universally accepted" ) , please take a look at the java coding style I'm using ( methods starting with lower case and braces in the same line ). Sometimes it is important to respect the platform you're coding in. At least that's what I do when I code in C# ( very seldom btw )

OscarRyz
if ( result != msg )? Tsk, tsk!
Alan Moore
I've never claimed that the *naming* conventions aren't pretty much universally accepted. Only the bracing style. That's because it doesn't matter how Sun braces their code - inconsistency between my code and theirs doesn't show up in my code. Naming does, because I use Sun's classes within my code.
Jon Skeet
+2  A: 

A more elegant holder class could be reused for any type of object by utilizing generics:

public class Holder<T> {
  T item;
  public Holder( T item) { set( item);}
  public T get( ) { return item;}
  public void set( T item) { this.item = item;}
}

DoStuff( ) would then look like:

public static void DoStuff( ) {
  String msg = "";
  Holder<String> holder = new Holder<String>( msg);
  if ( getMessage( holder)) { System.out.println( holder.get( ));}
}

and GetMessage( ) would have to call holder.set( a_string).

J. A. Faucett
+4  A: 

First off I probably wouldn’t have these requirements. I’m sure they can be worked around. If you don’t want to do that, I’d recommend returning a container object for your two results:

public class ResultContainer {
    private final boolean success;
    private final String result;
    public ResultContainer(boolean success, String result) {
        this.success = success;
        this.result = result;
    }
    public boolean isSuccess() { return success; }
    public String getResult() { return result; }
}

And in your main code:

ResultContainer resultContainer = GetMessage(message);
if (resultContainer.isSuccess()) {
    System.out.println(resultContainer.getResult());
}

GetMessage() would obviously create a new instance of a ResultContainer and return it, filled with the return values.

(Using Generics for the ResultContaineris left as an exercise for the reader.)

Bombe
+5  A: 

I strongly suggest you do not use StringBuilder, holder or similar. They are hacks. You want to be working with Strings, not builders.

The most obvious approach is to return an object containing the data you want to return. David's [bombe.livejournal.com's] solution covers that, so I wont repeat it. However, I would suggest instead of trying to make it generic ball of data, make it specific. Make it like an object, perhaps it could even grow real behaviour. (And if you really want to go to town, hidea the constructor and give it a static creation method instead.)

A second approach, not so well supported in Java, is to invert the calls. Instead of returning a result, tell a callback the result.

The (more important) usage code would be something like (it looks a bit odd because it isn't specific, nor is it generic):

String userMessage = thing.doStuff(new StuffHandler<String>() {
    public String stuff(boolean success, String message) {
        reutrn message+" was "+(success ? "succesful" :  "unsuccesful");
    }
});

The implementation goes something like:

public interface StuffHandler<T> {
    T stuff(boolean success, String message);
}

    public <T> T doStuff(StuffHandler<T> handler) {
        handler.stuff(isSuccess(), getMessage());
    }

A third approach is simply to break the method in two. That may or may not be feasible.

Tom Hawtin - tackline
Thanks Tom for putting in the effort. StringBuilder worked for me even though, as you say, it is a hack. I needed the simplest and most understood solution for now.
tgeros
+2  A: 

Java's a class-based object oriented language, so its idioms tend to create classes to encapsulate data with the behaviour that surrounds it.

You have a datum - the message - which is obtained in some manner, then if some condition is met, something else is done with it. Making that behaviour a sequence of gets, ifs and other operations in an external controlling object is often a sign that the programmer hasn't understood OOP.

I am constrained to return boolean only. Exceptions can't be thrown.

May I suggest you should be using Fortran or C rather than Java? Procedural languages often have the idiom of mutation and returning a flag, which is well suited to that paradigm (in the absence of automatic memory management, the caller creates and passes in a buffer which is populated; this allows the buffer to be freed safely when the caller is done with it; Java doesn't need to do that, so if you look at say Map.get() it returns a String or null if it fails - no need to manage the memory in the caller). At least, don't bother trying to find the accepted way of doing it in idiomatic Java - with those constraints, it won't be, and whoever is forcing them on you has made a bad choice, which will mean you either have hacks, or end up with verbose code trying to make a non-hacky solution.

Pete Kirkham
Thanks. Your answer made me chuckle.
tgeros
A: 

public boolean doStuff(String msg) { boolean boolTest = false; msg += "Appending something to msg"; int msgLength = msg.length(); if ( msgLength > 80 ) { boolTest = true; return boolTest; } return boolTest; }

Is this kind of what you're looking for? I'm assuming the boolean test is something like testing if the changed message is too long for a display (greater than 80 length) or something similar, and that you don't need to call another method to change the message string inside of doStuff().

Could be completely off-base here, though. :-)

A: 

first u write teh programs and make them from the code like this:

Process p = Runtime.exec("java GetMessage.class " + String);

Tip for you : Runtime.exec should be used everywhere. Then you can make many programs.

Then u wait to get back a status code like this:

if (p.returnCode() = 1) 
  Out.printWord("1 made back"):
else 
  {
  Out.printWord("B Made back");
  }

This way u can use the program else like out side of this program. It is good to make the code resusable. Take it from me, I've been in it for years. This is how the pros make code.