2

我来自.net 背景,想知道创建返回布尔值并修改通过参数传入的字符串的方法的公认方式。我知道字符串在 Java 中是不可变的,所以下面的代码片段总是会产生一个空字符串。我只能返回布尔值。不能抛出异常。如果我需要将 String 类包装在 StringHolder 中,我可以在哪个包中找到它。

public static void DoStuff()
{
    String msg = "";
    if (GetMessage(msg))
    {
       System.out.println(msg);
    }
}
4

11 回答 11

9

使用 java.lang.StringBuilder - 基本上是一个可变字符串。但是,返回修改后的字符串会更安全、更“Java 风格”。

于 2008-12-05T01:28:07.143 回答
6

我强烈建议你不要使用 StringBuilder、holder 或类似的东西。他们是黑客。您想使用字符串,而不是构建器。

最明显的方法是返回一个包含您要返回的数据的对象。David 的 [bombe.livejournal.com's] 解决方案涵盖了这一点,所以我不会重复。但是,我建议不要尝试使其成为通用数据球,而是使其具体化。让它像一个物体,也许它甚至可以成长为真正的行为。(如果你真的想去镇上,隐藏构造函数并给它一个静态创建方法。)

第二种方法,在 Java 中没有得到很好的支持,是反转调用。不是返回结果,而是告诉回调结果。

(更重要的)使用代码将类似于(它看起来有点奇怪,因为它不是特定的,也不是通用的):

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

实现类似于:

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

[...]

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

第三种方法是简单地将方法一分为二。这可能可行,也可能不可行。

于 2008-12-05T12:18:07.907 回答
5

首先,我可能不会有这些要求。我相信他们可以解决。如果您不想这样做,我建议为您的两个结果返回一个容器对象:

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

在您的主要代码中:

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

GetMessage()显然会创建一个 a 的新实例ResultContainer并返回它,并用返回值填充。

(使用泛型ResultContainer作为练习留给读者。)

于 2008-12-05T11:37:35.697 回答
3

通过使用泛型,可以为任何类型的对象重用一个更优雅的持有者类:

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( )然后看起来像:

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

并且GetMessage( )必须打电话给holder.set( a_string).

于 2008-12-05T04:55:50.267 回答
2

Java 是一种基于类的面向对象语言,因此它的习惯用法倾向于创建类来封装数据及其周围的行为。

你有一个数据 - 消息 - 以某种方式获得,然后如果满足某些条件,则对其进行其他操作。使该行为成为外部控制对象中的一系列获取、ifs 和其他操作通常表明程序员还没有理解 OOP。

我只能返回布尔值。不能抛出异常。

我可以建议您使用 Fortran 或 C 而不是 Java 吗?过程语言通常具有变异和返回标志的习惯用法,这非常适合该范例(在没有自动内存管理的情况下,调用者创建并传入一个填充的缓冲区;这允许缓冲区在以下情况下安全释放调用者完成了它;Java 不需要这样做,所以如果您查看说 Map.get() 它返回一个字符串,如果失败则返回 null - 无需管理调用者中的内存)。至少,不要费心试图在惯用的 Java 中找到公认的方法——有了这些限制,它就不会了,而且强迫它们的人做出了错误的选择,这意味着你要么有黑客,或者以试图制作非hacky解决方案的冗长代码结束。

于 2008-12-05T12:43:27.637 回答
1

您不能使用字符串作为输出参数。这样做的方法是使用 StringBuilder 类,或者返回 null 以表示失败。

在这里讨论

于 2008-12-05T01:28:44.287 回答
1

字符串是不可变的,所以是的,您需要将字符串包装在 StringHolder 中。你可以写你自己的,就像

  class StringHolder
  {
     String msg;
  }

  StringHolder sMsg = new StringHolder();
  sMsg.msg = "";
  if (GetMessage(sMsg))
  {
     System.out.println(sMsg.msg);
  }
于 2008-12-05T01:29:38.577 回答
1

一个平凡的 StringHolder 将是一个 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 可能是执行此操作的规范方法。

于 2008-12-05T02:20:11.267 回答
1

这是一个奇怪的要求。

为什么不以正确的方式(或至少以 java 方式)?就像试图从一个函数中获得两个结果。就像减法( 2 , 2 )返回 0 和“早上好先生”一样。

无论如何,您可以尝试这两个选项。

第一个。StringBuilder不是最好用的东西,因为你不是在“构建”一个字符串。

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

第二个StringHolder(任何持有者)也不是太 java 风格,但做的工作。这将是我认识的大多数 java 开发人员使用的。

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

第三。选项。不是你问什么,而是我会做什么。不幸的是违反了“返回布尔”条件。

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
}

选一个。

笔记

虽然不是每个人都喜欢这个(Jon Skeet 会说“不被普遍接受”),但请看一下我正在使用的 java 编码风格(方法以小写开头,大括号在同一行中)。有时尊重你正在编码的平台很重要。至少我在 C# 中编码时就是这样做的(顺便说一句很少)

于 2008-12-05T03:00:07.863 回答
0

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

这就是你要找的吗?我假设布尔测试类似于测试更改的消息是否太长而无法显示(大于 80 长度)或类似的东西,并且您不需要调用其他方法来更改 doStuff 内部的消息字符串()。

不过,这里可能完全不在基地。:-)

于 2008-12-20T01:43:22.513 回答
0

首先,你编写程序并用这样的代码制作它们:

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

给你的提示: Runtime.exec 应该在任何地方使用。然后你可以制作很多程序。

然后你等待取回这样的状态码:

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

这样你就可以在这个程序之外使用其他程序。使代码可重用是件好事。把它从我这里拿走,我已经参与了很多年。这就是专业人士编写代码的方式。

于 2008-12-20T02:18:28.420 回答