Scope and destruction of objects in Java and Android - java

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.

Related

What protection does casting do?

The cast to Bar is necessary in this code. I'm trying to understand what problem it avoids. If the compiler would let me use the Foo as a Bar without casting, would it not be able to use the extended functionality that Bar could have? Or is there some more important reason? Or is the example too trivial to explain why I must cast?
class Foo { }
class Bar extends Foo { }
public class Main {
public static void main(String[] args) {
Foo f1 = new Bar();
Bar b1 = (Bar) f1;
}
}
Can we write a simple example where I see and understand that if I don't cast there will be trouble? I could think that the runtime could help itself without casting in the code above, but certainly I have not understood the deep details why I must do the casting.
This protects you from wrong casting. If you will want to use not casted class, which actually is now of type Bar what you will expect to see when using its method? For example you actually make f1 of type Foo, and then you try to make b1 of type Bar point to class Foo. You are trying to invoke method from Bar, but there is no implementation of it. What you expect? Compiler won't know either. In this case if you are trying to cast wrong class you will obtain just java.lang.ClassCastException, which we know how to protect from.
The necessity of the cast becomes more clear if you add another class to your hierarchy. Consider this set of classes instead:
class Foo {}
class Bar extends Foo {}
class Baz extends Foo {}
Now if you have a reference of type Foo, it may refer to a Foo instance, a Bar instance, or a Baz instance. Consider this code snippit:
Foo f;
if (Math.random() > 0.5) {
f = new Bar();
} else {
f = new Baz();
}
You can't simply call f a Bar, because it may be the case that f isn't a Bar, but rather a Baz. Hence, the cast is essentially saying , "I know there's a chance this may fail, but I have reason to believe it won't so go ahead and try it". For example, we could do the following:
Foo f;
if (Math.random() > 0.5) {
f = new Bar();
} else {
f = new Baz();
}
if (f instanceof Bar) {
Bar b = (Bar) f;
// do stuff with b...
}
Within the if block, we have reason to believe that f is a Bar instance, even though the java compiler can't be sure of that. (In this example it seems trivial, but there could be thousands of lines and multiple stack frames separating the if condition and the cast). Hence, we can make the cast with confidence.
If, however, you're wrong about that, that the cast is in fact not valid, you'll get a ClassCastException on the line where the cast was attempted. This makes the issue more clear: instead of getting the exception on a random line where the instance in question doesn't have the desired functionality, it happens where the conversion was attempted.

How does Java dereferencing work?

I need to get some clarification on Java references (pointers).
I have read this (Java is Pass-by-Value, Dammit! by Scott Stanchfield) excellent write up on Java's way of passing variables around. As far as I understand everything is passed around as memory pointers.
public class foo{
int a;
int b;
public foo(a, b){
this.a = a;
this.b = b;
}
}
so in some code like this:
foo aFoo = new foo(1,2); //new foo created at adress 0x40 for instance
someFunc(aFoo);
the argument to someFuncis actually the number 0x40 (albeit this might be a simplification, but to get a sense for the pattern).
Now, suppose i created another class
public class bar{
foo aFoo;
public bar(){
this.aFoo = new foo(1,2);
}
}
and instantiated the following variables
bar aBar = new bar();
foo bFoo = new foo(3,4);
now suppose i want to copy the values of aBar.aFoo into bFoo like
bFoo = aBar.aFoo;
If i now do
bFoo.a = 1234;
did i also just change aBar.aFoo.a into 1234 or does that variable still hold the value 1?
By my own logic, bFoo.a is just a pointer, so assigning a new variable should alter both places, but this seems incorrect. So I guess i have not fully understood Java's "reference is really a pointer" concept. Or rather, i might understand the pointer part of it, but not the dereferencing of the pointers, since this is done implicitly compared to in C where you always know.
bFoo = aBar.aFoo;
-> you have assigned the aBar.aFoo reference to bFoo local variable. This is called aliasing because now you have two ways to refer to the same object: bFoo and aBar.aFoo.
bFoo.a = 1234;
-> you have assigned 1234 to the a field of the object referred to by bFoo. This object is referred to by aBar.aFoo as well.
Result: you have changed the value of aBar.aFoo.a.

Does ArrayList.clear() nullify all objects inside recurcively?

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.

How to perform correctly a deep and a shallow copy in java

1. Definitions
- The class Object has a protected method clone which performs a shallow copy of the object, this method should be overridden in any class cloneable.
- There is a very particular Cloneable interface, when it's implemented in a class, it does not require the redefinition of the clone method.
- The declaration: class X implements Cloneable
mentioned that class X can make a deep copy by calling the clone method which is the clone method of Object class or method provided by X.
1.1 I want to know if the definitions and rules described above are correct or not?
2. Example
When i want to make a deep copy of an object of a class, i used the following example:
class A implements Cloneable
{
int valueA = 10;
B b = new B();
public A clone()
{
A result = new A();
try
{
result = (A)(super.clone());
}
catch (CloneNotSupportedException e)
{
}
return result;
}
}
class B
{
int valueB = 20;
}
public class Test
{
public static void main(String[] args)
{
A a = new A();
A a1 = a.clone();
a1.valueA = 12;
a1.b.valueB = 64;
System.out.println("a.valueA = " + a.valueA);
System.out.println("a1.valueA = " + a1.valueA);
System.out.println("a.b.valueB = " + a.b.valueB);
System.out.println("a1.b.valueB = " + a1.b.valueB);
}
}
The output is :
a.valueA = 10
a1.valueA = 12
a.b.valueB = 64
a1.b.valueB = 64
I see that the deep copy is not well done because the valueB of object field b in object a is modified.
2.1 Why i get this ? is it due to my lack of comprehension of how should i make deep copy ? or the example is not enough ?
2.2 Can anyone give two correct examples of how should i make correctly shallow and deep copy ?
If you want to make a deep copy, then you need to also clone B when you clone A (or create another B instance using, for example, a copy constructor). Object.clone() simply creates a new instance of the objects containing references to the same objects as the object being cloned. It's a shallow copy. There is no way to correctly make a generic deep copy, simply because it often doesn't make sense:
cloning a String, for example, is useless since Strings are immutable
cloning a Socket, for example, makes no sense as a Socket is not clonable, since it represents an active side of a TCP connection, that can't be duplicated.
You should generally avoid using Cloneable. Prefer copy constructors instead. And favor immutability rather than deep copies.

C++'s out parameter object creation and JNA

Disclaimer: I ignore pretty much everything about C++, so I hope I'm not saying stupid things here, if I am, please feel free to correct me.
As a Java developer, when I want to create a new object, I use a constructor method that will allocate this object in memory and return a handle on it for me, and I will store this handle in a variable, I do it like this.
Foo o = new Foo();
But in C++, I've been given to understand, that despite the fact it is possible to do so
Foo createFoo(){
Foo f;
f.doSomething();
return f;
}
// ...
Foo f = createFoo();
I can also define a handle by myself, and then call a initializer on it that will allocate memory and bind the handle on it, like this:
void initializeFoo(Foo **f){
f.doSomething();
return;
}
// ...
Foo f;
initializeFoo(&f);
So my question is, what happens when we want to use those C++ methods in Java, with JNA?
Let's suppose I have the following C++ header:
typedef struct Foo f;
Foo createFoo();
void initializeFoo(Foo **f);
As I don't have any idea on what a Foo is, or what the Foo structure contains, I'm just going to create a JNA PointerType to declare my structure:
public class Foo extends PointerType{
public Foo(Pointer address) {
super(address);
}
public Foo() {
super();
}
}
Using the createFoo method should be pretty easy as well:
public class TestFoo{
static{
System.loadLibrary("foolib");
}
public static void main(String[] args){
FooLib lib = (FooLib)Native.loadLibrary("foolib", FooLib.class);
Foo f = lib.createFoo();
}
Right?
But my question is, how can I use the initializeFoo function??? I suppose I would have to create a Pointer and give it to the function, but how do I create a non NULL pointer in JNA? I tried the following code, but it results in an EXCEPTION_ACCESS_VIOLATION.
public class TestFoo{
static{
System.loadLibrary("foolib");
}
public static void main(String[] args){
FooLib lib = (FooLib)Native.loadLibrary("foolib", FooLib.class);
Foo f = new Foo();
lib.initializeFoo(f); // EXCEPTION_ACCESS_VIOLATION
lib.initializeFoo(f.getPointer()); // EXCEPTION_ACCESS_VIOLATION
}
Any idea?
Thanks!
Foo f;
initializeFoo(&f);
initializeFoo() does not "allocate memory and bind the handle" for f, as you say. Foo f; creates f and allocates it in memory. initializeFoo() could do something like assign values to f's member properties, and the like, as well as create another Foo object and assign it to f, but it does not do what you say.
On the other hand,
Foo *f;
f = new Foo();
declares a Foo pointer. new allocates memory and creates a Foo object, and assigns the memory location to f (you can think of a pointer as a integer containing an address).
I think you want to learn more about C++ and pointers before you go any further.
As I don't have any idea on what a Foo is, or what the Foo structure contains, I'm just going to create a JNA PointerType to declare my structure
This makes it impossible to allocate memory for Foo, as you have to know how much memory you need to allocate. For c structures jna needs a java class mirroring the structure or if you at least know its size you can try to use the Memory class which has a ctor taking a size argument.
For c++ structures and classes using c++ features like inheritance this fails since the required memory and layout depends on the compiler and enabled optimisations.

Categories