4

I use trim() method in order to trim leading and trailing whitespaces in some of the string field.

siteRequest.getName().trim();

However, when string field is null, it throws exception as expected. I can check the values before trimming as shown below:

siteRequest.getName() ? siteRequest.getName() : siteRequest.getName().trim();

However, if it is possible I would prefer a cleaner way so that several people had already faced this problem. Any suggestion with a smarter approach?

  • 1
    Java is not a "truthy" language, did you mean `siteRequest.getName() == null`?. With plain Java, you could take the ternary route `siteRequest.getName() == null ? null : /* other value */`, or there is `Optional#map` if it's already in the form of `Optional`. There isn't an elvis operator like in kotlin/scala, where you could do `siteRequest.getName()?.trim()` – Rogue Jun 06 '22 at 16:49
  • Do you have code access to the `getName()` getter method? Perhaps you can handle that nonsense there. – DevilsHnd - 退職した Jun 06 '22 at 19:41
  • @Rogue Thanks for useful information, yes I meant `siteRequest.getName() == null ?`. I also tried to use `siteRequest.getName()?.trim()` before asking the question, but as you mentioned, it is not supported by Java. –  Jun 06 '22 at 21:07
  • @DevilsHnd Never thought it, but is seems a good point as it can be managed in a single point. But not sure which one is better, in getter method or using a trim method. And suggestion? –  Jun 06 '22 at 21:09
  • 1
    It's a matter of... would the *name* returned from `getName()` ever need to have leading or trailing whitespace? It depends on what the actual Getter or any Getter is for. If a class instance object is created you would suspect it may have a name **or** at the very least, perhaps a temporary alternative, for example: `return ((this.name == null || this.name.isEmpty()) ? "N/A" : this.name);`. Again, it depends on what the Getter is for and how your application will ever use it. – DevilsHnd - 退職した Jun 06 '22 at 23:41
  • @DevilsHnd In this scene I think it would be better to proceed with a Util method. Voted up for your help ;) –  Jun 07 '22 at 06:40
  • It's entirely up to you @Jonathan, it's your application. It was merely a suggestion bud. – DevilsHnd - 退職した Jun 07 '22 at 10:56

5 Answers5

6

I like the idea from @Sebastiaan van den Broek but would prefer not to use the library and therefore look up its implementation:

// Trim
//-----------------------------------------------------------------------
/**
 * <p>Removes control characters (char &lt;= 32) from both
 * ends of this String, handling {@code null} by returning
 * {@code null}.</p>
 *
 * <p>The String is trimmed using {@link String#trim()}.
 * Trim removes start and end characters &lt;= 32.
 * To strip whitespace use {@link #strip(String)}.</p>
 *
 * <p>To trim your choice of characters, use the
 * {@link #strip(String, String)} methods.</p>
 *
 * <pre>
 * StringUtils.trim(null)          = null
 * StringUtils.trim("")            = ""
 * StringUtils.trim("     ")       = ""
 * StringUtils.trim("abc")         = "abc"
 * StringUtils.trim("    abc    ") = "abc"
 * </pre>
 *
 * @param str  the String to be trimmed, may be null
 * @return the trimmed string, {@code null} if null String input
 */
public static String trim(final String str) {
    return str == null ? null : str.trim();
}

From my point of view there is no better way to implement it. Using Optionals is not an option. Therefore, the original solution idea in the question is confirmed.

Franck
  • 1,340
  • 2
  • 3
  • 15
  • **1.** Normally I do not use `final` keyword for method parameters. But I think the usage in your example related to being immutable of String. If we do not use `final` for `str` parameter, does it cause `str.trim()` to create a new String in the string pool? –  Jun 06 '22 at 21:37
  • **2.** What about using these null control and trim in the getter of each property that is needed to be trim? Does it take to much work when we need to trim new properties? –  Jun 06 '22 at 21:39
  • At **1.**: See https://stackoverflow.com/questions/500508/why-should-i-use-the-keyword-final-on-a-method-parameter-in-java It has no effect on the behavior of `str.trim()`. – Franck Jun 06 '22 at 21:53
  • At **2.**: I do not think that the call of a static method and the trimming (which is most probably always a new string generation) for each property has a considerable impact on the overall performance of the request processing. – Franck Jun 06 '22 at 21:58
  • `String` is already immutable, so yes `#trim` will result in a different `String` object than you started with, unless it was already trimmed. Part of the reasoning of the comments on the question was to say you could `#trim` when you set the `name` parameter, rather than on retrieving it. – Rogue Jun 08 '22 at 11:32
1

Typically this is done with the Apache Commons library's trim method. This library is so commonplace that it's basically part of Java. It will return null for null Strings. E.g. StringUtils.trim("myString "); would return "myString"

Sebastiaan van den Broek
  • 5,818
  • 7
  • 40
  • 73
  • 1
    Not from OP, but myself. Answers that are simply suggesting to use a library that aren't clearly in use from the OP are not very helpful, as not everyone can simply just add commons or guava or what have you. Secondly, answers with just a link to a page and no further explanation are considered non-answers and tend to get deleted in review queues. – Rogue Jun 06 '22 at 16:50
  • No offense but the Apache Commons library isn't just 'a library' in the Java world. Nor will the documentation disappear. Use common sense. – Sebastiaan van den Broek Jun 06 '22 at 16:52
  • 1
    The documentation link to `StringUtils` has changed 3 times in the last 8 years (from the change of `javadocs`/`apidocs` in the link, as well as `api3.3`). It is also absolutely _not_ included in every Java project, there are a litany of reasons to not include a library, particularly in-house projects and licensing concerns (even with the apache license). While it may feel ubiquitous to you, that is only one person's experience. I will undo the downvote for including an example use, but do keep these things in mind. – Rogue Jun 06 '22 at 16:56
  • @Rogue changed, sure. Although those are most likely example improvements as the behavior hasn't fundamentally changed. Removed entirely? No. It's not StackOverflow's purpose to be (an out of date) copy of Apache library documentation. If they don't want to include a library then they are welcome to use the implementation as inspiration too. – Sebastiaan van den Broek Jun 06 '22 at 17:04
  • @Jonathan fyi, since you’re using Spring Boot, if you really don’t want additional libraries, chances are that you already have Spring’s StringUtils class which can do this too. – Sebastiaan van den Broek Jun 08 '22 at 06:38
1

Unfortunately Java still lacks a null-safe navigation operator. The closest way to replicate it would be with Optional:

String trimmed = Optional.ofNullable(untrimmed).map(String::trim).orElse(null);

However it's easy to see this does not beat a simple ternary most of the time. Where it does shine is if you have a long chain of potential nullables, and want to avoid nested ternaries:

String trimmed = Optional.ofNullable(request)
 .map(Request::getName)
 .map(String::trim)
 .orElse(null);
Mark Peters
  • 80,126
  • 17
  • 159
  • 190
  • Beat me by 19 seconds :/ – daniu Jun 06 '22 at 17:01
  • What about using these null control and trim in the getter of each property that is needed to be trim? Does it take to much work when we need to trim new properties? –  Jun 06 '22 at 21:39
  • @Jonathan: If you find yourself doing it a lot, you could make a null-safe helper method like others have posted. However, I would question why you would be doing this in a lot of properties. This is usually a sign that you don't trust the fields of your data object. If it's invalid for a field to have leading/trailing whitespace, this should typically be validated (or trimmed) when the object is *constructed*. Then your getters would just return the stored values. If that whitespace is legal, your properties shouldn't assume that the callers of your code want it trimmed. – Mark Peters Jun 07 '22 at 12:53
  • Thanks a lot amigo, voted up. It also seems to be logical, but I just wanted to be sure what the general convention in Java is (for this kind of situations). In that case, I think it would also be good idea to check values in the getter, right? –  Jun 07 '22 at 14:40
  • And, would you also add an example to aply the necessary logic to the getter of `siteName` property? –  Jun 07 '22 at 14:42
0
String name = siteRequest.getName();

name == null ? name : 
name.trim();

or

String name = siteRequest.getName();

if(name != null)
  name.trim();
  • Yes, but I do not want to use like that as I mentioned in my question. I need a cleaner way. –  Jun 06 '22 at 21:13
0

As answered above simple use a util method to do this. Ideally, null conditional operator would have made it better, but that doesn't exist in java

But create a util method. flavor it as you need e.g from the above answers you can do

public static String trim(final String str) {
    return str == null ? null : str.trim();
}

or if you want to return a default values

public static String trim(final String str) {
    return str == null ? "default_value" : str.trim();
}

or

public static String trim(final String str, String defaultValue) {
    return str == null ? defaultValue : str.trim();
}

or if you want to use options

public static Option<String> trim(final String str) {
    return str == null ? Optional.nullable() : Optional.of(str.trim());
}

It purely depends on what you need and how your source code has been written.

Dhruv Pal
  • 849
  • 2
  • 10
  • 25
  • Thanks a lot for this good explanations and annotations in the method explanations. I need to be clarified about these points >>> –  Jun 06 '22 at 21:35
  • **1.** Normally I do not use `final` keyword for method parameters. But I think the usage in your example related to being immutable of String. If we do not use `final` for `str` parameter, does it cause `str.trim()` to create a new String in the string pool? –  Jun 06 '22 at 21:37
  • **2.** What about using these null control and trim in the getter of each property that is needed to be trim? Does it take to much work when we need to trim new properties? –  Jun 06 '22 at 21:39
  • @Jonathan check here https://stackoverflow.com/questions/10233309/does-it-make-sense-to-define-a-final-string-in-java – Dhruv Pal Jun 07 '22 at 07:31
  • At 1: @Jonathan ideally it doesn't have any impact as string is immutable by default. It's just that someone doesn't create any logic that involves`str = "some value"`. So it will give a compilation error straightforward. But its value highlights in case we have non immutable as parameter e.g plain List – Dhruv Pal Jun 07 '22 at 07:56
  • At 2: I am not able to understand fully what are you talking about but I will answer on what I have understood. Don't create setters, in the constructor itself get elements and apply logic there with some default values maybe. You need to try out that your self – Dhruv Pal Jun 07 '22 at 08:00
  • Thanks a lot amigo, voted up. By question 2, I meant should I check and trim in the getter of each property, or create an Util method and use it for each property that needed to be trimmed? –  Jun 07 '22 at 08:02
  • ```Class SiteName { private final String name; constructor(String name) { this.name = name === null ? "" : name; } getName(){ return this.name } }``` I would have preferred something like above – Dhruv Pal Jun 07 '22 at 11:58