Passing Object reference,Not getting expected result. - java

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");`

Related

Why does this method reference assignment compile?

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.

Why is the output not changed in this code snippet when I use the object form of int?

Given this code snippet:
class Ex1{
public static void main(String args[]){
int x = 10;
int y = new Ex1().change(x);
System.out.println(x+y);
}
int change(int x){
x=12;
return x;
}
}
I understand that the x in main won't get changed by the change method and return the value 22 because Java primitives are call-by-value. However, if I change all the int to Integer, making them objects and therefore theoretically call-by-value-of-reference, why does the program still return 22?
Is it possible to modify the method change such that it also modifies the variable x in main?
EDIT: new snippet
class Ex1{
public static void main(String args[]){
Integer x = 10;
Integer y = new Ex1().change(x);
System.out.println(x+y);
}
Integer change(Integer x){
x=12;
return x;
}
}
Both value and reference types are passed by-value in Java (see the Java Tutorials). This means that the passed-in reference still points at the same object as before the call, even if the internals of a method change the reference assigned to a method's parameter variable.
The primitive wrappers are all reference types, so there is no difference between their behaviour and the behaviour of any other reference type when passed as an argument to a method.
However, you can change the values inside a reference object, and those changes will be reflected after the method call completes, in the calling method. You can't do this with the primitive wrappers though: they are immutable.
public static void main(String[] args){
Foo parentFoo = new Foo(1);
System.out.println(parentFoo); // prints "instance 1, data is now 1"
changeReferenceFail(parentFoo); // prints "instance 2, data is now 2"
System.out.println(parentFoo); // prints "instance 1, data is now 1"
mutateReference(parentFoo); // prints "instance 1, data is now 3"
System.out.println(parentFoo); // prints "instance 1, data is now 3"
}
private static void changeReferenceFail(Foo myFoo) {
myFoo = new Foo(2); // assigns a new object to the myFoo parameter variable
System.out.println(myFoo);
}
private static void mutateReference(Foo myFoo) {
myFoo.setData(3); // changes the reference variable internals
System.out.println(myFoo);
}
...
class Foo {
private static int iidSeed = 0;
private int iid = 0;
private int data;
public Foo(int data) {
this.data = data;
this.iid = ++iidSeed;
}
public void setData(int data) { this.data = data; }
public String toString() {
return String.format("instance %d, data is now %d", this.iid, this.data);
}
}
You asked: "Is it possible to modify the method change such that it also modifies the variable x in main?".
You can either pass a reference object, and modify an internal field (as per mutateReference above). Or you can return a new integer and assign it to your local variableexactly as you are doing already.
Integer change(Integer x){
x=12;
return x;
}
Because this does not change what is stored inside the object Integer x, but assigns a new value to the variable x. It is not the original argument object being changed, but a new Integer object is created assigned to the variable formerly holding the original object.
As you said, when passing an object to a function, you actually pass the value of its reference. Thus, statements like myParam = something have no effect on the object passed to the method, only method calls such as myParam.mutate() can change its state. Nevertheless, Integer is an immutable class so you will not be able by any mean, to change the value of the Integer in the main.
You are passing the value of x to your method, that applies that value to another variable x. You would need to modify the correct instance of x to change it in main. This snippet changes x, although I'm sure you knew how to do this already.
class Ex1{
int x = 10;
public static void main(String args[]){
System.out.println(x);
changeX(15);
System.out.println(x);
}
void changeX(int newVal){
x=newVal;
}
}

How do i get a string to get an integer that is inside a method

I have created an example class for my problem below.
public class testClass {
public void testMethod()
{
int testInteger = 5;
}
String testString = "Hello World" + testInteger;
}
I have an integer inside a method and a string that is in no method as seen above. I want the string to get the integer that inside the method but it cannot. Can someone please help explain why that is so and tell me how to make the string the integer. thanks.
For example:
public class testClass {
public int testMethod()
{
int testInteger = 5;
return testInteger;
}
String testString = "Hello World" + testMethod();
}
The integer is a variable inside the method; it has scope of the method which means it can't be accessed from outside the method. The String is a field; it has scope of the class, so it can be accessed from anywhere inside the class including inside the method.
It's basic Java... the testInteger is defined in the method so not available out of the method. You could let the method return an int (being your testInteger) and call that method.
You cannot access a local variable from another method without returning it.
public int testMethod()
{
int testInteger = 5;
return testInteger;
}
Then you can get the value by calling the method (assuming you have an instance of your class in a reference instance),
String testString = "Hello World" + instance.testMethod();
From The Java Tutorials: Variables,
Local Variables Similar to how an object stores its state in fields, a method will often store its temporary state in local variables. The syntax for declaring a local variable is similar to declaring a field (for example, int count = 0;). There is no special keyword designating a variable as local; that determination comes entirely from the location in which the variable is declared — which is between the opening and closing braces of a method. As such, local variables are only visible to the methods in which they are declared; they are not accessible from the rest of the class.
Lets break down your code to see what is going on
you have such a function
public void testMethod()
{
int testInteger = 5;
}
as you see the return type is void so nothing will be return to anywhere that is called this method.
you have this line after your testMethod
String testString = "Hello World" + testInteger;
first it looks odd why?
because you do not have any main method so I do not know how your code runs
but Imagine you have main method like this
public static void main(String[] args){
String testString = "Hello World" + testInteger;
}
second, you did not even call your testMethod in order to utilize it inside your main method
Issues
1. you did not call your testMethod at all
2. Even if you called it, it would not help you because your return type is void
3. you need main method in order your code to be ran
Remedies
1. change your return type to int
your function signature:
public int testMethod()
2. if you want to use your method, you have to use it in your main method like
for example:
String testString = "Hello World" + testMethod();
3. do not forget to have your main method because it is necessary for your code to be ran
your main method signature is
public static void main(String[] args)

Passing Argument in Java

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.

Java shallow and deep copying JLS [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Java pass by reference issue
In my codes below, methodA will be called, which then delegates a call to methodB, in doing so, methodB assigns the input parameter with String literal "bbb", however, back at methodA, the string literal was not there, which section of the JLS defines this behavior?
package sg.java.test2;
public class TestApple {
public static void main(String args[]){
methodA();
}
public static void methodA(){
String a = null;
methodB(a);
System.out.println(a);
}
public static void methodB(String a){
a = new String("bbb");
}
}
this is a pass by value vs pass by reference issue. Java is pass by value ONLY. When you call
methodB(a)
the reference a gets copied; in the context of methodB, a is a different variable that has the same value as in methodA. So when you change it in methodB, a in methodA still points to the original String.
Another issue that comes into play here is that Strings are immutable, so you can't change the value of a String once it is set. From the docs.
Strings are constant; their values cannot be changed after they are
created.
What you could do is
a = methodB();
and return "bbb" in methodB. There is no reason to pass a in because you are not operating on it; I think you were only doing it to try to change a in the context that calls methodB, which you cannot do.
Finally, the relevant part of the JLS is 8.4.1, which says
When the method or constructor is invoked (§15.12), the values of the
actual argument expressions initialize newly created parameter
variables, each of the declared Type, before execution of the body of
the method or constructor. The Identifier that appears in the
DeclaratorId may be used as a simple name in the body of the method or
constructor to refer to the formal parameter.
Java is pass by value, not pass by reference.
The method signature is shorthand for this:
methodB() {
String a = arguments[0];
i.e. it is a difference reference. When you assign to 'a', you are assigning to the reference 'a' created as part of the method signature, not to the 'a' you declared in the code block that contained the call to methodB().
You can modify the value if it is an object, however.
class MyObj {
String prop;
public MyObj(String s) { prop = s; }
public MyObj() { }
}
public void methodB(MyObj o) {
o.prop = "foo";
}
public void methodA() {
MyObj a = new MyObj();
System.out.println(a.prop); // null
methodB(a);
System.out.println(a.prop); // foo
}

Categories