Basically i want to add students to a class list. Assuming i have the following code
public class ClassList {
//Constructor methods...
private Student [] studList = new Student [20];
public boolean addStudent (Student newStudent)
{
studList[14] = newStudent;
}
}
Does studList[14] add a reference to newStudent object or copies that object into the studList[14] student object?
As far as i understand newStudent object will get deleted when the method addStudent() is called a second time. So studList[14] will point to null then? What if i want studList[14] to persist throughout the code execution?
Sorry if it is hard to understand, i do not know how to explain my query easier...
There's one fundamental rule in Java that you have to wrap your head around:
The only way you can access an object is via its reference. And the only values that variables can hold are references(*). That's true for local variables, parameters, instance fields and static fields: they all are the same in this respect.
The object itself is never "contained" in a variable.
This directly leads to the answer to your first question:
The reference is copied into the array (as an array can only hold references(*), never objects).
This also mean that "newStudent being deleted" is not actually a big deal: it's just another reference to the same object, and if it goes away nothing much happens.
Now, if all references to a given object are removed (or no longer reachable), then the object itself becomes eligible for garbage collection, but that's not a bad thing, because you could not access it anymore anyway.
(*) ... or primitive values, but we'll ignore those for this dicussion.
The assignment doesn't copy the object. It just adds a reference to the object into the array.
An object gets deleted by the garbage collector after there are no more references to it anywhere. You don't need to worry too much about this process, because it's kind of invisible most of the time; and once there are no references to an object, you couldn't have used it anyway.
Perhaps you want to be able to pass in an int to your method, to tell it which entry in the array to set, instead of always setting entry number 14?
You should have a look at the JLS about types, values and variables:
The values of a reference type are references to objects.
If there is no remaining reference (aside weak ones) to an object it will be garbage-collected out of the heap.
If you call two times: addStudent(new Student());
the first Student object created is qualified for GC since you have no other reference variable "pointing" to the object.
Related
I get stuck in this problem in java docs. The second problem's answer said that after the code execute, "Neither object is eligible for garbage collection. The array students is not eligible for garbage collection because it has one reference to the object studentName even though that object has been assigned the value null. The object studentName is not eligible either because students[0] still refers to it."
But I don't think studentName and students are object, they just variables to refer to objects, and they will not be garbage recycled. I think only the String "Peter Parker" is an object in the code below. What's wrong?
...
String[] students = new String[10];
String studentName = "Peter Parker";
students[0] = studentName;
studentName = null;
....
This statement is fundamentally wrong on more levels than confusing objects and variables.
You are right in that it confuses names and objects, to the highest amount ever seen. Not only is “reference to the object studentName” wrong as studentName is not an object, “even though that object has been assigned the value null” is even worse, as objects can not be assigned to null and what is supposed to explain that setting a reference to null does not imply that the referent becomes unreachable, is achieving the opposite.
But that’s not the end, as the entire logic is wrong. Let’s remove the names, to avoid that confusion. Then, the phrase reads as “The array … is not eligible for garbage collection because it has one reference to the object …”. That’s completely wrong. If X has a reference to Y, it does not prevent the garbage collection of X, as only references to X matter.
What may prevent the garbage collection of the array, is the variable students holding a reference to it, but of course, an author who fails to distinguish between variables and objects, is not able to express this relationship.
It’s worth noting, that if students is a local variable, it does not prevent the garbage collection of the array in every case, as explained in Can java finalize an object when it is still in scope? But skipping this in a tutorial may be acceptable for simplification, see also Lie-to-children.
Another issue is that objects created for string literals like "Peter Parker" will stay in memory as long as there’s at least one piece of code in the JVM having a reference to it, as all string literals (and compile-time constants of type string) of the same contents evaluate to the same object.
If you want to go the route of simplified reasoning about garbage collection, the students variable contains a reference to a String[] array instance, which is prevented from garbage collection due to this reference, and the array contains a reference to a String object, which prevents the String instance from garbage collection (in addition to other references which may exist).
Most of the time, you shouldn’t try to guess what the garbage collector could collect, because the very purpose of the garbage collector is to remove the burden of thinking about this from the developer.
Unfortunately, the doc does not clearly distinguish bewtween variables and objects. There are two objects in this snippet: the array new string[10] and the string "Peter Parker". In line 1 the variable students is set to a reference of the array object; in line 2 the variable studentName is set to a reference of the string object; in line 3 the array element 0 is set to a reference to the string object; and finally in line 4 the variable studentName is set to null.
Now the array object cannot be garbage collected because the variable students still holds a reference and the string objects cannot be garbage collected because the array element 0 still has a reference.
If there were a line 5 where the variable students is set to null as well, both objects could be garbage collected because both are no longer reachable (a string literal however is never garbage collected - but this for another reason). It does not matter that the array element 0 still has a reference to the string object in this case because the array object itself is no longer reachable.
I am currently thinking about how to create n objects of type x in Java.
Thought experiment: You want to create all entries from a specific database table as an object.
The number of entries are given by counting them.
The object to be created is a model of a table entry.
My current strategy would be to create Lists foreach column.
After that, I would create an Object by looping through the Lists, append it to a HashSet and continue with the next row.
But probably there is a problem with the references, because the created objects would have the same name and if I remember right, I would overwrite the pointer by creating another object in this case. So it's the question if the HashSet still contains the old reference or not.
Besides this solution would be very ineffective cause of the number of loops.
Pseudocode
HashSet for objects
lists of every column
iterate through lists
create object with values at position i of loop
append object to HashSet
If you have a clue about to solve the pointer problem or if it does not exist, I would be glad about your answer. Moreover, I would be grateful for more suited solutions.
PS: I did not found any design pattern for this use case
If I'm correctly understanding the "pointer problem" to which you refer, it does not exist. I think you may have some misconceptions about how references, as they are properly called in Java, work.
Take the following code
Set<MyObject> mySet = new HashSet<>();
MyObject myOb;
myOb = new MyObject("Object #1"); // 1
mySet.add(myOb); // 2
myOb = new MyObject("Object #2"); // 3
mySet.add(myOb); // 4
At the lines marked // 1 and // 2 we create a MyObject object with the data "Object #" and add it into a Set; the variable myOb references the object we've just created.
If we were to print the contents of the set at this point, we'd see
{["Object #1"]}
At line // 3, we create another new MyObject object, this time with the data "Object #2", and assign myOb to reference it.
But wait! We've just added myOb (which was referencing an object with the data "Object #1") to the set, and now we're changing myOb to reference a different object. Does that mean our set suddenly looks like:
{["Object 2"]}
No, it doesn't, because what was added to the set was not myOb itself, but the rather the myObject object that myOb happened to be referencing at the moment that mySet.add(myOb) was called. All the set received was a reference to a MyObject instance; it hasn't the slightest clue that the reference happened to be stored in the variable myOb.
Thus we can make myOb reference (or "point to", if you prefer) any other MyObject object (or even the same object again) without affecting the set in the slightest.
Please correct me if I am wrong, I just want some clarification that I'm understanding this right.
When you create an object in java you use the new keyword followed by the class type. Ex. new [someclassnamehere]();
Depending on your constructors you can pass arguments by supplying them in the parameter when you create the object.
I'm not sure if it would ever be useful to just have a line of code that creates a new object o by just using the new keyword, because nothing is actually holding the reference to that information. But it's correct it seems.
So you can create a variable that contains the reference to the new object you are creating by using type name.Such as: Employee someData; . But it has yet to actually reference an object, seeing as one hasn't been created yet. So by applying the above information discussed:
Employee someData = new Employee(name);
We now created an Employee object that contains some name of the employee. The new keyword created an instance of the class Employee, an object, in which the someData variable references that newly created object.
So now the someData variable can be said to reference the Employee object because it contains the address in memory of where the object is stored. This address will allow us to access the actual data of the object, in this case the name of the employee.
If I were to create an ArrayList that has the datatype Employee, I can store Employee objects in it. So I can add the someData variable to the arrayList as well as someData2,someData3,etc. (Just assuming they are all of the same type but contain different employee information).
So each of those variables contain references to these objects. The ArrayList object then contains references to these objects as well because the ArrayList elements contain these someData variables which reference the Employee Objects.
example:
ArrayList.get(1) -> someData -> reference variable(address) -> employee Object
ArrayList.get(2) -> someData2 -> reference variable(address) -> employee Object2
Pretty sure I got the idea down so far, but what slightly throws me off is when you actually don't create a reference variable.
So let's say you create a loop which creates an object(data is being read from some database,etc) and adds it to an ArrayList. In this loop you collect the data you want and use that to create an object, which is then directly added to an ArrayList.
Let's say it looks like this (combination of some pseudo code and actual code)
ArrayList<Employee> list = new ArrayList<Employee>();
// While data from the database still exist (while loop,etc)
// extract some sort of data from the database, such as their name and hours
// create an object of this information and store it in an ArrayList
list.add(new Employee(name, hours);
// end loop
For simplicity, let's said the loop ran 5 times so it created 5 objects.
This means it added 5 objects to the ArrayList List and the references to these objects are actually contained in the ArrayList elements. So to get the first object added to the ArrayList you would use list.get(1) (I'm pretty sure ArrayList start at 1 and not 0 for indexes), which returns the reference to that object.
EDIT: Please forgive me for my mistake here, I suppose I had a brainfart and got mixed up. I don't know why I thought ArrayList indexes worked like that for a second
Is this correct and standard way of creating objects through the use of a loop?
I'm not sure if it would ever be useful to just have a line of code that creates a new object o by just using the new keyword, because nothing is actually holding the reference to that information. But it's correct it seems.
Imagine that the constructor starts a new thread. No reference, but
new AmazingThread();
is fine in that case.
Well, this question is huge. And yes, creating objects like this is completely legit. You can think of ArrayList having it's own variable storing the reference.
I was wondering what would be the advantage of a class variable storing a reference to an object rather than storing the object directly in its memory location?
Does it have to do with memory issues or is it a security issue.
I tried looking around, i could not find this question.
Thanks.
Java stores Object in heap memory but from code we need to access that Object using some handle, and so is the reference
Also while GCing when there is no active reference object is no longer needed and will be GC ready
Its more about memory as while copying or passing object to function you need not create/copy a object you just copy reference.
For Eg:
Class1 a = new Class1();
Class1 b = a;
If you don't store references then in that case you will need to create another Object for b causing duplicity.
Secondly ,
public void(Class1 obj){
//Some operation to Object
}
If you pass whole of Object rather than reference , you will again need memory to hold the copied Object.
If you didn't have referencing it would be impossible to implement most data structures. Consider doubly linked lists, or a tree where the nodes contain parent links.
I've searched but I did not find a good answer.
I've used an ArrayList object.I created an instance object, (example object X), I used that ArrayList as a parameter on constructor object X, but everytime I created an instance of object X, the ArrayList included the old values, didn't create a new ArrayList.
I need to use add method like arraylist. This is the code:
public DataPacket(int hop, int TTL, ArrayList onetimevisit){
this.hop = hop;
this.TTL = TTL;
this.visited = onetimevisit;
}
in other looping process, DataPacket will meet object NodeRandom:
public NodeRandom(int id){
this.id = id;
}
then DataPacket will add the id of NodeRandom.
Is there an Object in Collection isn't static?
I'll take a guess that your issue has to do with an incorrect assumption about how java passes objects as parameters in method calls. Check out this answer: Is Java "pass-by-reference" or "pass-by-value"?
Short answer:
change
this.visited = onetimevisit;
to
this.visited = new ArrayList (onetimevisit);
Longer answer:
ArrayLists are not necessarily static. I think you're incorrectly inferring that the ArrayList must somehow have been set to static from the fact that there is only one copy of the ArrayList when you pass it in the way you've passed it. The thing to understand is that when you pass an object in Java (an ArrayList, for example), you're passing a reference to the object. A reference is something akin to a C-style pointer with the distinction that pointer arithmetic and such is not allowed. When you call a method and pass an object, the called method just gets a copy of the reference and not a copy of the object. Likewise, when you use the = operator to assign one object to another, you're only assigning the references to equal each other, and there is still only one copy of the object. In your code, both this.visited and onetimevisit are references that come to point to the same object in memory.
On the other hand, ArrayList has something that is somewhat akin to a copy constructor. This constructor, called in my sample code above, creates a shallow copy of the given ArrayList, which seems to be what you want. It is worth noting that an ArrayList does not copy the objects added to it (it stores references to them), so perhaps what you really need is to create copies of the objects as well. This would be done by calling their copy constructors (if they allow copying by providing such a constructor) before inserting them into the ArrayList.
If you want a new ArrayList() you have to create one, it won't do it automagically.