Borek
Borek

Reputation: 91

Best strategies when calling a method that should modify more than one variable

I am pretty new to Java, I have to convert C/C++ code to Java and I am running into obstacles. Because of the way variables are passed to the methods, their modification in the method is not straightforward, and I have no idea what is the most reasonable approach to take. Sorry for the pseudocode examples, I hope they will clearly explain what I am talking about without delving into unnecessary details.

I need something that would be equivalent to C

ModifyMyString(type1 &t1,type2 &t2);

(return type doesn't matter, it can be void) as I need the function to modify both t1 and t2.

I can easily modify one of the variables, say t1, by declaring in Java

type1 modifyMyString(type1 t1, type2 t2);    

and assigning the returned value to

t1 = modifyMyString(t1,t2);

but it is only half of a success, as the new value of t2 is lost.

I can declare new class

class JustToPassTwoVariables {
    type1 t1;
    type2 t2;
    JustToPassTwoVariables(type1 tt1, type2 tt2) { t1 = tt1; t2 = tt2; }
}

and do something like

JustToPassTwoVariables jtptv = modifyMyString(JustToPassTwoVariables(t1,t2));

but I feel like it is clumsy and makes the code unreadable.

In desperation I could also resign the idea of using a modifyMyString method, and repeat all the code locally in each place I would call modifyMyString - but it makes even less sense than using JustToPassTwoVariables class.

Is there a correct (or at least widely used, accepted as a standard, whatever) strategy to code such things in Java?

Upvotes: 4

Views: 795

Answers (8)

venergiac
venergiac

Reputation: 7717

Java discourages this strategy beacause in-variable should be immutable, but if you have to migrate from C/C++/C# and you have a lot of "void function with parameters passed as in/out", you can create a Custom "Reference" class like this and you can incapsulate the original object.

public class CustomRef {
      public Object internal;

      public CustomRef(Object object) {
             this.internal=object;
      }


 }

then when you call

 CustomRef ref1= new CustomRef(myParams1);
 CustomRef ref2= new CustomRef(myParams2);

 myFunction(ref1, ref2);

 myParams1 = ref1.internal;
 myParams2 = ref2.internal;

the function is

 void myFunction(CustomRef ref1, CustomRef  ref2) {

      Object param1 = ref1.internal 
      // a lot of code
      ref1.internal = param1;

 }

really discouraged way ... such as using ArrayList, arrays [] to "pass by reference". NOTE: this way is a waste of resource; CustomRef instance should be reused through object pool (another discouraged way).

Upvotes: 1

Buhb
Buhb

Reputation: 7149

The recommended way in java is (in some people's opinion the clumsy way) to create a class containing the two fields and return an instance of that class.

I feel that it is much less clumsy if you stop and think about what the method is actually doing, and taking care to properly name both the method and the class returning the two values.

Upvotes: 7

Ben Thurley
Ben Thurley

Reputation: 7161

Java is an OO language so to get the best out of it you should look to an OO solution. It's hard to give you a definite solution with this abstract example but this is how I would approach this.

You mention that t1 and t2 both need to be updated by this modify procedure/method. Also that they need to be updated at the same time, if they were unrelated then you could just call modify on each string in turn. If these two strings are related like this then it's likely they belong to the same type.

So we need a class containing type 1 and type 2.

public class TypeContainer
{

  private String type1;
  private String type2;

  .. getters and setters 
}

Obviously you'll want a better class name.

You suggest something similar yourself but call it JustToPassTwoVariables. This is missing the point of OO. You could write a simple wrapper like this and pass it to some other method to modify the values but a more OO approach would be to add the modify method to this class itself.

...
public void modfiy(String val1, String val2)
{
  type1 = val1;
  type2 = val2;
}
...

I'm not sure what your modify is trying to do but in this case I would probably have these as two separate setter methods. This is quite an abstract example!

Basically I would avoid having the modify method in some other unrelated class. You should look to group common related attributes into classes and then write methods in those classes for any actions you need to take (such as modify).

Trying to convert a procedural C program into an OO Java program sounds like a PITA. It's a complete paradigm shift. Having said that I have seen automated conversions which while technically Java are still very procedural. Not very pretty and hard to maintain but was done for political reasons.

Upvotes: 1

TheLostMind
TheLostMind

Reputation: 36304

There are several methods to modify a group of objects "of the same type/class". The simplest of them being, add them to a "list" pass that list to your modification function, do whatever modifications/additions/deletions etc.. The list reference will be automatically available outside with the "changes made in the called function" .

So, you can do

List<String> l = new ArrayList<String>();
    l.add("Hello");
    l.add("world");
    ModifyMyString(l);
    // here also l = "hello" , "world" , "added"

    public void ModifyMyString(List l)
    {
     l.add("added"); // now l = "hello" , "world" , "added"
    }

Upvotes: 2

SamYonnou
SamYonnou

Reputation: 2068

In Java if you want to do this you would generally make type1 and type2 into object whose values can be modified. The method can then modify the values of the parameters to get the desired effect. For example :

void myMethod(type1 arg0, type2 arg1) {
    arg0.setValue(newValue0);
    arg1.setValue(newValue1);
}

If type1 and/or type2 do not have any way of changing their values (e.g. they are of type String) then you would either make a wrapper class for each of them e.g.

class Type1Wrapper {
    private type1 type1;

    type1 getType1() {
        return type1;
    }

    void setType1(type1 newType1) {
        type1 = newType1;
    }
}

or you would make a wrapper for both of the types simultaneously like you have in your question (although the method return type will be void and the method will modify your wrapper's values)

Upvotes: 2

Keerthivasan
Keerthivasan

Reputation: 12890

You can't return two values from a method in java. The way is to return an object and set all the values in it. i.e. In your case, you need to create a value container class i.e. say Result class that will have two fields storing the type1 and type2 value in it. The return type of the method would be of value container object type i.e. say Result instance with two fields in it - type1 and type2

Example :

Result result = modifyMyString(t1,t2);
result.getT1(); //gets t1 value
result.getT2(); // gets t2 value

Please learn about setters and getters in Java to work on the class or object level fields

Upvotes: 3

Emanuele Paolini
Emanuele Paolini

Reputation: 10162

I would use a StringBuffer. You can initialize it with a String and convert it back to a String

Upvotes: -5

Tim B
Tim B

Reputation: 41198

The simple answer is no. This sort of feature is not allowed in Java.

The correct way to do it is to pass in the object to be modified not the two variables. After all in virtually all cases those variables are already wrapped in an object, in cases where they aren't they often easily can be.

Either split the function into two functions and call it once for each variable, or wrap the variables into an object and pass that object into the function.

Don't forget Java allows Inner Classes which makes this sort of thing less painful.

Upvotes: 5

Related Questions