New to Java here, please help. How arguments are passed in java? Why am I unable to change argument value in the calling method from within called method?
Code
public class PassTest {
public static void changeInt(int value)
{
value=55;
}
int val;
val=11;
changeInt(val);
System.out.println("Int value is:" + val);// calling modifier changeInt
}
Output
Int value is: 11
why it is not 55..?
Java passes by value, not by reference. In your method value contains a copy of the value from val. Modifying the copy does not change the original variable.
You could pass an int wrapped inside an object if you want your changes to be visible to the caller. You can for example use the class org.apache.commons.lang.mutable.MutableInt.
Java : Best way to pass int by reference
Java passes ByValue, meaning the value of the object you put as a parameter is passed, but not the object itself, therefore
val=11;
changeInt(val);
does the exact same thing as
int val=11;
int val2=val
changeInt(val2);
int is a primitive, primitives don't "wrap" a value, you could try to use an Integer class, or make your own class that stores an integer, and then change that classes integer value. Instances of an object are sometimes passed ByReference if setup right. here is an example
MyStringClass.java
public class MyStringClass{
private String string = null;
public MyStringClass(String s){
string = s;
}
public String getValue(){
return string;
}
public void setValue(String s){
string = s;
}
}
and then the workings
public static void addTo(String s){
s += " world";
}
public static void addTo(MyStringClass s){
s.setValue(s.getValue() + " world");
}
public static void main(String[] args){
String s = "hello";
MyStringClass s1 = new MyStringClass("hello");
addTo(s);
addTo(s1);
System.out.println(s);//hello
System.out.println(s1);//hello world
}
I would wonder why you need to change the value instead of just returning it? isn't it easier?
Java passes by Value, it makes a copy which is completely dis-associated with the original variable reference, which means it doesn't have access to change the original int. This is true for primitives as well as object references as well.
You can use AtomicInteger or something like it, to achieve what you are desiring to do.
Primitive variables are passed by value not reference as you are suggesting.
As others said, Java passes byValue by default which means that you are just getting a copy in the function. You can pass byReference, which will pass a pointer to the object and allow you to directly edit but this is not seen as best practice. I would suggest doing it like this:
public class PassTest {
public int changeInt(int value)
{
value = 55;
return value;
}
int val;
val=11;
val = changeInt(val);
System.out.println("Int value is:" + val);// calling modifier changeInt
Here is a Example to pass argument:
class Test {
int a,b;
public Test(int j, int k) {
a=j;
b=k;
}
void change(Test ko){
ko.a=ko.b+ko.a;
ko.a=ko.b-12;
}
}
class sdf {
public static void main(String[] args){
Test op=new Test(12,32);
System.out.println(op.a+" "+op.b);
op.change(op);
System.out.println(op.a+" "+op.b);
}
}
Take a look at this piece of code::
you can see , in this case the action inside change() have affected the object passed to the method
When an object reference is passed to the method ,the reference itself is passed to the method call-by-value . therefore , the parameter receives a copy of the reference used in this argument .As a result A change to the parameter (such as making it refers to the different object ) will not affect the reference used as the argument . however , since the parameter and the argument both refer to the same object , a change through the parameter will affect the object reffered by the argument.
Related
I'm struggling to see why the following code compiles:
public class MethodRefs {
public static void main(String[] args) {
Function<MethodRefs, String> f;
f = MethodRefs::getValueStatic;
f = MethodRefs::getValue;
}
public static String getValueStatic(MethodRefs smt) {
return smt.getValue();
}
public String getValue() {
return "4";
}
}
I can see why the first assignment is valid - getValueStatic obviously matches the specified Function type (it accepts a MethodRefs object and returns a String), but the second one baffles me - the getValue method accepts no arguments, so why is it still valid to assign it to f?
The second one
f = MethodRefs::getValue;
is the same as
f = (MethodRefs m) -> m.getValue();
For non-static methods there is always an implicit argument which is represented as this in the callee.
NOTE: The implementation is slightly different at the byte code level but it does the same thing.
Lets flesh it out a bit:
import java.util.function.Function;
public class MethodRefs {
public static void main(String[] args) {
Function<MethodRefs, String> f;
final MethodRefs ref = new MethodRefs();
f = MethodRefs::getValueStatic;
f.apply(ref);
//is equivalent to
MethodRefs.getValueStatic(ref);
f = MethodRefs::getValue;
f.apply(ref);
//is now equivalent to
ref.getValue();
}
public static String getValueStatic(MethodRefs smt) {
return smt.getValue();
}
public String getValue() {
return "4";
}
}
A non-static method essentially takes its this reference as a special kind of argument. Normally that argument is written in a special way (before the method name, instead of within the parentheses after it), but the concept is the same. The getValue method takes a MethodRefs object (its this) and returns a string, so it's compatible with the Function<MethodRefs, String> interface.
In the Java Tutorial it is explained that there are 4 different types of method references:
reference to a static method
reference to an instance method of a particular object
reference to an instance method of an arbitrary object of a particular type
reference to a constructor
Your case is #3, meaning that when you have an instance of MethodRef i.e. ref, calling apply on your function f will be equivalent to String s = ref.getValue().
For non-static methods, the type of this is considered implicitly to be the first argument type. Since it's of type MethodRefs, the types check out.
public class JavaApplication6 {
public static void a(int b)
{
b++;
}
I am calling the function a and passing the variable b with the intention of incrementing it like a C++ reference (&b). Will this work? If not, why?
public static void main(String[] args) {
int b=0;
a(b);
System.out.println(b);
}
}
While you can't really accomplish that with int (the primitive type for integer), you can accomplish something very similar with AtomicInteger. Simply invoke the getAndIncrement method on an instance of the class. Something like this:
public static void a(AtomicInteger b) {
b.getAndIncrement();
}
(Note that you also can't do this with java.lang.Integer, because java.lang.Integer is an immutable class.)
First of all: Java does not allow for pass-by-reference. Further, out-parameters (when a function's calculations/results are placed in one or more of the variables passed to it) are not used; instead, something is returned from a method like so:
b = a(b);
Otherwise, in Java, you pass objects as pointers (which are incorrectly called references). Unfortunately (in your case) most types corresponding to int (Integer, BigInteger, etc.) are immutable, so you cannot change the properties in the object without creating a new one. You can, however, make your own implementation:
public static class MutableInteger {
public int value;
public MutableInteger(int value) {
this.value = value;
}
}
public static void main(String[] args) {
MutableInteger b = new MutableInteger(2);
increment(b);
System.out.println(b.value);
}
public static void increment(MutableInteger mutableInteger) {
mutableInteger.value++;
}
The following will be printed to the console when this code is run:
3
At the end of the day, using the above requires a strong argument on the programmer's part.
You can't do that with primitive types like int, because Java passes primitives by value. Simply wrap b in a mutable container object :
class Holder {
int b;
}
Now you can modify the value by doing :
public static void a(Holder h) {
h.b++;
}
You should, however, consider to work with Immutable Objects, which are generally considered a good thing in Java to avoid side effects and concurrency issues.
You cannot pass a value by reference in Java. If a primitive is passed to a method, the JVM passes it by value. If it is an object that is sent to a method, the JVM creates a copy of the its reference. Since this is a "copy" the modification won't change the initial object. But still, there are workaround such as using the AtomicInteger suggested in the previous posts.
I know here is no pointer in Java. But how do I change a value in the calling scope? For instance, I want to write a function that takes an integer num, set the integer to 0 if it's greater than 21, otherwise do nothing.
In the main, my code is as follow:
int a=34;
KillOver21(a);
System.out.print(a);
I expect an 0.
Java is pass by value, so a copy of the parameter a is sent to the method, so modification to a in the method will not affect the original argument a in main
The max you can do is return int from KillOver21(a) method
int z = KillOver21(a); // This will return 0
System.out.print(z);
But you can achieve something like that with custom objects, say you have a class
class AHolder {
public int a;
}
then you can expect AHolder instance to change
public static void main(String [] args) {
AHolder a = new AHolder();
a.a = 34;
killOver21(a);
System.out.println(a.a);
}
public static void killOver21(AHolder b) {
if(b.a > 21) {
b.a = 0;
}
}
Since in the latter (even if its Pass by Value) , the reference is copied and both reference point to same object. So changes made inside the killOver21 method actually changes the object.
It is simply not possible, Java supports pass by value. int a's value will be copied to the function.
You could use Object instead of primitive where the reference value will be copied to your function by which you can get the actual object and modify it.
Fundamentally impossible in Java, period. int are immutable, and passed by value. You would need to create a mutable int type:
class MutableInt {
private int value;
public MutableInt(int value) { this.value = value; }
public getValue() { return this.value; }
public setValue(int value) { this.value = value; }
}
Then:
void KillOver21(MutableInt m) {
if(m.getValue() > 21) { m.setValue(0); }
}
However, be aware the mutable types that represent concepts that are defined by their value rather than their identity are generally an extremely bad idea. But, this is the only way to achieve what you're trying to achieve. Again, I caution you with the strongest words: what you're doing is a bad idea. You should find another way.
Doc, it hurts when I do this.
Then don't do that!
The simpliest way (quick&dirty) is to put value within an array
int holder[] = new int[]{ a};
KillOver21(holder)
System.out.printf( "value=[%d]", holder[0] );
void KillOver21(int holder[] ) {
holder[0] = 0;
}
on passing object reference to static method m1() why it does not become null and why last statement doesn't give errror. Output is X
class I {
private String name;
public String name() {
return name;
}
public I (String s) {
name = s;
}
}
class J {
public static void m1 (I i){
i = null;
}
public static void main (String[] arg)
{
I i = new I("X");
m1(i);
System.out.print(i.name());
}
}
Java is pass by value so scope of i is limited to m1()
public static void m1 (I i){ // i is copied from i which is in main method but it is another variable whose scope lies within m1() only
i = null; // original i in main lies in main() method scope
}
If you change name of i in method m1(), confusion will be lesser like :
public static void m1 (I iObj){
iObj = null; // i in main() method still points to Object
}
Java uses pass by value exclusively. Changing the value of i within m1 only changes that parameter's value. It doesn't do anything to the variable i within main.
What may confuse you - it certainly confuses plenty of other people - is that although the arguments are passed by value, if the type of the parameter is a class, then that value is a reference... and indeed the value of the i variable in each case is a reference. That reference is still passed by value - the value of the argument is directly copied as the initial value of the parameter. However, if instead of changing the parameter itself you make a change to the object that the parameter value refers to, that's a different matter:
void foo(StringBuilder builder) {
builder.append("Hello");
}
void bar() {
StringBuilder x = new StringBuilder();
foo(x);
System.out.println(x); // Prints Hello
}
See the Java tutorial on passing information to a method or constructor for more details.
Java is pass by value (Read second answer in the link specially)
I i scope of i is limited to method m1 only.
In execution it looks something like:
`I i` in `m1()` points to `null` reference
I i method reference still points to `new I("X");`
Lets say this is the C++ code:
void change(int& x){
x++;
}
or
void change2(int* a){
*a++;
}
Both will change the global x, right?
So how can I do something like that in java?
Specifically, I want to point to a Vector object
But since Java has no pointers, I'm not sure what to do.
From searching the internet I saw people saying that Java does that in some other way, but I haven't found any real example.
Thanks for
help!
In Java, instead of pointers you have references to objects. You cannot pass a primitive type by reference, but you can wrap a primitive type inside an object and then pass a reference to that object.
Java provides the type Integer which wraps int, however this type is immutable so you cannot change its value after construction. You could however use MutableInt from Apache Commons:
void change(MutableInt x) {
x.increment();
}
The change to x will be visible to the caller.
Specifically, I want to point to a Vector object
When you write Vector v = ...; you are assigning a reference to a vector to the variable v. A reference in Java is very similar to a pointer. References are in fact implemented internally using pointers.
Java uses pass by value. When you pass a vector to a method, you are actually copying a reference to that vector. It does not clone the vector itself. So passing a reference in Java is very similar to passing a pointer in C++.
With Java you cannot pass primitive types like int by reference, they are passed only by value.
The only things you can do is to find artifices to do that, because instead Objects are passed by reference. Here two examples.
Use an array of single value, like this
int[] value = new int[1];
value[0] = 2;
// call a method
obj.setValue(value);
// and in setValue
public void setValue(int[] value) {
value[0] = 5;
}
Or second approach use an holder class:
public class Holder<T> {
public T value;
public Holder(T value) {
this.value = value;
}
}
// then use it in this way
Holder<Integer> h = new Holder<Integer>(2);
obj.setValue(h);
// and in setValue
public void setValue(Holder<Integer> h) {
h.value = 5;
}
In this case I use an holder class implements with generics but you can have a simple holder too, only for integer. For example:
public class IntHolder {
public int value;
public IntHolder(int value) {
this.value = value;
}
}
Java always passes by value and there are no global variables as in the C++ sense. So if you want to do the same as in C++ you need to return the new value.
Thusly:
public int change(int x) {
return ++x;
// or
// return x + 1;
}
To test it:
int x = 2;
change(x);
System.out.println(x); // returns 2
x = change(x);
System.out.println(x); // returns 3
So it doesn't make any sense to let the method be called change, it is more sensible along the lines of calculateThisInt.
Java does pass objects by value. But as Mark Byers mentions the Integer class is immutable and you could use MutableInt from Apache Commons library. To describe how this works you could implement it yourself for your example:
public class MyInt() {
public int i;
public void setInt(int i) {
this.i = i;
}
public int getInt() {
return this.i;
}
public int increment() {
this.i++;
}
}
You need to change your change function to have the above MyInt object as argument:
public void change(MyInt i) {
i.increment();
}
Usage:
MyInt x = new MyInt();
x.setInt(2);
change(x);
System.out.println(x.getInt); // returns 3
In your case you want to change a Vector object...
public void changeVector(Vector v) {
// anything you do with 'v' will change it even
// for the scope that called this method
}
// Usage:
Vector v = new Vector();
changeVector(v);
// v should be changed after calling change vector method
Hope this all makes sense.
Both will change the global x, right?
So how can I do something like that in java? Specifically, I want to
point to a Vector object
The question is somewhat vague, but I got the impression that you ultimately want a global Vector that you can keep stuff in?
Many ways to do that, but one of the simplest is to have a static field in a class, with public static methods for accessing it. (Or simply a public static field which is accessed directly, but that really wouldn't be idiomatic in Java.)
public class Foo {
private static List<Integer> globalVector = new Vector<Integer>();
public static void add(int number){
globalVector.add(number);
}
// ... plus whatever other accessors to the global list that you need
}
Anywhere else in code:
Foo.add(23); // modifies the global vector
(Btw, Vector is kinda obsolete, and typically we'd use ArrayList in its place now. As the Javadoc says, it's been retrofitted to implement the List interface, which I also used in the example.)
While you can't replace an object that's been passed to a function, you can change its state by altering fields directly or calling methods. If you need something like a pointer to a primitive, wrap it in an object. To follow your code, you could do this:
public class IntPointer {
public int value;
public IntPointer(int value) {
this.value = value;
}
}
Then elsewhere you could say:
public static void change(IntPointer ipoint) {
ipoint.value++;
}
public static void main(String[] args) {
IntPointer a = new IntPointer(10);
change(a);
}
This might seem a bit awkward, but it hasn't come up for me as often as you'd think. I'd be more likely to do something like this:
public class ABPair {
private int a = 0;
private int b = 0;
public static void changeA() {
a++;
}
public static void changeB() {
b++;
}
}
So that elsewhere I can say:
public static void main(String[] args) {
ABPair ab = new ABPair();
if (ACondition) {
ab.changeA();
}
}
In other words, my data tends to already be wrapped in some sort of object, and I tend to use the data object's methods to mediate any changes.
Java supports what it calls "references". References act alot like pointers in C/C++-like languages. They don't act the same way "references" work in those languages.
The major differences between a pointer in C and a reference in Java are:
You can't do pointer arithmetic in Java (i.e. you can't "add" or "subtract" from a Java reference, you can only dereference it or compare it with another one).
You can't cast it to an incompatible type: Java is strongly type-safe, you can't "re-interpret" the bytes in memory as some other object.
For some uses of pointers this has no real effect (for example linked lists work pretty much the same in both languages), for others the difference is quite major (arrays in C are just fancy pointer arithmetic, in Java they work quite differently).
So in a way Java references could be called "restricted pointers".