Параметри на Java String

Идвам от .net фон и искам да знам приетия начин за създаване на метод, който връща булево и модифицира низ, който е предаден чрез параметър. Разбирам, че низовете са неизменни в Java, така че фрагментът по-долу винаги ще създава празен низ. Принуден съм да връщам само булев. Не могат да се правят изключения. Ако трябва да обвия класа String в, да речем, StringHolder, в какъв пакет мога да намеря това.

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

person tgeros    schedule 05.12.2008    source източник
comment
Това, което харесвам в този въпрос, е, че съм принуден да връщам само булеви стойности. Изключение не може да бъде хвърлено. Ще ви кажат ли също, че всички for цикли трябва да се правят като while цикли? Защо да си правите труда да използвате Java, ако не ви е позволено да използвате Java. Късмет.   -  person jmucchiello    schedule 20.12.2008
comment
Можете ли да изясните какво ви трябва? Пишете, че съм принуден да връщам булево, но декларацията на вашия метод гласи public static void DoStuff()   -  person Bevan    schedule 20.12.2008
comment
@joe_mucchuiello Това е един разработчик, който отказа да използва изключения или всякакви модерни езикови идиоми. @Bevan Това е методът GetMessage, който трябваше да върне булево значение. Не толкова DoStuff. Извинения за объркването.   -  person tgeros    schedule 24.12.2008


Отговори (11)


Използвайте java.lang.StringBuilder - основно променлив низ. Въпреки това би било по-безопасно и по-"стил Java" да се върне модифицираният низ.

person Michael Borgwardt    schedule 05.12.2008

Горещо препоръчвам да не използвате StringBuilder, държач или подобни. Те са хакове. Искате да работите с низове, а не със строители.

Най-очевидният подход е да върнете обект, съдържащ данните, които искате да върнете. Решението на David [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());
    }

Трети подход е просто да разделите метода на две. Това може или не може да бъде осъществимо.

person Tom Hawtin - tackline    schedule 05.12.2008
comment
Благодаря на Том, че положи усилия. StringBuilder работи за мен, въпреки че, както казвате, е хак. Имах нужда от най-простото и разбираемо решение за момента. - person tgeros; 08.12.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 и ще го върне, изпълнен с върнатите стойности.

(Използването на Generics за ResultContainerе оставено като упражнение за читателя.)

person Bombe    schedule 05.12.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).

person J. A. Faucett    schedule 05.12.2008

Java е базиран на класове обектно-ориентиран език, така че неговите идиоми са склонни да създават класове за капсулиране на данни с поведението, което ги заобикаля.

Имате даденост - съобщението - което се получава по някакъв начин, тогава, ако е изпълнено някакво условие, с него се прави нещо друго. Превръщането на това поведение в последователност от gets, ifs и други операции във външен управляващ обект често е знак, че програмистът не е разбрал OOP.

Принуден съм да връщам само булев. Не могат да се правят изключения.

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

person Pete Kirkham    schedule 05.12.2008

Не можете да използвате низ като изходен параметър. Начинът да го направите би бил да използвате вместо това клас StringBuilder или да върнете null за грешка.

Дискусия тук

person JamesSugrue    schedule 05.12.2008

Низовете са неизменни, така че да, ще трябва да обвиете низа в StringHolder. Можете да напишете свой собствен толкова просто, колкото

  class StringHolder
  {
     String msg;
  }

  StringHolder sMsg = new StringHolder();
  sMsg.msg = "";
  if (GetMessage(sMsg))
  {
     System.out.println(sMsg.msg);
  }
person Paul Tomblin    schedule 05.12.2008

Тривиален 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 обаче вероятно е каноничният начин да го направите.

person Stobor    schedule 05.12.2008

Това е някакво странно изискване.

Защо не го направите по правилния начин (или поне по java)? Това е като да се опитвате да получите два резултата от функция. Like subtract( 2 , 2 ) връща 0 и „Добро утро сър“.

Както и да е, можете да опитате тези два варианта.

1-во 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;
    }
}

2-ри 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;
    }
}

3-то. опция. не това, което поиска, а това, което бих направил. За съжаление нарушава условието за "връщане на булево".

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# (между другото много рядко)

person OscarRyz    schedule 05.12.2008
comment
if (резултат!= msg)? цц, цц! - person Alan Moore; 05.12.2008
comment
Никога не съм твърдял, че конвенциите за именуване не са универсално приети. Само стилът на укрепване. Това е така, защото няма значение как Sun поддържа кода си - несъответствието между моя и техния код не се показва в моя код. Наименуването го прави, защото използвам класовете на Sun в моя код. - person Jon Skeet; 05.12.2008

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

Може обаче да е напълно извън базата тук. :-)

person Community    schedule 20.12.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");
  }

По този начин можете да използвате програмата иначе като извън тази програма. Добре е кодът да се използва повторно. Вземете го от мен, аз съм в него от години. Ето как професионалистите правят код.

person Community    schedule 20.12.2008