Paramètres de chaîne Java


Je viens d'un arrière-plan.net et je veux connaître la façon acceptée de créer une méthode qui renvoie un booléen et modifie une chaîne qui a été transmise via un paramètre. Je comprends que les chaînes sont immuables en Java, donc l'extrait ci-dessous produira toujours une chaîne vide. Je suis contraint de retourner uniquement booléen. Les exceptions ne peuvent pas être levées. Si j'ai besoin d'envelopper la classe String dans, disons, un StringHolder, dans quel paquet pourrais-je le trouver.

public static void DoStuff()
{
    String msg = "";
    if (GetMessage(msg))
    {
       System.out.println(msg);
    }
}
Author: tgeros, 2008-12-05

11 answers

Utilisez un java.lang.StringBuilder-fondamentalement une chaîne mutable. Cependant, il serait plus sûr et plus "style Java" de renvoyer la chaîne modifiée.

 9
Author: Michael Borgwardt, 2008-12-05 01:28:07

Je vous suggère fortement de ne pas utiliser StringBuilder, holder ou similaire. Ils sont des hacks. Vous voulez travailler avec des chaînes, pas des constructeurs.

L'approche la plus évidente consiste à renvoyer un objet contenant les données que vous souhaitez renvoyer. David's [bombe.livejournal.com la solution couvre cela, donc je ne le répéterai pas. Cependant, je suggérerais au lieu d'essayer d'en faire une boule de données générique, de la rendre spécifique. Faire comme un objet, peut-être qu'il pourrait même atteindre comportement réel. (Et si vous je veux vraiment aller en ville, cacher le constructeur et lui donner une méthode de création statique à la place.)

Une deuxième approche, pas si bien prise en charge en Java, consiste à inverser les appels. Au lieu de renvoyer un résultat, dites à un rappel le résultat.

Le code d'utilisation (plus important) serait quelque chose comme (il semble un peu étrange car il n'est pas spécifique, ni générique):

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

L'implémentation va quelque chose comme:

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

[...]

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

Une troisième approche consiste simplement à casser la méthode en de deux. Qui peut ou peut ne pas être faisable.

 6
Author: Tom Hawtin - tackline, 2015-05-07 12:59:36

Tout d'abord, je n'aurais probablement pas ces exigences. Je suis sûr qu'ils peuvent être contournées. Si vous ne voulez pas le faire, je vous recommande de renvoyer un objet conteneur pour vos deux résultats:

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

Et dans votre code principal:

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

GetMessage() créerait évidemment une nouvelle instance de a ResultContainer et la renverrait, remplie des valeurs de retour.

(L'utilisation de génériques pour le ResultContainer est laissée comme un exercice pour le lecteur.)

 5
Author: Bombe, 2008-12-05 11:37:35

Une classe holder plus élégante pourrait être réutilisée pour tout type d'objet en utilisant des génériques:

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( ) ressemblerait alors:

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

Et GetMessage( ) faudrait appeler holder.set( a_string).

 3
Author: J. A. Faucett, 2008-12-05 04:55:50

Java est un langage orienté objet basé sur des classes, donc ses idiomes ont tendance à créer des classes pour encapsuler les données avec le comportement qui les entoure.

Vous avez une donnée - le message - qui est obtenue d'une manière ou d'une autre, puis si une condition est remplie, quelque chose d'autre est fait avec. Faire de ce comportement une séquence de gets ,fs et d'autres opérations dans un objet de contrôle externe est souvent un signe que le programmeur n'a pas compris la POO.

Je suis contraint de retourner boolean seulement. Les exceptions ne peuvent pas être levées.

Puis-je suggérer que vous devriez utiliser Fortran ou C plutôt que Java? Les langages procéduraux ont souvent l'idiome de la mutation et du retour d'un drapeau, ce qui est bien adapté à ce paradigme (en l'absence de gestion automatique de la mémoire, l'appelant crée et passe dans un tampon qui est rempli; cela permet au tampon d'être libéré en toute sécurité lorsque l'appelant en a fini avec lui; Javaget() il renvoie un Chaîne ou null si elle échoue-pas besoin de gérer la mémoire dans l'appelant). Au moins, ne vous embêtez pas à essayer de trouver la façon acceptée de le faire en Java idiomatique - avec ces contraintes, ce ne sera pas le cas, et celui qui vous les force a fait un mauvais choix, ce qui signifiera que vous avez des hacks, ou que vous vous retrouvez avec du code verbeux essayant de faire une solution non hacky.

 2
Author: Pete Kirkham, 2008-12-05 13:56:31

Vous ne pouvez pas utiliser une chaîne comme paramètre de sortie. La façon de le faire serait d'utiliser une classe StringBuilder à la place ou de renvoyer null en cas d'échec.

La Discussion Ici

 1
Author: JamesSugrue, 2008-12-05 01:28:44

Les chaînes sont immuables, donc oui, vous devrez envelopper la chaîne dans un StringHolder. Vous pouvez écrire le vôtre aussi simplement que

  class StringHolder
  {
     String msg;
  }

  StringHolder sMsg = new StringHolder();
  sMsg.msg = "";
  if (GetMessage(sMsg))
  {
     System.out.println(sMsg.msg);
  }
 1
Author: Paul Tomblin, 2008-12-05 01:29:38

Un StringHolder trivial serait une 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 est probablement la façon canonique de le faire, cependant.

 1
Author: Stobor, 2008-12-05 02:20:11

C'est une exigence étrange.

Pourquoi ne pas le faire de la bonne façon (ou du moins de la manière java ) ? C'est comme essayer d'obtenir deux résultats à partir d'une fonction. Comme soustraction (2 , 2 ) renvoie 0 et "Bonjour monsieur".

Eh bien de toute façon, vous pouvez essayer ces deux options.

1st. StringBuilder Pas la meilleure chose à utiliser, puisque vous ne "construisez" pas une chaîne.

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

2ndStringHolder ( quelque chose de titulaire d'ailleurs ) Pas trop de style java non plus mais faire le travail. Ce serait celui utilisé par la plupart des développeurs java que je connais.

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ème. Option. pas ce que tu as demandé, mais ce que je ferais. Viole malheureusement la condition "return boolean".

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
}

Choisissez-en un.

Note

Bien que tout le monde n'aime pas cela ( Jon Skeet dirait "N'est pas universellement accepté" ) , veuillez jeter un œil au style de codage java que j'utilise ( méthodes commençant par des minuscules et des accolades dans la même ligne ). Parfois c'est le cas important de respecter la plate-forme sur laquelle vous codez. Au moins c'est ce que je fais quand je code en C# (très rarement btw)

 1
Author: OscarRyz, 2008-12-05 03:06:39

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

Est-ce un peu ce que vous cherchez? Je suppose que le test booléen est quelque chose comme tester si le message modifié est trop long pour un affichage (longueur supérieure à 80) ou quelque chose de similaire, et que vous n'avez pas besoin d'appeler une autre méthode pour changer la chaîne de message à l'intérieur de doStuff().

Pourrait être complètement hors-base ici, cependant. :-)

 0
Author: , 2008-12-20 01:43:22

Commencez par écrire les programmes et faites-les à partir du code comme ceci:

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

Astuce pour vous : Runtime.exec doit être utilisé partout. Ensuite, vous pouvez créer de nombreux programmes.

Ensuite, vous attendez de récupérer un code d'état comme celui-ci:

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

De cette façon, vous pouvez utiliser le programme autrement comme à l'extérieur de ce programme. Il est bon de rendre le code resusable. Prends-le-moi, j'y suis depuis des années. C'est ainsi que les pros font du code.

 0
Author: , 2008-12-20 02:18:28