Is passing object to constructor pass by reference [duplicate] - java

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 9 years ago.
Suppose I have a class and constructor called TestClass.
public class TestClass {
Foo foo;
public TestClass(Foo foo) {
this.foo = foo;
}
}
Here, the constructor accepts an object which is an instance of class Foo. Suppose my static void main(String[] args) does the following, completely separate from any TestClass;
(1) Instantiate foo
(2) Pass instance foo to TestClass constructor
(3) Change the internal state of foo
After step (3), will the foo within my instance of TestClass also have its state changed?

It is not passed by reference. Rather, it is passed by value of the reference, which is a subtle but important distinction.
After you mutate foo in the rest of your main() method, the foo field will also exhibit these mutations, as you state, since both variables point to the same instance. However, if you reassign foo to something new, the foo field will not be changed. This would not be true if foo were truly passed by reference. In short, everything is passed by value in Java; it just so happens that objects are dealt with by reference, and so the values of these references are passed.
I'll try to illustrate this with an example. Consider the following class:
class A {
public int n;
public A(int n) {
this.n = n;
}
}
and the following method:
public static void mutate(A a) {
a.n = 42;
}
Now we can have something like this:
A a = new A(0);
A.mutate(a);
System.out.println(a.n);
42
We can see that the state of a was changed in mutate(). Now let's modify the static method:
public static void mutate(A a) {
a = new A(42);
}
and try again:
A a = new A(0);
A.mutate(a);
System.out.println(a.n);
0
As you can see, the state of a is unchanged. If the reference had been passed to the function, we would expect the effect of the reassignment to be evident beyond the scope of the method. Nevertheless, some reference was in fact passed, since mutating the argument caused changes outside of the method as well.

Yes, because you are assigning same object to another reference of Foo class, i.e. object is same, but being referred by two reference.

After step (3), will the foo within my instance of TestClass also have
its state changed?
Yes.
You might like to take a read through this
Updated...
Now, assuming you pass the constructor a primitive value...
public class TestClass {
int foo;
public TestClass(int foo) {
this.foo = foo;
}
public String toString() {
return "TestClass: " + foo;
}
}
public static void main(String args[]) {
int myFoo = 1;
TestClass test = new TestClass(myFoo);
myFoo += 2;
System.out.println("myFoo = " + myFoo);
System.out.println("yourFoo = " + test);
}
This will output...
myFoo = 3
yourFoo = 1
Which demonstrates the fact that changing the value of a primitive does not change the value maintained by the constructor/method.
Equally, if you change the object reference after you pass it
public class TestClass {
Foo foo;
public TestClass(Foo foo) {
this.foo = foo;
}
public Foo getFoo() {
return foo;
}
}
public static void main(String args[]) {
Foo myFoo = new Foo();
TestClass test = new TestClass(myFoo);
myFoo = new Foo();
System.out.println("myFoo == yourFoo = " + myFoo.equals(test.getFoo()));
}
Will output
myFoo == yourFoo = false
As the object references are not the same.

Related

Class initialization trouble: static variables are null when accessed [duplicate]

I'm running into a problem when I compile my code. When I compile my code foo2.var returns null in class foo and I can't seem to figure out why. Is there something wrong in how I'm doing the static initialization in the foo2 class to cause foo2.var to be null in the foo class?
Any help is appreciated.
public class foo extends bar {
public final static String blah = foo2.var;
...
}
public abstract class bar {
...
}
public class foo2 extends bar {
public final static String var;
static {
var = "newstring";
}
...
}
Null pointer error on the foo2.var line in this example.
Accessing a static field (whose value is not a compile-time-constant expression) will trigger initialization of the class declaring that field, during which which the static initializers are executed. However, initialization is only guaranteed to have completed by the time the field is read if there is no cyclic dependency among initializers.
For instance, if you run the program
class Bar {
static final long bar;
static {
System.out.println("Assigning bar");
bar = Foo.foo;
}
}
class Foo extends Bar {
static final long foo;
static {
System.out.println("Assigning foo");
foo = 1;
}
}
public class Test {
public static void main(String[] args) {
new Foo();
System.out.println(Bar.bar);
}
}
you get the following output:
Assigning bar
Assigning foo
0
1
because to create a new instance of Foo, Foo.class is initialized, which first initializes its super class Bar.class, which reads the field of Foo.class, but Foo.class is already being initialized. The Java Language Specification mandates in section 12.4.2, step 3, that such a recursive initialization completes immediately, i.e. the caller will see the class in a partially initialized state. That is, Foo.foo is unassigned at the time it is read, and therefore still contains the default value of 0. That value is assigned to Bar.bar, completing initialization of Bar.class. Then, initialization of Foo.class is resumed by running the initializer, which sets Foo.foo to 1.
Practically speaking, you might wish to review the dependencies of your classes and structure your program such that there are no cyclic dependencies among initializers.
You have not specified a type for var try public final static String VAR;
and then why not just
public class foo2 extends bar {
public final static String var = "newstring";
var doesn't have a type. Also constants in Java are uppercase by convention. Make it:
public class Foo2 {
public final static String VAR;
static {
VAR = "newstring";
}
...
}
You are missing a type for var, change that line to the following:
public final static String VAR;
Specify var type.
Also, by coding convention class names should be written in CamelCase and constants, UNDERSCORED_CAPS
public class Foo2 {
public final static VAR = "newstring"; // why not?
...
}
Also, you may shadow foo2 class by some variable. Check your imports. Because class static field reference cannot produce NPE!

Does editing an object within a function mean I need to return it back to update the value

If I edit the data of an object in a function do I need to return the object back to update it in java.
Say I have something like this:
public void foo1() {
Foo foo = new Foo();
someFunction(foo);
// Is the state of foo changed here or not?
}
public void someFunction(Foo foo) {
foo.doSomething();
}
I know objects are passed by reference in java. Will this mean the object is updated/changed at the end of the foo1() function or not?
Does foo change? It's possible but it depends on what the method does.
Here's an example where foo does not change:
public class NoChange {
public static void main(String[] args) {
Foo foo = new Foo();
foo.noChange();
}
}
class Foo {
private int n = 0;
public void noChange() {
System.out.println(n);
}
}
If you run this code, the call to foo.noChange() will print out "0", and nothing in foo will change.
Here's a slight modification of that example which introduces a doChange() method on class Foo. The new method does change something in an instance of Foo – specifically, it takes the value of n and increments it by one.
public class YesChange {
public static void main(String[] args) {
Foo foo = new Foo();
foo.doChange(); // increment n by one
foo.noChange(); // print out n
}
}
class Foo {
private int n = 0;
public void noChange() {
System.out.println(n);
}
public void doChange() {
n++;
}
}
When you run that second example code – which first calls doChange(), then calls noChange() to print out current "n" – the output is "1".
So, the behavior depends on whether the method changes state (for example, by changing setting a value such as incrementing a number) or has side effects (the method might call some other method which in turn does change state). If the method does none of these things, it would be a "pure function".

Java. Can i delete instance of class from method of this class?

public class Foo{
public Foo(){}
public void Method()
{
this = null; //doesn't work
}
}
I know that in C# i can't do this, but may be can in Java?
nope , you can not do.
you will get below error.
The left-hand side of an assignment must be a variable
Can i delete instance of class from method of this class?
There is no instance of the class yet unless you've created it.
Foo foo=new Foo();
You can dereference foo by
foo=null;
Now the foo object which the foo reference points to on the heap will be collected by garbage collector
public class Foo{
public static void main(String[] args)
{
Foo foo=new Foo();
System.out.println(foo);
foo=null;
System.out.println(foo);
}
}
Output
Temp#1a8c4e7
null
Can i delete instance of class from method of this class?
No. Because it doesn't make sense right. You didn't create any object so far and you are trying to dereference it..??
In Java, Memory management is handled by JVM and all the objects are destructed by JVM when they are no more referenced.
So you can not guarantee an instance to be deleted at specific time.
public class Foo {
public Foo() {
}
public void Method() {
// some code
}
}
public class Test {
public static void main(String[] args){
Foo foo = new Foo(); // Constructor-Instance created and referenced
foo = null; // reference variable foo is made null.
}
}
Once foo is made null, the instance for Foo is available for GC.

Global variables and constructor(Java)

When are variables at the top of the class initialized in comparison to the constructor?
Sorry, this is what I meant:
public class aClass {
private int num;
public aClass {...}
Default values (null for object fields, 0 etc. for primitive fields`) are technically never explicitly assigned as far as the emitted bytecode is concerned. (This is done "internally" during object instantiation, before any initializer/constructor code runs.)
Explicit initializer code for instance fields is "copied" at the start of every constructor, after a superclass constructor call (if there is any) in the class by the compiler. The code sample:
class Foo {
int bar = 123;
public Foo() {
// ...
}
public Foo(int bar) {
this.bar = bar;
// ...
}
}
is compiled into bytecode equivalent to:
class Foo {
int bar;
public Foo() {
this.bar = 123;
// ...
}
public Foo(int bar) {
this.bar = 123;
this.bar = bar;
// ...
}
}
Same goes for initializer blocks. This means these variables get initialised before any normal constructor code executes.
Members defined with values are initialized in the constructor, just like any other members. But it's not exactly the constructor you wrote; Java changes each constructor behind the scenes by inserting member initializers and initializer blocks in the beginning of it. You could view it as the members getting initialized just before the constructor, if you want to view it temporally.
Effectively, you can consider them initialized before your constructor gets called. So if you have:
class Dog {
private String voice = "woof";
public Dog() {
System.out.println(voice);
}
}
You'll get "woof" printed to the console successfully, rather than null.

How to pass an object between multiple classes? Java

public class FooClass {
BarClass bar = null;
int a = 0;
int b = 1;
int c = 2;
public FooClass(BarClass bar) {
this.bar = bar;
bar.setFoo(this);
}
}
public class BarClass {
FooClass foo = null;
public BarClass(){}
public void setFoo(FooClass foo) {
this.foo = foo;
}
}
elsewhere...
BarClass theBar = new BarClass();
FooClass theFoo = new FooClass(theBar);
theFoo.a //should be 0
theBar.foo.a = 234; //I change the variable through theBar. Imagine all the variables are private and there are getters/setters.
theFoo.a //should be 234 <-----
How can I pass an object to another class, make a change, and have that change appear in the original instance of the first object?
or
How can I make a cycle where one change to a class is reflected in the other class?
That's already exactly how objects work in Java. Your code already does what you want it to.
When you pass theBar to the FooClass constructor, that's passing the value of theBar, which is a reference to a BarClass object. (theBar itself is passed by value - if you wrote foo = new FooClass(); in the BarClass constructor, that wouldn't change which object theBar referred to. Java is strictly pass-by-value, it's just that the values are often references.)
When you change the value within that object using theBar.foo.a, then looking at the value of a again using theFoo.a will see the updated value.
Basically, Java doesn't copy objects unless you really ask it to.

Categories