Title: Initialization and Cloning
1Initialization and Cloning Slides adapted from
course text Thinking in Java Bruce Eckel
2Guaranteed Initialization with the
Constructor class Rock Rock()
System. out. println(" Creating Rock")
public class SimpleConstructor public
static void main( String args) for(
int i 0 i lt 10 i) new
Rock()
3Method Overloading class Tree int height
Tree() prt(" Planting a
seedling") height 0
Tree( int i) prt(" Creating new Tree
that is " i " feet tall")
height i
4void info() prt(" Tree is " height
" feet tall") void info( String s)
prt( s " Tree is " height
" feet tall") static void prt( String s)
System. out. println( s)
5public class Overloading static Random
rand new Random() static int pRand( int
mod) return Math. abs( rand.
nextInt()) mod public static void
main( String args)
6 int i 0 while( i ! 9)
Tree t new Tree( i pRand( 10))
t. info() t. info(" overloaded
method") // Overloaded
constructor new Tree()
7Default Constructor Takes no Arguments
Compiler creates one for you if you write
exactly 0 constructors class Bird int
i public class DefaultConstructor
public static void main( String args)
Bird nc new Bird() // default!
8this Handle to Current Object public class Leaf
private int i 0 Leaf increment()
i return this // return
handle to //
current object
9void print() System. out. println(" i "
i) public static void main( String args)
Leaf x new Leaf() x. increment().
increment(). increment(). print()
10this Calling Constructors from
Constructors this To clear up ambiguity class
Flower String s Flower( int i) /
... / Flower( String s) / ... /
Flower( String s, int x) this( x)
// if done, must be done first! //! this(
s) // Can't call two! this. s s //
Another use of "this" System. out.
println(" String int args") // ...
11Member Initialization void f() int i // No
initialization i Produces compile-
time error Inside class, primitives are given
default values if you dont specify values
12class Data int i 999 long l //
defaults to zero // ...
13Constructor Initialization Order of
initialization Order that variables/ objects
are defined in class Static data initialization
class Cupboard Bowl b3 new Bowl(
3) static Bowl b4 new Bowl( 4)
14// ... b4 only created on first access or when
first object of class Cupboard is created Its
helpful to summarize the process of creating an
object. Consider a class called Dog 1. The
first time an object of type Dog is created, or
the first time a static method or static field
of class Dog is accessed, the Java interpreter
must locate Dog.class, which it does by
searching through the classpath.
15- As Dog.class is loaded (which creates a Class
object, which - Youll learn about later), all of its static
initializers are - Run. Thus, static initialization takes place
only once, - as the Class object is loaded for the first time.
- When you create new Dog(), the construction
process for a - Dog object first allocates enough storage for a
Dog object - on the heap.
- This storage is wiped to zero, automatically
setting all - The primitives in Dog to their default values
(zero for - numbers and the equivalent for boolean and char).
16- Any initializations that occur at the point of
field definition are executed. - Constructors are executed.
- Assignment and Aliasing
- Assignment of primitives is as you would expect.
If c and d are handles then cd sets c to refer
to the same object as d. This is called aliasing.
17 Aliasing will also occur when you pass an object
into a method. Example Sometype pnew
Sometype() Sometype hp System.out.println(h
inp)
18The code above invokes objects toString(). Why?
19Aliasing Issues Aliasing happens automatically
during argument passing There are no local
objects, only local handles Handles have
scopes, objects do not Object lifetime is never
an issue There is no language support to
prevent objects from being modified (to prevent
negative effects of aliasing)
20Passing Handles All arguments are passed as
handles You never pass the object itself Very
efficient if Youre only reading the object
You want to modify the outside object Sometimes
its necessary to create a local Changes only
affect the local object, not the outside object
Java doesnt support this directly, but
provides cloning
21Making Local Copies In general, you call a
method in order to produce a return value and/or
a change of state in the object that the method
is called for. It is much less common to call a
method in order to manipulate its arguments
this is referred to a calling a method for its
side effects. If you need to modify an argument
during a method call And dont intend to modify
the outside argument, then you Should protect
that argument by making a copy inside your method.
22Cloning Objects To produce pass- by- value
effect, explicitly clone the object thats passed
to you void f( Sheep x) x (Sheep) x.
clone() // Now we have a local sheep
object // Any changes to x are private
changes
23// A simple Int class class Int private int
i public Int( int i) this. i i
public void increment() i public String
toString() return Integer.toString(
i)
24public class Cloning public static void
main( String args) Int v new
Int10 for( int i 0 i lt 10 i )
vi new Int(i) for(int i
0 i lt 10 i) System. out.
print("v" i "" vi " ")
System.out.println() Int v2 (Int)
v. clone()
25// Increment all v2's elements for(int i
0 i lt 10 i) v2i.increment()
// See if it changed v's elements
for(int i 0 i lt 10 i)
System. out. print("v" i "" vi "
")
26Only A Shallow Clone Is Available for Arrays.
v00 v11 v22 v33 v44 v55 v66
v77 v88 v99 v01 v12 v23 v34
v45 v56 v67 v78 v89 v910
- Safest thing to do in this case no guarantee
that object in array are cloneable - If you create a new class you must write code
to make that class cloneable - But why bother?
27// Forgetting to clone may break
encapsulation class BankAccount private
double balance public BankAccount() balance
0 public BankAccount(double
initialBalance) balance initialBalance
public void deposit(double amount) balance
amount public void withdraw(double amount )
balance balance - amount public double
getBalance() return balance public String
toString() return Double.toString(balance)
28class Customer private BankAccount account
private String name public Customer(String
aName) name aName account new
BankAccount(0) public String getName()
return name
29 public BankAccount getAccount()
return account public void
addToAccount(double amt)
account.deposit(amt) public String
toString() return name account
30// Anyone can withdraw money! public class
CustomerTest public static void main(String
args) Customer joe new
Customer("Joeseph Smith") BankAccount
sureItsPrivate joe.getAccount()
joe.addToAccount(1000) sureItsPrivate.withd
raw(100) System.out.println(joe)
Joeseph Smith900.0
31Adding Clonability to a class Object.
clone( ) is protected so you cant normally
access it Must override and make it
public Must also implement the
Cloneable interface A
flag interface Cloneable
// Empty! Allows you to
check it if( myHandle
instanceof Cloneable) //
Tested by Object. clone( ) Virtually
always call Object. clone( ) in your
new clone (via super. clone( ) )
32// Allow others to clone objects of class
BankAccount class BankAccount implements
Cloneable private double balance public
BankAccount() balance 0 public
BankAccount(double initialBalance) balance
initialBalance public void deposit(double
amount) balance amount public void
withdraw(double amount ) balance balance -
amount public double getBalance() return
balance public String toString() return
Double.toString(balance)
33public Object clone() try
Object clonedAccount super.clone()
return clonedAccount
catch(CloneNotSupportedException e)
// can't happen -- we implement cloneable
return null
34class Customer private BankAccount account
private String name public Customer(String
aName) name aName account new
BankAccount(0) public String getName()
return name
35public BankAccount getAccount() return
(BankAccount)account.clone() public void
addToAccount(double amt)
account.deposit(amt) public String
toString() return name account
36// We can only review Joe's account. // We can
change it only through the proper
interface. public class CustomerTest public
static void main(String args) Customer
joe new Customer("Joeseph Smith")
BankAccount sureItsPrivate joe.getAccount()
joe.addToAccount(1000)
sureItsPrivate.withdraw(100)
System.out.println(joe) Joeseph
Smith1000.0
37The Effect of Object. clone( ) Copies the bits
for the exact object (not just the root class
Object) Should always be the first part of your
cloning process (via super. clone( ) ) Copies
the handle values, but not what theyre pointing
to (a shallow copy)
38- To perform a deep copy you must clone the
contents - of the handles as well
- Once you make clone public, it remains public
in derived - classes (the protected trick may only be used
once).
39- Be Careful when cloning a class with references.
- We can provide a clone method for the Customer
class. - We have to remember to clone the account object.
40class Customer implements Cloneable private
BankAccount account private String name
public Customer(String aName) name
aName account new BankAccount(0)
public String getName() return name
41public BankAccount getAccount() return
(BankAccount)account.clone() public
void addToAccount(double amt)
account.deposit(amt) public String
toString() return name "\t" account
42public Object clone() try
Object clonedCustomer super.clone()
((Customer)clonedCustomer).account
(BankAccount)account.clone()
return clonedCustomer
43catch(CloneNotSupportedException e)
// can't happen we implement
// cloneable return
null
44public class CustomerTest2 public static
void main(String args) Customer list
new Customer3 Customer list2
list0 new Customer("Mike") list1
new Customer("Sue") list2 new
Customer("Bill") list2 (Customer)
list.clone()
45for(int j 0 j lt 3 j)
list2j (Customer) listj.clone()
list2j.addToAccount(100) for
(int j 0 j lt 3 j)
System.out.print(listj "\t")
System.out.println() for (int j 0 j lt
3 j) System.out.print(list2j
"\t")
46Inserting Clonability in a derived class class
Person class Hero extends Person class
Scientist extends Person implements Cloneable
public Object clone() try return
super. clone() catch (CloneNotSupportedEx
ception e)
47// This should never happen // It's
Cloneable already! throw new
InternalError() class MadScientist
extends Scientist
48public class HorrorFlick public static void
main( String args) Person p new
Person() Hero h new Hero() Scientist
s new Scientist() MadScientist m new
MadScientist() // p (Person) p. clone()
// Compile error // h (Hero) h. clone() //
Compile error s (Scientist) s. clone()
m (MadScientist) m. clone()
49// Snake.java public class Snake implements
Cloneable private Snake next private char
c // Value of i number of segments
Snake(int i, char x) c x if(--i gt
0) next new Snake(i, (char)(x 1))
50void increment() c if(next ! null)
next.increment() public String
toString() String s "" c if(next
! null) s next.toString() return
s
51public Object clone() Object o null
try o super.clone() catch
(CloneNotSupportedException e) return o
52public static void main(String args)
Snake s new Snake(5, 'a')
System.out.println("s " s) Snake s2
(Snake)s.clone() System.out.println("s2 "
s2) s.increment() System.out.println(
"after s.increment, s2 " s2)
53C\McCarthy\eckelbook\source\c12gtjava Snake s
abcde s2 abcde after s.increment, s2
acdef
54 Homework Why doesnt snake.java work
properly? What changes would you make to fix it?