Returning multiple primitive objects in java . Unrecommended?












2















I'm just beginning to learn OOP programming in java. I have already programmed a little in C++, and one of the things I miss the most in Java is the possibility to return multiple values. It's true that C++ functions only strictly return one variable, but we can use the by-reference parameters to return many more. Conversely, in Java we can't do such a thing, at least we can't for primitive types.



The solution I thought off was to create a class grouping the variables I wanted to return and return an instance of that class. For example, I needed to look for an object in a an array and I wanted to return a boolean(found or not) and an index. I know I could make this just setting the index to -1 if nothing was found, but I think it's more clear the other way.



The thing is that I was told by someone who knows much more about Java than I know that I shouldn't create classes for the purpose of returning multiple values ( even if they are related). He told classes should never be used as C++ structs, just to group elements. He also said methods shouldn't return non-primitive objects , they should receive the object from the outside and only modify it. Which of these things are true?










share|improve this question























  • "I shouldn't create classes for the purpose of returning multiple values ( even if they are related). He told classes should never be used as C++ structs, just to group elements" Data classes are both useful and common practice. In fact, there are many classes (eg tuple) which do exactly as you described, but they aren't built into the JDK. You can either create your own, or pick up a good library which already has "tuple" classes defined.

    – flakes
    Nov 23 '18 at 21:29













  • Honestly, if you're just starting out, solve the problems you're trying to solve. Clean Code, design patterns and coding conventions are great, but don't mean much before you work in an environment where maintainability, extensibility and readability matter.

    – daniu
    Nov 23 '18 at 21:30






  • 4





    Further: "methods shouldn't return non-primitive objects , they should receive the object from the outside and only modify it" This is just false.

    – flakes
    Nov 23 '18 at 21:30











  • "I needed to look for an object in a an array and I wanted to return a boolean(found or not) and an index" - check the new java Optional class. It's perfect for this scenario.

    – Andrei Ciobanu
    Nov 25 '18 at 19:32
















2















I'm just beginning to learn OOP programming in java. I have already programmed a little in C++, and one of the things I miss the most in Java is the possibility to return multiple values. It's true that C++ functions only strictly return one variable, but we can use the by-reference parameters to return many more. Conversely, in Java we can't do such a thing, at least we can't for primitive types.



The solution I thought off was to create a class grouping the variables I wanted to return and return an instance of that class. For example, I needed to look for an object in a an array and I wanted to return a boolean(found or not) and an index. I know I could make this just setting the index to -1 if nothing was found, but I think it's more clear the other way.



The thing is that I was told by someone who knows much more about Java than I know that I shouldn't create classes for the purpose of returning multiple values ( even if they are related). He told classes should never be used as C++ structs, just to group elements. He also said methods shouldn't return non-primitive objects , they should receive the object from the outside and only modify it. Which of these things are true?










share|improve this question























  • "I shouldn't create classes for the purpose of returning multiple values ( even if they are related). He told classes should never be used as C++ structs, just to group elements" Data classes are both useful and common practice. In fact, there are many classes (eg tuple) which do exactly as you described, but they aren't built into the JDK. You can either create your own, or pick up a good library which already has "tuple" classes defined.

    – flakes
    Nov 23 '18 at 21:29













  • Honestly, if you're just starting out, solve the problems you're trying to solve. Clean Code, design patterns and coding conventions are great, but don't mean much before you work in an environment where maintainability, extensibility and readability matter.

    – daniu
    Nov 23 '18 at 21:30






  • 4





    Further: "methods shouldn't return non-primitive objects , they should receive the object from the outside and only modify it" This is just false.

    – flakes
    Nov 23 '18 at 21:30











  • "I needed to look for an object in a an array and I wanted to return a boolean(found or not) and an index" - check the new java Optional class. It's perfect for this scenario.

    – Andrei Ciobanu
    Nov 25 '18 at 19:32














2












2








2








I'm just beginning to learn OOP programming in java. I have already programmed a little in C++, and one of the things I miss the most in Java is the possibility to return multiple values. It's true that C++ functions only strictly return one variable, but we can use the by-reference parameters to return many more. Conversely, in Java we can't do such a thing, at least we can't for primitive types.



The solution I thought off was to create a class grouping the variables I wanted to return and return an instance of that class. For example, I needed to look for an object in a an array and I wanted to return a boolean(found or not) and an index. I know I could make this just setting the index to -1 if nothing was found, but I think it's more clear the other way.



The thing is that I was told by someone who knows much more about Java than I know that I shouldn't create classes for the purpose of returning multiple values ( even if they are related). He told classes should never be used as C++ structs, just to group elements. He also said methods shouldn't return non-primitive objects , they should receive the object from the outside and only modify it. Which of these things are true?










share|improve this question














I'm just beginning to learn OOP programming in java. I have already programmed a little in C++, and one of the things I miss the most in Java is the possibility to return multiple values. It's true that C++ functions only strictly return one variable, but we can use the by-reference parameters to return many more. Conversely, in Java we can't do such a thing, at least we can't for primitive types.



The solution I thought off was to create a class grouping the variables I wanted to return and return an instance of that class. For example, I needed to look for an object in a an array and I wanted to return a boolean(found or not) and an index. I know I could make this just setting the index to -1 if nothing was found, but I think it's more clear the other way.



The thing is that I was told by someone who knows much more about Java than I know that I shouldn't create classes for the purpose of returning multiple values ( even if they are related). He told classes should never be used as C++ structs, just to group elements. He also said methods shouldn't return non-primitive objects , they should receive the object from the outside and only modify it. Which of these things are true?







java struct return return-value






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 23 '18 at 21:21









SevenSeven

236




236













  • "I shouldn't create classes for the purpose of returning multiple values ( even if they are related). He told classes should never be used as C++ structs, just to group elements" Data classes are both useful and common practice. In fact, there are many classes (eg tuple) which do exactly as you described, but they aren't built into the JDK. You can either create your own, or pick up a good library which already has "tuple" classes defined.

    – flakes
    Nov 23 '18 at 21:29













  • Honestly, if you're just starting out, solve the problems you're trying to solve. Clean Code, design patterns and coding conventions are great, but don't mean much before you work in an environment where maintainability, extensibility and readability matter.

    – daniu
    Nov 23 '18 at 21:30






  • 4





    Further: "methods shouldn't return non-primitive objects , they should receive the object from the outside and only modify it" This is just false.

    – flakes
    Nov 23 '18 at 21:30











  • "I needed to look for an object in a an array and I wanted to return a boolean(found or not) and an index" - check the new java Optional class. It's perfect for this scenario.

    – Andrei Ciobanu
    Nov 25 '18 at 19:32



















  • "I shouldn't create classes for the purpose of returning multiple values ( even if they are related). He told classes should never be used as C++ structs, just to group elements" Data classes are both useful and common practice. In fact, there are many classes (eg tuple) which do exactly as you described, but they aren't built into the JDK. You can either create your own, or pick up a good library which already has "tuple" classes defined.

    – flakes
    Nov 23 '18 at 21:29













  • Honestly, if you're just starting out, solve the problems you're trying to solve. Clean Code, design patterns and coding conventions are great, but don't mean much before you work in an environment where maintainability, extensibility and readability matter.

    – daniu
    Nov 23 '18 at 21:30






  • 4





    Further: "methods shouldn't return non-primitive objects , they should receive the object from the outside and only modify it" This is just false.

    – flakes
    Nov 23 '18 at 21:30











  • "I needed to look for an object in a an array and I wanted to return a boolean(found or not) and an index" - check the new java Optional class. It's perfect for this scenario.

    – Andrei Ciobanu
    Nov 25 '18 at 19:32

















"I shouldn't create classes for the purpose of returning multiple values ( even if they are related). He told classes should never be used as C++ structs, just to group elements" Data classes are both useful and common practice. In fact, there are many classes (eg tuple) which do exactly as you described, but they aren't built into the JDK. You can either create your own, or pick up a good library which already has "tuple" classes defined.

– flakes
Nov 23 '18 at 21:29







"I shouldn't create classes for the purpose of returning multiple values ( even if they are related). He told classes should never be used as C++ structs, just to group elements" Data classes are both useful and common practice. In fact, there are many classes (eg tuple) which do exactly as you described, but they aren't built into the JDK. You can either create your own, or pick up a good library which already has "tuple" classes defined.

– flakes
Nov 23 '18 at 21:29















Honestly, if you're just starting out, solve the problems you're trying to solve. Clean Code, design patterns and coding conventions are great, but don't mean much before you work in an environment where maintainability, extensibility and readability matter.

– daniu
Nov 23 '18 at 21:30





Honestly, if you're just starting out, solve the problems you're trying to solve. Clean Code, design patterns and coding conventions are great, but don't mean much before you work in an environment where maintainability, extensibility and readability matter.

– daniu
Nov 23 '18 at 21:30




4




4





Further: "methods shouldn't return non-primitive objects , they should receive the object from the outside and only modify it" This is just false.

– flakes
Nov 23 '18 at 21:30





Further: "methods shouldn't return non-primitive objects , they should receive the object from the outside and only modify it" This is just false.

– flakes
Nov 23 '18 at 21:30













"I needed to look for an object in a an array and I wanted to return a boolean(found or not) and an index" - check the new java Optional class. It's perfect for this scenario.

– Andrei Ciobanu
Nov 25 '18 at 19:32





"I needed to look for an object in a an array and I wanted to return a boolean(found or not) and an index" - check the new java Optional class. It's perfect for this scenario.

– Andrei Ciobanu
Nov 25 '18 at 19:32












4 Answers
4






active

oldest

votes


















2















I shouldn't create classes for the purpose of returning multiple values



classes should never be used as C++ structs, just to group elements.



methods shouldn't return non-primitive objects, they should receive the object from the outside and only modify it




For any of the above statements this is definitely not the case. Data objects are useful, and in fact, it is good practice to separate pure data from classes containing heavy logic.



In Java the closest thing we have to a struct is a POJO (plain old java object), commonly known as data classes in other languages. These classes are simply a grouping of data. A rule of thumb for a POJO is that it should only contain primitives, simple types (string, boxed primitives, etc) simple containers (map, array, list, etc), or other POJO classes. Basically classes which can easily be serialized.



Its common to want to pair two, three, or n objects together. Sometimes the data is significant enough to warrant an entirely new class, and in others not. In these cases programmers often use Pair or Tuple classes. Here is a quick example of a two element generic tuple.



public class Tuple2<T,U>{
private final T first;
private final U second;

public Tuple2(T first, U second) {
this.first = first;
this.second = second;
}

public T getFirst() { return first; }
public U getSecond() { return second; }
}


A class which uses a tuple as part of a method signature may look like:



public interface Container<T> {
...
public Tuple2<Boolean, Integer> search(T key);
}


A downside to creating data classes like this is that, for quality of life, we have to implement things like toString, hashCode, equals getters, setters, constructors, etc. For each different sized tuple you have to make a new class (Tuple2, Tuple3, Tuple4, etc). Creating all of these methods introduce subtle bugs into our applications. For these reasons developers will often avoid creating data classes.



Libraries like Lombok can be very helpful for overcoming these challenges. Our definition of Tuple2, with all of the methods listed above, can be written as:



@Data
public class Tuple2<T,U>{
private final T first;
private final U second;
}


This also makes it extremely easy to create custom response classes. Using the custom classes can avoid autoboxing with generics, and increase readability greatly. eg:



@Data
public class SearchResult {
private final boolean found;
private final int index;
}
...
public interface Container<T> {
...
public SearchResult search(T key);
}





methods should receive the object from the outside and only modify it




This is bad advice. It's much nicer to design data around immutability. From Effective Java 2nd Edition, p75




Immutable objects are simple. An immutable object can be in exactly one state, the state in which it was created. If you make sure that all constructors establish class invariants, then it is guaranteed that these invariants will remain true for all time, with no further effort on your part or on the part of the programmer who uses the class. Mutable objects, on the other hand, can have arbitrarily complex state spaces. If the documentation does not provide a precise description of the state transitions performed by mutator methods, it can be difficult or impossible to use a mutable class reliably.



Immutable objects are inherently thread-safe; they require no synchronization. They cannot be corrupted by multiple threads accessing them concurrently. This is far and away the easiest approach to achieving thread safety. In fact, no thread can ever observe any effect of another thread on an immutable object. Therefore, immutable objects can be shared freely.







share|improve this answer































    1














    As to your specific example ("how to return both error status and result?")




    I needed to look for an object in a an array and I wanted to return a boolean(found or not) and an index. I know I could make this just setting the index to -1 if nothing was found, but I think it's more clear the other way.




    Returning special invalid result values such as -1 for "not found" is indeed very common, and I agree with you that it is not too pretty.



    However, returning a tuple of (statusCode, resultValue) is not the only alternative.



    The most idiomatic way to report exceptions in Java is to, you guessed it, use exceptions. So return a result or if no result can be produced throw an exception (NoSuchElementException in this case). If this is appropriate depends on the application: You don't want to throw exceptions for "correct" input, it should be reserved for irregular cases.



    In functional languages, they often have built-in data structures for this (such as Try, Option or Either) which essentially also do statusCode + resultValue internally, but make sure that you actually check that status code before trying to access the result value. Java now has Optional as well. If I want to go this route, I'd pull in these wrapper types from a library and not make up my own ad-hoc "structs" (because that would only confuse people).




    "methods shouldn't return non-primitive objects , they should receive the object from the outside and only modify it"




    That may be very traditional OOP thinking, but even within OOP the use of immutable data absolutely has its value (the only sane way to do thread-safe programming in my book), so the guideline to modify stuff in-place is pretty terrible. If something is considered a "data object" (as opposed to "an entity") you should prefer to return modified copies instead of mutating the input.






    share|improve this answer

































      0














      For some static Information you can use the static final options. Variables, declared as static final, can be accessed from everywhere.



      Otherwise it is usual and good practise to use the getter/ setter concept to receive and set parameters in your classes.






      share|improve this answer































        0














        Strictly speaking, it is a language limitation that Java does not natively support tuples as return values (see related discussion here). This was done to keep the language cleaner. However, the same decision was made in most other languages. Of course, this was done keeping in mind that, in case of necessity, such a behaviour can be implemented by available means. So here are the options (all of them except the second one allow to combine arbitrary types of return components, not necessarily primitive):




        1. Use classes (usually static, self-made or predefined) specifically designed to contain a group of related values being returned. This option is well covered in other answers.



        2. Combine, if possible, two or more primitive values into one return value. Two ints can be combined into a single long, four bytes can be combined into a single int, boolean and unsigned int less than Integer.MAX_VALUE can be combined into a signed int (look, for example, at how Arrays.binarySearch(...) methods return their results), positive double and boolean can be combined into a single signed double, etc. On return, extract the components via comparisons (if boolean is among them) and bit operations (for shifted integer components).



          2a. One particular case worth noting separately. It is common (and widely used) convention to return null to indicate that, in fact, the returned value is invalid. Strictly speaking, this convention substitutes two-field result - one implicit boolean field that you're using when checking



          if (returnValue != null)


          and the other non-primitive field (which can be just a wrapper of a primitive field) containing the result itself. You use it after the above checking:



          ResultClass result = returnValue;



        3. If you don't want to mess with data classes, you can always return an array of Objects:



          public Object returnTuple() {
          return new Object{1234, "Text", true};
          }


          and then typecast its components to desired types:



          public void useTuple() {
          Object t = returnTuple();
          int x = (int)t[0];
          String s = (String)t[1];
          boolean b = (boolean)t[2];
          System.out.println(x + ", " + s + ", " + b);
          }



        4. You can introduce field(s) into your class to hold auxiliary return component(s) and return only the main component explicitly (you decide which one is the main component):



          public class LastResultAware {
          public static boolean found;
          public static int errorCode;

          public static int findLetter(String src, char letter) {
          int i = src.toLowerCase().indexOf(Character.toLowerCase(letter));
          found = i >= 0;
          return i;
          }

          public static int findUniqueLetter(String src, char letter) {
          src = src.toLowerCase();
          letter = Character.toLowerCase(letter);
          int i = src.indexOf(letter);
          if (i < 0)
          errorCode = -1; // not found
          else {
          int j = src.indexOf(letter, i + 1);
          if (j >= 0)
          errorCode = -2; // ambiguous result
          else
          errorCode = 0; // success
          }
          return i;
          }

          public static void main(String args) {
          int charIndex = findLetter("ABC", 'b');
          if (found)
          System.out.println("Letter is at position " + charIndex);
          charIndex = findUniqueLetter("aBCbD", 'b');
          if (errorCode == 0)
          System.out.println("Letter is only at position " + charIndex);
          }
          }


          Note that in some cases it is better to throw an exception indicating an error than to return an error code which the caller may just forget to check.
          Depending on usage, this return-extending fields may be either static or instance. When static, they can even be used by multiple classes to serve a common purpose and avoid unnecessary field creation. For example, one public static int errorCode may be enough. Be warned, however, that this approach is not thread-safe.








        share|improve this answer























          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53453058%2freturning-multiple-primitive-objects-in-java-unrecommended%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          4 Answers
          4






          active

          oldest

          votes








          4 Answers
          4






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          2















          I shouldn't create classes for the purpose of returning multiple values



          classes should never be used as C++ structs, just to group elements.



          methods shouldn't return non-primitive objects, they should receive the object from the outside and only modify it




          For any of the above statements this is definitely not the case. Data objects are useful, and in fact, it is good practice to separate pure data from classes containing heavy logic.



          In Java the closest thing we have to a struct is a POJO (plain old java object), commonly known as data classes in other languages. These classes are simply a grouping of data. A rule of thumb for a POJO is that it should only contain primitives, simple types (string, boxed primitives, etc) simple containers (map, array, list, etc), or other POJO classes. Basically classes which can easily be serialized.



          Its common to want to pair two, three, or n objects together. Sometimes the data is significant enough to warrant an entirely new class, and in others not. In these cases programmers often use Pair or Tuple classes. Here is a quick example of a two element generic tuple.



          public class Tuple2<T,U>{
          private final T first;
          private final U second;

          public Tuple2(T first, U second) {
          this.first = first;
          this.second = second;
          }

          public T getFirst() { return first; }
          public U getSecond() { return second; }
          }


          A class which uses a tuple as part of a method signature may look like:



          public interface Container<T> {
          ...
          public Tuple2<Boolean, Integer> search(T key);
          }


          A downside to creating data classes like this is that, for quality of life, we have to implement things like toString, hashCode, equals getters, setters, constructors, etc. For each different sized tuple you have to make a new class (Tuple2, Tuple3, Tuple4, etc). Creating all of these methods introduce subtle bugs into our applications. For these reasons developers will often avoid creating data classes.



          Libraries like Lombok can be very helpful for overcoming these challenges. Our definition of Tuple2, with all of the methods listed above, can be written as:



          @Data
          public class Tuple2<T,U>{
          private final T first;
          private final U second;
          }


          This also makes it extremely easy to create custom response classes. Using the custom classes can avoid autoboxing with generics, and increase readability greatly. eg:



          @Data
          public class SearchResult {
          private final boolean found;
          private final int index;
          }
          ...
          public interface Container<T> {
          ...
          public SearchResult search(T key);
          }





          methods should receive the object from the outside and only modify it




          This is bad advice. It's much nicer to design data around immutability. From Effective Java 2nd Edition, p75




          Immutable objects are simple. An immutable object can be in exactly one state, the state in which it was created. If you make sure that all constructors establish class invariants, then it is guaranteed that these invariants will remain true for all time, with no further effort on your part or on the part of the programmer who uses the class. Mutable objects, on the other hand, can have arbitrarily complex state spaces. If the documentation does not provide a precise description of the state transitions performed by mutator methods, it can be difficult or impossible to use a mutable class reliably.



          Immutable objects are inherently thread-safe; they require no synchronization. They cannot be corrupted by multiple threads accessing them concurrently. This is far and away the easiest approach to achieving thread safety. In fact, no thread can ever observe any effect of another thread on an immutable object. Therefore, immutable objects can be shared freely.







          share|improve this answer




























            2















            I shouldn't create classes for the purpose of returning multiple values



            classes should never be used as C++ structs, just to group elements.



            methods shouldn't return non-primitive objects, they should receive the object from the outside and only modify it




            For any of the above statements this is definitely not the case. Data objects are useful, and in fact, it is good practice to separate pure data from classes containing heavy logic.



            In Java the closest thing we have to a struct is a POJO (plain old java object), commonly known as data classes in other languages. These classes are simply a grouping of data. A rule of thumb for a POJO is that it should only contain primitives, simple types (string, boxed primitives, etc) simple containers (map, array, list, etc), or other POJO classes. Basically classes which can easily be serialized.



            Its common to want to pair two, three, or n objects together. Sometimes the data is significant enough to warrant an entirely new class, and in others not. In these cases programmers often use Pair or Tuple classes. Here is a quick example of a two element generic tuple.



            public class Tuple2<T,U>{
            private final T first;
            private final U second;

            public Tuple2(T first, U second) {
            this.first = first;
            this.second = second;
            }

            public T getFirst() { return first; }
            public U getSecond() { return second; }
            }


            A class which uses a tuple as part of a method signature may look like:



            public interface Container<T> {
            ...
            public Tuple2<Boolean, Integer> search(T key);
            }


            A downside to creating data classes like this is that, for quality of life, we have to implement things like toString, hashCode, equals getters, setters, constructors, etc. For each different sized tuple you have to make a new class (Tuple2, Tuple3, Tuple4, etc). Creating all of these methods introduce subtle bugs into our applications. For these reasons developers will often avoid creating data classes.



            Libraries like Lombok can be very helpful for overcoming these challenges. Our definition of Tuple2, with all of the methods listed above, can be written as:



            @Data
            public class Tuple2<T,U>{
            private final T first;
            private final U second;
            }


            This also makes it extremely easy to create custom response classes. Using the custom classes can avoid autoboxing with generics, and increase readability greatly. eg:



            @Data
            public class SearchResult {
            private final boolean found;
            private final int index;
            }
            ...
            public interface Container<T> {
            ...
            public SearchResult search(T key);
            }





            methods should receive the object from the outside and only modify it




            This is bad advice. It's much nicer to design data around immutability. From Effective Java 2nd Edition, p75




            Immutable objects are simple. An immutable object can be in exactly one state, the state in which it was created. If you make sure that all constructors establish class invariants, then it is guaranteed that these invariants will remain true for all time, with no further effort on your part or on the part of the programmer who uses the class. Mutable objects, on the other hand, can have arbitrarily complex state spaces. If the documentation does not provide a precise description of the state transitions performed by mutator methods, it can be difficult or impossible to use a mutable class reliably.



            Immutable objects are inherently thread-safe; they require no synchronization. They cannot be corrupted by multiple threads accessing them concurrently. This is far and away the easiest approach to achieving thread safety. In fact, no thread can ever observe any effect of another thread on an immutable object. Therefore, immutable objects can be shared freely.







            share|improve this answer


























              2












              2








              2








              I shouldn't create classes for the purpose of returning multiple values



              classes should never be used as C++ structs, just to group elements.



              methods shouldn't return non-primitive objects, they should receive the object from the outside and only modify it




              For any of the above statements this is definitely not the case. Data objects are useful, and in fact, it is good practice to separate pure data from classes containing heavy logic.



              In Java the closest thing we have to a struct is a POJO (plain old java object), commonly known as data classes in other languages. These classes are simply a grouping of data. A rule of thumb for a POJO is that it should only contain primitives, simple types (string, boxed primitives, etc) simple containers (map, array, list, etc), or other POJO classes. Basically classes which can easily be serialized.



              Its common to want to pair two, three, or n objects together. Sometimes the data is significant enough to warrant an entirely new class, and in others not. In these cases programmers often use Pair or Tuple classes. Here is a quick example of a two element generic tuple.



              public class Tuple2<T,U>{
              private final T first;
              private final U second;

              public Tuple2(T first, U second) {
              this.first = first;
              this.second = second;
              }

              public T getFirst() { return first; }
              public U getSecond() { return second; }
              }


              A class which uses a tuple as part of a method signature may look like:



              public interface Container<T> {
              ...
              public Tuple2<Boolean, Integer> search(T key);
              }


              A downside to creating data classes like this is that, for quality of life, we have to implement things like toString, hashCode, equals getters, setters, constructors, etc. For each different sized tuple you have to make a new class (Tuple2, Tuple3, Tuple4, etc). Creating all of these methods introduce subtle bugs into our applications. For these reasons developers will often avoid creating data classes.



              Libraries like Lombok can be very helpful for overcoming these challenges. Our definition of Tuple2, with all of the methods listed above, can be written as:



              @Data
              public class Tuple2<T,U>{
              private final T first;
              private final U second;
              }


              This also makes it extremely easy to create custom response classes. Using the custom classes can avoid autoboxing with generics, and increase readability greatly. eg:



              @Data
              public class SearchResult {
              private final boolean found;
              private final int index;
              }
              ...
              public interface Container<T> {
              ...
              public SearchResult search(T key);
              }





              methods should receive the object from the outside and only modify it




              This is bad advice. It's much nicer to design data around immutability. From Effective Java 2nd Edition, p75




              Immutable objects are simple. An immutable object can be in exactly one state, the state in which it was created. If you make sure that all constructors establish class invariants, then it is guaranteed that these invariants will remain true for all time, with no further effort on your part or on the part of the programmer who uses the class. Mutable objects, on the other hand, can have arbitrarily complex state spaces. If the documentation does not provide a precise description of the state transitions performed by mutator methods, it can be difficult or impossible to use a mutable class reliably.



              Immutable objects are inherently thread-safe; they require no synchronization. They cannot be corrupted by multiple threads accessing them concurrently. This is far and away the easiest approach to achieving thread safety. In fact, no thread can ever observe any effect of another thread on an immutable object. Therefore, immutable objects can be shared freely.







              share|improve this answer














              I shouldn't create classes for the purpose of returning multiple values



              classes should never be used as C++ structs, just to group elements.



              methods shouldn't return non-primitive objects, they should receive the object from the outside and only modify it




              For any of the above statements this is definitely not the case. Data objects are useful, and in fact, it is good practice to separate pure data from classes containing heavy logic.



              In Java the closest thing we have to a struct is a POJO (plain old java object), commonly known as data classes in other languages. These classes are simply a grouping of data. A rule of thumb for a POJO is that it should only contain primitives, simple types (string, boxed primitives, etc) simple containers (map, array, list, etc), or other POJO classes. Basically classes which can easily be serialized.



              Its common to want to pair two, three, or n objects together. Sometimes the data is significant enough to warrant an entirely new class, and in others not. In these cases programmers often use Pair or Tuple classes. Here is a quick example of a two element generic tuple.



              public class Tuple2<T,U>{
              private final T first;
              private final U second;

              public Tuple2(T first, U second) {
              this.first = first;
              this.second = second;
              }

              public T getFirst() { return first; }
              public U getSecond() { return second; }
              }


              A class which uses a tuple as part of a method signature may look like:



              public interface Container<T> {
              ...
              public Tuple2<Boolean, Integer> search(T key);
              }


              A downside to creating data classes like this is that, for quality of life, we have to implement things like toString, hashCode, equals getters, setters, constructors, etc. For each different sized tuple you have to make a new class (Tuple2, Tuple3, Tuple4, etc). Creating all of these methods introduce subtle bugs into our applications. For these reasons developers will often avoid creating data classes.



              Libraries like Lombok can be very helpful for overcoming these challenges. Our definition of Tuple2, with all of the methods listed above, can be written as:



              @Data
              public class Tuple2<T,U>{
              private final T first;
              private final U second;
              }


              This also makes it extremely easy to create custom response classes. Using the custom classes can avoid autoboxing with generics, and increase readability greatly. eg:



              @Data
              public class SearchResult {
              private final boolean found;
              private final int index;
              }
              ...
              public interface Container<T> {
              ...
              public SearchResult search(T key);
              }





              methods should receive the object from the outside and only modify it




              This is bad advice. It's much nicer to design data around immutability. From Effective Java 2nd Edition, p75




              Immutable objects are simple. An immutable object can be in exactly one state, the state in which it was created. If you make sure that all constructors establish class invariants, then it is guaranteed that these invariants will remain true for all time, with no further effort on your part or on the part of the programmer who uses the class. Mutable objects, on the other hand, can have arbitrarily complex state spaces. If the documentation does not provide a precise description of the state transitions performed by mutator methods, it can be difficult or impossible to use a mutable class reliably.



              Immutable objects are inherently thread-safe; they require no synchronization. They cannot be corrupted by multiple threads accessing them concurrently. This is far and away the easiest approach to achieving thread safety. In fact, no thread can ever observe any effect of another thread on an immutable object. Therefore, immutable objects can be shared freely.








              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Nov 23 '18 at 22:24









              flakesflakes

              6,55111850




              6,55111850

























                  1














                  As to your specific example ("how to return both error status and result?")




                  I needed to look for an object in a an array and I wanted to return a boolean(found or not) and an index. I know I could make this just setting the index to -1 if nothing was found, but I think it's more clear the other way.




                  Returning special invalid result values such as -1 for "not found" is indeed very common, and I agree with you that it is not too pretty.



                  However, returning a tuple of (statusCode, resultValue) is not the only alternative.



                  The most idiomatic way to report exceptions in Java is to, you guessed it, use exceptions. So return a result or if no result can be produced throw an exception (NoSuchElementException in this case). If this is appropriate depends on the application: You don't want to throw exceptions for "correct" input, it should be reserved for irregular cases.



                  In functional languages, they often have built-in data structures for this (such as Try, Option or Either) which essentially also do statusCode + resultValue internally, but make sure that you actually check that status code before trying to access the result value. Java now has Optional as well. If I want to go this route, I'd pull in these wrapper types from a library and not make up my own ad-hoc "structs" (because that would only confuse people).




                  "methods shouldn't return non-primitive objects , they should receive the object from the outside and only modify it"




                  That may be very traditional OOP thinking, but even within OOP the use of immutable data absolutely has its value (the only sane way to do thread-safe programming in my book), so the guideline to modify stuff in-place is pretty terrible. If something is considered a "data object" (as opposed to "an entity") you should prefer to return modified copies instead of mutating the input.






                  share|improve this answer






























                    1














                    As to your specific example ("how to return both error status and result?")




                    I needed to look for an object in a an array and I wanted to return a boolean(found or not) and an index. I know I could make this just setting the index to -1 if nothing was found, but I think it's more clear the other way.




                    Returning special invalid result values such as -1 for "not found" is indeed very common, and I agree with you that it is not too pretty.



                    However, returning a tuple of (statusCode, resultValue) is not the only alternative.



                    The most idiomatic way to report exceptions in Java is to, you guessed it, use exceptions. So return a result or if no result can be produced throw an exception (NoSuchElementException in this case). If this is appropriate depends on the application: You don't want to throw exceptions for "correct" input, it should be reserved for irregular cases.



                    In functional languages, they often have built-in data structures for this (such as Try, Option or Either) which essentially also do statusCode + resultValue internally, but make sure that you actually check that status code before trying to access the result value. Java now has Optional as well. If I want to go this route, I'd pull in these wrapper types from a library and not make up my own ad-hoc "structs" (because that would only confuse people).




                    "methods shouldn't return non-primitive objects , they should receive the object from the outside and only modify it"




                    That may be very traditional OOP thinking, but even within OOP the use of immutable data absolutely has its value (the only sane way to do thread-safe programming in my book), so the guideline to modify stuff in-place is pretty terrible. If something is considered a "data object" (as opposed to "an entity") you should prefer to return modified copies instead of mutating the input.






                    share|improve this answer




























                      1












                      1








                      1







                      As to your specific example ("how to return both error status and result?")




                      I needed to look for an object in a an array and I wanted to return a boolean(found or not) and an index. I know I could make this just setting the index to -1 if nothing was found, but I think it's more clear the other way.




                      Returning special invalid result values such as -1 for "not found" is indeed very common, and I agree with you that it is not too pretty.



                      However, returning a tuple of (statusCode, resultValue) is not the only alternative.



                      The most idiomatic way to report exceptions in Java is to, you guessed it, use exceptions. So return a result or if no result can be produced throw an exception (NoSuchElementException in this case). If this is appropriate depends on the application: You don't want to throw exceptions for "correct" input, it should be reserved for irregular cases.



                      In functional languages, they often have built-in data structures for this (such as Try, Option or Either) which essentially also do statusCode + resultValue internally, but make sure that you actually check that status code before trying to access the result value. Java now has Optional as well. If I want to go this route, I'd pull in these wrapper types from a library and not make up my own ad-hoc "structs" (because that would only confuse people).




                      "methods shouldn't return non-primitive objects , they should receive the object from the outside and only modify it"




                      That may be very traditional OOP thinking, but even within OOP the use of immutable data absolutely has its value (the only sane way to do thread-safe programming in my book), so the guideline to modify stuff in-place is pretty terrible. If something is considered a "data object" (as opposed to "an entity") you should prefer to return modified copies instead of mutating the input.






                      share|improve this answer















                      As to your specific example ("how to return both error status and result?")




                      I needed to look for an object in a an array and I wanted to return a boolean(found or not) and an index. I know I could make this just setting the index to -1 if nothing was found, but I think it's more clear the other way.




                      Returning special invalid result values such as -1 for "not found" is indeed very common, and I agree with you that it is not too pretty.



                      However, returning a tuple of (statusCode, resultValue) is not the only alternative.



                      The most idiomatic way to report exceptions in Java is to, you guessed it, use exceptions. So return a result or if no result can be produced throw an exception (NoSuchElementException in this case). If this is appropriate depends on the application: You don't want to throw exceptions for "correct" input, it should be reserved for irregular cases.



                      In functional languages, they often have built-in data structures for this (such as Try, Option or Either) which essentially also do statusCode + resultValue internally, but make sure that you actually check that status code before trying to access the result value. Java now has Optional as well. If I want to go this route, I'd pull in these wrapper types from a library and not make up my own ad-hoc "structs" (because that would only confuse people).




                      "methods shouldn't return non-primitive objects , they should receive the object from the outside and only modify it"




                      That may be very traditional OOP thinking, but even within OOP the use of immutable data absolutely has its value (the only sane way to do thread-safe programming in my book), so the guideline to modify stuff in-place is pretty terrible. If something is considered a "data object" (as opposed to "an entity") you should prefer to return modified copies instead of mutating the input.







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Nov 23 '18 at 23:49

























                      answered Nov 23 '18 at 23:43









                      ThiloThilo

                      193k77416572




                      193k77416572























                          0














                          For some static Information you can use the static final options. Variables, declared as static final, can be accessed from everywhere.



                          Otherwise it is usual and good practise to use the getter/ setter concept to receive and set parameters in your classes.






                          share|improve this answer




























                            0














                            For some static Information you can use the static final options. Variables, declared as static final, can be accessed from everywhere.



                            Otherwise it is usual and good practise to use the getter/ setter concept to receive and set parameters in your classes.






                            share|improve this answer


























                              0












                              0








                              0







                              For some static Information you can use the static final options. Variables, declared as static final, can be accessed from everywhere.



                              Otherwise it is usual and good practise to use the getter/ setter concept to receive and set parameters in your classes.






                              share|improve this answer













                              For some static Information you can use the static final options. Variables, declared as static final, can be accessed from everywhere.



                              Otherwise it is usual and good practise to use the getter/ setter concept to receive and set parameters in your classes.







                              share|improve this answer












                              share|improve this answer



                              share|improve this answer










                              answered Nov 23 '18 at 21:26









                              FabianLinnFabianLinn

                              14




                              14























                                  0














                                  Strictly speaking, it is a language limitation that Java does not natively support tuples as return values (see related discussion here). This was done to keep the language cleaner. However, the same decision was made in most other languages. Of course, this was done keeping in mind that, in case of necessity, such a behaviour can be implemented by available means. So here are the options (all of them except the second one allow to combine arbitrary types of return components, not necessarily primitive):




                                  1. Use classes (usually static, self-made or predefined) specifically designed to contain a group of related values being returned. This option is well covered in other answers.



                                  2. Combine, if possible, two or more primitive values into one return value. Two ints can be combined into a single long, four bytes can be combined into a single int, boolean and unsigned int less than Integer.MAX_VALUE can be combined into a signed int (look, for example, at how Arrays.binarySearch(...) methods return their results), positive double and boolean can be combined into a single signed double, etc. On return, extract the components via comparisons (if boolean is among them) and bit operations (for shifted integer components).



                                    2a. One particular case worth noting separately. It is common (and widely used) convention to return null to indicate that, in fact, the returned value is invalid. Strictly speaking, this convention substitutes two-field result - one implicit boolean field that you're using when checking



                                    if (returnValue != null)


                                    and the other non-primitive field (which can be just a wrapper of a primitive field) containing the result itself. You use it after the above checking:



                                    ResultClass result = returnValue;



                                  3. If you don't want to mess with data classes, you can always return an array of Objects:



                                    public Object returnTuple() {
                                    return new Object{1234, "Text", true};
                                    }


                                    and then typecast its components to desired types:



                                    public void useTuple() {
                                    Object t = returnTuple();
                                    int x = (int)t[0];
                                    String s = (String)t[1];
                                    boolean b = (boolean)t[2];
                                    System.out.println(x + ", " + s + ", " + b);
                                    }



                                  4. You can introduce field(s) into your class to hold auxiliary return component(s) and return only the main component explicitly (you decide which one is the main component):



                                    public class LastResultAware {
                                    public static boolean found;
                                    public static int errorCode;

                                    public static int findLetter(String src, char letter) {
                                    int i = src.toLowerCase().indexOf(Character.toLowerCase(letter));
                                    found = i >= 0;
                                    return i;
                                    }

                                    public static int findUniqueLetter(String src, char letter) {
                                    src = src.toLowerCase();
                                    letter = Character.toLowerCase(letter);
                                    int i = src.indexOf(letter);
                                    if (i < 0)
                                    errorCode = -1; // not found
                                    else {
                                    int j = src.indexOf(letter, i + 1);
                                    if (j >= 0)
                                    errorCode = -2; // ambiguous result
                                    else
                                    errorCode = 0; // success
                                    }
                                    return i;
                                    }

                                    public static void main(String args) {
                                    int charIndex = findLetter("ABC", 'b');
                                    if (found)
                                    System.out.println("Letter is at position " + charIndex);
                                    charIndex = findUniqueLetter("aBCbD", 'b');
                                    if (errorCode == 0)
                                    System.out.println("Letter is only at position " + charIndex);
                                    }
                                    }


                                    Note that in some cases it is better to throw an exception indicating an error than to return an error code which the caller may just forget to check.
                                    Depending on usage, this return-extending fields may be either static or instance. When static, they can even be used by multiple classes to serve a common purpose and avoid unnecessary field creation. For example, one public static int errorCode may be enough. Be warned, however, that this approach is not thread-safe.








                                  share|improve this answer




























                                    0














                                    Strictly speaking, it is a language limitation that Java does not natively support tuples as return values (see related discussion here). This was done to keep the language cleaner. However, the same decision was made in most other languages. Of course, this was done keeping in mind that, in case of necessity, such a behaviour can be implemented by available means. So here are the options (all of them except the second one allow to combine arbitrary types of return components, not necessarily primitive):




                                    1. Use classes (usually static, self-made or predefined) specifically designed to contain a group of related values being returned. This option is well covered in other answers.



                                    2. Combine, if possible, two or more primitive values into one return value. Two ints can be combined into a single long, four bytes can be combined into a single int, boolean and unsigned int less than Integer.MAX_VALUE can be combined into a signed int (look, for example, at how Arrays.binarySearch(...) methods return their results), positive double and boolean can be combined into a single signed double, etc. On return, extract the components via comparisons (if boolean is among them) and bit operations (for shifted integer components).



                                      2a. One particular case worth noting separately. It is common (and widely used) convention to return null to indicate that, in fact, the returned value is invalid. Strictly speaking, this convention substitutes two-field result - one implicit boolean field that you're using when checking



                                      if (returnValue != null)


                                      and the other non-primitive field (which can be just a wrapper of a primitive field) containing the result itself. You use it after the above checking:



                                      ResultClass result = returnValue;



                                    3. If you don't want to mess with data classes, you can always return an array of Objects:



                                      public Object returnTuple() {
                                      return new Object{1234, "Text", true};
                                      }


                                      and then typecast its components to desired types:



                                      public void useTuple() {
                                      Object t = returnTuple();
                                      int x = (int)t[0];
                                      String s = (String)t[1];
                                      boolean b = (boolean)t[2];
                                      System.out.println(x + ", " + s + ", " + b);
                                      }



                                    4. You can introduce field(s) into your class to hold auxiliary return component(s) and return only the main component explicitly (you decide which one is the main component):



                                      public class LastResultAware {
                                      public static boolean found;
                                      public static int errorCode;

                                      public static int findLetter(String src, char letter) {
                                      int i = src.toLowerCase().indexOf(Character.toLowerCase(letter));
                                      found = i >= 0;
                                      return i;
                                      }

                                      public static int findUniqueLetter(String src, char letter) {
                                      src = src.toLowerCase();
                                      letter = Character.toLowerCase(letter);
                                      int i = src.indexOf(letter);
                                      if (i < 0)
                                      errorCode = -1; // not found
                                      else {
                                      int j = src.indexOf(letter, i + 1);
                                      if (j >= 0)
                                      errorCode = -2; // ambiguous result
                                      else
                                      errorCode = 0; // success
                                      }
                                      return i;
                                      }

                                      public static void main(String args) {
                                      int charIndex = findLetter("ABC", 'b');
                                      if (found)
                                      System.out.println("Letter is at position " + charIndex);
                                      charIndex = findUniqueLetter("aBCbD", 'b');
                                      if (errorCode == 0)
                                      System.out.println("Letter is only at position " + charIndex);
                                      }
                                      }


                                      Note that in some cases it is better to throw an exception indicating an error than to return an error code which the caller may just forget to check.
                                      Depending on usage, this return-extending fields may be either static or instance. When static, they can even be used by multiple classes to serve a common purpose and avoid unnecessary field creation. For example, one public static int errorCode may be enough. Be warned, however, that this approach is not thread-safe.








                                    share|improve this answer


























                                      0












                                      0








                                      0







                                      Strictly speaking, it is a language limitation that Java does not natively support tuples as return values (see related discussion here). This was done to keep the language cleaner. However, the same decision was made in most other languages. Of course, this was done keeping in mind that, in case of necessity, such a behaviour can be implemented by available means. So here are the options (all of them except the second one allow to combine arbitrary types of return components, not necessarily primitive):




                                      1. Use classes (usually static, self-made or predefined) specifically designed to contain a group of related values being returned. This option is well covered in other answers.



                                      2. Combine, if possible, two or more primitive values into one return value. Two ints can be combined into a single long, four bytes can be combined into a single int, boolean and unsigned int less than Integer.MAX_VALUE can be combined into a signed int (look, for example, at how Arrays.binarySearch(...) methods return their results), positive double and boolean can be combined into a single signed double, etc. On return, extract the components via comparisons (if boolean is among them) and bit operations (for shifted integer components).



                                        2a. One particular case worth noting separately. It is common (and widely used) convention to return null to indicate that, in fact, the returned value is invalid. Strictly speaking, this convention substitutes two-field result - one implicit boolean field that you're using when checking



                                        if (returnValue != null)


                                        and the other non-primitive field (which can be just a wrapper of a primitive field) containing the result itself. You use it after the above checking:



                                        ResultClass result = returnValue;



                                      3. If you don't want to mess with data classes, you can always return an array of Objects:



                                        public Object returnTuple() {
                                        return new Object{1234, "Text", true};
                                        }


                                        and then typecast its components to desired types:



                                        public void useTuple() {
                                        Object t = returnTuple();
                                        int x = (int)t[0];
                                        String s = (String)t[1];
                                        boolean b = (boolean)t[2];
                                        System.out.println(x + ", " + s + ", " + b);
                                        }



                                      4. You can introduce field(s) into your class to hold auxiliary return component(s) and return only the main component explicitly (you decide which one is the main component):



                                        public class LastResultAware {
                                        public static boolean found;
                                        public static int errorCode;

                                        public static int findLetter(String src, char letter) {
                                        int i = src.toLowerCase().indexOf(Character.toLowerCase(letter));
                                        found = i >= 0;
                                        return i;
                                        }

                                        public static int findUniqueLetter(String src, char letter) {
                                        src = src.toLowerCase();
                                        letter = Character.toLowerCase(letter);
                                        int i = src.indexOf(letter);
                                        if (i < 0)
                                        errorCode = -1; // not found
                                        else {
                                        int j = src.indexOf(letter, i + 1);
                                        if (j >= 0)
                                        errorCode = -2; // ambiguous result
                                        else
                                        errorCode = 0; // success
                                        }
                                        return i;
                                        }

                                        public static void main(String args) {
                                        int charIndex = findLetter("ABC", 'b');
                                        if (found)
                                        System.out.println("Letter is at position " + charIndex);
                                        charIndex = findUniqueLetter("aBCbD", 'b');
                                        if (errorCode == 0)
                                        System.out.println("Letter is only at position " + charIndex);
                                        }
                                        }


                                        Note that in some cases it is better to throw an exception indicating an error than to return an error code which the caller may just forget to check.
                                        Depending on usage, this return-extending fields may be either static or instance. When static, they can even be used by multiple classes to serve a common purpose and avoid unnecessary field creation. For example, one public static int errorCode may be enough. Be warned, however, that this approach is not thread-safe.








                                      share|improve this answer













                                      Strictly speaking, it is a language limitation that Java does not natively support tuples as return values (see related discussion here). This was done to keep the language cleaner. However, the same decision was made in most other languages. Of course, this was done keeping in mind that, in case of necessity, such a behaviour can be implemented by available means. So here are the options (all of them except the second one allow to combine arbitrary types of return components, not necessarily primitive):




                                      1. Use classes (usually static, self-made or predefined) specifically designed to contain a group of related values being returned. This option is well covered in other answers.



                                      2. Combine, if possible, two or more primitive values into one return value. Two ints can be combined into a single long, four bytes can be combined into a single int, boolean and unsigned int less than Integer.MAX_VALUE can be combined into a signed int (look, for example, at how Arrays.binarySearch(...) methods return their results), positive double and boolean can be combined into a single signed double, etc. On return, extract the components via comparisons (if boolean is among them) and bit operations (for shifted integer components).



                                        2a. One particular case worth noting separately. It is common (and widely used) convention to return null to indicate that, in fact, the returned value is invalid. Strictly speaking, this convention substitutes two-field result - one implicit boolean field that you're using when checking



                                        if (returnValue != null)


                                        and the other non-primitive field (which can be just a wrapper of a primitive field) containing the result itself. You use it after the above checking:



                                        ResultClass result = returnValue;



                                      3. If you don't want to mess with data classes, you can always return an array of Objects:



                                        public Object returnTuple() {
                                        return new Object{1234, "Text", true};
                                        }


                                        and then typecast its components to desired types:



                                        public void useTuple() {
                                        Object t = returnTuple();
                                        int x = (int)t[0];
                                        String s = (String)t[1];
                                        boolean b = (boolean)t[2];
                                        System.out.println(x + ", " + s + ", " + b);
                                        }



                                      4. You can introduce field(s) into your class to hold auxiliary return component(s) and return only the main component explicitly (you decide which one is the main component):



                                        public class LastResultAware {
                                        public static boolean found;
                                        public static int errorCode;

                                        public static int findLetter(String src, char letter) {
                                        int i = src.toLowerCase().indexOf(Character.toLowerCase(letter));
                                        found = i >= 0;
                                        return i;
                                        }

                                        public static int findUniqueLetter(String src, char letter) {
                                        src = src.toLowerCase();
                                        letter = Character.toLowerCase(letter);
                                        int i = src.indexOf(letter);
                                        if (i < 0)
                                        errorCode = -1; // not found
                                        else {
                                        int j = src.indexOf(letter, i + 1);
                                        if (j >= 0)
                                        errorCode = -2; // ambiguous result
                                        else
                                        errorCode = 0; // success
                                        }
                                        return i;
                                        }

                                        public static void main(String args) {
                                        int charIndex = findLetter("ABC", 'b');
                                        if (found)
                                        System.out.println("Letter is at position " + charIndex);
                                        charIndex = findUniqueLetter("aBCbD", 'b');
                                        if (errorCode == 0)
                                        System.out.println("Letter is only at position " + charIndex);
                                        }
                                        }


                                        Note that in some cases it is better to throw an exception indicating an error than to return an error code which the caller may just forget to check.
                                        Depending on usage, this return-extending fields may be either static or instance. When static, they can even be used by multiple classes to serve a common purpose and avoid unnecessary field creation. For example, one public static int errorCode may be enough. Be warned, however, that this approach is not thread-safe.









                                      share|improve this answer












                                      share|improve this answer



                                      share|improve this answer










                                      answered Nov 25 '18 at 19:13









                                      John McClaneJohn McClane

                                      1,5452419




                                      1,5452419






























                                          draft saved

                                          draft discarded




















































                                          Thanks for contributing an answer to Stack Overflow!


                                          • Please be sure to answer the question. Provide details and share your research!

                                          But avoid



                                          • Asking for help, clarification, or responding to other answers.

                                          • Making statements based on opinion; back them up with references or personal experience.


                                          To learn more, see our tips on writing great answers.




                                          draft saved


                                          draft discarded














                                          StackExchange.ready(
                                          function () {
                                          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53453058%2freturning-multiple-primitive-objects-in-java-unrecommended%23new-answer', 'question_page');
                                          }
                                          );

                                          Post as a guest















                                          Required, but never shown





















































                                          Required, but never shown














                                          Required, but never shown












                                          Required, but never shown







                                          Required, but never shown

































                                          Required, but never shown














                                          Required, but never shown












                                          Required, but never shown







                                          Required, but never shown







                                          Popular posts from this blog

                                          Sphinx de Gizeh

                                          Dijon

                                          Langue