Let's say I have such a class:
class C
{
int a, b;
ArrayList<int> c = new ArrayList();
};
and such a collection:
ArrayList<ArrayList<C>> MyList = new ArrayList<ArrayList<C>>();
Would calling MyList.clear() nullify all the references to every ArrayList in the MyList and any additional objects inside of the each ArrayList in MyList? So, more precisely, will all elements inside class C.c be nullified as well as C.a and C.b?
No, but if nothing else has reference to them, they will be eligible for garbage collection.
E.g., simpler example:
class Foo {
Date dt;
Foo() {
this.dt = new Date();
}
}
ArrayList<Foo> list = new ArrayList<Foo>();
list.add(new Foo());
list.clear();
As of the clear, the Foo object's dt has not been "nulled" or anything, but the Foo object and the things only it refers to (the Date inside it, in this case) are eligible for garbage collection.
Whereas:
class Foo {
Date dt;
Foo() {
dt = new Date();
}
}
ArrayList<Foo> list = new ArrayList<Foo>();
Foo f = new Foo();
list.add(f);
list.clear();
Here, the Foo object isn't eligible for garbage collection, because f still refers to it even though the list doesn't. Of course, if f is a local variable in a method, then as soon as the method returns, f goes out of scope — at which point, if nothing else has a reference to the object, it's eligible for GC. But that's beside the point, the point is that when the clear completes, the object is still referenced (by f).
If c is the only object that contains strong references to the contained lists then eventually they'll be garbage collected.
They won't be directly emptied though, just removed from the containing list. For example
ArrayList<C> inner = new ArrayList<C>();
inner.add(new C());
ArrayList<ArrayList<C>> outer = new ArrayList<ArrayList<C>();
ArrayList<ArrayList<C>> outer2 = new ArrayList<ArrayList<C>();
outer.add(inner);
outer2.add(inner);
outer.clear();
In this situation inner will be removed from outer but not from inner2, and since there will be another strong reference to inner, it's not eligible for garbage collection. Otherwise it will be released evenually, but all at once, not by emptying the inner elements.
Related
So I have an object which needs certain variables to be instantiated. These variables are passed to the object through an array of objects. Then, each element in the array gets assigned to an internal variable.
Does this array get garbage collected after the internal variables are assigned and the array is never referenced again, or should it be manually done?
class MyObject () {
public static Object [] values;
public void setvalues(inputArray) {
values = inputArray;
}
}
Memory is kind of important because I need to create a few hundred of these objects plus the rest of the code.
Whether the array is eligible for GC depends on this condition:
Is there anything still referencing the array?
If, you have something like this:
public class Foo {
private int[] myArray = {1, 2, 3, 4};
YourObject obj;
public void someMethod() {
obj = new YourObject(myArray);
}
}
Then myArray is not eligible for garbage collection because the variable myArray in the Foo object is still referencing it. You can then set myArray to null to make it eligible for GC.
If myArray were a local variable, however:
public class Foo {
YourObject obj;
public void someMethod() {
int[] myArray = {1, 2, 3, 4};
obj = new YourObject(myArray);
}
}
Then it is eligible for GC after someMethod returns because myArray will have gone out of scope by then.
Also, note that "eligible for GC" doesn't mean "will be collected immediately". It just mean that the GC has a possibility of collecting it in the future. When exactly? We don't know.
I am assuming your code looks like this
//Client class
o.setValues(arrayOfObjects);
//In the receiving object
public void setValues (Object[] objects){
// Dostuff
}
Two things need to happen for arrayOfObjects to be a candidate for GC -
arrayOfObjects needs to go out of scope. OR
arrayOfObject needs to be assigned another value or null.
If you are really concerned about memory, I would surmise it's the contents of the array that need to be garbage collected, not the array itself. The contents will clearly be referenced by the receiving object, so they will not be garbage collected.
Hope this helps.
During the first launch (after the installation) of my Android application I create nearly 1000 objects and then save them in an SQLite database through greenDAO ORM. I'm new to Java programming and I'd like to ask if I can get better performance by putting in brackets in order to invoke object destruction through the garbage collector.
The code is:
Foo foo1 = new Foo();
Foo foo2 = new Foo();
Foo foo3 = new Foo();
Foo foo4 = new Foo();
.
.
.
Foo foo1000 = new Foo();
And the idea for destroying objects in memory through scopes is:
{
Foo foo1 = new Foo();
Foo foo2 = new Foo();
}
{
Foo foo3 = new Foo();
Foo foo4 = new Foo();
}
{
.
.
.
Foo foo1000 = new Foo();
}
So my idea is that the garbage collector frees objects from memory right after passing each bracket. If this is not the right way, what is your suggestion to achieve better performance in this scenario?
In your case, if you don't ever need to simultaneously hold multiple instances of your class, you might as well create one object and re-use it 1000 times.
Foo my_foo = new Foo();
for(int i = 0; i < 1000; i ++){
my_foo.setValue(i);
saveToDB(my_foo);
}
If those 1000 objects are always created the same you may want to distribute your application with a pre-populated database. There is a good SQLiteAssetHelper library to do that.
As per the below statement,
An array of subclass may be assigned to an array of its superclass. An array of implementing class may be assigned to an array of its interface type. Size is irrelevant.
I wrote below sample code to check the behavior of size in array
interface I{}
class C implements I{}
/* dummy.java*/
public class dummy{
public static void main(String[] args){
C[] c = new C[6];
I[] i = new I[2];
c[0] = new C();
c[1] = new C();
c[2] = new C();
c[3] = new C();
c[4] = new C();
c[5] = new C();
i = c;
System.out.println(i[5].getClass());
}
}
When i say, new C[6];, an object [null,null,null,null,null,null] gets created of type class [LC and c points to this object. When i say, new I[2];, an object [null,null] gets created of type class [LI and i points to this object.
My question:
How interface array is working here, when i say i[5], despite an object [null, null] being created after defining new I[2]? What exactly is happening when i say i = c;? Is size of array of interface new I[2]; getting modified during assignment i = c;?
What that quote is trying to say is that the size of an array is part of the object, ie. it is not part of the reference or the variable type.
In
i = c;
you are assigning a copy of the value of the reference held in c to i. That is, i will reference the same instance as c.
Is size of array of interface new I[2]; getting modified during assignment i=c;?
No, that's the whole point. i and c are just variables. Variable assignment has no side effects.
When you set
i=c
You are setting i to point to the object created by c. Therefore, i will now point to C[6]; < this array
So...
i[1] = new I();
c[1] will return a I object
Lets says I have the code in the entity class:
this.setCurrentState(new NormalState(this));
if in the normal state class I switch the state of the entity to:
entity.setCurrentState(new HungryState(entity));
will the NormalState object be garbage collected event though it holds a reference to the entity that is still active or will it not cause memory leaks?
Java's garbage collector removes all objects who don't have any references to them. If calling the setCurrentState method replaces the stored reference to the instance of NormalState and there isn't another reference to that object in the whole VM, then it's marked as garbage and thus, it'll be collected.
The garbage collector removes all objects not being used; if your NormalState is not held in a variable, nor being used by code, it will be garbage collected. The Entity will also be garbage collected if NormalState was the only object containing a reference to it.
For example, given two classes, A and B, where A contains a B as so:
public class A {
B inner = new B();
public A(B in) {
inner = in;
}
}
myB will be garbage collected (When our A is collected) in the following example:
public static void main(String[] args) {
B myB;
//setting a value with = returns the value
//myB = new B() -> myB
A firstObject = new A(myB = new B())
//bad coding practice, but the fastest way to clear variables
firstObject = null;
myB = null;
}
However, the following will not garbage collect myB because there's still a reference:
public static void main(String[] args) {
B myB;
A firstObject = new A(myB = new B())
A secondObject = new A(myB);
//clear references. secondObject still has a reference to what was myB.
//the now unnamed B will not be collected until secondObject changes.
firstObject = null;
myB = null;
}
NOTE: It's very annoying trying to name an object; as long as it has a variable, it's easy to say myB, but even after your stop calling it myB, it's still there in the computer. I don't know what to call it because I stopped calling it myB when I did myB = null;.
consider the code below :
class B
{
int j =100;
}
class A extends B
{
int i=10;
}
public class Test
{
public static void main(String[] args)
{
A obj =new A();
System.out.println(obj);
B obj1 =obj;
System.out.println(obj1); // here i am confused
if( obj1 instanceof A )
{
System.out.println("yes"); //here i am confused
}
}
}
here the output is :
A#35186a
A#35186a
yes
Now obj1 is an instance of class B which is superclass , so why does the toString() show it to be object of A ? Also how can instanceof operator show it to be instance of class A ?
You have to distinguish between the reference and the actual object.
B obj1 = obj;
Here you create a new reference of type B named obj1. The object referenced is still an A object though, this can never be changed.
obj1 is pointing at obj which is an instance of A (see the new A()) you have got there. On the left hand side you are just referencing the super class. Your obj1 will only be able to see methods in B. obj will be able to see all methods in B and A (subject to correct access)
From the java trail
Declaration: The code left of the = associates a variable name with an object type.
Instantiation: The new keyword is a Java operator that creates the object.
Initialization: The new operator is followed by a call to a constructor, which initializes the new object.
There isn't any toString method in your code, you print the memory place holders (Java don't allow you to see the exact location of the object in the memory).
When you do "extends" you say "A is a son of B",then in the lines:
A obj =new A();
System.out.println(obj);
You create an A object and print is memory place holder (remember, A is son of B, so if you want to describe it, imagine a box called A and a box called B connected to her (on top of her, because it's her father)).
Now in the next lines:
B obj1 =obj;
System.out.println(obj1); // here i am confused
You create another object called obj1 and you assign him the memory place holder of A so, it's the first object that you created, called obj. how can you assign A object to a B? Polymorphism!1 and again you print it's memory place holder.
Next you do if:
if( obj1 instanceof A ){
System.out.println("yes"); //here i am confused
}
So, obj1 is an instanceof of A (it's a box of A and on top of her is a box of B (it's father, polymorphism)), and you print "Yes".
In polymorphism you print the lowest method, so you print the A methods if there is any, and if there isn't you "climbing up" to the father and check there and so on..
Polymorphism (computer science)
Now obj1 is an instance of class B which is superclass
That is not true, obj1 is still an instance of A. You just happen to assign a pointer of the super class to an already existing pointer of class A.
If you want an instance of class B just do this:
B b = new B();
If you want an instance of class A you can do this:
A a1 = new A();
or
B a2 = new A();
The later, a2, is correct because A is of type B. However, a2 is still an instance of A, because we used new A().