3 - Java OCA 8 - Assignments

Réussis tes devoirs et examens dès maintenant avec Quizwiz!

Which of the following will compile? (Choose all that apply) a) double d = 1_234._25; b) double d = 1_234.25_; c) int d = 123_4; d) int d = 1234_; e) int d = _1234;

c) will compile. ➤ c) int d = 123_4; The Following Will Not Compile: ➤ a) double d = 1_234._25; You cannot place a '_' at the end of a literal as it gives a compiler error. ➤ b) double d = 1_234.25_; The above gives a compiler error ➤ d) int d = 1234_; The above gives a compiler error ➤ e) int d = _1234; You cannot place a '_' at the start of a literal as it gives a compiler error.

Given: class Beta { } class Alpha { static Beta b1; Beta b2; } public class Tester { public static void main(String[] args) { Beta b1 = new Beta(); Beta b2 = new Beta(); Alpha al = new Alpha(); Alpha a2 = new Alpha(); a1.b1 = b1; al.b2 = b1; a2.b2 = b2; al = null; b1 = null; b2 = null; 18. // do stuff }} When line 18 is reached, how many objects will be eligible for garbage collection? A. 0 B. 1 C. 2 D. 3 E. 4 F. 5

B. is corect. There will be 1 object available for garbage collection. ===Code Step Through=== 1: class Beta { } 2: class Alpha { 3: static Beta b1; 4: Beta b2; 5: } 6: public class Tester { 7: public static void main(String[] args) { 8: Beta b1 = new Beta(); 9: Beta b2 = new Beta(); 10: Alpha a1 = new Alpha(); 11: Alpha a2 = new Alpha(); 12: a1.b1 = b1; 13: a1.b2 = b1; 14: a2.b2 = b2; 15: a1 = null; 16: b1 = null; 17: b2 = null; 18: // do stuff }} On line 8 and line 9, two references named b1 and b2 which are of type Beta are pointing to two newly created Beta objects. The Java virtual machine (JVM) allocates addresses for these particular objects in heap memory e.g. @113 for b1 and &998 for b2 A depiction of the pseudocode of the object created on line 8 in heap memory: External b1 🠚 Object Beta( Heap Address @113) { } External b2 🠚 Object Beta( Heap Address &998) { } Note: there are no local methods or variables within these Beta objects above. ========2======== 1: class Beta { } 2: class Alpha { 3: static Beta b1; 4: Beta b2; 5: } 6: public class Tester { 7: public static void main(String[] args) { 8: Beta b1 = new Beta(); 9: Beta b2 = new Beta(); 10: Alpha a1 = new Alpha(); 11: Alpha a2 = new Alpha(); 12: a1.b1 = b1; 13: a1.b2 = b1; 14: a2.b2 = b2; 15: a1 = null; 16: b1 = null; 17: b2 = null; 18: // do stuff }} On line 10, a reference named a1 which are of type Alpha is pointing to a newly created Alpha object. The Java virtual machine (JVM) allocates an address for this particular object in heap memory e.g. @642 Inside the object Alpha instance there are two variables declared. The first is static variable named b1 which is of type Beta. This static b1 variable is unassigned (i.e. it is referring to null and not an object). The second variable b2 is an instance variable of type Beta and which is unassigned also. A depiction of the pseudocode of the object created on line 8 in heap memory: External a1 🠚 Object Alpha( Heap Address @642) { static Beta b1 🠢 null Beta b2 🠢 null } Note: All static variables and methods are stored in class memory. Once assigned to an object or variable, the static variable cannot be reassigned to any other object or variable. ========3======== 1: class Beta { } 2: class Alpha { 3: static Beta b1; 4: Beta b2; 5: } 6: public class Tester { 7: public static void main(String[] args) { 8: Beta b1 = new Beta(); 9: Beta b2 = new Beta(); 10: Alpha a1 = new Alpha(); 11: Alpha a2 = new Alpha(); 12: a1.b1 = b1; 13: a1.b2 = b1; 14: a2.b2 = b2; 15: a1 = null; 16: b1 = null; 17: b2 = null; 18: // do stuff }} On line 11, another Alpha object is created with a reference variable a2. The JVM allocates an address for this particular object in heap memory e.g. &887 A depiction of the pseudocode of the object created on line 8 in heap memory: External a2 🠚 Object Alpha( Heap Address &887) { static Beta b1 🠢 null Beta b2 🠢 null } ========4======== The following outlines a snapshot of the objects in memory at this point in time of the codes execution: Snapshot of Memory b1 🠚 Object Beta( Heap Address @113) { } b2 🠚 Object Beta( Heap Address &998) { } a1 🠚 Object Alpha( Heap Address @642) { static Beta b1 🠢 null Beta b2 🠢 null } a2 🠚 Object Alpha( Heap Address &887) { static Beta b1 🠢 null Beta b2 🠢 null } Note: Object Alpha( Heap Address @642) has an internal reference b1 and there is also an external reference b1 declared in the main() and pointing to Object Beta( Heap Address @113). This is perfectly fine. ========5======== 1: class Beta { } 2: class Alpha { 3: static Beta b1; 4: Beta b2; 5: } 6: public class Tester { 7: public static void main(String[] args) { 8: Beta b1 = new Beta(); 9: Beta b2 = new Beta(); 10: Alpha a1 = new Alpha(); 11: Alpha a2 = new Alpha(); 12: a1.b1 = b1; 13: a1.b2 = b1; 14: a2.b2 = b2; 15: a1 = null; 16: b1 = null; 17: b2 = null; 18: // do stuff }} On line 12, a1.b1 means the static Beta variable b1 (within the object referred to by a1) is assigned to the same Beta object referred to by the external reference b1. Since external b1 is referring to Object Beta(Heap Address @113) then a1.b1 will also refer to Object Beta( Heap Address @113). Therefore, there are now two references to Object Beta(Heap Address @113). Note: Since a1.b1 is an static variable, then that means the a2.b1 also gets assigned to Object Beta( Heap Address @113) as it is the same static variable. Snapshot of Memory b1 🠚 Object Beta( Heap Address @113) { } External b2 🠚 Object Beta( Heap Address &998) { } a1 🠚 Object Alpha( Heap Address @642) { Internal static Beta b1 🠢 Object Beta(Heap Address @113) Internal Beta b2 🠢 null } a2 🠚 Object Alpha( Heap Address &887) { static Beta b1 🠢 Object Beta(Heap Address @113) Beta b2 🠢 null } ========6======== 1: class Beta { } 2: class Alpha { 3: static Beta b1; 4: Beta b2; 5: } 6: public class Tester { 7: public static void main(String[] args) { 8: Beta b1 = new Beta(); 9: Beta b2 = new Beta(); 10: Alpha a1 = new Alpha(); 11: Alpha a2 = new Alpha(); 12: a1.b1 = b1; 13: a1.b2 = b1; 14: a2.b2 = b2; 15: a1 = null; 16: b1 = null; 17: b2 = null; 18: // do stuff }} On line 13, a1.b2 is the internal instance variable of the object referred to by a1 and gets assigned the object referred to by b1: Object Beta( Heap Address @113) Snapshot of Memory b1 🠚 Object Beta( Heap Address @113) { } External b2 🠢 Object Beta( Heap Address &998) { } a1 🠚Object Alpha( Heap Address @642) { Internal static Beta b1 🠢 Object Beta(Heap Address @113) Internal Beta b2 🠢 b1 🠢 Object Beta( Heap Address @113) } a2 🠚 Object Alpha( Heap Address &887) { Internal static Beta b1 🠢 Object Beta(Heap Address @113) Beta b2 🠢 null } ========7======== 1: class Beta { } 2: class Alpha { 3: static Beta b1; 4: Beta b2; 5: } 6: public class Tester { 7: public static void main(String[] args) { 8: Beta b1 = new Beta(); 9: Beta b2 = new Beta(); 10: Alpha a1 = new Alpha(); 11: Alpha a2 = new Alpha(); 12: a1.b1 = b1; 13: a1.b2 = b1; 14: a2.b2 = b2; 15: a1 = null; 16: b1 = null; 17: b2 = null; 18: // do stuff }} On line 14, a2.b2 is the internal instance variable of the object referred to by a2 and gets assigned the object referred to by b2: Object Beta( Heap Address &998) Snapshot of Memory b1 🠚 Object Beta( Heap Address @113) { } External b2 🠢 Object Beta( Heap Address &998) { } a1🠚 Object Alpha( Heap Address @642) { Internal static Beta b1 🠢 Object Beta(Heap Address @113) Internal Beta b2 🠢 Object Beta( Heap Address @113) } a2 🠚Object Alpha( Heap Address &887) { Internal static Beta b1 🠢 Object Beta(Heap Address @113) Beta b2 🠢 Object Beta( Heap Address &998) } ========8======== 1: class Beta { } 2: class Alpha { 3: static Beta b1; 4: Beta b2; 5: } 6: public class Tester { 7: public static void main(String[] args) { 8: Beta b1 = new Beta(); 9: Beta b2 = new Beta(); 10: Alpha a1 = new Alpha(); 11: Alpha a2 = new Alpha(); 12: a1.b1 = b1; 13: a1.b2 = b1; 14: a2.b2 = b2; 15: a1 = null; 16: b1 = null; 17: b2 = null; 18: // do stuff }} On line 15, 16 and 17 the external references a1, b1 and b2 are reassigned to null. There are now null references (represented by the character 'Ø') to the object with memory addresses @113, &998 and @642. Snapshot of Memory External b1 🠚 null Ø 🠚 Object Beta( Heap Address @113) { } External b2 🠢 null Ø 🠚 Object Beta( Heap Address &998) { } External a1 🠚 null Ø 🠚 Object Alpha( Heap Address @642) { Internal static Beta b1 🠢 Object Beta(Heap Address @113) Internal Beta b2 🠢 Object Beta( Heap Address @113) } External a2 🠚 Object Alpha( Heap Address &887) { Internal static Beta b1 🠢 Object Beta(Heap Address @113) Beta b2 🠢 Object Beta( Heap Address &998) } ========9======== The external reference a2 still refers to Object Alpha( Heap Address &887). Inside this object, there are internal references pointing to other objects. Namely, Internal static Beta b1 is referring to Object Beta(Heap Address @113). Therefore, the Object Beta(Heap Address @113) is not available for garbage collection even though it has no external references. The Object Alpha( Heap Address &887) also has an internal reference Beta b2 which is referring to the object Object Beta( Heap Address &998). Therefore, the Object Beta( Heap Address &998) is not available for garbage collection even though it has no external references. External b1 🠚 null Ø 🠚Object Beta( Heap Address @113) { } External b2 🠚 null Ø 🠚Object Beta( Heap Address &998) { } External a1 🠚 null Ø 🠚Object Alpha( Heap Address @642) { Internal static Beta b1 🠢 Object Beta(Heap Address @113) Internal Beta b2 🠢 Object Beta( Heap Address @113) } External a2 🠚 Object Alpha( Heap Address &887) { Internal static Beta b1 🠢 Object Beta(Heap Address @113) Beta b2 🠢 Object Beta( Heap Address &998) } ========10======== The only object that has no references pointing to it (either internal or external) is Object Alpha( Heap Address @642). This null reference is represented by the character 'Ø' in the pseudocode below. Therefore Object Alpha( Heap Address @642) is the only object that is available for garbage collection. Note: The Object Alpha( Heap Address @642) has internal references pointing to other external objects but this is not significant for the GC (garbage collection). Snapshot of Memory External b1 🠚 null Ø 🠚Object Beta( Heap Address @113) { } External b2 🠚 null Ø 🠚Object Beta( Heap Address &998) { } External a1 🠚 null Ø 🠚Object Alpha( Heap Address @642) { Internal static Beta b1 🠢 Object Beta(Heap Address @113) Internal Beta b2 🠢 Object Beta( Heap Address @113) } a2 🠚 Object Alpha( Heap Address &887) { Internal static Beta b1 🠢 Object Beta(Heap Address @113) Beta b2 🠢 Object Beta( Heap Address &998) } In summary, only 1 object is available for garbage collection Namely: Object Alpha(Heap Address @642) Note: The internal reference to the Beta object with address @113 has no external references however it is referenced internally by another object with external reference a2. In that instance it's the reference that gets destroyed and not the object within the Alpha object with Heap Address @642.

Given: class Mixer { Mixer() { } Mixer(Mixer m) { m1 = m; } Mixer m1; public static void main(String[] args){ Mixer m2 = new Mixer() ; Mixer m3 = new Mixer(m2); m3.go() Mixer m4 = m3.m1; m4.go() Mixer m5 = m2.m1; m5.go() } void go() { System.out.print ("hi ") ;} } What is the result? A. hi B. hi hi C. hi hi hi D. Compilation fails E. hi, followed by an exception F. hi hi, followed by an exception

F is correct. hi hi will be printed followed by an exception. class Mixer { Mixer() { } Mixer(Mixer m) { m1 = m; } Mixer m1; public static void main(String[] args){ Mixer m2 = new Mixer() ; Mixer m3 = new Mixer(m2); m3.go(); Mixer m4 = m3.m1; m4.go(); Mixer m5 = m2.m1; m5.go(); } void go() { System.out.print ("hi ") ;} } The m2 object's m1 instance variable is never initialized, so when m5 tries to use it, a NullPointerException is thrown. Note: The Mixer class has two constructors one default and one taking a Mixer as a reference. ===Code Step Through=== 1: class Mixer { 2: Mixer() { } 3: Mixer(Mixer m) { m1 = m; } 4: Mixer m1; 5: public static void main(String[] args){ 6: Mixer m2 = new Mixer(); 7: Mixer m3 = new Mixer(m2); m3.go(); 8: Mixer m4 = m3.m1; m4.go(); 9: Mixer m5 = m2.m1; m5.go(); 10: } 11: void go() { System.out.print ("hi ") ;} 12: } On line 6, the reference variable m2 is of type Mixer, and is 'pointing to' (referring to) newly created object of type Mixer with the default constructor (line 2). (All objects have a unique address except String objects). The following is a depiction in memory of the object Mixer with an arbitrary unique address @432 and with reference m2. It has an internal instance variable m1 of type Mixer which is not assigned (not referencing) an object (therefore it is 'pointing' to null). The object also has a method named go() which is stored in the stack memory: External m2 🠚 Object Mixer (Address @432) { internal Mixer m1 🠚 null go(){"hi "} } ========2======== 1: class Mixer { 2: Mixer() { } 3: Mixer(Mixer m) { m1 = m; } 4: Mixer m1; 5: public static void main(String[] args){ 6: Mixer m2 = new Mixer(); 7: Mixer m3 = new Mixer(m2); m3.go(); 8: Mixer m4 = m3.m1; m4.go(); 9: Mixer m5 = m2.m1; m5.go(); 10: } 11: void go() { System.out.print ("hi ") ;} 12: } On line 7, the reference variable m3 is of type Mixer and is 'pointing to' (referring to) newly created object of type Mixer with arbitrary unique address &721 and with the non-default constructor (line 3). (All objects have a unique address except String objects). On line 3, a copy of the Mixer reference m2 is passed into the Mixer constructor via the parameter reference named m. In other words, m parameter variable contains a copy of m2. The internal Mixer reference m1 is now 'pointing to' the same Mixer object that m2 is pointing to i.e. Object Mixer Address @432. In other words, the Internal reference m1 is now referring to the same object that external reference m2 is referring to, namely, Object A (Address @432). The following is a depiction in memory of the object Mixer with an unique address &721 and with reference m3. It has an internal instance variable m1 of type Mixer which is assigned (referencing) Object Mixer with address @432. The object also has a method named go() which is stored in the stack memory: External m3 🠚 Object Mixer (Address &721) { internal Mixer m1 🠢 Object Mixer (Address @432){m1🠢null} go(){"hi "} } ========3======== Following the execution of the above lines of code, the following outlines a snapshot of objects in the memory heap: External m2 🠚Object Mixer (Address @432) { internal Mixer m1 🠢 null go(){"hi "} } External m3 🠚 Object Mixer (Address &721) { internal Mixer m1 🠢 Object Mixer (Address @432){m1🠢 null} go(){"hi "} } ========4======== 1: class Mixer { 2: Mixer() { } 3: Mixer(Mixer m) { m1 = m; } 4: Mixer m1; 5: public static void main(String[] args){ 6: Mixer m2 = new Mixer(); 7: Mixer m3 = new Mixer(m2); m3.go(); 8: Mixer m4 = m3.m1; m4.go(); 9: Mixer m5 = m2.m1; m5.go(); 10: } 11: void go() { System.out.print ("hi ") ;} 12: } As outlined on line 7, you can have more than one statement on the same line provided they are separated by semi colon but it's not good programming practice as it may be more difficult to read/maintain/debug the code. Nonetheless, this could pop up as a question. Continuing on line 7, the object which is referenced by m3 calls its go() method which prints "hi " to the screen: External m3 🠚 Object Mixer (Address &721) { internal Mixer m1 🠢 Object Mixer (Address @432){m1🠢null} go(){"hi "} } ========5======== Following the execution of the above lines of code, the following outlines a snapshot of objects in the memory heap: External m2 🠚 Object Mixer (Address @432) { internal Mixer m1 🠢 null go(){"hi "} } External m3 🠚 Object Mixer (Address &721) { internal Mixer m1 🠢 Object Mixer (Address @432){m1🠢null} go(){"hi "} } ========6======== 1: class Mixer { 2: Mixer() { } 3: Mixer(Mixer m) { m1 = m; } 4: Mixer m1; 5: public static void main(String[] args){ 6: Mixer m2 = new Mixer(); 7: Mixer m3 = new Mixer(m2); m3.go(); 8: Mixer m4 = m3.m1; m4.go(); 9: Mixer m5 = m2.m1; m5.go(); 10: } 11: void go() { System.out.print ("hi ") ;} 12: } On line 8, the external Mixer object reference m4 is pointing to the internal Mixer object reference of m3 i.e. Object Mixer (Address @432). As a consequence, there are now two external references and one internal reference pointing to the object Object Mixer (Address @432) it. Following the execution of the above lines of code, the following outlines a snapshot of objects in the memory heap: External Mixer m4 🠚 m2 🠚 Object Mixer (Address @432) { internal Mixer m1 🠢 null go(){"hi "} } External m3 🠚 Object Mixer (Address &721) { internal Mixer m1 🠢 Object Mixer (Address @432){m1🠢null} go(){"hi "} } ========7======== 1: class Mixer { 2: Mixer() { } 3: Mixer(Mixer m) { m1 = m; } 4: Mixer m1; 5: public static void main(String[] args){ 6: Mixer m2 = new Mixer(); 7: Mixer m3 = new Mixer(m2); m3.go(); 8: Mixer m4 = m3.m1; m4.go(); 9: Mixer m5 = m2.m1; m5.go(); 10: } 11: void go() { System.out.print ("hi ") ;} 12: } Continuing on line 8, the object which is referenced by m4 calls its go() method which prints "hi " to the screen: External Mixer m4 🠚 m2 🠚 Object Mixer (Address @432) { internal Mixer m1 🠢 null go(){"hi "} } Following the execution of the above lines of code, the following outlines a snapshot of objects in the memory heap: External Mixer m4 🠚 m2 🠚 Object Mixer (Address @432) { internal Mixer m1 🠢 null go(){"hi "} } External m3 🠚 Object Mixer (Address &721) { internal Mixer m1 🠢 Object Mixer (Address @432){m1🠢null} go(){"hi "} } ========8======== 1: class Mixer { 2: Mixer() { } 3: Mixer(Mixer m) { m1 = m; } 4: Mixer m1; 5: public static void main(String[] args){ 6: Mixer m2 = new Mixer(); 7: Mixer m3 = new Mixer(m2); m3.go(); 8: Mixer m4 = m3.m1; m4.go(); 9: Mixer m5 = m2.m1; m5.go(); 10: } 11: void go() { System.out.print ("hi ") ;} 12: } On line 9, the external Mixer object reference m5 is pointing to the internal Mixer object reference of m2 i.e. Object Mixer (Address @432). However, the internal Mixer object reference of m2 is pointing to null. Following the execution of the above lines of code, the following outlines a snapshot of objects in the memory heap: External Mixer m4 🠚 m2 🠚 Object Mixer (Address @432) { internal Mixer m1 🠢 null go(){"hi "} } External m3 🠚 Object Mixer (Address &721) { internal Mixer m1 🠢 Object Mixer (Address @432){m1🠢null} go(){"hi "} } External Mixer m5 🠚 null ========9======== 1: class Mixer { 2: Mixer() { } 3: Mixer(Mixer m) { m1 = m; } 4: Mixer m1; 5: public static void main(String[] args){ 6: Mixer m2 = new Mixer(); 7: Mixer m3 = new Mixer(m2); m3.go(); 8: Mixer m4 = m3.m1; m4.go(); 9: Mixer m5 = m2.m1; m5.go(); 10: } 11: void go() { System.out.print ("hi ") ;} 12: } Continuing on line 9, the object Mixer reference m5 attempts to call its go() method but since m5 is referring to null it throws NullPointerException.

Which of the following will not compile? (Choose all that apply) a) int i1 = 1234567890; b) int i2= 12345678901; c) int i3=_1_0000_0; d) none of the above

b) and c) are correct. They both will not compile: ➤ b) int i2= 12345678901; The maximum int value is 10 digits. The above number is too large (by one digit) therefore it gives a compiler error. Solution: Store the above value as a long type e.g. long i2= 12345678901; ➤ c) int i3=_1_0000_0; The above will not compile as an int value cannot begin with _ when '_' is already present in the int value. Incorrect Answers: The following will compile and run fine. a) int i1 = 1234567890;

Given: 3. public class Ouch { 4. static int ouch = 7; 5. public static void main(String [] args) { 6. new Ouch().go(ouch); 7. System.out.print(" " + ouch); 9. void go(int ouch){ 10. ouch++; 11. for(int ouch = 3; ouch<6;ouch++) 12. ; 13. System.out.print(" " + ouch); 14 } 15 } What is the result? A. 5 7 B. 5 8 C. 8 7 D. 8 8 E. Compilation fails F. An exception is thrown at runtime

E is correct Compilation fails 3. public class Ouch { 4. static int ouch = 7; 5. public static void main(String [] args) { 6. new Ouch().go(ouch); 7. System.out.print(" " + ouch); 9. void go(int ouch){ 10. ouch++; 11. for(int ouch = 3; ouch<6;ouch++) 12. ; 13. System.out.print(" " + ouch); 14 } 15 } The parameter declared on line 9 is valid although ugly because a static variable already has the same name on line 4. The local variable, also called ouch, cannot be declared again on the line 11 in the same scope as the declaration on line 9.

Which of the following will give a compiler error? (Choose all that apply) a) boolean d = true; b) boolean d = 1; c) boolean d = 0; d) double d = false; e) none of the above

b) and c) will give compiler errors. In Java, there are only two variables that can be stored in a boolean: true or false. The following will give compiler errors: b) boolean d = 1; c) boolean d = 0; The above can be executed in C but not in Java

Which of the following are not valid operators? (Choose all that apply) a) << b) <<< c) >>> d) instanceof d) equals

b) and d) are not valid operators. ➤ b) <<< The above is not a valid operator ➤ d) equals equals() is a method not an operator

Which of the following are true? (Choose all that apply) a) boolean[] b = new boolean[2]; for (boolean c : b) { System.out.println(c); } The above code will print: true true b) float[] f = new float[2]; for (float g : f) { System.out.println(g); } The above code will print: 0.0 0.0 c) String [] s = new String[2]; for (String s1 : s) { System.out.println(s1); } The above code will print: "" "" d) char [] c = new char[2]; for (char d : c) { System.out.println(d); } The above code will print: '' ''

b) is correct. float[] f = new float[2]; for (float g : f) { System.out.println(g); } The above code will print: 0.0 0.0 The correct default initialization values are as follows: Object is null byte, short, int, long is 0 float and double is 0.0 boolean is false char is '\u0000' Note: instance variables have default initialization but local variables are required to be explicitly initialized otherwise the code will give a compiler error.

Which of the following are the correct default initialization values of the said types? (Choose all that apply) a) Object is 0 b) byte, short, int and long is 0.0 c) float and double is 0.0 d) boolean is true e) char is '\u0000'

c) and e) are correct. The correct default initialization values are as follows: Object is null byte, short, int, long is 0 float and double is 0.0 boolean is false char is '\u0000' Note: instance variables have default initialization but local variables are required to be explicitly initialized otherwise the code will give a compiler error

Given: public class Wind { int id; Wind(int i) { id = i; } public static void main(String[] args) { new Wind(3).go(); // commented line } void go() { Wind w1 = new Wind(1); Wind w2 = new Wind(2); System.out.println(w1.id + " "+ w2.id); }} When execution reaches the commented line, which are true? (Choose all that apply.) A The output contains 1 B The output contains 2 C The output contains 3 D Zero Wind objects are eligible for garbage collection E, One Wind object is eligible for garbage collection F Two Wind objects are eligible for garbage collection G, Three Wind objects are eligible for garbage collection

A and B are correct. The program will compile and print: 1 2 ===Code Step Through=== 1: public class Wind { 2: int id; 3: Wind(int i) { id = i; } 4: public static void main(String[] args) { 5: new Wind(3).go(); 6: // commented line 7: } 8: void go() { 9: Wind w1 = new Wind(1); 10: Wind w2 = new Wind(2); 11: System.out.println(w1.id + " "+ w2.id); 12: }} On line 5, a new Wind object is created and the Java virtual machine allocates an arbitrary heap address to the object (e.g. @981). The value 3 is passed to the constructor of this particular object and is there is no reference to this particular object. ========2======== 1: public class Wind { 2: int id; 3: Wind(int i ) { id = i ; } 4: public static void main(String[] args) { 5: new Wind(3).go(); 6: // commented line 7: } 8: void go() { 9: Wind w1 = new Wind(1); 10: Wind w2 = new Wind(2); 11: System.out.println(w1.id + " "+ w2.id); 12: }} On line 3, the parameter int i contains the value 3 which was passed from the created Wind object on line 5. The following outlines the pseudocode depiction of the said object in memory after line 5 executes. There is a now a null reference (represented by the character 'Ø') to the object with memory address @981: Ø 🠚 Object Wind(Heap Address @981) { internal id 🠢 3 go() } Note: There is no reference to the above object. ========3======== 1: public class Wind { 2: int id; 3: Wind(int i) { id = i; } 4: public static void main(String[] args) { 5: new Wind(3).go(); 6: // commented line 7: } 8: void go() { 9: Wind w1 = new Wind(1); 10: Wind w2 = new Wind(2); 11: System.out.println(w1.id + " "+ w2.id); 12: }} On line 5, the go() method is called. ========4======== 1: public class Wind { 2: int id; 3: Wind(int i) { id = i; } 4: public static void main(String[] args) { 5: new Wind(3).go(); 6: // commented line 7: } 8: void go() { 9: Wind w1 = new Wind(1 ); 10: Wind w2 = new Wind(2); 11: System.out.println(w1.id + " "+ w2.id); 12: } } On line 9, the reference variable w1 is of type Wind, and is 'pointing to' (referring to) newly created object of type Wind with the value 1 passed to its constructor. The following is a depiction in memory of the object Wind with an arbitrary unique address @432 and with reference w1. It has an internal instance variable id of type int which is assigned the value 1. The object also has a method named go() which is stored in the stack memory: Memory Snapshot: External w1 🠚 Object Wind (Address @432) { internal id 🠢 1 go() } ========5======== 1: public class Wind { 2: int id; 3: Wind(int i) { id = i; } 4: public static void main(String[] args) { 5: new Wind(3).go(); 6: // commented line 7: } 8: void go() { 9: Wind w1 = new Wind(1); 10: Wind w2 = new Wind(2); 11: System.out.println(w1.id + " "+ w2.id); 12: }} On line 10, the reference variable w2 is of type Wind, and is 'pointing to' (referring to) newly created object of type Wind with the value 2 passed to its constructor. The following is a depiction in memory of the object Wind with an arbitrary unique address @550 and with reference w2. It has an internal instance variable id of type int which is assigned the value 2. The object also has a method named go() which is stored in the stack memory: External w2 🠚 Object Wind (Address @550) { internal id 🠢2 go() } ========6======== Memory Snapshot: External w1 🠚 Object Wind (Address @432) { internal id 🠢1 go() } External w2 🠚 Object Wind (Address @550) { internal id 🠢2 go() } ========7======== 1: public class Wind { 2: int id; 3: Wind(int i) { id = i; } 4: public static void main(String[] args) { 5: new Wind(3).go(); 6: // commented line 7: } 8: void go() { 9: Wind w1 = new Wind(1); 10: Wind w2 = new Wind(2); 11: System.out.println(w1.id + " "+ w2.id); 12: }} On line 11, the internal int id value stored in the object referenced by w1 is printed i.e. 1 ========8======== 1: public class Wind { 2: int id; 3: Wind(int i) { id = i; } 4: public static void main(String[] args) { 5: new Wind(3).go(); 6: // commented line 7: } 8: void go() { 9: Wind w1 = new Wind(1); 10: Wind w2 = new Wind(2); 11: System.out.println(w1.id + " "+ w2.id); 12: }} Again on line 11, the internal int id value stored in the object referenced by w2 is printed i.e. 2 Final Output: 1 2 When the commented line is reached, none of the three Wind objects can be accessed m(referenced), so they are eligible to be garbage collected: new Wind(3) Wind wl = new Wind(1); Wind w2 = new Wind(2);

Given: class Fizz { int x = 5; public static void main(String[] args) { final Fizz f1 = new Fizz(); Fizz f2 = new Fizz(); Fizz f3 = FizzSwitch (f1, f2); System.out.println((f1 == f3) + " " + (f1.x == f3.x)); } static Fizz FizzSwitch(Fizz x, Fizz y) { final Fizz z = x; z.x = 6; return z; } } What is the result? A. true true B. false true C. true false D. false false E. Compilation fails F. An exception is thrown at runtime

A is correct. The program will print: true true The references f1, z, and f3 all refer to the same instance of Fizz. class Fizz { int x = 5; public static void main(String[] args) { final Fizz f1 = new Fizz(); Fizz f2 = new Fizz(); Fizz f3 = FizzSwitch(f1, f2); System.out.printIn((f1 == f3) + " " + (f1.x == f3.x)); } static Fizz FizzSwitch(Fizz x, Fizz y) { final Fizz z = x; z.x = 6; return z; } } The final modifier assures that a reference variable cannot be referred to a different object as final doesn't keep the object's state from changing. The key word 'final' means 'constant' in Java. ===Code Step Through=== 1: class Fizz { 2: int x = 5; 3: public static void main(String[] args) { 4: final Fizz f1 = new Fizz(); 5: Fizz f2 = new Fizz(); 6: Fizz f3 = FizzSwitch (f1, f2); 7: System.out.println((f1 == f3) + " " + (f1.x == f3.x)); 8: } 9: static Fizz FizzSwitch(Fizz x, Fizz y) { 10: final Fizz z = x; 11: z.x = 6; 12: return z; 13: } } On line 4, a final (constant) Fizz reference f1 points to a Fizz object instance and this Fizz object is allocated a unique address in the heap memory by the Java Virtual Machine (e.g. @863). The following below is a depiction in memory of the object Fizz with an heap address @863 and with reference f1. It has an internal primitive variable x of type int which is assigned the number 5. The object also contains a static method in class memory. A static method cannot be duplicated. That means that whenever the static method named FizzSwitch() gets called in the code, the JVM always refers to the FizzSwitch() method with its unique address in class memory (e.g. Class Memory Address &251). In other words, there can never be more than one static method in class memory with the same name. External Fizz f1 🠚 Object Fizz(Heap Address @863) { internal int x 🠢 5 FizzSwitch(Fizz x, Fizz y)(Class Memory &251) } =========2=========== 1: class Fizz { 2: int x = 5; 3: public static void main(String[] args) { 4: final Fizz f1 = new Fizz(); 5: Fizz f2 = new Fizz(); 6: Fizz f3 = FizzSwitch (f1, f2); 7: System.out.println((f1 == f3) + " " + (f1.x == f3.x)); 8: } 9: static Fizz FizzSwitch(Fizz x, Fizz y) { 10: final Fizz z = x; 11: z.x = 6; 12: return z; 13: } } On line 5, a Fizz reference f2 points to a Fizz object instance and this Fizz object is allocated a unique address in the heap memory by the Java Virtual Machine (e.g. &433). It has an internal primitive variable x of type int of type Fizz which is assigned the number 5. The object also contains a static method in class memory named FizzSwitch() which has the same class address (&251) as the FizzSwitch() method created in Object Fizz (Heap Address @863). The following is a depiction in memory of the object Fizz with an heap address &433 and with reference f2: External Fizz f2 🠚 Object Fizz (Heap Address &433) { internal int x 🠢 5 FizzSwitch(Fizz x, Fizz y)(Class Memory &251) } Following the execution of the above lines of code, the following outlines a snapshot of objects in memory: External Fizz f1 🠚 Object Fizz(Heap Address @863) { internal int x 🠢 5 FizzSwitch(Fizz x, Fizz y)(Class Memory &251) } External Fizz f2 🠚 Object Fizz (Heap Address &433) { internal int x 🠢 5 FizzSwitch(Fizz x, Fizz y)(Class Memory &251) } ========3======== 1: class Fizz { 2: int x = 5; 3: public static void main(String[] args) { 4: final Fizz f1 = new Fizz(); 5: Fizz f2 = new Fizz(); 6: Fizz f3 = FizzSwitch(f1, f2); 7: System.out.println((f1 == f3) + " " + (f1.x == f3.x)); 8: } 9: static Fizz FizzSwitch(Fizz x, Fizz y) { 10: final Fizz z = x; 11: z.x = 6; 12: return z; 13: } } On line 6 above, the static method FizzSwitch() gets called. As it is static method, it doesn't need a reference to be called. A copy of the Fizz object that is referenced by f1 and f2 are passed into the FizzSwitch() method. ========4======== 1: class Fizz { 2: int x = 5; 3: public static void main(String[] args) { 4: final Fizz f1 = new Fizz(); 5: Fizz f2 = new Fizz(); 6: Fizz f3 = FizzSwitch(f1, f2); 7: System.out.println((f1 == f3) + " " + (f1.x == f3.x)); 8: } 9: static Fizz FizzSwitch(Fizz x, Fizz y) { 10: final Fizz z = x; 11: z.x = 6; 12: return z; 13: } } On line 9, copies of Fizz references f1 and f2 (which are pointing to their respective Fizz objects) are passed to the static method FizzSwitch() via the methods parameters named x and y. Fizz reference x contains a copy of reference f1 and y contains a copy f2. ========5======== 1: class Fizz { 2: int x = 5; 3: public static void main(String[] args) { 4: final Fizz f1 = new Fizz(); 5: Fizz f2 = new Fizz(); 6: Fizz f3 = FizzSwitch(f1, f2); 7: System.out.println((f1 == f3) + " " + (f1.x == f3.x)); 8: } 9: static Fizz FizzSwitch(Fizz x, Fizz y) { 10: final Fizz z = x; 11: z.x = 6; 12: return z; 13: } } On line 10, the Fizz reference named z is being assigned to the object that is assigned to Fizz reference x (where x contains a copy of Fizz reference f1). The following is a depiction in memory of the object Fizz with (Heap Address @863) which now has two references (z and f1): z 🠚 f1 🠚 Object Fizz(Heap Address @863) { internal int x 🠢 5 FizzSwitch(Fizz x, Fizz y)(Class Memory &251) } Following the execution of the above lines of code, the following outlines a snapshot of objects in memory: z 🠚 f1 🠚 Object Fizz(Heap Address @863) { internal int x 🠢 5 FizzSwitch(Fizz x, Fizz y)(Class Memory &251) } f2 🠚 Object Fizz (Heap Address &433) { internal int x 🠢 5 FizzSwitch(Fizz x, Fizz y)(Class Memory &251) } ========6======== 1: class Fizz { 2: int x = 5; 3: public static void main(String[] args) { 4: final Fizz f1 = new Fizz(); 5: Fizz f2 = new Fizz(); 6: Fizz f3 = FizzSwitch(f1, f2); 7: System.out.println((f1 == f3) + " " + (f1.x == f3.x)); 8: } 9: static Fizz FizzSwitch(Fizz x, Fizz y) { 10: final Fizz z = x; 11: z.x = 6; 12: return z; 13: } } On line 11, the internal variable x of the object referenced by z is assigned the value 6. This means that any previous value gets overwritten. The following is a depiction in memory of the object Fizz which is referenced by z and which has Heap Address @863: z 🠚 f1 🠚 Object Fizz(Heap Address @863) { internal int x 🠢 6 FizzSwitch(Fizz x, Fizz y)(Class Memory &251) } Note: The above object has two references to it. Namley z and f1. ========7======== Following the execution of the above lines of code, the following outlines a snapshot of objects in memory: z 🠚 f1 🠚 Object Fizz(Heap Address @863) { internal int x 🠢 6 FizzSwitch(Fizz x, Fizz y)(Class Memory &251) } f2 🠚 Object Fizz (Heap Address &433) { internal int x 🠢 5 FizzSwitch(Fizz x, Fizz y)(Class Memory &251) } ========8======== 1: class Fizz { 2: int x = 5; 3: public static void main(String[] args) { 4: final Fizz f1 = new Fizz(); 5: Fizz f2 = new Fizz(); 6: Fizz f3 = FizzSwitch(f1, f2); 7: System.out.println((f1 == f3) + " " + (f1.x == f3.x)); 8: } 9: static Fizz FizzSwitch(Fizz x, Fizz y) { 10: final Fizz z = x; 11: z.x = 6; 12: return z; 13: } } On line 12, a copy of the Fizz reference z is returned to the main() method. Then on line 6, the Fizz object which is referenced by z is now also referenced by f3. The following is a depiction in memory of the object Fizz which is referenced by z and f3 and which has Heap Address @863: f3 🠚 z 🠚 f1 🠚 Object Fizz(Heap Address @863) { internal int x 🠢 6 FizzSwitch(Fizz x, Fizz y)(Class Memory &251) } Following the execution of the above lines of code, the following outlines a snapshot of objects in memory: f3 🠚 z 🠚 f1 🠚 Object Fizz(Heap Address @863) { internal int x 🠢 6 FizzSwitch(Fizz x, Fizz y)(Class Memory &251) } f2 🠚 Object Fizz (Heap Address &433) { internal int x 🠢 5 FizzSwitch(Fizz x, Fizz y)(Class Memory &251) } ========9======== 1: class Fizz { 2: int x = 5; 3: public static void main(String[] args) { 4: final Fizz f1 = new Fizz(); 5: Fizz f2 = new Fizz(); 6: Fizz f3 = FizzSwitch(f1, f2); 7: System.out.println((f1== f3) + " " + (f1.x == f3.x)); 8: } 9: static Fizz FizzSwitch(Fizz x, Fizz y) { 10: final Fizz z = x; 11: z.x = 6; 12: return z; 13: } } On line 7, f1== f3 checks that the object heap address that the reference f1 refers to, is the same address of the object that the reference f3 refers to. Looking at the memory snapshot below we can see that both referenced f1 and f3 are pointing to an object which has the same heap address @863. Therefore true gets printed: f3 🠚 z 🠚 f1 🠚 Object Fizz(Heap Address @863) { internal int x 🠢 6 FizzSwitch(Fizz x, Fizz y)(Class Memory &251) } ========10======== 1: class Fizz { 2: int x = 5; 3: public static void main(String[] args) { 4: final Fizz f1 = new Fizz(); 5: Fizz f2 = new Fizz(); 6: Fizz f3 = FizzSwitch(f1, f2); 7: System.out.println((f1 == f3) + " " + (f1.x ==f3.x)); 8: } 9: static Fizz FizzSwitch(Fizz x, Fizz y) { 10: final Fizz z = x; 11: z.x = 6; 12: return z; 13: } } On line 7, f1.x ==f3.x checks that the internal variable x of the object referenced by f1 contains the same value as the internal variable x of the object referenced by f3. Looking at the memory snapshot below we can see that both referenced f1 and f3 are pointing to an object which has the same heap address @863. Therefore, the same internal variable x contains the same value 6. As a consequence, true gets printed: f3 🠚 z 🠚 f1 🠚 Object Fizz(Heap Address @863) { internal int x 🠢 6 FizzSwitch(Fizz x, Fizz y)(Class Memory &251) } Final output: true true

Given: public class Network { Network(int x, Network n) { id = x; p = this; if (n != null) p = n; } int id; Network p; public static void main(String[] args) { Network n1 = new Network(1, null); n1.go(n1); } void go(Network n1) { Network n2 = new Network(2, n1); Network n3 = new Network(3, n2); System.out.println(n3.p.p.id); }} What is the result? A. 1 gets printed to do screen B. 2 gets printed to do screen C. 3 gets printed to do screen D. null E. Compilation fails

A is correct. The value 1 gets printed to the screen. ===Code Step Through=== 1: public class Network { 2: Network(int x, Network n) { 3: id = x; 4: p = this; 5: if (n != null) p = n; 6: } 7: int id; 8: Network p; 9: public static void main(String[] args) { 10: Network n1 = new Network(1, null); 11: n1.go(n1); 12: } 13: void go(Network n1) { 14: Network n2 = new Network(2, n1); 15: Network n3 = new Network(3, n2); 16: System.out.println(n3.p.p.id); 17 }} On line 10, a new object is created of type Network with a reference n1. In the objects parameters, the value 1 and null are passed and stored in the object. ========2======== 1: public class Network { 2: Network(int x, Network n) { 3: id = x; 4: p = this; 5: if (n != null) p = n; 6: } 7: int id; 8: Network p; 9: public static void main(String[] args) { 10: Network n1 = new Network(1, null); 11: n1.go(n1); 12: } 13: void go(Network n1) { 14: Network n2 = new Network(2, n1); 15: Network n3 = new Network(3, n2); 16: System.out.println(n3.p.p.id); 17 }} On line 3, variable x contains value1 is stored in the id int type and n1 is stored in the Network reference p. On line 4, the internal reference p is assigned the value n1 (this) which is a reference to itself. On line 5, a check is undertaken to see if the reference n, passed to the constructor is null. If n is null, then the value assigned to p will remain as n1 (this) (as is the case above). Otherwise the value p will be assigned n (which is referring to the object pointed to by n). The object also contains an instance method go() and instance methods/variables are stored in stack memory. The Java virtual machine would allocate an address in heap memory for this newly created object e.g. &012 and also the stack address of the instance method go(). The following is a pseudocode depiction of the object stored in heap memory following the execution of line 10: External n1 🠚 Object Network(1,null) (Heap Address &012) { Internal int id 🠢 1 Internal Network p 🠢 n1 go() } ========3======== 1: public class Network { 2: Network(int x, Network n) { 3: id = x; 4: p = this; 5: if (n != null) p = n; 6: } 7: int id; 8: Network p; 9: public static void main(String[] args) { 10: Network n1 = new Network(1, null); 11: n1.go(n1); 12: } 13: void go(Network n1) { 14: Network n2 = new Network(2, n1); 15: Network n3 = new Network(3, n2); 16: System.out.println(n3.p.p.id); 17 }} On line 11, the go() method is called via the object declared on line 10 with the address &012 and with reference n1. A copy of the reference n1 is passed into the parameter of the method go(n1). ========4======== 1: public class Network { 2: Network(int x, Network n) { 3: id = x; 4: p = this; 5: if (n != null) p = n; 6: } 7: int id; 8: Network p; 9: public static void main(String[] args) { 10: Network n1 = new Network(1, null); 11: n1.go(n1); 12: } 13: void go(Network n1) { 14: Network n2 = new Network(2, n1); 15: Network n3 = new Network(3, n2); 16: System.out.println(n3.p.p.id); 17 } } On line 13, the copy of the Network reference n1 enters the method go(). Note: The parameter name of the go(Network n1) method is the same as the Network instance variable reference n1. This is perfectly fine. On line 14, a new Network object is created with a local reference n1 inside the method go(). As with all newly created objects, the (JVM) Java Virtual Machine allocates an address in keeping memory for this object e.g @864. The following is a pseudocode depiction of the object stored in heap memory following the execution of line 14: Local n2 🠚 Object Network(2, n1) (Heap Address @864) { Internal int id 🠢 2 Internal Network p 🠢 n1 🠢 Object Network (Heap Address &012) go() } Note: The reference of the above object is pointing to (referencing) the Network object with the heap address &012. This means that the object with the heap address &012 now has two references pointing to it i.e. local reference p and external reference n1. Memory Snapshot: n2.p 🠚 n1 🠚 Object Network(1, null) (Heap Address &012) { Internal int id 🠢 1 Internal Network p 🠢 null go() } Local n2 🠚 Object Network(2,n1 ) (Heap Address @864) { Internal int id 🠢 2 Internal Network p 🠢 n1 🠢 Object Network (Heap Address &012) go() } ========5======== 1: public class Network { 2: Network(int x, Network n) { 3: id = x; 4: p = this; 5: if (n != null) p = n; 6: } 7: int id; 8: Network p; 9: public static void main(String[] args) { 10: Network n1 = new Network(1, null); 11: n1.go(n1); 12: } 13: void go(Network n1) { 14: Network n2 = new Network(2, n1); 15: Network n3 = new Network(3, n2); 16: System.out.println(n3.p.p.id); 17 }} On line 15, another Network object is created a local reference n3 referring to it. The Java virtual machine allocates an arbitrary address for the above object in heap memory e.g. &261 The following is a pseudocode depiction of the object stored in heap memory following the execution of line 15: Local n3 🠚 Object Network(3, n2) (Heap Address &261) { Internal int id 🠢 3 Internal Network p 🠢 n2 🠢 Object Network (Heap Address @864) go() } Note: The internal reference p is pointing to the same object that external reference n2 is referencing. Memory Snapshot: n2.p 🠚 n1 🠚 Object Network(1, null) (Heap Address &012) { Internal int id 🠢 1 Internal Network p 🠢 null go() } n3.p 🠚n2 🠚Object Network(2,n1) (Heap Address @864) { Internal int id 🠢 2 Internal Network p 🠢 n1 🠢 Object Network (Heap Address &012) go() } Local n3 🠚 Object Network(3, n2) (Heap Address &261) { Internal int id 🠢 3 Internal Network p 🠢 n2 🠢 Object Network (Heap Address @864) go() } ========6======== 1: public class Network { 2: Network(int x, Network n) { 3: id = x; 4: p = this; 5: if (n != null) p = n; 6: } 7: int id; 8: Network p; 9: public static void main(String[] args) { 10: Network n1 = new Network(1, null); 11: n1.go(n1); 12: } 13: void go(Network n1) { 14: Network n2 = new Network(2, n1); 15: Network n3 = new Network(3, n2); 16: System.out.println(n3.p.p.id); 17 }} To understand line 16, a step through of the execution of the variable n3.p.p.id is undertaken with the use of use snapshots of the objects in heap memory. The variable call on n3.p.p.id gets executed from left to right. n3.p.p.id aspect gets executed which retrieves the Object Network (Heap Address &261). Memory Snapshot: n2.p 🠚 n1 🠚 Object Network(1,null) (Heap Address &012) { Internal int id 🠢 1 Internal Network p 🠢 null go() } n3.p 🠚 n2 🠚 Object Network(2,n1) (Heap Address @864) { Internal int id 🠢 2 Internal Network p 🠢 n1 🠢 Object Network (Heap Address &012) go() } Local n3 🠚 Object Network(3,n2) (Heap Address &261) { Internal int id 🠢 3 Internal Network p 🠢 n2 🠢 Object Network (Heap Address @864) go() } ========7======== n3.p.p.id states that inside the Object Network (Heap Address &261), the object which is referenced by the variable p is retrieved: Object Network (Heap Address @864) Memory Snapshot: n2.p 🠚 n1 🠚 Object Network(1,null) (Heap Address &012) { Internal int id 🠢 1 Internal Network p 🠢 null go() } n3.p 🠚 n2 🠚 Object Network(2,n1) (Heap Address @864) { Internal int id 🠢 2 Internal Network p🠢 n1 🠢 Object Network (Heap Address &012) go() } Local n3 🠚 Object Network(3,n2) (Heap Address &261) { Internal int id 🠢3 Internal Network p 🠢 n2 🠢 Object Network (Heap Address @864) go() } ========8======== n3.p.p.id states that inside Object Network (Heap Address @864), the object which is referenced by the variable p is retrieved: Object Network (Heap Address &012) Memory Snapshot: n2.p 🠚 n1 🠚 Object Network(1,null) (Heap Address &012) { Internal int id 🠢 1 Internal Network p 🠢 null go() } n3.p 🠚 n2 🠚 Object Network(2,n1) (Heap Address @864) { Internal int id 🠢 2 Internal Network p 🠢 n1 🠢 Object Network (Heap Address &012) go() } Local n3 🠚 Object Network(3,n2) (Heap Address &261) { Internal int id 🠢 3 Internal Network p 🠢 n2 🠢 Object Network (Heap Address @864) go() } ========9======== n3.p.p.id states that inside Object Network (Heap Address &012), the variable id is retrieved i.e. 1 Memory Snapshot: n2.p 🠚 n1 🠚 Object Network(1,null) (Heap Address &012) { Internal int id 🠢 1 Internal Network p 🠢 null go() } n3.p 🠚 n2 🠚 Object Network(2,n1) (Heap Address @864) { Internal int id 🠢 2 Internal Network p 🠢 n1 🠢 Object Network (Heap Address &012) go() } Local n3 🠚 Object Network(3,n2) (Heap Address &261) { Internal int id 🠢 3 Internal Network p 🠢 n2 🠢 Object Network (Heap Address @864) go() } =======10========= Final output: 1

Given: class A { Integer i = 100; A go(A cb) { cb = null; return cb; } public static void main(String[] args) { A c1 = new A(); A c2 = new A(); A c3 = cl.go(c2); // do Stuff } } When // do Stuff is reached, how many objects are eligible for garbage collection? A. 0 B. 1 C. 2 D. Compilation fails E. It is not possible to know F. An exception is thrown at runtime

A is correct. There are 0 objects available for garbage collection. ===Code Step Through=== class A { Integer i = 100; A go(A cb) { cb = null; return cb; } public static void main(String[] args) { A c1 = new A(); A c2 = new A(); A c3 = cl.go(c2); // do Stuff } } The reference variables c1 and c2, are of type A, and are 'pointing to' (referring to) newly created objects of type A. (All objects have a unique heap address except String objects). The following is a depiction in memory of the object A with an arbitrary unique address @863 and with reference c1. It has an internal intance variable i. This internal variable is an object of type Integer with an arbitrary unique address &453 which is storing the int 100: External c1 🠚 Object A (Heap Address @863) { Internal i 🠢 Object Integer( Heap Address &453){100} } Likewise, the following is a depiction in memory of the object A with an arbitrary unique address &327 and with external reference c2. It has an internal intance variable i. This internal variable is an object of type Integer with an arbitrary unique address &178 which is wrapper class storing the int 100: External c2 🠚 Object A (Heap Address &327) { Internal i 🠢 Object Integer( Heap Address &178){100} } Below outlines a snapshot of objects in the memory heap, following the execution of the above lines of code: External c1 🠚 Object A (Heap Address @863) { Internal i 🠢 Object Integer( Heap Address &453){100} } External c2 🠚 Object A (Heap Address &327) { Internal i 🠢 Object Integer( Heap Address &178){100} } ========2======== class A { Integer i = 100; A go(A cb) { cb = null; return cb; } public static void main(String[] args) { A c1 = new A(); A c2 = new A(); A c3 = c1.go(c2); // do Stuff } } The method go() is called by the A reference c1 where c1 is pointing to the object instance A (with Heap Address @863). ========3======== class A { Integer i = 100; A go(A cb) { cb = null; return cb; } public static void main(String[] args) { A c1 = new A(); A c2 = new A(); A c3 = c1.go(c2); // do Stuff } } A copy of the A reference c2 is stored in the reference variable cb which is passed into the go() method. In other words, a pointer to the A object (with Heap Address &327) is passed into the go() method. As a consequence, there are two references to the A object (with Heap Address &327), namely, cb and c2: cb 🠚 c2 🠚 Object A (Heap Address &327) { Internal i 🠢 Object Integer( Heap Address &178){100} } Below outlines a snapshot of objects in the memory heap, following the execution of the above lines of code: External c1 🠚 Object A (Heap Address @863) { Internal i 🠢 Object Integer( Heap Address &453){100} } cb 🠚 c2 🠚 Object A (Heap Address &327) { Internal i 🠢 Object Integer( Heap Address &178){100} } ========4======== class A { Integer i = 100; A go(A cb) { cb = null; return cb; } public static void main(String[] args) { A c1 = new A(); A c2 = new A(); A c3 = c1.go(c2); // do Stuff } } Inside the go() method, the A reference cb is reassigned to null (i.e. the cb reference is not pointing to anything). A copy of the cb variable, which is pointing to null is returned to the main() method. When the go() method completes, it gets destroyed in the stack memory along with all its local variables. The destroyed methods internal objects are available for garbage collection. Below outlines a snapshot of objects in the memory heap, following the execution of the above lines of code: External c1 🠚 Object A (Heap Address @863) { Internal i 🠢 Object Integer( Heap Address &453){100} } cb 🠚 c2 🠚 Object A (Heap Address &327) { Internal i 🠢 Object Integer( Heap Address &178){100} } Snapshot of the Stack Memory: go(){cb 🠢 null} cb is an object reference and pointing to null i.e. no object. ========5======== class A { Integer i = 100; A go(A cb) { cb = null; return cb; } public static void main(String[] args) { A c1 = new A(); A c2 = new A(); A c3 = c1.go(c2); // do Stuff } } The contents of the variable cb of type A which contains null is returned to the main() method. This null is assigned to the A reference c3 in the main() method. Below outlines a snapshot of objects in the memory heap, following the execution of the above lines of code: External c1 🠚 Object A (Heap Address @863) { Internal i 🠢 Object Integer( Heap Address &453){100} } cb 🠚 c2 🠚 Object A (Heap Address &327) { Internal i 🠢 Object Integer( Heap Address &178){100} } c3 🠢 null From the above snapshot you can see there are no objects available for garbage collection. Note: Stack memory stores local variables and methods (function). Heap memory stores object instances no matter where they are located. This means objects that are stored externally or internally.

Given: public class Mirror { int size = 7; public static void main(String[] args) { Mirror m1 = new Mirror(); Mirror m2 = m1; int i1 = 10; int i2 = i1; go(m2 , i2); System.out.println(m1.size + " " + i1); } static void go(Mirror m, int i){ m.size = 8; i = 12; }} What is the result? A. 7 10 B. 8 10 C. 7 12 D. 8 12 E. Compilation fails F. An exception is thrown at runtime

B is correct. The program will print: 8 10 ===Code Step Through=== 1: public class Mirror { 2: int size = 7; 3: public static void main(String[] args) { 4: Mirror m1 = new Mirror(); 5: Mirror m2 = m1; 6: int i1 = 10; 7: int i2 = i1; 8: go(m2 , i2); 9: System.out.println(m1.size + " " + i1); 10: } 11: static void go(Mirror m, int i){ 12: m.size = 8; 13: i = 12; 14: }} On line 4, a reference named m1 variable of type Mirror is referring to an object of type Mirror. This Mirror object is allocated a unique address in the heap memory by the Java Virtual Machine (e.g. @863). The object has an internal primitive int variable named size which is assigned the number 7. The object also contains an instance method which is stored in the stack memory. Note: Objects are stored in heap memory and local variables and static methods are stored in classmemory. The following depicts the object with allocated address @863 stored in the heap memory: External Mirror m1 🠚 Object Mirror (Heap Address @863) { internal int size🠢 7 go(Mirror m, int i)(Class Memory &251) } Note above: the method go() has its own allocated address &251 in class memory as it is a static method. Static methods can only be declared once. ========2======== 1: public class Mirror { 2: int size = 7; 3: public static void main(String[] args) { 4: Mirror m1 = new Mirror(); 5: Mirror m2 = m1; 6: int i1 = 10; 7: int i2 = i1; 8: go(m2 , i2); 9: System.out.println(m1.size + " " + i1); 10: } 11: static void go(Mirror m, int i){ 12: m.size = 8; 13: i = 12; 14: }} On line 5, a reference variable of type Mirror and named m2 is assigned to the same object which is referred to by the reference variable named m1. The following is a pseudocode depiction in memory of the object Mirror with an heap address @863, with reference m2 and m1. External Mirror m2 🠚 m1 🠚 Object Mirror (Heap Address @863) { internal int size 🠢 7 go(Mirror m, int i)(Class Memory &251) } ========3======== 1: public class Mirror { 2: int size = 7; 3: public static void main(String[] args) { 4: Mirror m1 = new Mirror(); 5: Mirror m2 = m1; 6: int i1 = 10; 7: int i2 = i1; 8: go(m2 , i2); 9: System.out.println(m1.size + " " + i1); 10: } 11: static void go(Mirror m, int i){ 12: m.size = 8; 13: i = 12; 14: }} On line 6, a primitive type int variable with identifier i1 is assigned a value 10. On line 7, another primitive type int variable identifier named i2 is assigned the same value that is stored in a variable i1 i.e. 10. ========4======== 1: public class Mirror { 2: int size = 7; 3: public static void main(String[] args) { 4: Mirror m1 = new Mirror(); 5: Mirror m2 = m1; 6: int i1 = 10; 7: int i2 = i1; 8: go(m2 , i2); 9: System.out.println(m1.size + " " + i1); 10: } 11: static void go(Mirror m, int i){ 12: m.size = 8; 13: i = 12; 14: }} On line 8, the go() method is called. A copy of the Mirror reference type named m2 is passed into its paramter. Also, a copy of the contents of the int value named i2 is passed into the parameter of the go() method i.e. 10. ========5======== 1: public class Mirror { 2: int size = 7; 3: public static void main(String[] args) { 4: Mirror m1 = new Mirror(); 5: Mirror m2 = m1; 6: int i1 = 10; 7: int i2 = i1; 8: go(m2 , i2); 9: System.out.println(m1.size + " " + i1); 10: } 11: static void go(Mirror m, int i){ 12: m.size = 8; 13: i = 12; 14: }} On line 11, the Mirror type with identifier named m contains a copy of the reference type named m2. The int type parameter named i, contains the same value that is stored in the int named i2 i.e. 10. The following is a pseudocode depiction in memory of the object Mirror with an heap address @863, with reference m, m2 and m1. m 🠚 m2 🠚 m1 🠚 Object Mirror (Heap Address @863) { internal int size🠢 7 go(Mirror m, int i)(Class Memory &251) } ========6======== 1: public class Mirror { 2: int size = 7; 3: public static void main(String[] args) { 4: Mirror m1= new Mirror(); 5: Mirror m2 = m1; 6: int i1 = 10; 7: int i2 = i1; 8: go(m2 , i2); 9: System.out.println(m1.size + " " + i1); 10: } 11: static void go(Mirror m, int i){ 12: m.size = 8; 13: i = 12; 14: }} On line 12, the size variable which is stored in the Mirror object with reference m2 gets assigned a new value of 8 (the previous value of 7 gets wiped). Memory Snapshot: m 🠚 m2 🠚 m1 🠚 Object Mirror (Heap Address @863) { internal int size🠢 8 go(Mirror m, int i)(Stack Memory &251) } ========7======== 1: public class Mirror { 2: int size = 7; 3: public static void main(String[] args) { 4: Mirror m1 = new Mirror(); 5: Mirror m2 = m1; 6: int i1 = 10; 7: int i2 = i1; 8: go(m2 , i2); 9: System.out.println(m1.size + " " + i1); 10: } 11: static void go(Mirror m, int i ){ 12: m.size = 8; 13: i = 12; 14: }} On line 13, the int variable named i gets assigned a new value of 12. After this, the go() method completes and all its local variables gets destroyed. This means that the local variable i is destroyed. ========8======== Memory Snapshot: m 🠚 m2 🠚 m1 🠚 Object Mirror (Heap Address @863) { internal int size🠢 8 go(Mirror m, int i)(Stack Memory &251) } ========9======== 1: public class Mirror { 2: int size = 7; 3: public static void main(String[] args) { 4: Mirror m1 = new Mirror(); 5: Mirror m2 = m1; 6: int i1 = 10; 7: int i2 = i1; 8: go(m2 , i2); 9: System.out.println(m1.size+ " " + i1); 10: } 11: static void go(Mirror m, int i){ 12: m.size = 8; 13: i = 12; 14: }} On line 9, the value of size which is stored in the object referenced by m1 gets printed i.e. 8. On the same line 9, the value of int type named i1 gets printed i.e. 10 The final output is: 8 10

Given: public class Telescope { static int magnify = 2; public static void main(String [] args) { go(); } static void go() { int magnify = 3; zoomln(); } static void zoomIn() { magnify *= 5; zoomMore(magnify); System.out.printIn(magnify); } static void zoomMore(int magnify) { magnify *= 7; }} What is the result? A. 2 B. 10 C. 15 D. 30 E. 70 F. 105 G. Compilation fails

B is correct. The program will compile and print: 10 Let's step through the code to see how it runs: ===Code Step Through=== 1: public class Telescope { 2: static int magnify = 2; 3: public static void main(String [] args) { 4: go(); 5: } 6: static void go() { 7: int magnify = 3; 8: zoomIn(); 9: } 10: static void zoomIn() { 11: magnify *= 5; 12: zoomMore(magnify); 13: System.out.println(magnify); 14: } 15: static void zoomMore(int magnify) { 16: magnify *= 7; 17: }} On line 4, the static go() method gets called. Class Memory Snapshot: static int magnify = 2; ========2======== 1: public class Telescope { 2: static int magnify = 2; 3: public static void main(String [] args) { 4: go(); 5: } 6: static void go() { 7: int magnify = 3; 8: zoomIn(); 9: } 10: static void zoomIn() { 11: magnify *= 5; 12: zoomMore(magnify); 13: System.out.println(magnify); 14: } 15: static void zoomMore(int magnify) { 16: magnify *= 7; 17: }} On line 6, the go() method commences execution. On line 7, there is a local variable named magnify gets the value 3 assigned to it. This is not the same variable as the static magnify declared on line 2. ========3======== 1: public class Telescope { 2: static int magnify = 2; 3: public static void main(String [] args) { 4: go(); 5: } 6: static void go() { 7: int magnify = 3; 8: zoomIn(); 9: } 10: static void zoomIn() { 11: magnify *= 5; 12: zoomMore(magnify); 13: System.out.println(magnify); 14: } 15: static void zoomMore(int magnify) { 16: magnify *= 7; 17: }} On line 8, the method zoomIn() gets called. Memory Snapshot: static int magnify = 2; ========4======== 1: public class Telescope { 2: static int magnify = 2; 3: public static void main(String [] args) { 4: go(); 5: } 6: static void go() { 7: int magnify = 3; 8: zoomIn(); 9: } 10: static void zoomIn() { 11: magnify *= 5; 12: zoomMore(magnify); 13: System.out.println(magnify); 14: } 15: static void zoomMore(int magnify) { 16: magnify *= 7; 17: }} On line 10, the zoomIn() method executes. On line 11, the static magnify method has the contents of its value 2 multiplied by 5 to give 10. This value 10 is stored in the static variable magnify. Memory Snapshot: static int magnify = 10; ========5======== 1: public class Telescope { 2: static int magnify = 2; 3: public static void main(String [] args) { 4: go(); 5: } 6: static void go() { 7: int magnify = 3; 8: zoomIn(); 9: } 10: static void zoomIn() { 11: magnify *= 5; 12: zoomMore(magnify); 13: System.out.println(magnify); 14: } 15: static void zoomMore(int magnify) { 16: magnify *= 7; 17: }} On line 12, the zoomMore(magnify) with the contents of the static variable magnify passed into it i.e. 10 ========6======== 1: public class Telescope { 2: static int magnify = 2; 3: public static void main(String [] args) { 4: go(); 5: } 6: static void go() { 7: int magnify = 3; 8: zoomIn(); 9: } 10: static void zoomIn() { 11: magnify *= 5; 12: zoomMore(magnify); 13: System.out.println(magnify); 14: } 15: static void zoomMore(int magnify) { 16: magnify *= 7; 17: } } On line 15, the zoomMore(int magnify) method gets executed. On line 15, the contents of the shadow variable magnify are passed into zoomMore() method body i.e. 10 is passed. Note: The paramter zoomMore(int magnify) is shadowing the static variable of the same name (magnify). ========7======== 1: public class Telescope { 2: static int magnify = 2; 3: public static void main(String [] args) { 4: go(); 5: } 6: static void go() { 7: int magnify = 3; 8: zoomIn(); 9: } 10: static void zoomIn() { 11: magnify *= 5; 12: zoomMore(magnify); 13: System.out.println(magnify); 14: } 15: static void zoomMore(int magnify) { 16: magnify *= 7; 17: } } On line 16, the contents of the method parameter named magnify (shadowed variable) is multiplied by 7 using the compund operator '*=' 10 x 7 = 70 This results in the number 70 being assigned to (stored in) the local magnify variable that was declared in the method parameter and NOT the static magnify variable which was declared on the line 2. When the method completes, this local magnify variable is destroyed along with its contents by the JVM (Java Virtual Machine). Memory Snapshot: static int magnify = 10; ========8======== 1: public class Telescope { 2: static int magnify = 2; 3: public static void main(String [] args) { 4: go(); 5: } 6: static void go() { 7: int magnify = 3; 8: zoomIn(); 9: } 10: static void zoomIn() { 11: magnify *= 5; 12: zoomMore(magnify); 13: System.out.println(magnify ); 14: } 15: static void zoomMore(int magnify) { 16: magnify *= 7; 17: }} On line 13, the contents of the static variable magnify get printed i.e. 10 Note: ➤ Local variables and methods are stored on the stack memory. ➤ Static variables and methods are stored in class memory. ➤ Objects are stored in heap memory.

Given: public class Literally { public static void main(String[] args) { // line A int i1 = 1_000; // line B int i2 = 10_00; // line C int i3 = _10_000; // line D int i4 = 0b101010; // line E int i5 = 0B10_1010; // line F int i6 = 0x2_a; }} Which lines WILL NOT compile? (Choose all that apply.) A. Line A B. Line B C. Line C D. Line D E. Line E F. Line F

C is correct. Line C will NOT compile. public class Literally { public static void main(String[] args) { // line A int i1 = 1_000; // line B int i2 = 10_00; // line C int i3 = _10_000; // line D int i4 = 0b101010; // line E int i5 = 0B10_1010; // line F int i6 = 0x2_a; }} As of Java 7, underscores '_' can be included in numeric literals, but not at the beginning or the end. A, B, D, E, and F will compile fine. A and B are legal numeric literals: // line A int i1 = 1_000; // line B int i2 = 10_00; D and E are examples of valid binary literals, which were new to Java 7: // line D int i4 = 0b101010; // line E int i5 = 0B10_1010; F is a valid hexadecimal literal that uses an underscore: // line F int i6 = 0x2_a;

Given: class CardBoard { int story = 200; CardBoard go(CardBoard cb) { cb = null; return cb; } public static void main(String[] args) { CardBoard c1 = new CardBoard(); CardBoard c2 = new CardBoard(); CardBoard c2 = c1.go(c2); c1 = null; // do Stuff } } When '// do Stuff' is reached, how many objects are available for garbage collection? A. 0 B. 1 C. 2 D. Compilation fails E. It is not possible to know F. An exception is thrown at runtime

C is correct. There are 2 objects available for garbage collection. ===Code Step Through=== class CardBoard { int story = 200; CardBoard go(CardBoard cb) { cb = null; return cb; } public static void main(String[] args) { CardBoard c1 = new CardBoard(); CardBoard c2 = new CardBoard(); CardBoard c2 = c1.go(c2); c1 = null; // do Stuff } } The reference variables c1 and c2, are of type CardBoard, and are 'pointing to' (referring to) newly created objects of type CardBoard. (All objects have a unique heap address except String objects). The following is a depiction in memory of the object CardBoard with an arbitrary unique heap address @863 and with reference c1. It has an internal variable story which is assigned 200: External c1 🠚 Object CardBoard (Heap Address @863) { int story 🠢 200 } Likewise, the following is a depiction in memory of the object CardBoard with an arbitrary unique heap address &327 and with reference c2: External c2 🠚 Object CardBoard (Heap Address &327) { internal int story 🠢 200 } Following the execution of the above lines of code, the following outlines a snapshot of objects in the memory heap: External c1 🠚 Object CardBoard (Heap Address @863) { int story 🠢 200 } External c2 🠚 Object CardBoard (Heap Address &327) { internal int story 🠢 200 } ========2======== class CardBoard { int story = 200; CardBoard go(CardBoard cb) { cb = null; return cb; } public static void main(String[] args) { CardBoard c1 = new CardBoard(); CardBoard c2 = new CardBoard(); CardBoard c2 = c1.go(c2); c1 = null; // do Stuff } } The method go() is called by the CardBoard reference c1 where c1 is pointing to the object instance CardBoard (with Heap Address @863). =========3======= class CardBoard { int story = 200; CardBoard go(CardBoard cb) { cb = null; return cb; } public static void main(String[] args) { CardBoard c1 = new CardBoard(); CardBoard c2 = new CardBoard(); CardBoard c2 = c1.go(c2); c1 = null; // do Stuff } } A copy of the CardBoard reference c2 is stored in the reference variable cb which is passed into the go() method. In other words, a pointer to the CardBoard object (with Heap Address &327) is passed into the go() method. As a consequence, there are two references to the CardBoard object (with Heap Address &327). Namely, cb and c2: cb 🠚 c2 🠚 Object CardBoard (Heap Address &327) { internal int story 🠢 200 } Following the execution of the above lines of code, the following outlines a snapshot of objects in the memory heap: External c1 🠚 Object CardBoard (Heap Address @863) { int story 🠢 200 } cb 🠚 c2 🠚 Object CardBoard (Heap Address &327) { internal int story 🠢 200 } ========4======== class CardBoard { int story = 200; CardBoard go(CardBoard cb){ cb = null; return cb; } public static void main(String[] args) { CardBoard c1 = new CardBoard(); CardBoard c2 = new CardBoard(); CardBoard c2 = c1.go(c2); c1 = null; // do Stuff } } Inside the go() method, the CardBoard reference cb is reassigned to null (i.e. the cb reference is not pointing to anything). A copy of the cb variable, which is pointing to null is returned to the main() method. When the go() method completes, it gets destroyed in the stack memory along with all its local variables. Following the execution of the above lines of code, the following outlines a snapshot of objects in the memory heap: External c1 🠚 Object CardBoard (Heap Address @863) { int story 🠢 200 } cb 🠚null c2 🠚 Object CardBoard (Heap Address &327) { internal int story 🠢 200 } Snapshot of the Stack Memory: go(){cb 🠚 null} ========5======== class CardBoard { int story = 200; CardBoard go(CardBoard cb) { cb = null; return cb; } public static void main(String[] args) { CardBoard c1 = new CardBoard(); CardBoard c2 = new CardBoard(); CardBoard c2 = c1.go(c2); c1 = null; // do Stuff } } The contents of the variable cb of type CardBoard which contains null is returned to the main() method. This null is assigned to the CardBoard reference c2 in the main() method. This means c2 variable, which was referring to the CardBoard object (with Heap Address &327), is reassigned to null. This means that there are no references to the CardBoard object (with Heap Address &327). Following the execution of the above lines of code, the following outlines a snapshot of objects in the memory heap: c1 🠚 Object CardBoard (Heap Address @863) { int story 🠢 200 } c2 🠚 null Object CardBoard (Heap Address &327) { internal int story 🠢 200 } ========6======== class CardBoard { int story = 200; CardBoard go(CardBoard cb) { cb = null; return cb; } public static void main(String[] args) { CardBoard c1 = new CardBoard(); CardBoard c2 = new CardBoard(); CardBoard c2 = c1.go(c2); c1 = null; // do Stuff } } The c1 variable, which was referring to the CardBoard object (with Heap Address @863), is reassigned to null. There is a now a null reference (represented by the character 'Ø') to the object with memory address @863 and &327. This means that there are no references to the CardBoard object (with Heap Address @863). Following the execution of the above lines of code, the following gives a snapshot of objects in the memory heap: c1 🠚 null Ø 🠚Object CardBoard (Heap Address @863) { int story 🠢 200 } c2 🠚 null Ø 🠚Object CardBoard (Heap Address &327) { internal int story 🠢 200 } The above snapshot shows that there are two objects Heap Addresses @863 and &327 which have no references and therefore are available for garbage collection. Note: Stack memory stores local variables and methods (function). Heap memory stores object instances.

Given: class A { Integer i = 100; A go(A cb) { cb = null; return cb; } public static void main(String[] args) { A c1 = new A(); A c2 = new A(); c2 = c1.go(c2); // do Stuff } } When // do Stuff is reached, how many objects are eligible for garbage collection? A. 0 B. 1 C. 2 D. Compilation falls E. It is not possible to know F. An exception is thrown at runtime

C is correct. There are 2 objects available for garbage collection. ===Code Step Through=== class A { Integer i = 100; A go(A cb) { cb = null; return cb; } public static void main(String[] args) { A c1 = new A(); A c2 = new A(); c2 = c1.go(c2); // do Stuff } } The reference variables c1 and c2, are of type A, and are 'pointing to' (referring to) newly created objects of type A. (All objects have a unique heap address except String objects). The following is a depiction in memory of the object A with an arbitrary unique address @863 and with reference c1. It has an internal intance variable i. This internal variable is an object of type Integer with an arbitrary unique address &453 which is wrapper class storing the int 100. i.e. External c1 🠚 Object A (Heap Address @863) { Internal i 🠢 Object Integer(Heap Address &453){100} } Likewise, the following is a depiction in memory of the object A with an arbitrary unique address &327 and with external reference c2. It has an internal intance variable i. This internal variable is an object of type Integer with an arbitrary unique address &178 which is wrapper class storing the int 100. i.e. External c2 🠚 Object A (Heap Address &327) { Internal i 🠢 Object Integer(Heap Address &178){100} } Below outlines a snapshot of objects in the memory heap, following the execution of the above lines of code: External c1 🠚 Object A (Heap Address @863) { Internal i 🠢 Object Integer(Heap Address &453){100} } External c2 🠚 Object A (Heap Address &327) { Internal i 🠢 Object Integer(Heap Address &178){100} } ========2======== class A { Integer i = 100; A go(A cb) { cb = null; return cb; } public static void main(String[] args) { A c1 = new A(); A c2 = new A(); c2 = c1.go(c2); // do Stuff } } The method go() is called by the A reference c1 where c1 is pointing to the object instance A (with Heap Address @863). ========3======== class A { Integer i = 100; A go(A cb) { cb = null; return cb; } public static void main(String[] args) { A c1 = new A(); A c2 = new A(); c2 = c1.go(c2); // do Stuff } } A copy of the A reference c2 is stored in the reference variable cb which is passed into the go() method. In other words, a pointer to the A object (with Heap Address &327) is passed into the go() method. As a consequence, there are two references to the A object (with Heap Address &327). Namely, cb and c2 i.e cb 🠚 c2 🠚 Object A (Heap Address &327) { Internal i 🠢 Object Integer( Heap Address &178){100} } Below outlines a snapshot of objects in the memory heap, following the execution of the above lines of code: External c1 🠚 Object A (Heap Address @863) { Internal i 🠢 Object Integer(Heap Address &453){100} } cb 🠚 c2 🠚 Object A (Heap Address &327) { Internal i 🠢 Object Integer( Heap Address &178){100} } ========4======== class A { Integer i = 100; A go(A cb) { cb = null; return cb; } public static void main(String[] args) { A c1 = new A(); A c2 = new A(); c2 = c1.go(c2); // do Stuff } } Inside the go() method, the A reference cb is reassigned to null (i.e. the cb reference is not pointing to anything). A copy of the cb variable, which is pointing to null is returned to the main() method. When the go() method completes, it gets destroyed in the stack memory along with all its local variables. The destroyed methods internal objects are available for garbage collection. Below outlines a snapshot of objects in the memory heap, following the execution of the above lines of code: c1 🠚 Object A (Heap Address @863) { Internal i 🠢 Object Integer( Heap Address &453){100} } c2 🠚Object A (Heap Address &327) { Internal i 🠢 Object Integer( Heap Address &178){100} } Snapshot of the Stack Memory: go(){cb 🠚 null} cb is an internal object reference and pointing to null i.e. no object. Note: instance variables and methods are stored in stack memory. ========5======== class A { Integer i = 100; A go(A cb) { cb = null; return cb; } public static void main(String[] args) { A c1 = new A(); A c2 = new A(); c2 = c1.go(c2); // do Stuff } } The contents of the variable cb of type A which contains null is returned to the main() method. This null is assigned to the A reference c2 in the main() method. Below outlines a snapshot of objects in the memory heap, following the execution of the above lines of code. There is a null reference (represented by the character 'Ø') to the object with memory address &327. c1 🠚 Object A (Heap Address @863) { Internal i 🠢 Object Integer( Heap Address &453){100} } c2 🠚 null Ø 🠚Object A (Heap Address &327) { Internal i 🠢 Object Integer(Heap Address &178){100} } From the above snapshot you can see there are two objects available for garbage collection. i.e. The Object A with Heap Address &327 and its internal object Integer with Heap Address &178 is available for garbage collection. Note: Stack memory stores local variables and methods (function). Heap memory stores object instances no matter where they are located. This means objects that are stored externally or internally.

Given: public class A { String name; A(String s) { name = s; } public static void main(String[] args) { A d1 = new A("Boi"); A d2 = new A("Tyri"); System.out.print((d1 == d2) + " "); A d3 = new A("Boi"); d2 = d1; System.out.print((d1 == d2) + " "); System.out.print((d1 == d3) + " "); }} What is the result? A. true true true B. true true false C. false true false D. false true true E. false false false F. An exception will be thrown at runtime

C is correct. The program will print: false true false The '==' operator tests if two objects of the same type have the same address in memory. If they have the same address then they are equal and the result is true. ===Code Step Through=== 1: public class A { 2: String name; 3: A(String s) { name = s; } 4: public static void main(String[] args) { 5: A d1 = new A("Boi"); 6: A d2 = new A("Tyri"); 7: System.out.print((d1 == d2) + " "); 8: A d3 = new A("Boi"); 9: d2 = d1; 10: System.out.print((d1 == d2) + " "); 11: System.out.print((d1 == d3) + " "); 12: }} On line 5 and 6, two A objects are created with reference names d1 and d2. The Java Virtual Machine (JVM), allocates addresses in memory for these objects e.g. d1 object is allocated &432 and d2 object is allocated &198. The following is a pseudo code snapshot of the objects created in heap memory: External d1 🠚 Object A (Heap Address &432) { String name 🠢 null } External d2 🠚 Object A (Heap Address &198) { String name 🠢 null } ========2======== 1: public class A { 2: String name; 3: A(String s) { name = s; } 4: public static void main(String[] args) { 5: A d1 = new A("Boi"); 6: A d2 = new A("Tyri"); 7: System.out.print((d1 == d2) + " "); 8: A d3 = new A("Boi"); 9: d2 = d1; 10: System.out.print((d1 == d2) + " "); 11: System.out.print((d1 == d3) + " "); 12: }} On line 7, the address of the object that is referenced by d1 is compared with the address of the object that is referenced by d2. As the memory address of d1 object is &432 and memory address of d2 object is &198 are not equal: The output is false ========3======== 1: public class A { 2: String name; 3: A(String s) { name = s; } 4: public static void main(String[] args) { 5: A d1 = new A("Boi"); 6: A d2 = new A("Tyri"); 7: System.out.print((d1 == d2) + " "); 8: A d3 = new A("Boi"); 9: d2 = d1; 10: System.out.print((d1 == d2) + " "); 11: System.out.print((d1 == d3) + " "); 12: }} On line 8, a new object is created with its own to me address in memory: External d3 🠚 Object A (Heap Address &847) { String name 🠢 null } The following is a snapshot of the objects in memory: Heap Memory Snapshot External d1 🠚 Object A (Heap Address &432) { String name 🠢 null } External d2 🠚 Object A (Heap Address &198) { String name 🠢 null } External d3 🠚 Object A (Heap Address &847) { String name 🠢 null } ========4======== 1: public class A { 2: String name; 3: A(String s) { name = s; } 4: public static void main(String[] args) { 5: A d1 = new A("Boi"); 6: A d2 = new A("Tyri"); 7: System.out.print((d1 == d2) + " "); 8: A d3 = new A("Boi"); 9: d2 = d1; 10: System.out.print((d1 == d2) + " "); 11: System.out.print((d1 == d3) + " "); 12: }} On line 9, the reference d2 is reassigned to the object that is being pointed to by the reference d1. There is a now a null reference (represented by the character 'Ø' below) to the object with memory address &198. The following is a snapshot of the objects in memory: Heap Memory Snapshot d2 🠚 d1 🠚 Object A (Heap Address &432) { String name 🠢 null } Ø 🠚Object A (Heap Address &198) { String name 🠢 null } External d3 🠚 Object A (Heap Address &847) { String name 🠢 null } ========5======== 1: public class A { 2: String name; 3: A(String s) { name = s; } 4: public static void main(String[] args) { 5: A d1 = new A("Boi"); 6: A d2 = new A("Tyri"); 7: System.out.print((d1 == d2) + " "); 8: A d3 = new A("Boi"); 9: d2 = d1; 10: System.out.print((d1 == d2) + " "); 11: System.out.print((d1 == d3) + " "); 12: }} On line 10, the address of the object that is referenced by d1 is compared with the address of the object that is referenced by d2. As references d1 and d2 are pointing to the same object with address &432 then they are both equal. The output is true ========6======== 1: public class A { 2: String name; 3: A(String s) { name = s; } 4: public static void main(String[] args) { 5: A d1 = new A("Boi"); 6: A d2 = new A("Tyri"); 7: System.out.print((d1 == d2) + " "); 8: A d3 = new A("Boi"); 9: d2 = d1; 10: System.out.print((d1 == d2) + " "); 11: System.out.print((d1 == d3) + " "); 12: }} On line 11, the address of the object that is referenced by d1 is compared with the address of the object that is referenced by d3. As references d1 and d3 are not pointing to the same object. Therefore the output is false Heap Memory Snapshot d2 🠚 d1 🠚 Object A (Heap Address &432) { String name 🠢 null } Ø 🠚Object A (Heap Address &198) { String name 🠢 null } External d3 🠚 Object A (Heap Address &847) { String name 🠢 null } Final output: false true false

Given: 3. public class Dark { 4. int x = 3; 5. public static void main(String[] args) { 6. new Dark().go1(); 7 } 8. void go1() { 9. int x; 10. go2(++x); 11. } 12. void go2(int y) { 13. int x = ++y; 14. System.out.printIn(x); 15. } 16 } What is the result? A. 2 B. 3 C. 4 D. 5 E. Compilation fails F. An exception is thrown at runtime

E is correct Compilation fails In go1(), the local variable x is not initialized. Local variables must be initialized. 3. public class Dark { 4. int x = 3; 5. public static void main(String[] args) { 6. new Dark().go1(); 7 } 8. void go1() { 9. int x; 10. go2(++x); 11. } 12. void go2(int y) { 13. int x = ++y; 14. System.out.printIn(x); 15. } 16 }

Given: public class Fishing { byte b1 = 4; int i1 = 123456; // line A long L1 = (long) i1; // line B short s2 = (short) i1; //line C byte b2 = (byte) i1; // line D int i2 = (int) 123.456; // line E byte b3 = b1 + 7; } Which lines WILL NOT compile? (Choose all that apply.) A. Line A B. Line B C. Line C D. Line D E. Line E

E is correct. Compilation fails on line E. public class Fishing { byte b1 = 4; int i1 = 123456; // line A long L1 = (long) i1; // line B short s2 = (short) i1; //line C byte b2 = (byte) i1; // line D int i2 = (int) 123.456; // line E byte b3 = b1 + 7; } b1 + 7 is autocast to int. The resulting 'int' value needs to be stored in byte b3. However, conversion from int to byte is a narrowing of type which gives a compile error. Solution: Cast is required // line E byte b3 = (byte)(b1 + 7); Note: The Rules for Primitive Type Conversions are an essential aspect of the exam and will pop up regularly in questions. Primitive type conversion rules are comprised of: ➤ Rules for Widening (not requiring casting) ➤ Rules for Narrowing (requiring casting) In the case of Widening Type Conversion (i.e. not requiring casting), the following suggested abbreviation should be memorised for the exam: "b-silfd" where: b = byte, s = short, i = int, l = long, f = float, d = double With the above abbreviation, you can derive the following Widening Type Conversion "Tree" (it's best advised to memorise this for the exam as a reference) Widening Type Conversion "Tree" (not requiring casting): byte to short, int, long, float, double .................. ↲ short to int, long float, double .................. ↲ int to long float, double .............. ↲ long to float, double .................. ↲ float to double. In other words, when converting the above e.g. converting from byte to short, a cast is not needed. As an example: byte b1 = 13; short s1 = b1 ; System.out.println(s1); The above will output: 13 byte to short What this means is that a byte value can be assigned to a short type without casting. This is called Widening Type Conversion. =================== The opposite of the above is termed Narrowing Type Conversion In the case of Narrowing Type Conversion (i.e. requiring casting), the following suggested abbreviation should be memorised for the exam : "dbs-cilf" where: d = double, b =byte, s = short, c = char, i = int, l = long, f = float, With the above abbreviation, you can derive the following Narrowing Type Conversion 'Tree' (it's best advised to memorise this for the exam as a reference): Narrowing Type Conversion 'Tree' (requiring casting): double to byte, short, char, int, long, float ............................................................................. ↲ float to byte to short, char, int, long ................................................................ ↲ long to byte to short, char, int ........................................................ ↲ int to byte, short, char ................................... ↲ charto byte, short. .......................... ↲ short to byte or char. In other words, when converting the above, a cast is required. For instance converting from an int to byte type or a short to char type requires casting. As an example: byte b4 = 4; byte b5 = ( byte ) (b4+4); System.out.println(b5); When the addition operation is executed between b4 + 4, the result value (8) is of primitive type int This int value needs to be casted to byte to store byte value from the Narrowing Primitive Type 'tree': int to byte, short, char. By casting, the resultant output would be: 8

Let T = true and F = false. List all of the values of the following logical operators considering the following boolean value sequences: A B--- A&&B---- A||B T T------?----------? T T------?----------? F F-----?----------? F F-----?----------?

This is an imperative question which will pop up frequently in exam questions. You will need to memorize this table for the exam: A B---A&&B---- A||B T T -----T----------T T F -----F---------T F T-----F----------T F F-----F----------F Short-Circuit - Boolean Operators One of the aspects that you will also need to know for the exam is the short-circuit evaluation of boolean operators. This short-circuiting for the '&&' and '||' operators are explained below: Logical '&&' Short-Circuit: Let's look at the highlighted aspects of the table which outlines the logical '&&' short-circuit: A B---A&&B T T ------T T F ------F F T------F F F------F Looking at the table above, if A is false (F), then the operator '&&' does not check the value of B to see whether or not it is true (T) or false (F), it simply short-circuits to the result to false (F). Logical '||' Short-Circuit: Likewise, looking at the highlighted aspects of the table which outlines the logical '||' short-circuit: A B-----A||B T T ------T T F ------T F T ------T F F ------F Likewise, looking at the table above, if A is false (T), then the operator '||' doesn't check the value of B to see whether or not it is true (T) or false (F), it simply short-circuits to the result to true (T). Note: Bitwise operators like & | ^ are not on the exam Java 6 Java 7 Java 8

Which of the following will give a compiler error? (Choose all that apply) a) int j, k=1, 1, m=3; b) int j, k=1, p, m=3; c) int j, k=1, p, m=k+3; d) int j, k=m+3, p, m=1; e) none of the above

a) and d) will give compiler errors. a) int j, k=1, 1, m=3; The above is the equivalent of: int j; int k=1; int 1; int m = 3; This gives the compiler error ================ d) int j, k=m+3, p, m=1; The above is the equivalent of: int j; int k=m+3; int p; int m=1; m assigned before being intialised therefore it gives a compiler error ================ b) int j, k=1, p, m=3; The above is the equivalent of: int j; int k=1; int p; int m=3; The above compiles fine ================ c) int j,k=1, p, m=k+3; The above is the equivalent of: int j; int k=1; int p; int m=k+3; The above compiles fine

Given: int x = 15; int y = x%4; System.out.println(y); Whats the output of the above

a) is correct. It will compile and print: 1 Let's step through the code to see how it runs: ===Code Step Through=== 1: public class A { 2: public static void main(String[] args) { 3: int x = 21; 4: int y = x%4; 5: System.out.println(y); 6: }} On the line 3, int variable 'x' is assigned the value 21. ========2======== 1: public class A { 2: public static void main(String[] args) { 3: int x = 21; 4: int y = x%4; 5: System.out.println(y); 6: }} On the line 4, the expression 'x%4' is executed which has the modulus operator '%'. The modulus operator executes in two sequential stages: ➤ Firstly it calculates how many times the value on the right-hand side of the operator can fit into the value on the left-hand side of the operator as a whole. As we can see, 4 divides into 21 five whole times to make 20. ➤ Next, the whole number on the left-hand side of the modulus '%' operator is subtracted from 20: 21-20 = 1. This gives the us the result i.e. 1

Given: class Cat{} class Dog { public static void main(String[] args){ Dog d = new Dog(); System.out.println(d instanceof Cat); }} What is the result? (Choose all that apply) a) compiler error b) runtime error c) compile and print true d) none of the above

a) is correct. The code will give a compiler error. Looking at the code below: class Cat {} class Dog { public static void main(String[] args){ Dog d = new Dog(); System.out.println(d instanceof Cat); } } Dog is not a type of Cat. These classes are unrelated therefore the gives a compiler error. Solution: The following would return true: class Cat {} class Dog extends Cat { public static void main(String[] args){ Dog d = new Dog(); System.out.println(d instanceof Cat); } }

Given: class A { private int j; static void m(A a1, A a2){ a1.j=1; a1=a2; } public static void main(String[] args) { A x = new A(); A y = new A(); System.out.println("x: "+x.j); System.out.println("y: "+y.j); m(x, y); System.out.println("x: "+x.j); System.out.println("y: "+y.j); }} What is the result? (Choose all that apply) a) x: 0 y: 0 x: 1 y: 0 b) x: 0 y: 0 x: 0 y: 0 c) x: 0 y: 0 x: null y: 0 d) none of the above

a) is correct. The following will be printed: x: 0 y: 0 x: 1 y: 0 ===Code Step Through=== class A { private int j; static void m(A a1, A a2){ a1.j=1; a1=a2; } public static void main(String[] args) { A x = new A(); A y = new A(); System.out.println("x: "+x.j); System.out.println("y: "+y.j); m(x, y); System.out.println("x: "+x.j); System.out.println("y: "+y.j); }} A variable x of type A is 'pointing to' (referring to) a newly created object of type A. All objects have a unique address). The following is a depiction of an object A in memory with j being its instance variable. i.e. x 🠚 Object A(heap address 123){ j=0 } A variable y of type A is 'pointing to' (referring to) a newly created object of type A. y 🠚 Object A (heap address 456){ j=0 } ========2======== class A { private int j; static void m(A a1, A a2){ a1.j=1; a1=a2; } public static void main(String[] args) { A x = new A(); A y = new A(); System.out.println("x: "+x. j ); System.out.println("y: "+y. j ); m(x, y); System.out.println("x: "+x.j); System.out.println("y: "+y.j); }} As the int instance variable j (in the object referenced by x) is not initialised, the default value will be 0. Also, as the int instance variable j (in the object referenced by y ) is not initialised, the default value will be 0. Therefore, the output will be: Outputs: x: 0 Outputs: y: 0 ========3======== class A { private int j; static void m(A a1, A a2){ a1.j=1; a1=a2; } public static void main(String[] args) { A x = new A(); A y = new A(); System.out.println("x: "+x.j); System.out.println("y: "+y.j); m(x , y ); System.out.println("x: "+x.j); System.out.println("y: "+y.j); }} The static method m() gets called and has passed to it COPIES of the original references x and y. In essence, the above will pass copies of 'pointers' to the addresses of the objects that are referenced by x and y. ========4======== class A { private int j; static void m(A a1, A a2) { a1.j=1; a1=a2; } public static void main(String[] args) { A x = new A(); A y = new A(); System.out.println("x: "+x.j); System.out.println("y: "+y.j); m(x, y); System.out.println("x: "+x.j); System.out.println("y: "+y.j); }} The original reference x and a copy reference a1 are now pointing to same Object A (address 123): x🠚 a1 🠚 Object A (heap address 123) { j=0 } The original reference y and a copy reference a2 are pointing to the same Object A (unique address 456): y🠚 a2 🠚 Object A (heap address 456) { j=0 } ========5======== class A { private int j; static void m(A a1, A a2){ a1. j =1; a1=a2; } public static void main(String[] args) { A x = new A(); A y = new A(); System.out.println("x: "+x.j); System.out.println("y: "+y.j); m(x, y); System.out.println("x: "+x.j); System.out.println("y: "+y.j); }} In the above, the instance variable j which is located in the object referred to by a1 (and x) gets assigned the value 1: x🠚 a1 🠚 Object A (heap address 123) { j =1 } ========6======== class A { private int j; static void m(A a1, A a2){ a1.j=1; a1=a2; } public static void main(String[] args) { A x = new A(); A y = new A(); System.out.println("x: "+x.j); System.out.println("y: "+y.j); m(x, y); System.out.println("x: "+x.j); System.out.println("y: "+y.j); }} In the above, a1 is now referencing ('pointing') to the same object A that reference a2 is pointing to. As a consequence, it has dereferenced its old object with unique heap address 123 and is pointing to the object A with heap address 456: x 🠚 Object A (heap address 123) { j=1 } y🠚 a1🠚 a2🠚 Object A (heap address 456) { j=0 } =========7======== class A { private int j; static void m(A a1, A a2){ a1.j=1; a1=a2; } public static void main(String[] args) { A x = new A(); A y = new A(); System.out.println("x: "+x.j); System.out.println("y: "+y.j); m(x, y); System.out.println("x: "+x.j ); System.out.println("y: "+y.j); }} The above calls the instance variable j from the object A which is referred to by reference x: x 🠚 Object A (heap address 123) { j =1 } Output: x: 1 ========8========= class A { private int j; static void m(A a1, A a2){ a1.j=1; a1=a2; } public static void main(String[] args) { A x = new A(); A y = new A(); System.out.println("x: "+x.j); System.out.println("y: "+y.j); m(x, y); System.out.println("x: "+x.j); System.out.println("y: "+y.j ); }} The above calls the instance variable j from the object A which is referred to by reference y (The object is also referenced by a2 and a1): y 🠚 a2 🠚 a1 🠚 Object A (heap address 456) { j =0 } Output: y: 0

Which of the following will not compile? (Choose all that apply) a) double d = 1_234_.25; b) double d = 1_234.25; c) double d = 0_1234.25; d) double d = 0_1_2_3_4.2_5;

a) is correct. The following will give a compiler error: double d = 1_234_.25; You cannot place a '_' at the end of a literal. b) double d = 1_234.25; c) double d = 0_1234.25; d) double d = 0_1_2_3_4.2_5; Will all print 1234.25 Note: You can use '_' in a double (or int) literal to make the literal easier to read.

Given: Integer i = new Integer(3); Short s = new Short("3"); System.out.println(i==s); What is the result? (Choose all that apply) a) compiler error b) Runtime error c) compile and print true d) none of the above

a) is correct. The program will give a compiler error. If two objects (wrapped types) are of different type and unrelated it would give a compiler error. Integer i = new Integer(3); Short s = new Short("3"); System.out.println(i ==s );

Given: class A { public static void main(String[] args) { int k; System.out.println(++k); }} What is the result? (Choose all that apply) a) compiler error b) runtime error c) compile and print 1 d) none of the above

a) is correct. The program will give a compiler error. The local variable 'k' must be initialized before use i.e. class A { public static void main(String[] args) { int k=0; System.out.println(++k); }}

Given: short s = 3.0; int i = 3; System.out.println(i==s); What is the result? (Choose all that apply) a) compiler error b) Runtime error c) compile and print false d) none of the above

a) is correct. The program will give a compiler error. short s = 3.0; int i = 3; System.out.println(i==s); Primitive 'short' types store whole numbers only. Minimum value of a short type is -32,768 Maximum value of a short type is 32,767 Solution: Change the value of short s = 3; will compile and print true. short s = 3; int i = 3; System.out.println(i==s); The above output true

Given: float f=5.5; double d = 3.8; int i = (int) (f+d); System.out.println(i); What is the result? (Choose all that apply) a) compiler error b) runtime error c) compile and print 9 d) none of the above

a) is correct. There is a missing f in the float digit which causes a compiler error: float f=5.5; double d = 3.8; int i = (int) (f+d); System.out.println(i); Solution: float f=5.5f; double d = 3.8; int i = (int) (f+d); System.out.println(i); Note: double d1 = 5.5f where f is optional when declaring a double type value.

Which of the following is the correct compound operator for the following expression: int y = 6; y = y-6; (Choose all that apply) a) y -= 6; b) y =- 6; c) y -= y-6; d) none of the above

a) is correct. y -= 6; Compound operators are more efficient. The compound operator of y = y-6 is the following: y -= 6 which results in 'y' getting initilised to: '0' The Following Are Incorrect ➤ b) y=-6 The above results in 'y' getting initilised to '-6'. ➤ c) y -= y-6 The above results in 'y' getting initilised to '6'.

Which of the following are true statements? (Choose all that apply) a) Declaring static variables makes the program less memory efficient b) Declaring static variables makes the program more memory efficient c) Declaring static variables makes the program more easier to read d) none of the above

b) is correct. Declaring static variables makes the program more memory efficient. Note: Stack Memory stores the reference variables to objects and method calls e.g. 'a1' and 'a2'. Consider the following sample program: 1: public class Employee{ 2: private static int companyName; 3: private int id; 4: public A(int anId){ 5: id=anId; 6: } 7: public static void main(String[] args){ 8: Employee a1 = new Employee(1); 9: Employee a2 = new Employee(2); 10: }} On the line 8 and 9 of the main() method, local reference variables 'a1' and 'a2' are declared. If there was an infinite recursive call to a method in the program, this could cause a StackOverflowError where the references collide with methods stored on the stack. On the other hand, Heap Memory is used to store objects and member variables (instance variables). On the line 8 and 9 above, there are objects created of type Employee. new Employee(1); new Employee(2); On the line 2, there is an instance variable named 'companyName'. If there are variables that are no longer used in the program but not available for garbage collection, this could cause a memory 'leak' or OutOfMemoryError. Class Memory stores static: • Variables • Methods • Method blocks Declaring static variables makes the program more memory efficient as there is only one static variable ccreated a class and not per object instance. Conversely in the case of instance variables, these are created per object instance and not per class.

Given: public static void m(int n) { 1: String s; 2: System.out.println(s); 3: if(n>0) 4: s="true"; 5: else 6: s="false"; } What line will cause the compiler error: (Choose all that apply) a) Line 1 b) Line 2 c) Line 4 d) none of the above

b) is correct. Line 2 gives a compiler error. public static void m(int n) { 1: String s; 2: System.out.println(s); 3: if(n>0) 4: s="true"; 5: else 6: s="false"; } You must initialize local variables, otherwise the code will give a compiler error. If line 2 was removed, then it would not give a compiler error as the variable 's' is not used.

Given: System.out.println(1+2+"3"); What is the result? (Choose all that apply) a) compiler error b) compile and print 33 c) compile and print 6 d) none of the above

b) is correct. The program will compile and print: 33 System.out.println(1+2+"3"); Based on the Rules of Precedence, the execution of the '+' operator starts on the left hand side of the expression and moves to the right (goes from left to right): 1+2+"3" ↓ 3+"3" ↓ "33" Operator Order of Precedence This question tests your knowledge on the Operator Order of Precedence (Rules of Precedence). This is very important to learn for the exam. Expressions, Operators and Operands: Firstly, it's important to explain expressions, operators and operands. Below is an example of an expression. 1 + 2 + "3" Expressions are comprised of operands(e.g. numbers and/or objects). Below is an outline of operands in an expression i.e. 1,3 and the String object "3": 1 + 2 + "3" Expressions are also comprised of operators (e.g. +, -, %, /, etc). Below is an outline of the operators in the question: 1 + 2 + "3" The Problem: Where does an expression (equation) start when executed? On the left-hand side, right hand side or somewhere else in the equation? Java has well-defined rules for solving the above problem. Solution The Operator Order of Precedence Rules solves this. Below outlines 16 rules in order of precedence. The rules are as follows where: Rule 1 has the highest priority operator in the expression (equation) execute first. Rule 2 has the second highest priority operator in an expression executed next and so forth. Below also outlines the 16 rules in relation to associativity. Associativity: Associativity is important when an expression has more than one operator of the same kind (e.g. 3 - 2 - 1 where '-' is the minus symbol). Do we start with subtracting 2 from 3 or do we start with subtracting 1 from 2 first? The order of precedence provides the answer to this also. It would be advisable to memorise the operator order of precedence with the following suggested 16 rule abbreviation (write this down in the exams as a reference): B-PUC-MAS-REBBLLTA Where: B = Brackets P = Postfix i++ etc. Operator Order of Precedence: 1 Brackets e.g. () [] method(); (Associativity: Starting left to right) 2 Postfix e.g. i++, i-- (Associativity: Starting left to right) 3 Unary e.g. ++i, --j (Associativity: Starting right to left) 4 Cast or object creation e.g. (int), newObject() (Associativity: Starting right to left) 5 Multiplication, Division, mod % e.g. *, /, % (Associativity: Starting left to right) 6 Addition subtraction e.g. +, - (Associativity: Starting left to right) 7 Shift e.g. >>, <<, >>> (Associativity: Starting left to right) 8 Relational e.g. <, <=, >, >= instanceof (Associativity: Starting left to right) 9 Equality e.g. ==, != (Associativity: Starting left to right) 10 Bitwise AND, & (Associativity: Starting left to right) 11 Bitwise XOR ^ (Associativity: Starting left to right) 12 Bitwise OR | (Associativity: Starting left to right) 13 Logical AND && (Associativity: Starting left to right) 14 Logical OR || (Associativity: Starting left to right) 15 Tiernary e.g. (boolean)?varA:varB; (Associativity: Starting right to left) 16 Assignment e.g. = =, /=, %=, +=, -=, &=, ^=, |=, <<=, >>=, >>>= (Associativity: Starting right to left) It would also be prudent to memorise for the exam the following associativity rules which executes right to left instead of the majority left-to-right as outlined above: U-CAST-TA 3 Unary e.g. ++i, --j (Associativity: Starting right to left) 4 Cast or object creation e.g. (int), newObject() (Associativity: Starting right to left) 15 Tiernary e.g. (boolean)?varA:varB; (Associativity: Starting right to left) 16 Assignment e.g. = =, /=, %=, +=, -=, &=, ^=, |=, <<=, >>=, >>>= (Associativity: Starting right to left) The Operator Order of Precedence can be explained as with the following example: System.out.println(1+2+"3"); 1 + 2 + "3" is an expression with two operators that are the same (i.e. +) Rule 6 applies to the above expression: 6 Addition subtraction e.g. +, - (Associativity: Starting left to right) with associativity starting from left to right 1+2+"3" 3+"3" After that, the expression is comprised of the digit 3 and the String object containing "3" outlined above. According to the rules of precedence again: 6 Addition subtraction e.g. +, - (Associativity: Starting left to right) Therefore the digit 3 gets appended to the string object "3". This results in the final output: "33"

Given: boolean b = false; if (b=true) { System.out.println("true"); } else { System.out.println("false"); } What is the result? (Choose all that apply) a) compiler error b) compile and print true c) compile and print false d) none of the above

b) is correct. The program will print true. boolean b = false; if (b=true) { System.out.println("true"); } else { System.out.println("false"); } b is ASSIGNED '=' true and not compared to true. Solution: Use the equality operator boolean b = false; if (b==true) { System.out.println("true"); } else { System.out.println("false"); }

Given: class A { private A n; public static void main(String[] args) { A a1 = new A(); A a2 = new A(); a2.n=a1; a2=null; a1=null; a1.n=a2; }} What is the result? (Choose all that apply) a) compiler error b) runtime error c) compile and run fine d) none of the above

b) is correct. The program will throw a runtime error. java.lang.NullPointerException will be thrown. For questions of this kind, it is imperative that you write out (depict) on paper the states of values and references in memory as each line executes. Essentially you will be simulating the compiler. ===Code Step Through=== class A { private A n; public static void main(String[] args) { A a1 = new A(); A a2 = new A(); a2.n=a1; a2=null; a1=null; a1.n=a2; }} The reference variables a1 and a2, are of type A, and are 'pointing to' (referring to) newly created objects of type A. (All objects have a unique address except String objects). The following is a depiction in memory of the object A with an arbitrary unique heap address @863 and with reference a1. It has an internal instance variable n of type A which is not assigned (not referencing) an object (therefore it is 'pointing' to null): External a1 🠚 Object A (Address @863) { internal A n 🠢 null } Likewise, the following is a depiction in memory of the object A with an arbitrary unique heap address &327 and with reference a2. It has an internal instance variable n of type A which is not assigned (not referencing) an object (therefore it is 'pointing' to null). External a2 🠚 Object A (Address &327) { internal A n 🠢 null } Following the execution of the above lines of code, the following outlines a snapshot of objects in the memory heap: External a1 🠚 Object A (Address @863) { internal A n 🠢 null } External a2 🠚 Object A (Address &327) { internal A n 🠢 null } ========2======== class A { private A n; public static void main(String[] args) { A a1 = new A(); A a2 = new A(); a2.n = a1; a2=null; a1=null; a1.n=a2; }} The Internal reference n (of the object that the reference a2 is referring to) is now referring to the same object that external reference a1 is referring to, namely, Object A (Address @863): External a2 🠚 Object A (Address &327) { internal n 🠢 Object A { n=null} (Address @863) } =========3======= class A { private A n; public static void main(String[] args) { A a1 = new A(); A a2 = new A(); a2.n=a1; a2 = null; a1=null; a1.n=a2; }} The external reference a2 gets reassigned to null. Which means that a2 doesn't point to any object. There is a now a null reference (represented by the character 'Ø') to the object with memory address &327. This means that no external references are pointing to Object A (Address &327). External a2 🠚 null Ø 🠚Object A (Address &327) { internal n 🠢 Object A{ n=null} (Address @863)} } Commenting on the above depiction, even though no external references are pointing to the object A with address &327, this object A is still not available for garbage collection as it is indirectly referencing another object A via its internal reference n, namely, Object A (Address @863) This is what is known as Island of Isolation. Following the execution of the above line of code, the following outlines a snapshot of objects in the memory heap: External a1 🠚 Object A (Address @863) { internal A n🠚 null } External a2 🠚 null Ø 🠚Object A (Address &327) { internal A n 🠚 Object A { n=null} (Address @863)} } ========4======== class A { private A n; public static void main(String[] args) { A a1 = new A(); A a2 = new A(); a2.n=a1; a2=null; a1 = null; a1.n=a2; }} The External reference a1 gets reassigned to null. Which means that a1 no longer points to any object. There is a now a null reference (represented by the character 'Ø') to the object with memory address @863. Which means that no external references are pointing to object A (Address @863): External a1 🠚 null Ø 🠚 Object A (Address @863) { internal A n 🠚 null } After the above line gets executed, there are no external references to the above object A (Address @863) and (Address &327) therefore both objects are available for garbage collection. The following outlines a snapshot of objects in the memory heap which depicts the object available for garbage collection: External a1 🠚 null Ø 🠚 Object A (Address @863) { internal A n 🠚 null } External a2 🠚 null Ø 🠚 Object A (Address &327) { internal A n 🠚 Object A { n=null} (Address @863)} } ========5======== class A { private A n; public static void main(String[] args) { A a1 = new A(); A a2 = new A(); a2.n=a1; a2=null; a1=null; a1.n = a2; }} Now that the object A (Address @863) and (Address &327) are pointing to null. That means they are not referring to any object External a1 🠚 null External a2 🠚 null Therefore when the reference a1 attempts to call an internal instance variable n, the compiler throws: java.lang.NullPointerException Note 1: The garbage collector is called when there are no references to objects in memory. It is not possible to effectively call the garbage collector manually as the execution of the garbage collector is at the discretion of the Java Virtual Machine. In other words, the garbage collector overrules any manual call to it by the developer. Note 2: Islands of Isolation: As stated above, islands of isolation are where there is an object in memory, which has no longer any external references but that particular objects internal instance variables may still point to external objects in memory. This means that even though this object is not referenced and therefore not used in the code, it is still not available for garbage collection. This has the potential for a kind of 'memory leak' in Java because the more islands of isolation in the code, the greater the chance of memory running out and the application failing. Note 3: This kind of question involving assigning and reassigning objects will be tested in the exam. If you can understand and successfully complete this question, then you have no difficulty.

Which of the following will not compile (Choose all that apply) a) int j,k,i; j=k=i=1; b) int j=k=i=0; d) none of the above

b) is correct. int j = k = i = 0; You cannot do a chained intialisation. This will give compiler error a) int j,k,i; j = k = i = 1; You can do chained assignments

Given: public class Employee{ private static int companyName; private int id; public A(int anId){ id=anId; } public static void main(String[] args){ Employee a1 = new Employee(1); Employee a2 = new Employee(2); }} What is the result? (Choose all that apply) a) Employee a1 and a2 refs are stored in heap memory Member variable id is stored in the stack memory static variable companyName is stored in class memory b) Employee a1 and a2 refs are stored in stack memory Member variable id is stored in the heap memory static variable companyName is stored in class memory c) Employee a1 and a2 refs are stored in stack memory Member variable id is stored in the class memory static variable companyName is stored in heap memory d) none of the above

b) is correct. ➤ Employee a1 and a2 reference variables are stored in stack memory. ➤ Member variable id is stored in the heap memory. ➤ Static variable companyName is stored in class memory. public class Employee{ private static int companyName; private int id; public A(int anId){ id=anId; } public static void main(String[] args){ Employee a1 = new Employee(1); Employee a2 = new Employee(2); }} Note: Stack Memory stores the reference variables to objects and method calls e.g. 'a1' and 'a2'. This can cause a StackOverflowError where the references collide with methods stored on the stack. Heap Memory is used to store objects and member variables e.g. new Employee(1); new Employee(2); Heap memory can cause an OutOfMemoryError. Class Memory stores static: • Variables • Methods • Method blocks Declaring static variables makes the program more memory efficient.

What is the following in decimal literal form: int i = 010; a) 7 b) 8 c) 9 d) none of the above

b) is the correct answer i.e. 8 This question tests your knowledge of Octal Literals. To convert a decimal number into an Octal Literal, the rule states: ➤ Only digits 0 to 7 are used. ➤ Place a zero in front of the number e.g. int one = 01; int two = 02; int three = 03; int four = 04; int five = 05; int six = 06; int seven = 07; ============== int eight = 010; int nine = 011; int ten = 012; int elven = 013; int twelve = 014; int thirteen = 015; int fourteen = 016; int fifteen = 017; =============== int sixteen = 020; int seveteen = 021; int eighteen = 022; . . .

Which of the following will give a compiler error? (Choose all that apply) a) char c = 0x892; b) char c = -29; c) char c = (char) 7000; d) char c = (char) -98; e) none of the above

b) will give a compiler error. char c = -29; Compiler error - possible loss of precision needs a cast

Given: boolean b = 100>99; System.out.println(b); What is the result? (Choose all that apply) a) compiler error b) runtime error c) compile and print false d) none of the above

d) is correct. The answer will be: 'none of the above' The output is: true Taking another example: boolean b = 100>99; System.out.println(b); The above will compile and run fine.

Given: class A { public static void main(String[] args) { int [] nums = new int[3]; if (nums instanceof Object) { System.out.println("True"); }}} What is the result? (Choose all that apply) a) compiler error b) runtime error c) compile and print True d) none of the above

c) is correct. It will compile and print: True class A { public static void main(String[] args) { int [ ] nums = new int[3]; if (nums instanceof Object) { System.out.println("True"); }}} Arrays are objects. 'instanceof' compares objects only Therefore the code will compile and run fine

Given: FinWhale extends Whale extends Mammal extends Animal Spider extends Invertibrate extends Animal Which of the following will compile a) Animal object instanceof Mammal b) Spider object instanceof Mammal c) none

c) is correct. The answer is none will compile. For questions of such nature it may be beneficial to sketch out a UML class hierarchy of the objects: [Spider] 🠇 extends 🠇 [Invertibrate] 🠇 extends 🠇 [Animal] 🠅 extends 🠅 [Mammal] 🠅 extends 🠅 [Whale] 🠅 extends 🠅 [FinWhale] Incorrect Answers: a) Animal object instanceof Mammal. The above will give a compile error as a Mammal is an instance of Animal not the other way around. b) Spider object instanceof Mammal The above and also give a compiler error as Spider can never be an instance of Mammal. They are completely unrelated classes.

Given: class A { static String m(){ return "m"; } public static void main(String[] args) { long x = 42L; long y = 44l; System.out.println(x+y+m()); }} What is the result? (Choose all that apply) a) compiler error b) runtime error c) compile and print 86m d) none of the above

c) is correct. The program will compile and print: 86m class A { static String m(){ return "m"; } public static void main(String[] args) { long x = 42L; long y = 44l; System.out.println(x+y+m()); }} Based on the Rules of Precedence, method 'm()' gets executed first which returns the string value "m": x+y+m() -----↓-- x+y+"m" Then addition and subtraction is executed from right to left: 42+44+"m" -↓--------- 86+"m" Digit 86 is added to the string object starting right to left: 86+"m" ---↓---- "86m" Note: Operator Order of Precedence This question tests your knowledge on the Operator Order of Precedence (Rules of Precedence). This is very important to learn for the exam. Expressions, Operators and Operands: Firstly, it's important to explain expressions, operators and operands. Below is an example of an expression. 1 + 2 + "3" Expressions are comprised of operands(e.g. numbers and/or objects). Below is an outline of operands in an expression i.e. 1,3 and the String object "3": 1 + 2 + "3" Expressions are also comprised of operators (e.g. +, -, %, /, etc). Below is an outline of the operators in the question: 1 + 2 + "3" The Problem: Where does an expression (equation) start when executed? On the left-hand side, right hand side or somewhere else in the equation? Java has well-defined rules for solving the above problem. Solution The Operator Order of Precedence Rules solves this. Below outlines 16 rules in order of precedence. The rules are as follows where: Rule 1 has the highest priority operator in the expression (equation) execute first. Rule 2 has the second highest priority operator in an expression executed next and so forth. Below also outlines the 16 rules in relation to associativity. Associativity: Associativity is important when an expression has more than one operator of the same kind (e.g. 3 - 2 - 1 where '-' is the minus symbol). Do we start with subtracting 2 from 3 or do we start with subtracting 1 from 2 first? The order of precedence provides the answer to this also. It would be advisable to memorise the operator order of precedence with the following suggested 16 rule abbreviation (write this down in the exams as a reference): B-PUC-MAS-REBBLLTA Where: B = Brackets P = Postfix i++ etc. Operator Order of Precedence: 1 Brackets e.g. () [] method(); (Associativity: Starting left to right) 2 Postfix e.g. i++, i-- (Associativity: Starting left to right) 3 Unary e.g. ++i, --j (Associativity: Starting right to left) 4 Cast or object creation e.g. (int), newObject() (Associativity: Starting right to left) 5 Multiplication, Division, mod % e.g. *, /, % (Associativity: Starting left to right) 6 Addition subtraction e.g. +, - (Associativity: Starting left to right) 7 Shift e.g. >>, <<, >>> (Associativity: Starting left to right) 8 Relational e.g. <, <=, >, >= instanceof (Associativity: Starting left to right) 9 Equality e.g. ==, != (Associativity: Starting left to right) 10 Bitwise AND, & (Associativity: Starting left to right) 11 Bitwise XOR ^ (Associativity: Starting left to right) 12 Bitwise OR | (Associativity: Starting left to right) 13 Logical AND && (Associativity: Starting left to right) 14 Logical OR || (Associativity: Starting left to right) 15 Tiernary e.g. (boolean)?varA:varB; (Associativity: Starting right to left) 16 Assignment e.g. = =, /=, %=, +=, -=, &=, ^=, |=, <<=, >>=, >>>= (Associativity: Starting right to left) It would also be prudent to memorise for the exam the following associativity rules which executes right to left instead of the majority left-to-right as outlined above: U-CAST-TA 3 Unary e.g. ++i, --j (Associativity: Starting right to left) 4 Cast or object creation e.g. (int), newObject() (Associativity: Starting right to left) 15 Tiernary e.g. (boolean)?varA:varB; (Associativity: Starting right to left) 16 Assignment e.g. = =, /=, %=, +=, -=, &=, ^=, |=, <<=, >>=, >>>= (Associativity: Starting right to left) The Operator Order of Precedence can be explained as with the following example: System.out.println(1+2+"3"); 1 + 2 + "3" is an expression with two operators that are the same (i.e. +) Rule 6 applies to the above expression: 6 Addition subtraction e.g. +, - (Associativity: Starting left to right) with associativity starting from left to right 1+2+"3" 3+"3" After that, the expression is comprised of the digit 3 and the String object containing "3" outlined above. According to the rules of precedence again: 6 Addition subtraction e.g. +, - (Associativity: Starting left to right) Therefore the digit 3 gets appended to the string object "3". This results in the final output: "33"

Given: abstract class A { public static void main(String[] args) { A a = null; }} What is the result? (Choose all that apply) a) compiler error b) runtime error c) compile and run fine d) none of the above

c) is correct. The program will compile and run fine. An abstract class cannot be instantiated but it can have a main method without an instantiated instance of the abstract class. abstract class A { public static void main(String[] args) { A a = null; } }

Given: class A { public static void main(String[] args) { boolean happy = true; boolean h1 = false; 1: System.out.println(happy?"I'm happy":777); 2: System.out.println(happy?new Integer(12):777); 3: System.out.println(h1?777:4/2); }} What is the result? (Choose all that apply) a) compiler error line 3 b) compiler error line 1 c) compile and run fine d) none of the above

c) is correct. The program will compile and run fine. This program test your understanding of the ternary operator. class A { public static void main(String[] args) { boolean happy = true; boolean h1 = false; 1: System.out.println(happy ? "I'm happy" : 777); 2: System.out.println(happy ? new Integer(12) : 777); 3: System.out.println(h1? 777 : 4/2); }} I'm happy 12 2 You can use the Ternary Operator ? : e.g. boolean ? varA : Varb Where varA and varB can be different types. The above would mean: If the boolean value is true then execute varA otherwise execute varB ===Code Step Through=== class A { public static void main(String[] args) { boolean happy = true; boolean h1 = false; 1: System.out.println(happy ? "I'm happy" : 777); 2: System.out.println(happy?new Integer(12):777); 3: System.out.println(h1?777:4/2); }} On line 1, the compiler checks if the boolean variable happy contains true. As happy variable contains true, then "I'm happy" is printed to the screen. ==========2========= class A { public static void main(String[] args) { boolean happy = true; boolean h1 = false; 1: System.out.println(happy?"I'm happy":777); 2: System.out.println(happy ? new Integer(12) : 777); 3: System.out.println(h1?777:4/2); }} On line 2, the compiler checks if the boolean variable happy contains true. As happy boolean contains true, then the contents of the Wrapper object (new Integer()) is auto-unboxed and is printed to the screen. =========3========= class A { public static void main(String[] args) { boolean happy = true; boolean h1 = false; 1: System.out.println(happy?"I'm happy":777); 2: System.out.println(happy?new Integer(12):777); 3: System.out.println(h1 ? 777 : 4/2); }} On line 3, the compiler checks if the boolean variable h1 contains true. As h1 boolean contains false, then the contents of the expression is 4/2 is executed and the resultant value 2 is printed to the screen. Note 1: A Wrapper class enables primitive types to be wrapped as objects e.g. The 'int' primtive type wrapped as 'Integer' object, 'double' primitive type wrapped as 'Double' object and so forth. Note 2: Auto-unboxing means that the contents of a wrapper class can be converted to its primitive type (e.g. int) without explicitly calling a method to convert it (e.g. for conversion to int type intValue()) e.g. Without auto-unboxing: Integer i = new Integer(2); System.out.println( i .intValue()); Using intValue(), the above output is: 2 or With auto-unboxing: Integer i = new Integer(2); System.out.println( i ); The above uses auto-unboxing to convert the Integer wrapper object to its primitive int type. The output is also: 2

Given: float f=5.5f; double d = 3.8; int i = (int) (f+d); System.out.println(i); What is the result? (Choose all that apply) a) compiler error b) runtime error c) compile and print 9 d) none of the above

c) is correct. The program will compile in print: 9 float f=5.5f; double d = 3.8; int i = (int) (f+d); (int)5.5f + 3.8 -------↓--------- (int) 5.5+3.8 -------↓--------- (int) 9.3 -------↓--------- -------9--------- Note 1: The rule states that one must round down when converting values to an int. Note 2: In the above, we add the variables first before casting the result of the addition. Note 3: float f =5.5f; f is required at the end of the variable to indicate that the value is a float. The 'f' is optional in assigning double value e.g. double f = 5.5f; However: float f =5.5; The above would give the compiler error.

Given: Integer i = new Integer(3); Integer f = new Integer(3); System.out.println(i==f); What is the result? (Choose all that apply) a) compiler error b) Runtime error c) compile and print false d) none of the above

c) is correct. The program will compile in print: false The equality operator '==' compares addresses of objects and returns false as addresses are different. ===Code Step Through=== Integer i = new Integer(3); Integer f = new Integer(3); System.out.println(i==f); A new Integer object, which contains the value 3, is created and is referenced by i . All objects created in Java (apart from String objects) have unique addresses to enable them to be located and used in the Memory Heap. e.g. i = new new Integer(3); 🠘 Heap Address: &1234 ========2======== Integer i = new Integer(3); Integer f = new Integer(3); System.out.println(i==f); Next, another Integer object is created which is referenced by f and contains the same value 3 as the above object but has a different address in the memory heap. e.g. f = new new Integer(3); 🠘 Heap Address: @4563 ========3======== Integer i = new Integer(3); Integer f = new Integer(3); System.out.println(i==f); i==f compares the heap addresses of the Integer objects i.e. &1234 == @4563 As the above have different addresses, the output result is false Note: ➤ Objects are stored in the Memory Heap. ➤ Local variables and methods are stored in the Memory Stack. ➤ Static methods and variables are stored in Class Memory.

Given: System.out.println(100/9.9); What is the result? (Choose all that apply) a) compiler error b) 10 c) 10.1010101010101 d) none of the above

c) is correct. The value 100, which is a primitive type int, is converted to primitive type double without an explicit cast: 100/9.9 ↓ 100.0/9.9 Calculation executed: 100.0/9.9 ----↓---- 10.1010101010 Note: The Rules for Primitive Type Conversions are an essential aspect of the exam and will pop up regularly in questions. Primitive type conversion rules are comprised of: ➤Rules for Widening (not requiring casting) ➤Rules for Narrowing (requiring casting) In the case of Widening Type Conversion (i.e. not requiring casting), the following suggested abbreviation should be memorised for the exam: "b-silfd" where: b = byte, s = short, i = int, l = long, f = float, d = double With the above abbreviation, you can derive the following Widening Type Conversion "Tree" (it's best advised to memorise this for the exam as a reference) Widening Type Conversion "Tree" (not requiring casting): byte to short, int, long, float, double .................. ↲ short to int, long float, double .................. ↲ int to long float, double .............. ↲ long to float, double .................. ↲ float to double. In other words, when converting the above e.g. converting from byte to short, a cast is not needed. As an example: byte b1 = 13; short s1 = b1 ; System.out.println(s1); The above will output: 13 byte to short What this means is that a byte value can be assigned to a short type without casting. This is called Widening Type Conversion. =================== The opposite of the above is termed Narrowing Type Conversion In the case of Narrowing Type Conversion (i.e. requiring casting), the following suggested abbreviation should be memorised for the exam : "dbs-cilf" where: d = double, b =byte, s = short, c = char, i = int, l = long, f = float, With the above abbreviation, you can derive the following Narrowing Type Conversion 'Tree' (it's best advised to memorise this for the exam as a reference): Narrowing Type Conversion 'Tree' (requiring casting): double to byte, short, char, int, long, float ............................................................................. ↲ float to byte to short, char, int, long ................................................................ ↲ long to byte to short, char, int ........................................................ ↲ int to byte, short, char ................................... ↲ charto byte, short. .......................... ↲ short to byte or char. In other words, when converting the above, a cast is required. For instance converting from an int to byte type or a short to char type requires casting. As an example: byte b4 = 4; byte b5 = ( byte ) (b4+4); System.out.println(b5); When the addition operation is executed between b4 + 4, the result value (8) is of primitive type int This int value needs to be casted to byte to store byte value from the Narrowing Primitive Type 'tree': int to byte, short, char. By casting, the resultant output would be: 8

Given: int i = 207/200; What is the result? (Choose all that apply) a) compiler error b) compile and store 2 in i c) compile and store 1 in int i d) none of the above

c) will compile and store 1 in int i int/int = int 207/200 --↓----- 1.035 --↓----- --1----- As int types only store whole numbers, the decimal of the result is rounded down to 1.

Given: double d = 5.0; int i += d; What is the result? (Choose all that apply) a) compiler error b) runtime error c) compile and store the value 5 in int i d) none of the above

c) will compile and store the value 5 in int i. Compound assignment operators += do internal cast i.e. no cast is needed

Given: boolean a = false; boolean b = false; boolean c = false; boolean bool = (a=true) ||(b=true)&&(c=true); System.out.println(a+" "+b+" "+c); What is the result? (Choose all that apply) a) compiler error b) runtime error c) compile and print true true true d) none of the above

d is correct. The answer will be: 'none of the above'. It will print: true false false For this question, it is imperative that you understand and have memorized the Logical Truth Tables for the operators '&&' and '||'. See the notes at the end of the question which explains this in fine detail. Let's step to the code: ===Code Step Through=== 1: public class A { 2: public static void main(String[] args) { 3: boolean a = false; 4: boolean b = false; 5: boolean c = false; 6: boolean bool = (a=true) || (b=true) && (c=true); 7: System.out.println(a+" "+b+" "+c); 8: }} On the lines 3, 4 and 5, the boolean variables 'a', 'b', and 'c' are initialized false. ========2======== 1: public class A { 2: public static void main(String[] args) { 3: boolean a = false; 4: boolean b = false; 5: boolean c = false; 6: boolean bool = (a=true) || (b=true) && (c=true); 7: System.out.println(a+" "+b+" "+c); 8: }} Next, on the line 6, the value 'a' is assigned to 'true' The current state of the expression would look like: (true) || (b=true) && (c=true); ========3======== 1: public class A { 2: public static void main(String[] args) { 3: boolean a = false; 4: boolean b = false; 5: boolean c = false; 6: boolean bool = (a=true) || (b=true) && (c=true); 7: System.out.println(a+" "+b+" "+c); 8: }} For the next aspect of the expression to execute, we need to reference the Logical Truth Table (Short-Circuit): Logical '||' Short-Circuit: The following table outlines the logical '||' short-circuit: A B-----A||B T T ------T T F ------T F T ------T F F ------F Looking at the table above, if A is false (T), then the operator '||' doesn't check the value of B to see whether or not it is true (T) or false (F), it simply short-circuits to the result to true (T). Looking at the current state of the expression on the line 6, we can see that the left-hand side of the '||' operator is true: (true) || (b=true) && (c=true) Therefore, the variables 'b' and 'c' on the right hand side of the '||' operator are NOT assigned to true, they remain false as initialized on line 4 and 5. Therefore the output on the line 7 is: System.out.println(true+" "+false+" "+false); Note 1: Logical Truth Table Understanding logical truth tables would be an imperative aspect of the course. These type of questions pop up very regularly. You will need to understand and memorize this table for the exam (Where 'T' is true and 'F' is false): You will need to memorize this table for the exam: A B---A&&B---- A||B T T -----T----------T T F -----F---------T F T-----F----------T F F-----F----------F Short-Circuit - Boolean Operators One of the aspects that you will also need to know for the exam is the short-circuit evaluation of boolean operators. This short-circuiting for the '&&' and '||' operators are explained below: Logical '&&' Short-Circuit: Let's look at the highlighted aspects of the table which outlines the logical '&&' short-circuit: A B---A&&B T T ------T T F ------F F T------F F F------F Looking at the table above, if A is false (F), then the operator '&&' does not check the value of B to see whether or not it is true (T) or false (F), it simply short-circuits to the result to false (F). Logical '||' Short-Circuit: Likewise, looking at the highlighted aspects of the table which outlines the logical '||' short-circuit: A B-----A||B T T ------T T F ------T F T ------T F F ------F Likewise, looking at the table above, if A is false (T), then the operator '||' doesn't check the value of B to see whether or not it is true (T) or false (F), it simply short-circuits to the result to true (T). Note: Bitwise operators like & | ^ are not on the exam Java 6 Java 7 Java 8

Which of the following are true about the following primitive types? (Choose all that apply) a) 'short' can store 8 bits b) 'int' can store 16 bits c) 'long' can store 32 bits d) 'float' can store 32 bits e) 'double' can store 64 bits

d) and e) are correct. ➤ d) 'float' can store 32 bits ➤ e) 'double' can store 64 bits In this question, use an aspect of the Rules for Type Conversion to help. In particular, the Rules for Widening (not requiring casting). The following abbreviation would be best memorised for the exam: Note: The Rules for Primitive Type Conversions are an essential aspect of the exam and will pop up regularly in questions. Primitive type conversion rules are comprised of: ➤Rules for Widening (not requiring casting) ➤Rules for Narrowing (requiring casting) In the case of Widening Type Conversion (i.e. not requiring casting), the following suggested abbreviation should be memorised for the exam: "b-silfd" where: b = byte, s = short, i = int, l = long, f = float, d = double With the above abbreviation, you can derive the following Widening Type Conversion "Tree" (it's best advised to memorise this for the exam as a reference) Widening Type Conversion "Tree" (not requiring casting): byte to short, int, long, float, double .................. ↲ short to int, long float, double .................. ↲ int to long float, double .............. ↲ long to float, double .................. ↲ float to double. In other words, when converting the above e.g. converting from byte to short, a cast is not needed. As an example: byte b1 = 13; short s1 = b1 ; System.out.println(s1); The above will output: 13 byte to short What this means is that a byte value can be assigned to a short type without casting. This is called Widening Type Conversion. =================== The opposite of the above is termed Narrowing Type Conversion In the case of Narrowing Type Conversion (i.e. requiring casting), the following suggested abbreviation should be memorised for the exam : "dbs-cilf" where: d = double, b =byte, s = short, c = char, i = int, l = long, f = float, With the above abbreviation, you can derive the following Narrowing Type Conversion 'Tree' (it's best advised to memorise this for the exam as a reference): Narrowing Type Conversion 'Tree' (requiring casting): double to byte, short, char, int, long, float ............................................................................. ↲ float to byte to short, char, int, long ................................................................ ↲ long to byte to short, char, int ........................................................ ↲ int to byte, short, char ................................... ↲ charto byte, short. .......................... ↲ short to byte or char. In other words, when converting the above, a cast is required. For instance converting from an int to byte type or a short to char type requires casting. As an example: byte b4 = 4; byte b5 = ( byte ) (b4+4); System.out.println(b5); When the addition operation is executed between b4 + 4, the result value (8) is of primitive type int This int value needs to be casted to byte to store byte value from the Narrowing Primitive Type 'tree': int to byte, short, char. By casting, the resultant output would be: 8

Given: float f=5.5f; double d = 3.8; int i = (int) f+(int)d; System.out.println(i); What is the result? (Choose all that apply) a) compiler error b) runtime error c) compile and print 9 d) none of the above

d) is correct. None of the answers are correct. In questions of this type it is important to remember to round down when converting to primitive int type. int i = (int) f + (int) d; Let's step through the execution of the above expression: ===Code Step Through=== float f=5.5f; double d = 3.8; int i = (int) f+(int)d; System.out.println(i); In the above highlighted code, the primitive float variable named 'f ' is called which results in the current expression state looking like: int i = (int) 5.5f+(int)d; ========2======== float f=5.5f; double d = 3.8; int i = (int) 5.5f+(int)d; System.out.println(i); Likewise, in the above highlighted code, the primitive double variable 'd' is called which results in the current expression state looking like: int i = (int) 5.5f+(int)3.8; ========3======== float f=5.5f; double d = 3.8; int i = (int) 5.5f+(int)3.8; System.out.println(i); Next, the float value 5.5f in the expression gets cast to an int type which removes the remainder resulting in the expression looking like: int i = (int) 5+(int)3.8; ========4======== float f=5.5f; double d = 3.8; int i = 5+ (int)3.8; System.out.println(i); Likewise, in the above expression, the value of the variable 'd' is cast to an int type which rounds down to 3. This results in the expression's current state looking like: int i = 5+ 3; Note: In questions of this type, it is important to remember to round down when converting to int type. ========5======== float f=5.5f; double d = 3.8; int i = 5 + 3; System.out.println(i); Next, the expression resolves to '8' which gets stored in the variable 'i'. ========6======== float f=5.5f; double d = 3.8; int i = 5 + 3; System.out.println(i); The following is output to the screen at this stage: 8 Note: Even though 3.8 is closer to 4 than 3, the rule states that one must round down when converting values to an int type. In the above, we cast the variables to ints before adding together

Given: int k = 2; boolean b = (k>3); System.out.println(b); What is the result? (Choose all that apply) a) compiler error b) Runtime error c) compile and print true d) none of the above

d) is correct. None of the answers are correct. The output will be: false int k = 2; boolean b = (k>3); System.out.println(b); (k>3); is the correct syntax Compiler checks is 2>3, and the resultant value of false is assigned to the boolean b.

Given: short s = 3; Integer i = new Integer(3); System.out.println(i==s); What is the result? (Choose all that apply) a) compiler error b) Runtime error c) compile and print false d) none of the above

d) is correct. None of the answers are correct. The program prints: true Any two primitives can be compared with '==' Any primitive type and wrapped type can be compared with '==' If two objects (wrapped types) are of different type and unrelated it would give a compiler error e.g. Double d1 = new Double(10); Integer i1 = new Integer(10); System.out.println(d1==i1); The above will give a compiler error

Given: public class A { public static void main(String[] args) { int k = 1; k += ((k=4)+(k+2)); System.out.println(k); }} What is the result? (Choose all that apply) a) compile and print 10 b) compile and print 11 c) compile and print 6 d) none of the above

d) is correct. The correct answer is: 'none of the above' The code will compile and print: 11 Let's step through the code to see how it runs: ===Code Step Through=== 1: public class A { 2: public static void main(String[] args) { 3: int k = 1; 4: k += ((k=4)+(k+2)); 5: System.out.println(k); 6: }} On the line 3, the int variable 'k' is assigned 1. ========2======== 1: public class A { 2: public static void main(String[] args) { 3: int k = 1; 4: k += ((k=4)+(k+2)); 5: System.out.println(k); 6: }} On the line 4, += the compound assignment operator saves the current value of k in the expression: k+((k=4)+(k+2)) As 'k' is currently storing value 1, the expression state currently looks like this: k+((k=4)+(k+2)) ↓ 1+((k=4)+(k+2)) ========3======== 1: public class A { 2: public static void main(String[] args) { 3: int k = 1; 4: k += ((k=4)+(k+2)); 5: System.out.println(k); 6: }} Next, variable 'k' gets assigned 4 in the expression: k+((k=4)+(k+2)) ↓--------------- 1+((k=4)+(k+2)) ----↓----------- 1+((4)+(k+2)) ========4======== 1: public class A { 2: public static void main(String[] args) { 3: int k = 1; 4: k += ((k=4)+(k+2)); 5: System.out.println(k); 6: }} Next, the current value of k (which is 4) get added with 2: k+((k=4)+(k+2)) ↓--------------- 1+((k=4)+(k+2)) ----↓----------- 1+((4)+(k+2)) --------↓------- 1+((4)+(4+2)) --------↓------- 1+((4)+(6)) The expression then resolves to completion with the expression inside of brackets executed next (see rules of precedence below in notes): k+((k=4)+(k+2)) ↓--------------- 1+((k=4)+(k+2)) ----↓----------- 1+((4)+(k+2)) --------↓------- 1+((4)+(4+2)) --------↓------- 1+((4)+(6)) ---↓------------ 1+(10) -↓-------------- 11 As you can see above, the resultant output is 11 Note: Operator Order of Precedence This question tests your knowledge on the Operator Order of Precedence (Rules of Precedence). This is very important to learn for the exam. Expressions, Operators and Operands: Firstly, it's important to explain expressions, operators and operands. Below is an example of an expression. 1 + 2 + "3" Expressions are comprised of operands(e.g. numbers and/or objects). Below is an outline of operands in an expression i.e. 1,3 and the String object "3": 1 + 2 + "3" Expressions are also comprised of operators (e.g. +, -, %, /, etc). Below is an outline of the operators in the question: 1 + 2 + "3" The Problem: Where does an expression (equation) start when executed? On the left-hand side, right hand side or somewhere else in the equation? Java has well-defined rules for solving the above problem. Solution The Operator Order of Precedence Rules solves this. Below outlines 16 rules in order of precedence. The rules are as follows where: Rule 1 has the highest priority operator in the expression (equation) execute first. Rule 2 has the second highest priority operator in an expression executed next and so forth. Below also outlines the 16 rules in relation to associativity. Associativity: Associativity is important when an expression has more than one operator of the same kind (e.g. 3 - 2 - 1 where '-' is the minus symbol). Do we start with subtracting 2 from 3 or do we start with subtracting 1 from 2 first? The order of precedence provides the answer to this also. It would be advisable to memorise the operator order of precedence with the following suggested 16 rule abbreviation (write this down in the exams as a reference): B-PUC-MAS-REBBLLTA Where: B = Brackets P = Postfix i++ etc. Operator Order of Precedence: 1 Brackets e.g. () [] method(); (Associativity: Starting left to right) 2 Postfix e.g. i++, i-- (Associativity: Starting left to right) 3 Unary e.g. ++i, --j (Associativity: Starting right to left) 4 Cast or object creation e.g. (int), newObject() (Associativity: Starting right to left) 5 Multiplication, Division, mod % e.g. *, /, % (Associativity: Starting left to right) 6 Addition subtraction e.g. +, - (Associativity: Starting left to right) 7 Shift e.g. >>, <<, >>> (Associativity: Starting left to right) 8 Relational e.g. <, <=, >, >= instanceof (Associativity: Starting left to right) 9 Equality e.g. ==, != (Associativity: Starting left to right) 10 Bitwise AND, & (Associativity: Starting left to right) 11 Bitwise XOR ^ (Associativity: Starting left to right) 12 Bitwise OR | (Associativity: Starting left to right) 13 Logical AND && (Associativity: Starting left to right) 14 Logical OR || (Associativity: Starting left to right) 15 Tiernary e.g. (boolean)?varA:varB; (Associativity: Starting right to left) 16 Assignment e.g. = =, /=, %=, +=, -=, &=, ^=, |=, <<=, >>=, >>>= (Associativity: Starting right to left) It would also be prudent to memorise for the exam the following associativity rules which executes right to left instead of the majority left-to-right as outlined above: U-CAST-TA 3 Unary e.g. ++i, --j (Associativity: Starting right to left) 4 Cast or object creation e.g. (int), newObject() (Associativity: Starting right to left) 15 Tiernary e.g. (boolean)?varA:varB; (Associativity: Starting right to left) 16 Assignment e.g. = =, /=, %=, +=, -=, &=, ^=, |=, <<=, >>=, >>>= (Associativity: Starting right to left) The Operator Order of Precedence can be explained as with the following example: System.out.println(1+2+"3"); 1 + 2 + "3" is an expression with two operators that are the same (i.e. +) Rule 6 applies to the above expression: 6 Addition subtraction e.g. +, - (Associativity: Starting left to right) with associativity starting from left to right 1+2+"3" 3+"3" After that, the expression is comprised of the digit 3 and the String object containing "3" outlined above. According to the rules of precedence again: 6 Addition subtraction e.g. +, - (Associativity: Starting left to right) Therefore the digit 3 gets appended to the string object "3". This results in the final output: "33"

Given: System.out.println(90/100); a) compiler error b) 0.1 c) 0.9 d) none of the above

d) is correct. When the primitive int type is divided by a primitive int type, the result will be an int type. Looking at the expression below we can see the result is 0. 90/100 ----↓----- ---0.9---- ----↓----- ---0----- The value was initially 0.9 and this gets casted to them in which is is rounded down. This results in the final output: 0


Ensembles d'études connexes

Chapter 30 - Bowel Elimination Care

View Set

Chapter 4 Notes: Describing Bivariate Data

View Set