I am trying to write a Java function which has List object as output parameter.
boolean myFunction(int x, in y, List myList)
{
...Do things...
myList=anotherList.subList(fromIndex, toIndex);
return true
}
Before that I call the function I declare myList as follow:
List myList=null;
Then I call the function myFunction(x,y,myList)
But when I try to manipulate myList, I find that myList is still null.
I am sure the variable "antherList" in my function code is not null and I am sure that the subList function return a non-empty List.
What is the reason, and how can pass a List as output parameter in a Java function?
Thank you very much.
Java always uses pass by value. This means that manipulating a passed variable won't affect the variable that was passed by the caller.
In order to solve your problem there are some possibilities:
Return the sublist:
List myFunction(int x, int y) { return anotherList.subList(....);}
I know that this way gets rids of your boolean return value.
Create a structure that holds the pointer to the List and.
class Reference <T>
{
public T ref;
}
boolean myFunction(int x, int y, Reference<List> listRef)
{
listRef.ref = anotherList.subList(....);
return true;
}
Create a structure that holds all the output you want the method to return:
class MyFunctionOutput
{
List list;
boolean b;
}
MyFunctionOutput myFunction(int x, int y)
{
MyFunctionOutput out = new MyFunctionOutput();
out.list = anotherList.subList(....);
out.b = true;
return out;
}
Or the most easy way: pass an initialized List instead of null and let the function add the sublist, like Attila suggested.
You cannot pass an out parameter in Java. You will either need to state the return type as the List or change the contents of the passed list:
boolean myFunction(int x, in y, List myList)
{
...Do things...
myList.clear();
myList.addAll(anotherList.subList(fromIndex, toIndex));
return true
}
Note: out-parameter means that you change the value of the variable containing the value passed to the function. In your case it would mean returning a different List object. Instead, you are returning the same List object, but with changed content.
Think of the parameter as a local copy of the passed value: any changes that replace the whole object will be lost upon the function returning. If you just change its content/state, that change will remain as you are accessing the same object as you have passed in (the local copy is made of the reference pointing to the same object)
Note: it might have been for demonstration purposes, but you should use generics to specify the object contained by the list: e.g. List<String> instead of the raw List type
References in Java are passed by value. So you can't specify an out parameter.
What you can do (however) is to mutate an object passed in. So in your example above, you can pass in an empty List, and populate it within your called method.
i.e. in the above:
myList.addAll(...);
You would likely want to assert as a precondition that the passed list is empty.
I would perhaps suggest that this isn't a very common pattern in the Java world. Because out parameters don't exist, it's not expected behaviour that arguments passed in as parameters would change, and you may be better off creating a suitable object type to return.
The myList variable is local to that function. References are passed by value, not by pointer in the Java world. As soon as you exit, it is removed from the context stack. A possible option is to not return a boolean but return the list itself. Then you can test the list for null to see if your function worked or not.
Another option is to actually create your list, then pass it to the function (non-null). Then your function need not create a new list, but simply add values to it.
A short answer- just return the new list as return value of the function:
List myFunction(int x, in y, List myList) {
...Do things...
return anotherList.subList(fromIndex, toIndex);
}
the long answer is that java copy the pointer of your object when you call a function, that mean that if you assign a new object to the method param, it wouldn't affect the original variable. so you must save the param reference if you want to change the object value.
Related
I have a block of Java code that modifies an ArrayList by passing the ArrayList into a method, modifying the list in the method, and returns void. I thought that Java's pass-by-value would cause the original ArrayList to not be modified. What am I misunderstanding?
public class Question {
public static void weaveLists(LinkedList<Integer> first, LinkedList<Integer> second, ArrayList<LinkedList<Integer>> results, LinkedList<Integer> prefix) {
/* One list is empty. Add the remainder to [a cloned] prefix and
* store result. */
if (first.size() == 0 || second.size() == 0) {
LinkedList<Integer> result = (LinkedList<Integer>) prefix.clone();
result.addAll(first);
result.addAll(second);
results.add(result);
return;
}
/* Recurse with head of first added to the prefix. Removing the
* head will damage first, so we’ll need to put it back where we
* found it afterwards. */
int headFirst = first.removeFirst();
prefix.addLast(headFirst);
weaveLists(first, second, results, prefix);
prefix.removeLast();
first.addFirst(headFirst);
/* Do the same thing with second, damaging and then restoring
* the list.*/
int headSecond = second.removeFirst();
prefix.addLast(headSecond);
weaveLists(first, second, results, prefix);
prefix.removeLast();
second.addFirst(headSecond);
}
public static ArrayList<LinkedList<Integer>> allSequences(TreeNode node) {
ArrayList<LinkedList<Integer>> result = new ArrayList<LinkedList<Integer>>();
if (node == null) {
result.add(new LinkedList<Integer>());
return result;
}
LinkedList<Integer> prefix = new LinkedList<Integer>();
prefix.add(node.data);
/* Recurse on left and right subtrees. */
ArrayList<LinkedList<Integer>> leftSeq = allSequences(node.left);
ArrayList<LinkedList<Integer>> rightSeq = allSequences(node.right);
/* Weave together each list from the left and right sides. */
for (LinkedList<Integer> left : leftSeq) {
for (LinkedList<Integer> right : rightSeq) {
//This is the part I don't understand
ArrayList<LinkedList<Integer>> weaved = new ArrayList<LinkedList<Integer>>();
weaveLists(left, right, weaved, prefix);
result.addAll(weaved);
}
}
return result;
}
}
I would expect that the weaved array would not be modified when the result.addAll(weaved) is called, but weaved array is modified after the call to weaveLists(), even though it returns void.
You create a weaved reference to an ArrayList object that stored in memory. When you call new operator then a new object allocated in the memory. Then you pass the reference weaved to the weaveLists() method.
This method have a reference result, but this is only a reference that refer to the same object in the memory, because only new operator allocate a new memory. So, the weaveLists() method modify your original ArrayList. It is a major feature that you should understand, I suggest you to read the difference between pass-by-value and pass-by-reference.
To answer the question in short - you are misunderstanding what does the pass-by-value mean in Java.
If you pass an object (list in this case) and manipulate it's elements without changing it's reference, it is the same object you passed, nothing changed on the object (list) itself, it has the same reference it had when passed to function, but changes do apply to any of the elements being manipulated.
Pass by value in this context only means that if you created a new instance of a given list within the function and then manipulated it - no changes would apply on original list, since that would be observed as a local variable, not the passed one.
Check top answers to this question, or just read some java basics related to pass-by-value. Use this blog, or any other that you might like more.
I am new to java and I was writing some code to practice, but there is something that I am confused about. I have the following code:
public class test {
public static void main(String[]args) {
int n = 0;
ArrayList<String> fruits = new ArrayList();
setList(fruits);
n =setInt(9);
// get the values from fruits
for (String value: fruits) {
print(value);
}
}
public static void setList( ArrayList list) {
list.add("pear");
list.add("apple");
list.add("pear");
}
public static int setInt(int number) {
number = 3;
return number;
}
}
My question is why in order to set my Arraylist() there is no need to return the any value, but in order to set my int I need to return something.If run this code it prints all the values in my list, but I expected not to print anything because In my method setList I do not return any value. If I did not return any value with my setInt, the value of n would not change, and that makes sense to me.
Thank you.
There are different ways to that params get passed in functions. The usuall way that most beginners start with is pass by value. The other way is pass by reference. In passing by reference, the object itself is pass in, not a copy as is with pass by value. That means any changes will affect the param and remain, even after it is called. All objects in java are passed by reference, only primitives are passed by value. Thus, is why you don't have to return when using arraylist object.
Edit: Actually, I've made an error. What is actually occuring is that a copy of the reference itself is being passed by value. Take a look at this.
Everything in Java is Pass by Value.
I am a little confused as to how my Java program is allocating memory. Below is a typical situation in my program. I have an object created on the Heap inside of a class which I pass to other functions inside of other classes.
public class A {
private List<Integer> list = new ArrayList<Integer>();
public A() {
for(int i = 0; i < 100; i++)
list.add(i);
}
public void foo() {
B b = new B();
b.bar(this.list);
}
}
public class B {
A a = new A();
public int bar(List<Integer> list) {
list.add(-1);
return list.size();
}
public int getSize() {
List<Integer> list = a.list;
return a.size();
}
}
My question(s) are about how the memory is used. When A's list gets passed to B.bar(), does the memory get copied? Java is pass-by-value so I assumed the B.bar() function now contains a copy of the list which is also allocated on the heap? Or does it duplicate the list and put it on the stack? Or is the list duplicated at all? Similarly what applies to these memory questions inside of B.getSize()?
It's probably clearer to say that in Java, object references are passed by value.
So B gets a copy of the reference (which is a value) to the List, but not a copy of the List itself.
You can easily prove this to yourself by getting B to modify the List (by adding or removing something), and observing that A's List also changes (i.e. it is the same List).
However, if you change B's reference to the List (by creating and assigning a new List to it), A's reference is unchanged.
Java is pass-by-value, but the value of an expression or variable is always either a primitive or a reference. A reference, in turn, is either null or a pointer to some object.
In your case: private List<Integer> list = new ArrayList<Integer>(); declares list as having a reference type, and makes its value a pointer to a newly allocated ArrayList object.
When you use list as an actual argument, for example on the b.bar(this.list); call, the formal argument list in b.bar is initialized with a copy of that pointer. That is, bar's formal argument points to the same ArrayList object as A created. The ArrayList object is not copied.
Java is pass-by-value, dammit!
However, you only ever have access to references to Objects. In that sense, you are passing Object references by value.
I know this issue has been addressed many times - but my Java/C++ knowledge is so weak I can barely understand the answers :-( ... what I'd really like is just a super simple example.
In C++ I could write the following:
void func()
{
int x = 3;
add_one(x);
// now x is 4.
}
void add_one(int &var)
{
var++;
}
What I'd like to see now is the simplest way to achieve the same effect with java.
You can't directly. The closest you can get is to put the value in an object, and pass the reference (by value, so the reference gets copied) into the method.
void func()
{
int x = 3;
int[] holder = [x];
add_one(holder);
// now holder[0] is 4. x is still 3.
}
// container here is a copy of the reference holder in the calling scope.
// both container and holder point to the same underlying array object
void add_one(int[] container)
{
container[0]++;
}
Here I use an array, but the wrapper can be any object.
In java method arguments are pass-by-value, and can't be changed in the function. You must wrap the int - or any other primitive type - in an Object or an array. Passing an Object or an array as a method argument passes a reference which can be used to modify the object.
Java already has Object based wrappers for primitive types, e.g. Integer, but these are immutable by design. Some libraries provide mutable versions of these wrappers; you can also create your own:
public class MutableInt
{
private int val;
public MutableInt(int val)
{
this.val = val;
}
public void setValue(int newVal)
{
this.val = newVal;
}
public int getValue()
{
return this.val;
}
}
void func()
{
int x = 3;
MutableInt wrapper = new MutableInt(x);
add_one(wrapper);
}
void add_one(MutableInt arg)
{
arg.setValue(arg.getValue() + 1);
}
You cannot do this. Java is only pass by value. Primitives are obvious, but the thing that's passed for objects is a reference, not the object itself.
As you can see from the other answers, Java is purely pass by value. Objects are passed by what some call "value-reference". Since an object in java is simply a pointer reference, you can think of the "value" as the address where the object lives on the heap. So when you make a method call, you're copying the "value", aka address, to the method parameter:
Object x = new Object();
foo(x);
During object creation
Heap --> allocate Object (5000)
Variable Declaration
Stack --> allocate local variable (1000)
Variable Assignment
Stack address 1000 set to 5000 (to point to object instance)
So you can see that there are two separate memory allocations here. The "value" of the variable is considered to be it's address on the heap.
Method Call
Stack --> allocate method parameter 8000
Stack address 8000 set to same value as passed parameter 5000
This is why if you reassign an object instance in a method, it does not propagate back to the caller. You would have changed the heap location at stack location 8000. And the calling method's stack location 1000 still has the value 5000 (the original object instance).
Think of it like this in C:
void method(myobject * obj);
You can certainly change fields of "obj", and you can do this locally:
obj = new myobject();
But the caller will still see the original value it passed.
Java has no analog to the & reference operator.
And there are built in classes which can be used for the your purposes. AtomicInteger, AtomicLong, etc... are mutable, though you may suffer a performance hit due to synchronization involved.
I would recommend a generic ValueHolder class to account for all situations where you want to simulate pass by reference:
public class ValueHolder<T> {
private T value;
// getter/setter/constructor
}
Java allows copy by reference for objects and copy by vlaue for primitive types (int,float,etc..). This is so by default and is not subject to change. If you need to change the value of an int inside a function, then you can use the class Integer for example
public int getOneMore(int val) {
return val + 1;
}
Can we modify a Boolean value in class function in java, something like this wont work as the change is local to function. How can we make the following change passed variable reflect outside the method call?
public void changeboolean(Boolean b)
{
if( somecondition )
{
b=true;
}
else
{
b=false;
}
}
EDIT
The code could be like this:
public String changeboolean(Boolean b,int show)
{
if( somecondition )
{
b=true;
show=1;
return "verify again";
}
else
{
b=false;
show=2;
return "Logout";
}
show=3;
return verifed;
}
I'm searching for something like this
b.setvalue(true);
Is it possible?
Can we modify a Boolean value in class function in java
No, Boolean is immutable, like all the wrappers for the primitive types.
Options:
Return a boolean from your method (best choice)
Create a mutable equivalent of Boolean which allows you to set the embedded value. You would then need to modify the value within the instance that the parameter refers to - changing the value of the parameter to refer to a different instance wouldn't help you, because arguments are always passed by value in Java. That value is either a primitive value or a reference, but it's still passed by value. Changing the value of a parameter never changes the caller's variable.
Use a boolean[] with a single element as the wrapper type
Use AtomicBoolean as the wrapper type
Boolean is immutable, like all the wrappers for the primitive types.
Soln:
Trying using MutableBoolean of apacheCommon
http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/mutable/MutableBoolean.html