constructors, garbage collec on, sta cs - computer science
TRANSCRIPT
Constructors, garbage collec0on, sta0cs
CSCI 136: Fundamentals of Computer Science I • Keith Vertanen • Copyright © 2013
Overview
2
• Where Java stores stuff – The Heap – The Stack – Breaking both – Java Garbage Collector (GC)
• CreaAng objects – Copy constructors – Methods creaAng new objects
• StaAc keyword – StaAc methods and instance variables
Stack and Heap • Stack – Where method invocaAons live – Where local variables live – A chunk of memory
• Heap – Where all objects live – Another chunk of memory
3
The Stack • Methods are stacked – When you call a method, the method lands on top of a call stack
– Stack frame • Contains the state of the method • What line it is execuAng • Values of the method's local variables (including parameters)
– Method stays on stack unAl it finishes execuAng
4
5
public void doStuff() { boolean b = true; go(4); } public void go(int x) { int z = x + 24; crazy(); } public void crazy() { char c = 'a'; }
6
public void doStuff() { boolean b = true; go(4); } public void go(int b) { int c = b + 24; crazy(); } public void crazy() { char c = 'a'; }
doStuff() boolean b → true
doStuff() boolean b → true
go() int b → 4 int c → 28
1 2
doStuff() boolean b → true
go() int b → 4 int c → 28
3
crazy() char c → 'a'
doStuff() boolean b → true
go() int b → 4 int c → 28
4
CompuAng a factorial recursively
7
public class Factorial { public static long fact(long n) { if (n <= 1) return 1; return n * fact(n -‐ 1); } public static void main(String [] args) { System.out.println("4! = " + fact(4)); } }
0! = 1 1! = 1 2! = 1 x 2 = 2 3! = 1 x 2 x 3 = 6 4! = 4 x 3 x 2 x 1 = 24
Some example factorials.
main()
fact(4) n → 4
fact(3) n → 3
fact(2) n → 2
fact(1) n → 1
CompuAng a factorial recursively
8
public class Factorial { public static long fact(long n) { if (n <= 1) return 1; return n * fact(n -‐ 1); } public static void main(String [] args) { System.out.println("4! = " + fact(4)); } }
0! = 1 1! = 1 2! = 1 x 2 = 2 3! = 1 x 2 x 3 = 6 4! = 4 x 3 x 2 x 1 = 24
Some example factorials.
main() fact(4) = 24
fact(4) n → 4 return 4 * fact(3)
fact(3) n → 3 return 3 * fact(2)
fact(2) n → 2 return 2 * fact(1)
fact(1) n → 1 return 1
Breaking the stack
9
public class Factorial { public static long fact(long n) { return n * fact(n -‐ 1); } public static void main(String [] args) { System.out.println("4! = " + fact(4)); } }
0! = 1 1! = 1 2! = 1 x 2 = 2 3! = 1 x 2 x 3 = 6 4! = 4 x 3 x 2 x 1 = 24
Some example factorials.
main()
fact(4) n → 4
fact(3) n → 3
fact(2) n → 2
fact(1) n → 1
fact(0) n → 0
fact(-‐1) n → -‐1
fact(-‐2) n → -‐2
Exception in thread "main" java.lang.StackOverflowError at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) ...
Where things live • Local variables live on the stack – Local variables in a method – Parameters passed to a method – Reference variables
• Only the remote control lives on the stack
• Objects live on the heap – When you create objects, they live on the heap – Instance variables of an object
• Stored as part of the object living on the heap
10
The miracle of object creaAon • CreaAng an object in 3 easy steps:
1) Declare a reference variable
11
Heap
Duck myDuck
myDuck
The miracle of object creaAon • CreaAng an object in 3 easy steps:
1) Declare a reference variable 2) Create an object
12
Heap
new Duck();
myDuck
The miracle of object creaAon • CreaAng an object in 3 easy steps:
1) Declare a reference variable 2) Create an object 3) Link the object and the reference
13
Heap
Duck myDuck = new Duck();
myDuck
You have now consumed memory on the heap based on how much state a Duck requires to be stored (i.e. the number and type of its instance variables).
Java Garbage Collector • Java tracks # of variables referring to an object – Once no one refers to an object, its memory can be freed
– Java's automaAc Garbage Collector (GC) periodically handles this for you • Exactly when is up to the JVM • Enjoy it (while it lasts)
14
You're so going to have to this yourself in data structures.
Killing objects • Object-‐killer #1 – Reference goes out of scope permanently
15
public class DuckKiller1 { public static void makeDuck() { Duck d = new Duck(); } public static void main(String [] args) { makeDuck(); while (true) { // Do something } } }
main()
main()
makeDuck()
main()
dHeap
Heap
Killing objects • Object-‐killer #1b – Variable inside curly braces goes out of scope
16
00 public class DuckKiller1b 01 { 02 public static void main(String [] args) 03 { 04 if (args.length >= 0) 05 { 06 Duck d = new Duck(); 07 } 08 while (true) 09 { 10 // Do something 11 } 12 } 13 }
main() line 04 line 05 line 06
dHeap
Killing objects • Object-‐killer #1b – Reference goes out of scope permanently
17
00 public class DuckKiller1b 01 { 02 public static void main(String [] args) 03 { 04 if (args.length >= 0) 05 { 06 Duck d = new Duck(); 07 } 08 while (true) 09 { 10 // Do something 11 } 12 } 13 }
main() line 04 line 05 line 06 line 07 line 08
Heap
Killing objects • Object-‐killer #2 – Assign the reference to another object
18
00 public class DuckKiller2 01 { 02 public static void main(String [] args) 03 { 04 Duck d = new Duck(); 05 System.out.println("quack!"); 06 d = new Duck(); 07 System.out.println("quack!"); 08 d = new Duck(); 09 System.out.println("quack!"); 10 } 11 }
d
Heap
main() line 04
Killing objects • Object-‐killer #2 – Assign the reference to another object
19
00 public class DuckKiller2 01 { 02 public static void main(String [] args) 03 { 04 Duck d = new Duck(); 05 System.out.println("quack!"); 06 d = new Duck(); 07 System.out.println("quack!"); 08 d = new Duck(); 09 System.out.println("quack!"); 10 } 11 }
Heap
d
main() line 04 line 05 line 06
AEer execuFng line 06, no one is referring to the first Duck object anymore. It is now subject to garbage collecFon.
Killing objects • Object-‐killer #2 – Assign the reference to another object
20
00 public class DuckKiller2 01 { 02 public static void main(String [] args) 03 { 04 Duck d = new Duck(); 05 System.out.println("quack!"); 06 d = new Duck(); 07 System.out.println("quack!"); 08 d = new Duck(); 09 System.out.println("quack!"); 10 } 11 }
Heap
d
main() line 04 line 05 line 06 line 07 line 08
AEer execuFng line 08, both the first and second Ducks objects are can be garbage collected.
Killing objects • Object-‐killer #3 – Set the reference variable to null
21
00 public class DuckKiller3 01 { 02 public static void main(String [] args) 03 { 04 Duck d = new Duck(); 05 System.out.println("quack!"); 06 d = null; 07 System.out.println("quack!"); 08 } 09 }
main() line 04
dHeap
Killing objects • Object-‐killer #3 – Set the reference variable to null
22
00 public class DuckKiller3 01 { 02 public static void main(String [] args) 03 { 04 Duck d = new Duck(); 05 System.out.println("quack!"); 06 d = null; 07 System.out.println("quack!"); 08 } 09 }
Heap
main() line 04 line 05 line 06
d
AEer execuFng line 06, no one is referring to the Duck object anymore. The Java garbage collector can now free up the Duck's memory.
Breaking the heap • Memory is not infinite – You can't just keep new'ing objects forever without gefng rid of any
23
import java.util.*; public class HeapDeath { public static void main(String [] args) { ArrayList<Duck> list = new ArrayList<Duck>();
while (true) { Duck d = new Duck(); list.add(d); } } }
While variable d scopes out every loop, the Duck reference persists inside the ArrayList so memory is never freed
Size of variables in Java
24
Type Memory size (bits, 8 bits = byte) byte 8 short 16 int 32 long 64 float 32 double 64 boolean not precisely defined char 16
NOTE: The size of references variables (Strings, arrays, Ducks, etc.) is JVM dependent. But there is always overhead for objects!
25
00 public class HeapPuzzler 01 { 02 public static void main(String [] args) 03 { 04 Duck d = new Duck(); 05 Duck [] a = new Duck[4]; 06 for (int i = 0; i < a.length; i++) 07 a[i] = new Duck(); 08 System.out.println("quack!"); 09 a[0] = null; 10 a[1] = d; 11 System.out.println("quack!"); 12 } 13 }
AAer execu0ng line # Ducks on the heap Variable(s) that point to a Duck object
04
05
08
09
10
26
00 public class HeapPuzzler 01 { 02 public static void main(String [] args) 03 { 04 Duck d = new Duck(); 05 Duck [] a = new Duck[4]; 06 for (int i = 0; i < a.length; i++) 07 a[i] = new Duck(); 08 System.out.println("quack!"); 09 a[0] = null; 10 a[1] = d; 11 System.out.println("quack!"); 12 } 13 }
AAer execu0ng line # Ducks on the heap Variable(s) that point to a Duck object
04 1 d
05
08
09
10
27
00 public class HeapPuzzler 01 { 02 public static void main(String [] args) 03 { 04 Duck d = new Duck(); 05 Duck [] a = new Duck[4]; 06 for (int i = 0; i < a.length; i++) 07 a[i] = new Duck(); 08 System.out.println("quack!"); 09 a[0] = null; 10 a[1] = d; 11 System.out.println("quack!"); 12 } 13 }
AAer execu0ng line # Ducks on the heap Variable(s) that point to a Duck object
04 1 d
05 1 d
08
09
10
28
00 public class HeapPuzzler 01 { 02 public static void main(String [] args) 03 { 04 Duck d = new Duck(); 05 Duck [] a = new Duck[4]; 06 for (int i = 0; i < a.length; i++) 07 a[i] = new Duck(); 08 System.out.println("quack!"); 09 a[0] = null; 10 a[1] = d; 11 System.out.println("quack!"); 12 } 13 }
AAer execu0ng line # Ducks on the heap Variable(s) that point to a Duck object
04 1 d
05 1 d
08 5 d, a[0], a[1], a[2], a[3]
09
10
29
00 public class HeapPuzzler 01 { 02 public static void main(String [] args) 03 { 04 Duck d = new Duck(); 05 Duck [] a = new Duck[4]; 06 for (int i = 0; i < a.length; i++) 07 a[i] = new Duck(); 08 System.out.println("quack!"); 09 a[0] = null; 10 a[1] = d; 11 System.out.println("quack!"); 12 } 13 }
AAer execu0ng line # Ducks on the heap Variable(s) that point to a Duck object
04 1 d
05 1 d
08 5 d, a[0], a[1], a[2], a[3]
09 4 d, a[1], a[2], a[3]
10
30
00 public class HeapPuzzler 01 { 02 public static void main(String [] args) 03 { 04 Duck d = new Duck(); 05 Duck [] a = new Duck[4]; 06 for (int i = 0; i < a.length; i++) 07 a[i] = new Duck(); 08 System.out.println("quack!"); 09 a[0] = null; 10 a[1] = d; 11 System.out.println("quack!"); 12 } 13 }
AAer execu0ng line # Ducks on the heap Variable(s) that point to a Duck object
04 1 d
05 1 d
08 5 d, a[0], a[1], a[2], a[3]
09 4 d, a[1], a[2], a[3]
10 3 (d, a[1]), a[2], a[3]
Copy constructors • Copy constructor – A special constructor – Parameter is another object of the same type – Simply copies all the state of the passed in object
31
public class Duck { private String name = ""; private double weight = 0.0; public Duck(Duck otherDuck) { this.name = otherDuck.name; this.weight = otherDuck.weight; } }
A copy constructor!
Methods giving birth • An instance method can create a new object and return it
32
public Block move(double x, double y) // Create a new block based on this block // but at a new (x,y) position public Block rotate() // Create a new block based on this block // but rotated by 90 degrees
Hey rabbit, what do you know? "My locaAon and my size!" Hey rabbit, what can you do? "I can draw myself and I can tell if somebody clicks on me. Ohh and um, well you know, I can make them there baby rabbits…"
public class Rabbit { private double x = 0.0; private double y = 0.0; private static final double size = 0.06; public Rabbit(double x, double y) { this.x = x; this.y = y; } public void draw() { StdDraw.picture(x, y, "rabbit.png"); } public boolean intersect(double x, double y) { double deltaX = (this.x -‐ x); double deltaY = (this.y -‐ y); return (Math.sqrt(deltaX * deltaX + deltaY * deltaY) < size); } ...
Rabbit class, part 1
33
public Rabbit breed() { Rabbit baby = new Rabbit(this.x + (0.2 -‐ Math.random() * 0.4), this.y + (0.2 -‐ Math.random() * 0.4)); return baby; } public static void main(String [] args) { ArrayList<Rabbit> rabbits = new ArrayList<Rabbit>(); rabbits.add(new Rabbit(0.5, 0.5)); while (true) { for (int i = rabbits.size() -‐ 1; i >= 0; i-‐-‐) { Rabbit r = rabbits.get(i); r.draw();
if (r.intersect(StdDraw.mouseX(), StdDraw.mouseY())) rabbits.add(r.breed()); } StdDraw.show(100); } } }
Rabbit class, part 2
34
StaAc vs. non-‐staAc methods • StaAc methods – Forbidden from using instance vars of the class
• Non-‐staAc methods (instance methods) – Allowed to use instance vars
• A class can have: – All staAc methods
• e.g. Math class
– All non-‐staAc methods – A mix of both
• e.g. Wrapper classes like Double and Integer
35
Math.java
36
Method signature Descrip0on public static int round(float a) Round to the nearest integer
public static long round(double a)
public static int min(int a, int b) Find the minimum of two numbers
public static long min(long a, long b)
public static float min(float a, float b)
public static double min(double a, double b)
public static int abs(int a) Return absolute value of a number
public static long abs(long a)
public static float abs(float a)
public static double abs(double a)
public static double random() Get a random number in [0.0, 1.0)
public static double sqrt(double a) Take the square root of a number
A selecFon of the staFc methods in Math.java
Math.java
37
public static final double E = 2.7182818284590452354; public static final double PI = 3.14159265358979323846;
/** * Don't let anyone instantiate this class. */ private Math() {}
Constants in Math.java.
The constructor of the Math class.
A private constructor. Makes it impossible to actually create an object of type Math.
All calls via staAc method calls, e.g. Math.sqrt(), Math.min()
Using Math class
38
int x = Math.round(42.2); int y = Math.min(56, 12); int z = Math.abs(-‐343);
These methods don't use instance variables, so there is no specific object to call the methods on. Use class name instead.
Math mathObj = new Math();
You can't do this since the constructor is private:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The constructor Math() is not visible
There is no persistent state in the Math object, so no need to create an object on the heap.
Limits of staAc methods • StaAc methods – Cannot use non-‐staAc instance variables
39
public class Cow { private String name = ""; private double weight = 0.0; public static double getWeight() { return weight; } }
Since getWeight() is declared staAc, any use of a non-‐staAc instance variable results in a compile error:
Cow.java:8: non-‐static variable weight cannot be referenced from a static context
return weight; ^
Cow cow1 = new Cow(); Cow cow2 = new Cow(); System.out.println("weight = ", Cow.getWeight());
The weight of which cow?
Limits of staAc methods • StaAc methods – Cannot call non-‐staAc methods
40
public class Cow { private String name = ""; private double weight = 0.0; public double getWeight() { return weight; } public static boolean isBig() { return (getWeight() > 500.0); } }
Since isBig() is declared staAc, any use of a non-‐staAc instance method results in a compile error:
Cow.java:13: non-‐static method getWeight() cannot be referenced from a static context
return (getWeight() > 500.0); ^
StaAc variables • StaAc instance variable – One variable shared among all instances of a parAcular class
– Why? • Commonly used for constants
• Eliminate repeated variables that are always the same – Reduce memory needed to create many objects of same type
• Track a single value related to a class type – e.g. Number of objects created for a parAcular class
41
public static final double PI = 3.14159265358979323846;
Reducing memory usage
42
public class Cow { private String name = ""; private double weight = 0.0; private static AudioFile sound = new AudioFile("cow.wav"); public void makeNoise() { sound.play(); } }
Normal instance variables, each Cow object has its own set of these variables.
All Cow objects share the same sound object. Only one AudioFile object is created on the heap, thus saving memory.
CounAng created objects
43
public class Cow { private String name = ""; private double weight = 0.0; private static int numCows = 0; public Cow() { numCows++; } public Cow(Cow otherCow) { this.name = otherCow.name; this.weight = otherCow.weight; numCows++; } public static int getNumCows() { return numCows; } }
No maoer how many Cow objects we create, there is only ever one numCows instance variable that has a single value.
Normal instance variables, each Cow object has its own set of these variables.
Methods that only use staAc variables can be declared staAc (but don't have to be).