Java 8 - Object method reference executes method of null reference [duplicate] - java

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 2 years ago.
Please see my code below. I have a functional interface IFace with a method. I'm creating an implementation using Method reference from a class instance of Test. Can anyone tell me how the interface still refers to the instance method even if the reference is nullified? or reference is changed...?
public class Test {
private int intVar;
public Test() {
intVar = 123;
}
public Test(int intVar) {
this.intVar = intVar;
}
public void myInstanceMethod() {
System.out.println("Hello from instance: " + intVar);
}
public static void main(String[] args) {
Test t = new Test();
IFace i = t::myInstanceMethod;
i.method(); // Hello from instance: 123
t = null; // Nullifying the reference
i.method(); // Hello from instance: 123
// Why still executing the method if reference is nullified?????
t = new Test(456);
i.method(); // Hello from instance: 123
// Why not Hello from instance: 456 ??????
}
static interface IFace {
void method();
}
}

In a sense, the question is similar to asking why printing b does not output null in the following program:
String a = "abc";
String b = a;
a = null;
System.out.println(b);
When IFace i = t::myInstanceMethod; finishes running, i has captured a reference to the object that t points to at this time. That reference is independent from the variable t. Look at it like i, the method reference, has its own variable pointing to the same object.

The memory is not freed when you nullified the reference. It's freed when ALL references are gone. By passing method reference you created new reference to object itself, so the ref count is 2 at that point, i.e. the i holds reference to t underneath

Related

Storing reference to object [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 6 years ago.
I would like to store reference to variable in some class, and make operations on it inside this class. Operations should modify original variable.
In particular following code should print 1 instead of 0.
class Test {
private Long metric;
public Test(Long m) {
this.metric = m;
++this.metric;
}
}
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
Long metric = 0L;
Test test = new Test(metric);
System.out.println(metric);
}
}
How to achieve this behaviour?
You can replace Long with AtomicLong which is mutable. You'll lose autoboxing features though.
The problem in your code is that Integer is an immutable class.
Every time that you change the value you are really building a new instance of Integer.
Doing the same with mutable objects will work.
For example
class Test {
private StringBuilder metric;
public Test(StringBuilder m) {
this.metric = m;
this.metric.append(" Xter");
}
}
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
StringBuilder b = new StringBuilder("Hello ");
Test test = new Test(metric);
System.out.println(b.toString());
// Will print Hello Xter
}
}
As already metioned, the primitive wrapper classes are inmutable.
Since your metric is private in Test, and you want to use its value in the calling method main, you should use the java bean guidelines and use a getter for it:
public Long getMetric(){return this.metric;}
And on main:
metric=test.getMetric();
System.out.println(metric);

Java null object [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 8 years ago.
So as far as I know, in java you can't access objects directly, you only have the pointer to it. So for example I have this code:
public class App {
public App() {
Thing t = null;
doStuff(t);
System.out.println(t);
}
public void doStuff(Thing a) {
a = new Thing();
}
public static void main(String[] args) {
new App();
}
}
class Thing { }
And the output is null. Why? I've passed the pointer to a method which gave it a new Thing instance to point to. Is it because it's a new pointer? Also how can I resolve it without returning anything from doStuff()?
You have references not pointers, and a method cannot update the callers reference without an assignment in the caller - so this
public App() {
Thing t = null;
doStuff(t);
System.out.println(t);
}
public void doStuff(Thing a) {
a = new Thing();
}
Would work if you did,
public App() {
Thing t = null;
t = doStuff(t);
System.out.println(t);
}
public Thing doStuff(Thing a) {
a = new Thing();
return a;
}
This is because Java works by pass by value of Object references and not pass by reference of an Object ,even if the reference is an Object,it still gets passed by the value of reference.So you always work with new references
Refer:http://docs.oracle.com/javase/tutorial/java/javaOO/objectcreation.html
Declaring a Variable to Refer to an Object
Previously, you learned that to declare a variable, you write:
type name; This notifies the compiler that you will use name to refer
to data whose type is type. With a primitive variable, this
declaration also reserves the proper amount of memory for the
variable.
You can also declare a reference variable on its own line. For
example:
Point originOne; If you declare originOne like this, its value will be
undetermined until an object is actually created and assigned to it.
Simply declaring a reference variable does not create an object. For
that, you need to use the new operator, as described in the next
section. You must assign an object to originOne before you use it in
your code. Otherwise, you will get a compiler error.
A variable in this state, which currently references no object, can be
illustrated as follows (the variable name, originOne, plus a reference
pointing to nothing):

Passing object reference to a method [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 8 years ago.
If the Employee reference is made null in the changedetails(), variable id value is retained and NullPointerException is not thrown (Code 1) may be because we just pass a copy of object's reference, but in Code 2 why the variables value has changed
Code 1:
public class JavaPassing {
public static void changedetails(Employee e)
{
e=null;
}
public static void main(String args[])
{
Employee emp = new Employee("Vishal",7);
changedetails(emp);
System.out.println(emp.id);
}
}
Code 2:
public class JavaPassing {
public static void changedetails(Employee e)
{
e.id=9;
}
public static void main(String args[])
{
Employee emp = new Employee("Vishal",7);
changedetails(emp);
System.out.println(emp.id);
}
}
In both cases Reference 'e' in changedetails() and 'emp' in main() both point to same object.
In code (1)
In changedetails() when you make e=null; ONLY e STOPS POINTING TO OBJECT. BUT emp CONTINUES TO POINT TO OBJECT. So in main() when you do emp.id value prints and no NullPointerException
In code (2)
In changedetails() when you make e.id=9 remember Both References are pointing to same object i.e.
'e' in changedetails() and 'emp' in main() point to same object ....
So e.id=9 means change made on same object hence when you do emp.id in main() value is 9
In java references to objects are passed by value.
So,
public static void main(String args[])
{
Employee emp = new Employee("Vishal",7);
changedetails(emp); / /object Employee ahs only one reference - "emp"
System.out.println(emp.id);
}
public void changedetails(Employee emp1){ // here both emp1 and emp of main() point to the same Employee object.
emp1.setId(100); // now since emp1 also points to same Employee object, the data will be changed.
emp1 = null;// now emp1 points to null. So, only emp is pointing to E,ployee
}
--------
A -->| Object |<-- B
--------
A.id = 10; // Property of object modified
B.id = 10; // Property of object modified here also
B = null ; // B is set to null
--------
A -->| Object | B (reference is null)
--------
Here when you set B to null, A is not modified it will continue to point the Object in heap.
And that is why it will not throw NullPointerException if you will access id from reference A. All you are confused is between reference of Object and Object in memory.
In your case, A is emp and B is e.
You can find some good explanation in this question.
The argument you pass into the method changedetails() is a variable of its own, different from the variable emp in your main() method. They both refer to the same eployee so. Hence if you refer to the employee and change its state, the change is visible in both methods, changedetails() and main(). But if you assign null to the argument variable of the method changedetails() this is a local change visible only in that method.
Sidenote: it is considered bad practice to change the value of method arguments. And after leaving the method changedetails(), the method arguments are gone, because they live on the stack and not on the heap.

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
}

Java - This seems like pass by reference to me [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Is Java pass by reference?
So consider the following two examples and their respective output:
public class LooksLikePassByValue {
public static void main(String[] args) {
Integer num = 1;
change(num);
System.out.println(num);
}
public static void change(Integer num)
{
num = 2;
}
}
Output:
1
public class LooksLikePassByReference {
public static void main(String[] args) {
Properties properties = new Properties();
properties.setProperty("url", "www.google.com");
change(properties);
System.out.println(properties.getProperty("url"));
}
public static void change(Properties properties2)
{
properties2.setProperty("url", "www.yahoo.com");
}
}
Output:
www.yahoo.com
Why would this be www.yahoo.com? This doesn't look like passbyvalue to me.
The reference is passed by value. But the new reference is still pointing to the same original object. So you modify it. In your first example with the Integer you are changing the object to which the reference points. So the original one is not modified.
Your first example does:
num = 2
That is the same as
num = new Integer(2)
So you see how it is not quite the same as your second example. If Integer let you set the value in it, you could have done:
num.setValue(2) // I know Integer doesn't allow this, but imagine it did.
which would have done exactly what the second example did.
This is pass-by-value, but the value is the reference to properties, and you don't change it, only some inner field of it.
In the first case you change the reference, not any member of the reference, while in the second you change a member of the reference, but leave the reference as is.
Try this:
public class LooksLikePassByReference {
public static void main(String[] args) {
Properties properties = new Properties();
properties.setProperty("url", "www.google.com");
change(properties);
System.out.println(properties.getProperty("url"));
}
public static void change(Properties properties2)
{
properties2 = new Properties();
properties2.setProperty("url", "www.yahoo.com");
}
}
It prints out "www.google.com".
You are actually passing the value of the reference, so changes made to the object via that reference will be seen. If you assign a new object reference to the parameter, though, that change will not be reflected, since you've only passed the value of the reference, rather than an actual reference to a variable.
That's because properties2 is nothing more than an object reference. This means the references passed to the method are actually copies of the original references. As this illustrates,

Categories