class A
{
static int i;
A()
{
System.out.println(++i);
}
public static void main(String h[])
{
A obj[] = new A[30];
}
}
A obj[30] = new A[30]; :- this line should invoke the default
constructor 30 times ?
The line
A obj[30] = new A[30];
does not call the constructor for A. It creates 30 uninstantiated references to A;
To instantiate the 30 object references, you can use:
A obj[] = { new A(), new A(), ..28 more ->
};
or better in this case given the number of elements:
for (int i=0; i < obj.length; i++) {
obj[i] = new A();
}
Note, the first use of 30 in the array size declaration is illegal.
A obj[30] = new A[30];
^
No, this line does not invoke constructor at all. It just creates 30 elements long array of type A. Each element of array is null.
There is no way to do exactly what you want to do, but here are two things that come very close, both calling the default constructor 30 times:
A *obj = new A[30];
or
A obj[30];
The first answer will create an array of 30 A objects on the heap, calling the default constructor for each one of them. obj can be passed back to callers of this function since it is not on the stack. The problem is, obj no longer has a type of A[30], so sizeof(obj) will be different from the code in the original question. (Note that "delete []" must be used for obj, not just "delete".)
The second answer will create an array of 30 A objects on the stack. Now the compiler will understand the obj has 30 elements, and sizeof(obj) will be the same as in your question. However, obj can only be used within this function (or functions that it calls) because once the function returns, it will be eliminated from the stack, calling 30 destructors in the process. (It is a local variable only.)
With C++ (or any good object oriented language), creating an object always means both allocating the space and calling the constructor. Otherwise, you really don't have a useful object. So, when an object is created in any supported way (local variable or "new" for C++), it always calls the default constructor for every object you created and now have access to. (Note that if there were no default constructor, then neither answers would even compile!)
Related
This is a pretty simple question but I was wondering about making objects of classes without names. For example, if I had a class 'Zombie' how would I create a new one without assigning a new name each time (e.g., Zombie zombie1 = new Zombie();)
new Zombie() will create a new zombie instance. You do not, however, have to assign it to a local variable or data member if you don't want to. You could, for instance, accumulate these zombies in a collection:
List<Zombie> undeadLegion = new LinkedList<>();
for (int i = 0; i < 1000; ++i) {
undeadLegion.add(new Zombie());
}
What you're referring to is name binding: the association of data with an identifier.
The most common use of binding is to determine the scope of a variable. Bound data is guaranteed by the language to exist (say "in scope"). In Java, the converse is not true: unbound data might still exist on the heap before garbage collection. However, there is no way to access this data, because you have no way to identify it (short of deep magic involving the garbage collector).
You can create unbound data just by writing new Zombie(). You do not have to give it a specific name; it could be an unnamed member of a (named) array:
// Create a new ArrayList<> and bind it to the name list.
List<Zombie> list = new ArrayList<Zombie>();
// Create new Zombie objects, but do not name them.
// Instead, add them to the list.
for (int i = 0; i < 5; ++i) {
list.add(new Zombie());
}
You can also pass an object directly to a function. It won't be bound to any names in the caller's scope, but it will be bound in the callee's scope:
void a()
{
b(new Zombie());
}
void b(Zombie z)
{
}
Here, the new Zombie() is not named in a at all -- but once it's passed to b, it is bound to z.
Finally, you can create an object and do exactly nothing with it:
new Zombie();
It will immediately be unreachable unless its constructor stores a reference to itself somewhere. However, side effects such as printing to the console will still be visible.
Objects don't have names. There is no way to assign a name to the object, nor can you find out what it was at runtime (with help from debug information)
What you may have meant, is how do I avoid declaring a named reference to an object.
The simplest way it to use the reference as an expression like
System.out.println(new Zombie());
Objects don't have names. Variables have names. You don't have to store the result of new into a variable: you can pass it directly as a parameter for example, or just throw it away.
If you want to pass a new object to a method or such, you can just use the constructor call (new Zombie()) without assigning it to a variable.
For example, if you have method called doThingsWithZombie() that takes a Zombie object, you can do the following:
doThingsWithZombie(new Zombie());
You could also add the new object to a list:
LinkedList<Zombie> zombieList = new LinkedList<Zombie>();
zombieList.add(new Zombie()); // Add a zombie
zombieList.add(new Zombie()); // Add a zombie
zombieList.get(0) // Gets the first zombie
While playing in Java. I saw different behaviour if an object is modified and given a value and different value if it is assigned a new object. Here is code that I made to show the result.
public class Test {
int i;
public Test(int j) {
this.i = j;
}
public static void main(String[] args) {
Test A = new Test(5);
Test N = new Test(5);
add(A);
makeNew(N);
System.out.println("Value of A.i= "+A.i);
System.out.println("Value of N.i= "+N.i);
}
private static void add(Test t) {
t.i+= 3;
System.out.println("Inside method add() t.i= "+t.i);
}
private static void makeNew(Test t) {
t = new Test(8);
System.out.println("Inside method makeNew() t.i= "+t.i);
}
}
Here is the output of the above code.
Inside method add() t.i= 8
Inside method makeNew() t.i= 8
Value of A.i= 8
Value of N.i= 5
In above example object A is modified to value 8. And object B is given a new object itself. But calling them back only object A shows new value. Object B shows the old value itself. Should not they be showing same value because both case are pass by refernce? I was expecting same value for A.i and N.i.
Here's what happens:
Test A = new Test(5);
Test N = new Test(5);
add(A); // method is add(Test t)
makeNew(N)// method is makeNew(Test t)
t = new Test(8);
System.out.println("Value of A.i= "+A.i);
System.out.println("Value of N.i= "+N.i);
Whenever you make a variable equal to an object and later use new on that object somewhere else like through another reference, your variable you set to the objects reference no longer points to whatever the new object is, but still holds onto the old. So if multiple variables at different scopes hold a reference, they all need a way to have them made equal to whatever the new object is or they no longer are in synch.
I think this will make you doubt clear:
You see N still point to the first object
In your makeNew, you're overwriting the reference to the existing object (that's passed in as the paramter) with your new test(8) object. However, that's local inside makeNew, so the original object sitting inside main(...) is not affected.
Java is pass-by-value. You pass the reference of an object as a value, and you can thus modify that object. However, you cannot modify the actual reference of an object and make it point to something else.
Your question has already been answered here: Is Java "pass-by-reference" or "pass-by-value"?
In Java you do not pass the actual object nor do you pass the reference to the object. You pass copy of the reference to that object. Now when you say
makeNew(N);
N which is the reference to new Test(5) is not passed but the copy of it's reference is passed. In the makeNew() function this copy points to some new object and print the value appropriately but the N will still point to the original object.
#edit IT works, thanks for the answers:) I guess my bad was when I thought that
WORLD[i]=global.Values.CHUNKPATTERN();
simply takes the object on the right, clones its value('s), and assigns them to part on the left, while it turns out that it establishes a reference between two. Thanks again:)
I have simple begginer/newbie array problem:
for(int i=0; i<global.Values.WORLDVOLUME(); i++)
// global.Values.WORLDVOLUME() --> const, int. always the same.
{
WORLD[i]=global.Values.CHUNKPATTERN(); //to pre-define as 'zero only' object. Always the same. Const.
WORLD[i].chunknr=i+1;
}
System.out.println(WORLD[4].chunknr);
Of course I want WORLD[0] to have chunknr 1, WORLD[4] to have chunknr of 5 and so on.
Instead WORLD[i].chunknr=i+1; seems to update chunknr of ALL elements(not only WORLD[i]).
So that it looks like WORLD[0].chunknr = WORLD[1].chunknr=global.Values.WORLDVOLUME() here.
Anyone knows how to bypass that? I belive there's a simply solution...
Do I understand the array of objects correctly?
You can Have like(providing you have the class and constructor)
Point POINTARRAY[]= new Point[10];
POINTARRAY[1].x=5
POINTARRAY[1].y=6
POINTARRAY[3].x=17
POINTARRAY[3].y=1
Right?
How to assign that via loop?
Instead WORLD[i].chunknr=i+1; seems to update chunknr of ALL elements.
Are WORLD[0] and WORLD[1] different objects? They are not different if `WORLD[0] == WORLD[1] evaluates to true.
You have:
WORLD[i]=global.Values.CHUNKPATTERN();
Does CHUNKPATTERN create a new object every time it is called?
I bet this method
WORLD[i]=global.Values.CHUNKPATTERN();
always returns the same instance of an object so you have a reference to the same object in every slot of your array.
Subsequently
WORLD[i].chunknr=i+1;
you change the attribute chunknr of the same object in every iteration. You say
...seems to update chunknr of ALL elements
kind of true, because all elements reference the same instance.
You need to find a way to have global.Values.CHUNKPATTERN(); return a new object every time.
This line is your problem:
WORLD[i]=global.Values.CHUNKPATTERN();
This is assigning WORLD[i] a reference to global.Values.CHUNKPATTERN(), meaning that they both point to the same object! And for each iteration of your loop you are just creating more and more references to the same global object.
Sometimes this isn't what you want. In this case you need to copy the value, which can be done in a number of ways, but in most cases you can simple clone it. All Java objects support a clone() method, although sometimes you need to override it to do the correct thing for your class.
All this means is that you should replace the above line with:
WORLD[i]=(YourType)global.Values.CHUNKPATTERN().clone();
where YourType is the actual type of the class, since you omitted that from the code snippet you posted.
Hope that helps!
I guess the following line returns always the same reference:
global.Values.CHUNKPATTERN();
so the different array indices are actually point to the same referece. It's only a guess because you didn't tell us how the above function works.
Here's an example of what different array element could point to the same instace:
public class AClass{
public int val = 0;
}
AClass[] array = new AClass[2];
AClass classInstance = new AClass();
array[0] = classInstance;
array[1] = classInstance;
The code above instatiated a single AClass object (classInstance), but use 2 different array elements to reference the same instance:
System.out.println("array 1 value " + array[1].val ); // both element initialized to 0 so it prints 0
array[0].val = 15; // actually is classInstance.val to be modified, through the reference to it stored inside the first element of the array.
System.out.println("array 1 value " + array[1].val ); // print 15
For what concern the POINT example, you can use for loop this way:
Point POINTARRAY[]= new Point[10];
for(int i = 0 ; i < POINTARRAY.length; ++i)
{
POINTARRAY[1].x=...;
POINTARRAY[1].y=...;
}
I have come across two scenarios.
One in which an array is passed as argument to a method and if it is updated in the called method, it is reflecting in the calling method as well.
But in the second scenario, a String Object is passed as argument. The object is updated in the called method, but it doesn't reflect in the calling method.
I want to understand what is the difference between two, even though in both cases, value (of reference) is passed as argument. Please see below snippets.
Scenario 1:
class Test {
public static void main(String[] args){
int a[] = {3,4,5};
changeValue(a);
System.out.println("Value at Index 1 is "+a[1]);
}
public static void changeValue(int b[]){
b[1] = 9;
}
}
Output:
Value at Index 1 is 9
Here, reference (Memory Address) related to array a is passed to changeValue. Hence, b is just pointing to same address as a does.
Hence, whether I say b[1] or a[1], it is referring to same memory address.
Scenario 2:
public class Test {
public static void main(String[] args){
String value = "abc";
changeValue(value);
System.out.println(value);
}
public static void changeValue(String a){
a = "xyz";
}
}
Output:
abc
If I apply the same logic here, String Object VALUE's reference (Memory Address) is being passed to changeValue, which is recieved by a.
Hence, now a should be referring to the same memory location as VALUE does. Therefore, when a="xyz" is executed, it should replace "abc" with "xyz".
Can someone please point out where my understanding goes wrong? Thanks in advance!!
Java passes all its arguments by value. This means that a copy of the pointer to the String is made, and then passed to the method. The method then makes the pointer point at another object, but the original pointer still points to the same String.
This is not the same thing:
in the first example, you pass an array reference as an argument, therefore you correctly expect it to be changed by manipulating the reference directly;
in the second example however, you pass an object reference, sure -- but you change the reference itself in the method. Changes to a are not reflected when the method returns.
Consider any object:
public void changeObj(Object o)
{
o = new Whatever();
}
a new object is created, but it won't change o in the caller. The same happens here.
You're doing different things; with the string you set the parameter value, with the array you set something belonging to the reference.
For an equivalent array example you'd need to try setting the array reference to a new array:
public static void changeValue(int[] b) {
b = new int[] { 42, 60 };
}
The original array won't be changed.
The difference here is simple, and it is not actually about immutability of strings, as some other answers (now edited or deleted) might have originally implied. In one version (with the string), you have reassigned the reference, and in other version (with the array), you haven't.
array[0] = foo; // sets an element, no reassignment to variable
array = new int[] { 1,2,3 }; // assigns new array
obj = "hey"; // assigns new value
When you reassign the variable, you are not going to observe that change outside of the method. When you change elements of an array without reassigning the array variable, you will observe those changes. When you call a setter on an object without reassigning the actual variable of the object, you will observe those changes. When you overwrite the variable (new array, assigning new value, creating new object, etc.) those changes will go unobserved.
Arguments are passed (or copied) by value. The variable inside the method has the same value as the variable on the outside at the beginning. The variables are not linked, and they are not aliases for one another. They just happen to contain the same value. Once you reassign the value to one of them, that is no longer true! The variable on the outside is not affected by the variable on the inside, or even another local variable. Consider
Foo foo = new Foo();
Foo other = foo;
foo.setBar(1);
int bar = other.getBar(); // gets 1
foo = new Foo();
foo.setBar(42);
int bar2 = other.getBar(); // still gets 1
foo and other only referenced the same object for a time. Once foo was assigned a new object, the variables no longer had anything in common. The same is true for your reassignments to the parameter variable inside your method.
Thank you all for answers and updates..
I understood the difference between scenario 1 and 2 as below..
In scenario 1, the array reference is passed. The called method just updates one of the elements pointed by the reference.
While in scenario 2, the reference is passed, but when the called method assigns "xyz" to the reference variable (pointer), it actually creates a new String Object and its reference is assgined to a local reference variable 'a' (Pointer now points a different objct).
The code in called method is as good as
a = new String("xyz");
Hence, the object in called method and calling method are absolutely different and indepenedent and have no relation with each other.
The same could have happened with scenario 1, if instead of doing
b[1] = 9;
I would have used
b = new int[] {8,9,10};
I understood, Mutability fundamentals would have come in action, if I might have done like below..
String a="abc";
a="xyz";
In this case, object "abc" was being pointed by 'a'. When 'a' is assigned the duty to point to a new object "xyz", a new object "xyz" is created, which is not replacing the existing object "abc". i.e. "abc" is still existing but has no reference variable to keep itself accessible anymore. This non-replacement property is because of Immutability of String.
Please advice why primitives being used as method's parameters do a copy of its value while objects are used as is?
In Java, all arguments are passed by value - but in the case of reference types (i.e. everything other than a primitive) the value of a variable isn't the object itself - it's a reference to the object. Thus that reference is copied into the method's parameter, so it refers to the same object.
Note that this doesn't just apply to method calls:
StringBuilder x = new StringBuilder();
StringBuilder y = x; // Copy the value of x, which is a *reference*
y.append("Hello");
System.out.println(x); // Prints "Hello"
Here, x and y refer to the same object, even though they're separate variables. Thus when the contents of that object is changed via the append call through the y variable, the change is visible via the x variable too.
I think of it as being a bit like giving someone the address of your house: if I give two people my home address, and one of them paints the door red, then when the second person visits the house, they'll see the red door too. I'm not giving them my house itself, I'm giving them a way of getting to my house.
There are many, many articles about this - although unfortunately some will claim that objects are passed by reference in Java. They're not - the references are passed by value, as I said above. Scott Stanchfield has a good article about this, amongst many others.
To expand on what Jon Skeet said, primitive types are usually quite small - a double is 8 bytes. Objects, on the other hand, can be HUGE, and so passing a reference to them saves time and stack space versus copying the whole thing. Plus this allows you to modify the contents of the Object.
That's what it looks like but is not. Java is always pass by value.
When you declare something like this:
Date aDate = new Date();
The variable aDate is not really an object, but an object reference. When you pass that object reference to another method, a "copy" of that reference is passed ( just like with primitives a copy of the value is passed )
Now, since those two copies "reference" the same underlaying object, you see that sending a message on one of them affects the other, but if you change the reference to assign a new one, the other doesn't change.
For instance:
class Some {
int data = 0;
}
class Other {
void doSomething( Some o ) {
o.data = 10;
}
void change( Some a ) {
a = new Some();
a.data = 1024;
}
}
class Main {
public static void main( String [] args ) {
// create an object and get its object reference
Some original = new Some();
System.out.println( original.data ); // prints 0
// now pass it to a method from the class "Other"
Other o = new Other();
other.doSomething( original );
System.out.println( original.data ); // prints 10, because data was changed in "doSomething"
// To probe that the reference is not passed, but a copy of it
// invoke the "change" method.
other.change( original );
System.out.println( original.data ); // remains 10, instead of 1024.
// the value 1024 was changed in the new reference, and the one passed along
// didn't change. It still refers to the original object.
}
}
I hope this helps