Строковые параметры Java - PullRequest
       42

Строковые параметры Java

2 голосов
/ 05 декабря 2008

Я пришел из .net фона и хочу знать, как можно создать метод, который возвращает логическое значение и изменяет строку, переданную через параметр. Я понимаю, что строки являются неизменяемыми в Java, поэтому приведенный ниже фрагмент всегда создает пустую строку. Я вынужден возвращать только логическое значение. Исключения не могут быть выброшены. Если мне нужно обернуть класс String, скажем, в StringHolder, в каком пакете я могу найти это.

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

Ответы [ 11 ]

9 голосов
/ 05 декабря 2008

Используйте java.lang.StringBuilder - в основном изменяемая строка. Однако было бы безопаснее и больше использовать «стиль Java» для возврата измененной строки.

6 голосов
/ 05 декабря 2008

Я настоятельно рекомендую вам не использовать StringBuilder, держатель или аналогичные. Они хаки. Вы хотите работать со строками, а не строителями.

Наиболее очевидный подход - вернуть объект, содержащий данные, которые вы хотите вернуть. Решение Дэвида [bombe.livejournal.com] покрывает это, поэтому я не буду повторяться. Тем не менее, я бы предложил вместо того, чтобы пытаться сделать это общим шаром данных, сделать его конкретным. Сделайте это как объект, возможно это могло бы даже вырастить реальное поведение. (И если вы действительно хотите поехать в город, спрячьте конструктор и вместо него назначьте статический метод создания.)

Второй подход, не очень хорошо поддерживаемый в 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());
    }

Третий подход - просто разбить метод на две части. Это может или не может быть осуществимо.

5 голосов
/ 05 декабря 2008

Во-первых, у меня, вероятно, не было бы этих требований. Я уверен, что их можно обойти. Если вы не хотите этого делать, я бы рекомендовал вернуть объект контейнера для ваших двух результатов:

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(), очевидно, создаст новый экземпляр ResultContainer и вернет его, заполненный возвращаемыми значениями.

(Использование Обобщения для ResultContainer оставлено в качестве упражнения для читателя.)

3 голосов
/ 05 декабря 2008

Более элегантный класс держателей может быть повторно использован для любого типа объекта с использованием обобщений:

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).

2 голосов
/ 05 декабря 2008

Java является объектно-ориентированным языком на основе классов, поэтому его идиомы, как правило, создают классы для инкапсуляции данных с поведением, которое их окружает.

У вас есть датум - сообщение, которое получается каким-то образом, а затем, если выполняется какое-то условие, с ним что-то еще делается. Создание такого поведения в последовательности get, ifs и других операций во внешнем управляющем объекте часто является признаком того, что программист не понимает ООП.

Я вынужден возвращать только логическое значение. Исключения не могут быть выброшены.

Могу ли я предложить вам использовать Fortran или C, а не Java? Процедурные языки часто имеют идиому мутации и возврата флага, который хорошо подходит для этой парадигмы (при отсутствии автоматического управления памятью вызывающая сторона создает и передает в заполненный буфер; это позволяет буферу безопасно освобождаться, когда вызывающая сторона покончила с этим, Java не должна этого делать, поэтому, если вы посмотрите, скажем, Map.get (), он возвращает String или null в случае неудачи - нет необходимости управлять памятью в вызывающей стороне). По крайней мере, не пытайтесь найти приемлемый способ сделать это в идиоматической Java - с этими ограничениями этого не произойдет, и тот, кто навязывает их вам, сделал неправильный выбор, что будет означать, что у вас либо есть хаки или в конечном итоге с подробным кодом, пытающимся сделать нехакерское решение.

1 голос
/ 05 декабря 2008

Это странное требование.

Почему бы не сделать это правильным образом (или, по крайней мере, способом 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;
    }
}

2nd 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
}

Выберите один.

Примечание

Хотя не всем это нравится (Джон Скит сказал бы: «Не общепринятый»), пожалуйста, взгляните на стиль кодирования Java, который я использую (методы начинаются со строчных букв и фигурных скобок в одной строке). Иногда важно уважать платформу, на которой вы кодируете. По крайней мере, это то, что я делаю, когда я пишу код на C # (очень редко)

1 голос
/ 05 декабря 2008

Тривиальным StringHolder будет строка [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, вероятно, является каноническим способом сделать это.

1 голос
/ 05 декабря 2008

Строки являются неизменяемыми, поэтому да, вам нужно будет обернуть строку в StringHolder. Вы можете написать свой собственный как просто

  class StringHolder
  {
     String msg;
  }

  StringHolder sMsg = new StringHolder();
  sMsg.msg = "";
  if (GetMessage(sMsg))
  {
     System.out.println(sMsg.msg);
  }
1 голос
/ 05 декабря 2008

Вы не можете использовать строку в качестве выходного параметра. Способ сделать это - использовать класс StringBuilder или вернуть ноль в случае сбоя.

Обсуждение здесь

0 голосов
/ 20 декабря 2008

сначала вы пишите программы и делайте их из кода следующим образом:

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

Таким образом, вы можете использовать программу, как и вне этой программы. Это хорошо, чтобы сделать код повторно используемым. Возьми это у меня, я был в этом в течение многих лет. Вот как профессионалы делают код.

...