Lazy initialization

S

Sreenivas

Hi all,
I have a class like this .

import java.util.ArrayList;
import java.util.List;
public class Book
{
private String ISBN;
private String Title;
private String Author;
private float Price;

public Book(String ISBN)
{
this.ISBN = ISBN;
}

public String getBookName()
{
return Title;
}

public List<Book> getBooks()
{
List<Book> books = new ArrayList<Book>();
//Here goes code for making database connection and loading Book
objects
//into ArrayList
return books;
}
}
Now i have a couple of questions.
When is books (ArrayList ) object created ? I mean, is it created
the moment
i create Book object( Book book = new Book() ) or when i call getBooks
() method on Book object?
Is it fine to place getBooks() method in Book class? or i need to
create an antoher class
place getBooks() method in that class?


I have a difficulty in understanding Lazy Initialization .
Lazy Initialization:
Lazy Initialization for List<Book> in getBooks() method is like this ,
if i am not wrong

public List<Book> getBooks()
{
List<Book> books;
if(books==null)
{
books = new ArrayList<Book>();
//Here goes code for making database connection and loading Book
objects
//into ArrayList
}
return books;
}

If getBooks () method is requested and books variable is null
( doesn't exists in memory) then a new ArrayList<Book> is
created,populated with Book objects and returned.if books variable is
not null(presumably pointing to list of books)
then no database connection is made and List of books is returned.
In this way i am just preventing making of multiple database
connections for each request of getBooks().

If i don't use Lazy Initialization then i am making database
connection for each request of getBooks() method.
So, is my above explanation is right about Lazy Initialization?
Please point me in right direction, if i am wrong.
BTW, this is where i am reading about lazy Initialization
http://martinfowler.com/eaaCatalog/lazyLoad.html
 
P

Philipp

When is  books  (ArrayList ) object created ?

The Arraylist is a local variable. It is created on the call to
getBooks().
Is it fine to place getBooks() method in Book class?

It is probably not a good idea to place getBooks() as an instance
method in the Book class. In order to call it, you will need a Book
object. You would call it like this:
Book myBook = new Book("1234-45");
List<Book> list = myBook.getBooks();

Creating a dummy Book object to do this, doesn't make much sense.

The simplest modification would be to make that method static ( public
static List<Book> getBooks(){...} ) . As such it becomes something
like a helper method which can be called directly using code like
(note, we use the class the name before the dot):
List<Book> list = Book.getBooks();

On the other hand, you are writing about database connection etc. So
making the getBooks() call needs access to some information (database
name, login etc). In this case, it probably makes sense to create a
new class which handles this whole process.


I have a difficulty in understanding Lazy Initialization .
Lazy Initialization:
Lazy Initialization for List<Book> in getBooks() method is like this ,
if i am not wrong

public  List<Book> getBooks()
        {
                List<Book> books;
                if(books==null)
                {
                        books =  new ArrayList<Book>();
                        //Here goes code for making database connection and loading Book
objects
                        //into ArrayList
                }
                return books;
        }

This won't compile, as your local variable books has not been
initialized. What you probably want to do, is to have a member
variable which holds the books, so you can access that variable on
each call of getBooks() (possibly a static Field if you make your call
to getBooks() static, but I think that's a bad idea).

But, lazy initialization is an optimization. At the point where you
are, optimization is the last thing you should think about. First make
it work, then make it fast (if needed only).

I recommend that you read a book about Java to get the basic (like
static, member or local vars etc) before going on.

Best regards
Phil
 
L

Lew

Philipp said:
It is probably not a good idea to place getBooks() as an instance
method in the Book class. In order to call it, you will need a Book
object. You would call it like this:
Book myBook = new Book("1234-45");
List<Book> list = myBook.getBooks();

There might be nothing wrong with that, in particular because the Book object
contains state that might be relevant. Among other things, that state might
include information to make the connection and the connection itself. Often
these things are not readily shareable, necessitating that they be instance level.
Creating a dummy Book object to do this, doesn't make much sense.

In this simplified, stripped-down case it doesn't seem to, but in reality it
usually makes a lot of sense.
The simplest modification would be to make that method static ( public
static List<Book> getBooks(){...} ) . As such it becomes something

Bad advice in many cases.
like a helper method which can be called directly using code like
(note, we use the class the name before the dot):
List<Book> list = Book.getBooks();

Making methods (and variables) static introduces risk that is much easier to
manage at instance level.

One determinant is whether there is state that cannot easily be shared.
Another is thread safety. Such considerations may mandate instance-level action.
On the other hand, you are writing about database connection etc. So
making the getBooks() call needs access to some information (database
name, login etc). In this case, it probably makes sense to create a
new class which handles this whole process.

Sometimes. Looking at JPA, we see that it uses EntityManager to handle
connection details. An object will hold its own EntityManager instance to
access the data store. An EntityManager has instance-level methods to do
things like the 'getBooks()' in this example. Each EntityManager carries its
own state, e.g., connection information. They are not thread safe. If the
query methods of EntityManager were static, the class would be useless.
I have a difficulty in understanding Lazy Initialization .
Lazy Initialization:
Lazy Initialization for List<Book> in getBooks() method is like this ,
if i [sic] am not wrong

public List<Book> getBooks()
{
List<Book> books;

Dude, lighten up on indentation. Don't use TABs to indent Usenet listings.
Limit indent levels to, say, four spaces per level, or even fewer.

As Philipp points out, this is a compiler error.
This won't compile, as your local variable books has not been
initialized. What you probably want to do, is to have a member

Sreenivas, it is a very good practice to compile your examples prior to
posting them on Usenet. That way the only errors will be ones you
intentionally want there. (Sometimes we discuss compiler errors on Usenet, in
which case an example needs to show the relevant errors.)
variable which holds the books, so you can access that variable on
each call of getBooks() (possibly a static Field if you make your call
to getBooks() static, but I think that's a bad idea).

You're right, it's a bad idea.
But, lazy initialization is an optimization. At the point where you
are, optimization is the last thing you should think about. First make
it work, then make it fast (if needed only).

Good point. Also, lazy initialization is rife with danger. It's hard to make
thread safe, and if safe, hard to avoid synchronization slowness if there's a
lot of it.

I've worked on a major project (ca. a million lines of code) where my
predecessors were addicted to unsynchronized lazy initialization of static
variables. That caused major performance bottlenecks, up to tens of seconds
in processes that themselves were on the order of tens of seconds, and
incorrect results.
I recommend that you read a book about Java to get the basic (like
static, member or local vars etc) before going on.

The tutorials, white papers and other material on java.sun.com are a great start.
 
M

markspace

Sreenivas said:
Now i have a couple of questions.
When is books (ArrayList ) object created ? I mean, is it created
the moment
i create Book object( Book book = new Book() ) or when i call getBooks
() method on Book object?


The ArrayList is created when the method is called. You're using local
variables here. That's about as "lazy" as you can get. In this case
that's a good thing.

Is it fine to place getBooks() method in Book class? or i need to
create an antoher class
place getBooks() method in that class?


I find it a bit odd. I would create a second class. However, it's not
actually broken or anything.

I have a difficulty in understanding Lazy Initialization .
Lazy Initialization:
Lazy Initialization for List<Book> in getBooks() method is like this ,
if i am not wrong


Lazy initialization is for member variables, not local variables.
Member means static or instance.

public class Book {

private List<Books> books;

public List<Bootks> getBooks; {
if( books == null ) {
// Lazy init books
}
return books;
}
}


Note that "books" is outside the method. That makes it a member
variable, not a local variable. There's a big difference. You really
should read through the early part of the Java tutorial once again.
Keep an eye out for the distinction between static and instance
variables, and local variables.

Note that this type of lazy initialization in Java IS NOT THREAD SAFE.
That's a big deal because as soon as you mention databases I think of a
system which likely has multiple threads. If this is just a little
class project or something, the code above I showed above is probably OK
for now.

In this way i am just preventing making of multiple database
connections for each request of getBooks().


No your just making a local variable. Which is fine, but the lazy init
part is not needed for local variables. They are always "lazy."
 
A

Arne Vajhøj

Sreenivas said:
import java.util.ArrayList;
import java.util.List;
public class Book
{
private String ISBN;
private String Title;
private String Author;
private float Price;

public Book(String ISBN)
{
this.ISBN = ISBN;
}

public String getBookName()
{
return Title;
}

public List<Book> getBooks()
{
List<Book> books = new ArrayList<Book>();
//Here goes code for making database connection and loading Book
objects
//into ArrayList
return books;
}
}
Now i have a couple of questions.
When is books (ArrayList ) object created ? I mean, is it created
the moment
i create Book object( Book book = new Book() ) or when i call getBooks
() method on Book object?

When you execute:
new ArrayList said:
Is it fine to place getBooks() method in Book class? or i need to
create an antoher class
place getBooks() method in that class?

I would suggest another class.
I have a difficulty in understanding Lazy Initialization .
Lazy Initialization:
Lazy Initialization for List<Book> in getBooks() method is like this ,
if i am not wrong

public List<Book> getBooks()
{
List<Book> books;
if(books==null)
{
books = new ArrayList<Book>();
//Here goes code for making database connection and loading Book
objects
//into ArrayList
}
return books;
}

No.

Lazy loading is when reading the books when getBooks is called and
not at startup.

It can also mean loading books now but wait loading other objects
inside Book until they are needed - but that is not relevant here.

BTW, I do not think the above compiles - books is not initialized.
If getBooks () method is requested and books variable is null
( doesn't exists in memory) then a new ArrayList<Book> is
created,populated with Book objects and returned.if books variable is
not null(presumably pointing to list of books)
then no database connection is made and List of books is returned.
In this way i am just preventing making of multiple database
connections for each request of getBooks().

That can also be implemented. It is caching.
If i don't use Lazy Initialization then i am making database
connection for each request of getBooks() method.
So, is my above explanation is right about Lazy Initialization?
Please point me in right direction, if i am wrong.

You should get a connection from a connection pool every time
you need to access the database.
> BTW, this is where i am reading about lazy Initialization
> http://martinfowler.com/eaaCatalog/lazyLoad.html

Rather brief on the web.

Arne
 
A

Arne Vajhøj

Philipp said:
The Arraylist is a local variable. It is created on the call to
getBooks().

The ArrayList object is created inside getBooks. The reference
is assigned at the call to getBooks.

Arne
 
A

Arne Vajhøj

Lew said:
There might be nothing wrong with that, in particular because the Book
object contains state that might be relevant. Among other things, that
state might include information to make the connection and the
connection itself. Often these things are not readily shareable,
necessitating that they be instance level.

I consider it very unlikely that a design where a Book instance
keeps information needed to load other book instances is a good
OO model.

Arne
 
L

Lew

Arne said:
I consider it very unlikely that a design where a Book instance
keeps information needed to load other book instances is a good
OO model.

@Entity
public class Book
{
@Id private String ISBN;
private String author;
private String title;
@OneToMany Collection <Book> sequels;
@OneToMany Collection <Book> bibliography;
...
}
But generally, I agree with your point. Those collections would be filled by
an instance of some other class than Book. However, it would be by instance
methods, most likely, not static methods of that class.
 
T

Tom Anderson

@Entity
public class Book
{
@Id private String ISBN;
private String author;
private String title;
@OneToMany Collection <Book> sequels;
@OneToMany Collection <Book> bibliography;
...
}

Good point!
But generally, I agree with your point. Those collections would be
filled by an instance of some other class than Book. However, it would
be by instance methods, most likely, not static methods of that class.

That's what i was thinking. It could be called Library, perhaps.

tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top