Week 4 Notes and Questions
Constructors, factory methods, this, garbage collection
- Recap:
- in Java, a variable is either a "primitive" or a "reference".
- Both primitive and reference variables exist from the point at which
they are declared until the point where they go out of scope. Can be
declared anywhere (not just at the top of a method or code block)
- Both primitive and reference variables have a defined type, given in
their declaration.
- A "primitive" variable "contains" its value. A "reference" variable
contains either null or a reference to an object
- When you define a class, you provide methods which can be used to return
an object of your class to a user. There are two ways of doing this:
- "constructors" provide the functionality to initialize a new object in
various different ways.
- "factory method" - more on this in a minute
- Someone using the "new" operator, is asking to run one of the class
constructors. As long as the constructor works, a reference to the newly
created object will be returned to the caller. The way the object gets
built depends on which constructor is used.
- For example, the "Color" class has various c-tors including:
Color(int rgb)
Color(float r, float g, float b)
Color(int r, int g, int b)
which you could use like this:
Color myColor;
.
.
myColor = new Color(10,20,30);
myColor = new Color(Color.BLACK); // one of various predefined values
- Objects can only ever be created using the "new" operator (with the
exception of "String" which is a special case)
- Once you have created a "new" object, that object will exist at least as
long as there is a reference to it
- There is no way to force the JVM to make an object go away once it has
been constructed.
- There are no "destructors" in Java - there is a special method called
"finalize" method but that is not the same thing.
- There are no "copy constructors" in Java. The only way you'll ever get a
new object of your class created is if someone calls "new" and a
constructor is run.
- What might a constructor do? - initialize its data fields. Maybe do this
based on arguments to constructor. Initializing primitives is easy,
initializing references might well mean calls to "new"
class Person {
int age;
String name;
Color hairColor;
// Copy the values
public Person(String name, int age, Color hair)
{
// 1. what goes here?
this.name = name;
this.age = age;
this.hairColor = hair;
}
public Person(String name, int age)
{
// 2. what goes here?
this(name,age,null);
}
// "Factory" method
static public Person createBlonde(name,age)
{
// 3. what goes here?
return new Person(name,age,new Color(128,128,0));
}
}
1. copy in the user's parameters to the class member variables. Note the
use of "this" to distinguish member variables from user parameters of
the same name
2. no point in duplicating code - "this" here refers to our own
constructor
3. this returns a new Person object - note that the "new" operator is still
used.
- How might you use each of the above methods, given:
Person fred, john, marilyn;
Ans:
nick = new Person("fred",21,Color.black);
john = new Person("john",22);
marilyn = Person.createBlonde("marilyn",36);
- We might decide only to provide a "factory" method - make all our
constructors private. Why do this? In a factory method we don't *have*
to call "new". For example we might return a reference to an object we
created earlier. Why? - maybe our object is read-only, Example:
public static Boolean valueOf(boolean b) {
return (b ? Boolean.TRUE : Boolean.FALSE);
}
Advantages of factory methods:
- don't have to create a brand new object (could return a reference to a
read-only object, as per "Boolean", or maybe maintain a pool of objects
and return the first free one on the list)
- can give method meaningful names (if you have many c-tors it's not easy
to know how each of them differ)
Questions:
1. Get the "Person" class shown above to compile. Note that you'll need to
make some edits - the code above is not entirely correct.
2. Add a field to "Person" which will contain the date and time at which each
"Person" object was created.
3. What happens if you get your program to do:
Person me = new Person("nick",21); // 1
System.out.println("the person is " + me); // 2
Change your class so that line "2" prints out:
the person is nick, who is 21 and was created on xxxxx
where "xxxxx" is the date/time that the object was created
4. Add a loop to your program:
for (int i=0; i<1000; i++) {
Person pp = new Person("test",0);
}
How often do you think the garbage collector will run for this program?
Run the program with garbage collection logging turned on and find out
5. Add the line "System.gc()" to the end of the program. Run it again
with GC logging, what happens?
6. Add several more consecutive "System.gc()" lines, run with logging and
see what happens.
7. Find another class in the Java class libraries which has factory methods.
Explain why they're used in this case.
8. Explain the difference between the following two lines of code:
String myString = new String("hello"); // 1
String myString = "hello"; // 2
Back to index page