views:

165

answers:

8

In order to refactor some methods into smaller ones, I need pass by reference, since I can only have one return type. I could create a different return or parameter type whenever I need to do this, but then I'd end up with a bunch of bloated, seemingly unnecessary classes.

What is the best alternative here, besides redesigning the program, which can't be done?

edit: some of it CAN be redesigned, and that's what I am doing, but, for example, at one point it is finding the minimum and second minimum values in a huge collection and then manipulating them. I wanted to split that into 2 methods - one finds, another manipulates - but it seems highly unlikely I'll be able to do this cleanly.

A: 

bunch of bloated, seemingly unnecessary classes.

Hmm either the data belong together, which is why you have decided to return them from a single method, or they don't. If they do, isn't a new class is appropriate? As a last ditch you could return a Vector.

edit

or if you always had a finite number of return items you could use something like Pair<T1,T2> (or define some such generic tuple type)

Sanjay Manohar
The data is related, but as I do this on all the code, the amount of classes done just for grouping is stupidly large. Using a vector isn't a bad idea, though if I have objects of different classes I'd be stuck with Vector<Object> which isn't ideal. Then I have to start writing code to convert from Object to each MyClass and it goes downhill.
mr popo
+1  A: 

I need pass by reference

To be strictly precise, Java does not have pass by reference. There's only one passing mechanism in Java, and that's pass by value.

In the case of objects, the thing that's being passed is not the object itself, which lives on the heap. It's the reference to the object that's passed by value.

It might sound like a nitpick, but it's an important one.

I don't see what this has to do with refactoring. If you need to create new types just to be returned, by all means do so. I'd bet that you really don't have an object model that reflects the problem at hand, which is why you have this refactoring problem.

Doesn't sound very object-oriented to me, especially after reading your edit.

duffymo
yes, i realize that. i never said it has pass by value. i'm sorry if i sound grumpy, but this is always the answer given and it does not help
mr popo
can you explain better what you'd like to do then?
matt b
You sound confused - Java DOES have pass by value, it does not pass by reference. Even your comment, in which you claim to "know", is incorrect. Sorry.
duffymo
@matt-b have multiple returns from a function with the least amount of bloat code while also keeping it organized
mr popo
@duffymo you're right about that, i did get it confused in my comment lol. sorry about that
mr popo
@mr popo - I voted you up just for having a sense of humor. It would have been easy to descend into a back and forth, and you didn't. Kudos to you. I wish I could help more, but I'm not sure what to suggest.
duffymo
A: 

Promote your variables to instance variables, that way they'll be visible to both methods (you are allowed to have state in an object after all). If they don't look like they should belong on your object then I don't think you'll be able to get around a redesign.

CurtainDog
After your edit I'm even more convinced this is the way to go.
CurtainDog
no way, i'd have far too many instance variables
mr popo
@mr popo, that should be an indication that your class is probably be doing too much. try to create smaller, single focused classes.
Jeff Storey
+4  A: 

You are talking about "returning" multiple values by means of so-called out parameters, like you sometimes find in C, which are passed by reference?

You asked for an alternative to returning a single value class, but that is really the right thing to do.

But since you ask, yes, you're correct that you need a little more work to get pass-by-reference semantics in Java. Java is always pass-by-value (yes I mean that -- it is object references that are passed into methods, and those are passed by value). So to fake pass-by-reference, you could do something like pass an array of one Object, and change the reference it contains, if you wanted to pass back a new reference this way.

However I'd call this highly unconventional and would not recommend it. Any improvement you get by refactoring is destroyed by this.

Sean Owen
Use a Java Collection instead of an array.While this is what the OP wants, I would strongly discourage anyone from adopting this as a practice.
Tim Bender
A: 

Since in a method, the arguments the references of objects are passed by value, couldn't you do something along the lines of:

import java.awt.Point;

public class Example {
    public static void main(String args[]) {
        Point pnt1 = new Point(0, 0);
        Point pnt2 = new Point(0, 0);
        System.out.println("X: " + pnt1.x + " Y: " + pnt1.y);
        System.out.println("X: " + pnt2.x + " Y: " + pnt2.y);
        System.out.println(" ");
        sillyMethod(pnt1, pnt2);
        System.out.println("X: " + pnt1.x + " Y: " + pnt1.y);
        System.out.println("X: " + pnt2.x + " Y: " + pnt2.y);
    }

    public static void sillyMethod(Point arg1, Point arg2) {
        arg1.x = 100;
        arg1.y = 100;
        arg2.x = 200;
        arg2.y = 200;
    }
}

This way, you are changing the values of the objects, without returning diverging types.

Pran
what if i need to change arg1 itself though? i'd have to create a class for each parameter i'd like to change
mr popo
I'm sorry, I did not understood your comment. Isn't arg1 already been changed in the example; it's x and y coordinates have been set to 100.
Pran
+1  A: 

You could do something like create a generic class that could handle out values from a function.

private static class OutValue<T> {
    public T value;

    static <X> OutValue<X> makeOutValue(X value) {
        OutValue<X> outValue = new OutValue<X>();
        outValue.value = value;
        return outValue;
    }
}

Here is an example of how the class could be used to get an integer from a function.

void getInteger(OutValue<Integer> x)
{
    x.value = 1;
}

OutValue<Integer> outValue = OutValue.makeOutValue(0);
getInteger(outValue);
System.out.println("value = " + outValue.value);

It is probably not the most elegant overall solution, but it will keep you from having to write a ton of classes if you do not want to do a more involved refactor.

Matthew T. Staebler
this one is short and does what i want. might be a bad programming practice, but without actually having what i need, this seems like the best approach.
mr popo
A: 

Without more detail, it's difficult to give specific advice. But possibilities include:

Put related functions into a single class and make the data member variables. Like to take your "find and minipulate two smallest":

class ManipulateLeast2
{
  List<int> list;
  int firstSmallest;
  int secondSmallest;

  public ManipulateLeast2(List<int> list)
  {
    this.list=list;
  }
  public void findTwoSmallest()
  {
     .. scan list and populate firstSmallest and secondSmallest ...
  }
  public void processTwoSmallest()
  {
     ... process firstSmallest and secondSmallest and do whatever ...
  }
}

If that's awkward, another possibility is to create a class to hold the values you need and return that. Like:

public class Smallest
{
  int first;
  int second;
  public Smallest(int first, int second)
  {
    this.first=first;
    this.second=second;
  }
}
...
public Smallest findSmallest(List list)
{
  ... find two smallest and put in first and second ...
  // Create the object and return it
  return new Smallest(first, second);
}

I think this is much superior to faking out a pass-by-reference. But if you really insist, it could be done by putting the value in a wrapper, like this:

public StringWrapper
{
  public String s;
}
...
// callee
void getTwoStrings(StringWrapper sw1, StringWrapper sw2)
{
  sw1.s="Hello";
  sw2.s="Goodbye";
} 
// caller
StringWrapper sw1=new StringWrapper();
StringWrapper sw2=new StringWrapper();
getTwoStrings(sw1, sw2);
System.out.println("First is "+sw1.s);
System.out.println("Second is "+sw2.s);

To make this clean you'd need a separate wrapper for each class. I suppose you could make an ObjectWrapper to make it generic and then cast things, but this is getting quite messy.

I think you're much better off to think of how your data relates and move it into logical classes.

Jay
A: 

Just because a method can only have one return type doesn't mean that that type can't contain more than one piece of information. The solution to the type of problem you seem to be having is to declare data types which hold multiple pieces of information.

Following the example in the question ("finding the minimum and second minimum values in a huge collection and then manipulating them"):

public class MinimumHolder {
    private int min;
    private int secondMin;
    public MinimumHolder(int min, int secondMin) {
        this.min = min;
        this.secondMin = secondMin;
    }

    //getters...
}

public MinimumHolder findTwoMinimums(Set<Integer> numbers) {
    // ...
    return new MinimumHolder(...);
}

public MinimumHolder manipulateData(MinimumHolder mins) {
    // do stuff with the data, this method could also be
    // declared as void if MinimumHolder was mutable
}

You could also pretty easily refactor MinimumHolder so that it could hold a variable list of "minimums" which were exposed with a getMinimum(int position) if you ever wanted to find more than two minimums.

matt b
why the downvote - how does this not solve the direct problem?
matt b