3

May be I am just confused over nothing but here goes:

There are many cases that we have a recursive algorithm that values that we need are modified as we move from one recursion to the next.
Examples could be min max maxNoOfNodes etc.

In C++ one can pass the various parameters as references and all works ok.

In Java though this can not work since everything is copied by value and so one must create an extra class for the argument as a holder in order to modify it inside a function.
So this in C++:

int findLargestSeq(Tree *p, int &min, int &max,Tree *& seqTree)

could not be "translated" as is in Java but would have to be like:
int findLargestSeq(Tree p, Params p)
where Params would encapsulate the min max etc to be updated.

I was wondering is this the only way to go?
Is there a more "clean" approach or standard pattern in Java for this kind of algorithms?

I am thinking that perhaps the fact that we modify the arguments that are passed as reference in C++ is a habbit left-over from C programming while in Java which is pure OO I am also stuck thinking this in this "procedural" manner and can not see that I should somehow deal with these kind of problems differently.

Any input is highly welcome

Cratylus
  • 52,998
  • 69
  • 209
  • 339

5 Answers5

2

In Java, everything is copied. However, besides primitives (int, boolean, char, etc...), everything else is a pointer.

In Java, if you want to return multiple values, you create an aggregator class that contains the multiple values. If you really want to have a void method, or a method in which the given parameters are modified by the method to return the results, you can use the Holder pattern.

Guillaume Polet
  • 47,259
  • 4
  • 83
  • 117
  • +1 from me but I don't like the `Holder` as used in the jax-ws.It is good perhaps for a generic framework like jax-ws but for algorithms I can't see its usefulness.For example if I need to modify the `min` as in the OP and is an integer I wouldn't want to use some `generic` holder – Cratylus Mar 17 '12 at 17:11
2

When the algorithm is complicated enough to need recursive calls to be able to modify state variables as they go on, then a very simple solution is to use private fields in your class.

Riccardo T.
  • 8,907
  • 5
  • 38
  • 78
1

Can I pass parameters by reference in Java?

Use the AtomicReference Template. It looks ugly and long as hell, but I think this will give you the behavior you are looking for.

Community
  • 1
  • 1
Adam Reed
  • 3,294
  • 2
  • 15
  • 15
1

Java prefers to use objects and it only support references to objects, rather than primitives.

One way to re-inteporate

int findLargestSeq(Tree *p, int &min, int &max,Tree *& seqTree)

is

int findLargestSeq(Tree p, int[] min, int[] max,Tree[] seqTree)

which can be called

Tree p = ...
int[] min = { 0 };
int[] max = { Integer.MAX_VALUE };
Tree[] seqTree = { tree };

int ret = findLargestSeq(p, min, max, seqTree);
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • +1 as it is interesting approach.But isn't the method declaration confusing to a reader as it implies a series of values (the array)? And the intent is not obvious.I.e. it is worse on the code-clarity aspect? – Cratylus Mar 17 '12 at 17:49
  • I agree, unless you know that `[]` is a workaround. I would use the approach you mention where they are passed as an object. – Peter Lawrey Mar 17 '12 at 17:54
  • Code evolution: Start with the Lawrey-Method. Move to the user384706-method only when the extra complexity is justified. The reader of your code will only be confused by unneeded complexity. A class "Params"? C'mon. Why didn't the programmer just use the standard idiom for a pointer (the Lawrey method) if that's all that was necessary? On the other hand, the user384706 method would be the way to go if you need a pointer to a generic type. But the programmer should use a bland, generic sounding name like "wrapper" for such classes. Use a descriptive class name once it has has its own metnods – Dale Gerdemann Mar 19 '12 at 19:33
0

In Java, you don't pass a copy of the value, but a copy of the reference.

You can't change the reference by letting it point to another Object inside a method, but - if the object has methods to modify it - modify the object which is referenced.

void failToModify (Foo foo) {
    foo = new Bar (); // Useless
}

void modify (Foo foo) {
    foo.setFoo (new Bar ()); 
}

Note, that this is consistent with arrays:

void failToModify (int[] ia) {
    ia = {3, 4, 5}; // No influence for the caller
}

void modify (int[] ia) {
    ia[0] = 3;
    ia[1] = 4;
    ia[2] = 5;
}

And with build in types too:

void failToModify (int a) {
    a = 8; // No influence for the caller
}

void modifyImpossible (int a) {
    --a; 
    // a build in type is immutable. 
    // You can't modify 8 to be 7.
    // Only the local copy of the reference is decremented.
}

modifyImpossible (8);
int a = 7;
failToModify (a);

You are left with 2 possibilities: Either modify the parameter if it isn't immutable, or return a fresh, new Object. In a recursive method, you can pass a sofar-Object from step to step (a minSofar for example).

user unknown
  • 35,537
  • 11
  • 75
  • 121
  • Yes I know.But this is not what I asking about. – Cratylus Mar 17 '12 at 16:46
  • You wrote `since everything is copied by value`, which isn't the correct expression. Maybe my last modification/paragraph is still not answering your question - it isn't the clearest one. – user unknown Mar 17 '12 at 17:00
  • You are perhaps right on the not accuracy of the `copy by` expression.I understand what you are saying and I understand these subtleties that you mention.What I am looking for is if there is a cleaner/standard approach in designing algorithms dealing with issues like these without using extra objects just serving as wrappers to work-arround the issues that you correctly mention in your answer.Is this clearer now?I mean related to my concern in the OP? – Cratylus Mar 17 '12 at 18:05
  • It's not quiet clear what you mean with "wrappers", and what the code looks, that should be replaced. To me, it isn't clear how `int findLargestSeq (Tree *p, int &min, int &max, Tree *& seqTree)` is supposed to work internally, and how you imagine `int findLargestSeq (Tree p, Params p)` would look like. If you show an real algorithm, one can write an alternate implementation. In the current state it is a guessing game. – user unknown Mar 17 '12 at 21:33
  • But why is this confusing to you?The internal of `findLargestSeq` is irrelevant.What is relevant is that the `min` `max` and `seqTree` are updated in each function call and actually the changes in the function are reflected to the caller.In Java the `min` should be a member of another class in order for the caller to "see" any updates to me.And this class servers only as a wrapper – Cratylus Mar 18 '12 at 08:52
  • @user384706: From the C-Notation, I expect that `int &min` means, the caller is interested in the final result of min, or maybe it is just an attempt to avoid a copy? I don't know. If the result of the whole operation isn't only the size (`return int`), but mint, max and a seqTree, you could return a compound type, in a struct-like class. A third approach can be to create a class, pass that, and modify it's attributes, passing a final state of that class in the end. Or you can produce new instances at each step, which are immutable. Without seeing, what the method does, it is hard to tell. – user unknown Mar 18 '12 at 10:59