6 - Java OCA 8 - Array, ArrayList, String, StringBuilder, Lambda, and Date

¡Supera tus tareas y exámenes ahora con Quizwiz!

Which of the following will compile? a) int i = 0; for ( i = 0; i < 2; i++) { System.out.println(i); } b) int i; for ( i = 0; i < 2; i++) { System.out.println(i); } } c) int i=0; for ( i; i < 2; i++) { System.out.println(i); }} d) None of the answers are correct.

a) and b) are correct. a) Looking at the program below: 1: int i = 0; 2: for ( i = 0; i < 2; i++) { 3: System.out.println(i); 4: } On the line 1, the int variable i is declared and initialized to 0 before being used in the for loop on the line 2. This is perfectly okay. The above will print: 0 1 b) Looking at the program below: 1: int i ; 2: for ( i = 0; i < 2; i++) { 3: System.out.println(i); 4: } 5: } On the line 1, the int variable i is declared. On the line 2, the int variable is initialized to 0 and used in the for loop. This is perfectly fine. The above will print: 0 1 Incorrect Answers: c) int i=0; for ( i; i < 2; i++) { System.out.println(i); }} The Following Will Give a Compiler Error: 1: int i =0; 2: for ( i; i < 2; i++) { 3: System.out.println(i); 4: } 5: } On the line 1, the variable i is initialized to 0. On the line 2, the variable i is attempted to be used. Predefined variables declared before the for loop will give a compiler error.

Which of the following are true? a) ArrayList class has a size() method that returns the number of elements that exist in the ArrayList. b) ArrayList class has a length() method that returns the size or length of the ArrayList. c) Arrays have a size() method that returns the number of elements that exist in the Array. d) Arrays have a length() method that returns the number of elements that exist in the Array.

a) is correct. "ArrayList class has a size() method that returns the number of elements that exist in the ArrayList". The following are not true: ➤ "ArrayList class has a length() method that returns the size or length of the ArrayList." The above statement is untrue as ArrayList class does not have a length() method. ➤ "Arrays have a size() method that returns the number of elements that exist in the Array." The above statement is untrue as Arrays do not have a size() method. Arrays have a length attribute (variable) that returns the length of the array and not the number of elements within the array. ➤ "Arrays do not have a 'length()' method that returns the number of elements that exist in the Array." Arrays do not have a length() method, they have a length attribute (variable) that returns the length of the array and not the number of elements within the array. Incorrect Answers: b) "ArrayList class has a length() method that returns the size or length of the ArrayList." The statement is untrue as ArrayList class does not have a length() method. c) "Arrays have a size() method that returns the number of elements that exist in the Array." The above statement is untrue as Arrays do not have a size() method. Arrays have a 'length' attribute (variable) that returns the length of the array and not the number of elements within the array. d) "Arrays have a length() method that returns the number of elements that exist in the Array." The above statement is untrue. Arrays do not have a length() method, they have a length attribute (variable) that returns the length of the array and not the number of elements within the array.

Given: 1: public class A { 2: public static void main(String args[]) 3: { 4: int[][] a = new int[][3]; 5: int[]b[] = new int[2][3]; 6: int c[][] = new int[1][]; 7: } What is the result? a) compiler error on line 4 b) runtime error on line 5 c) compile and run fine d) compiler error on line 6 e) None of the answers are correct

a) is correct. A compiler error occurs on line 4. 1: public class A { 2: public static void main(String args[]) 3: { 4: int[ ][ ] a = new int[ ][3]; 5: int[]b[] = new int[2][3]; 6: int c[][] = new int[1][]; 7: } On the line 4, the row of a two-dimensional array must be initialized i.e. the square brackets highlighted in bold above. Note 1: The following initializations of two-dimensional arrays are valid below: int[ ]b[ ] = new int[ 2 ][ 3 ]; int c[ ][ ] = new int[ 1 ][ ]; Note 2: The column of two-dimensional arrays highlighted below do not need to be initialized. int c[ ][ ] = new int[ 1 ][ ]; However, the row must be initialized.

What's the name of the class that is the immediate superclass of ArrayList? a) AbstractList b) AbstractCollection c) Iterable d) List e) Cloneable

a) is correct. AbstractList is the immediate concrete superclass of ArrayList. Both AbstractList and ArrayList are located in the 'java.util' class library of the core Java API AbstractList ↑ extends ↑ ArrayList This question tests your knowledge of concrete class extensions of the ArrayList. In order to undertake this question, it would be advisable to know the interfaces and concrete class extensions of the ArrayList (See notes below). As an example, you can see below a program that utilizes the superclass of ArrayList, namely, AbstractList: // Java code to illustrate AbstractList import java.util.AbstractList; import java.util.ArrayList; public class A { public static void main(String args[]) { // Creating an empty AbstractList AbstractList<String> list = new ArrayList<String>(); // Use add() method to add elements in the list list.add("Hi"); list.add("Ho"); // Displaying the AbstractList System.out.println(list); } } Notes: Concrete Class Extensions of ArrayList Below is a depiction of the concrete class extensions of the ArrayList class. You can also see their locations in the Java API: java.lang.Object ↑ extends ↑ java.util.AbstractCollection<E> ↑ extends ↑ java.util.AbstractList<E> ↑ extends ↑ java.util.ArrayList<E> Next, let's look at the interface is implemented by the ArrayList below. Interfaces Implementted by ArrayList A suggested abbreviation is outlined to help you memorize the interfaces implemented by ArrayList: CRISCL Cloneable RandomAccess Iterable Serializable Collection List

Given: StringBuilder h1 = new StringBuilder("Hello"); h1.replace(0, 2, "b"); System.out.println(h1); What is the result? a) Compile and print "bllo" b) Compile and print "bello" c) Compile and print "blo" d) None of the answers are correct

a) is correct. As stated, the program will compile and print: "bllo" StringBuilder h1 = new StringBuilder("Hello"); h1.replace(0, 2, "b"); System.out.println(h1); The output is: "bllo" ===Code Step Through=== StringBuilder h1 = new StringBuilder("Hello"); h1.replace(0, 2, "b"); System.out.println(h1); The above replace() method replaces the String literal starting at index 0 and ending at index 2-1 with "b". Old chars: Index 0 = H Index 1 = e Index 2 = l Index 3 = l Index 4 = o New chars: Index 0 = b Index 1 = l Index 2 = l Index 3 = o The output is: bllo

Given: public class A { public static void main(String args[]) { boolean[] b1 = new boolean[2]; for (boolean c : b1) { System.out.print(c); } }} What is the result? a) Compiler error b) Runtime error c) Compile and print: falsefalse d) None of the answers are correct

c) is correct. As stated, the code will compile and print falsefalse. An array of primitive types will have default values when initialized. In the case of boolean arrays, the default value is false. ===Code Step Through=== 1: public class A { 2: public static void main(String args[]) 3: { 4: boolean[] b1 = new boolean[2]; 5: for (boolean c : b1) { 6: System.out.println(c); 7: } 8: }} On the line 4, an array of boolean's is declared with size 2. The default values of this boolean array will be false. Therefore the compiler automatically assigns false to each of the index 'cells' in the array i.e. b1[0] = false b1[1] = false ========2======== 1: public class A { 2: public static void main(String args[]) 3: { 4: boolean[] b1 = new boolean[2]; 5: for (boolean c : b1) { 6: System.out.println(c); 7: } 8: }} On the lines 5-7 is declared an enhanced for loop which iterates through the boolean array and prints all of the values stored in the array to the screen. i.e. falsefalse Note: Default Values of Primitive Types Below is a list of default values of primitive types. The following abbreviation may help to remember all of the primitive types: dbs-cilf-b double default value is: false byte default value is: 0 short default value is: 0 char default value is: \u0000 int default value is: 0 long default value is: 0 float default value is: 0.0 boolean default value is: false Note 2: Objects have a default value of null e.g. String, Integer, Double all have null as the default value

Given: StringBuilder h3 = new StringBuilder("Hello"); h3.insert(4, " yo"); System.out.println(h3); What is the result? a) Compiler error b) Compile and print "Hello yo" c) Compile and print "Hell yoo" d) None of the answers are correct

c) is correct. As stated, the program will compile and print "Hell yoo" StringBuilder h3 = new StringBuilder("Hello"); h3.insert(4, " yo"); System.out.println(h3); The above will output: "Hell yoo" ===Code Step Through=== StringBuilder h3 = new StringBuilder("Hello"); h3.insert(4, " yo"); System.out.println(h3); StringBuilder ref h3 is pointing to a newly created StringBuilder object containing string literal "Hello" h3 🠚 "Hello" ===========2============ StringBuilder h3 = new StringBuilder("Hello"); h3 .insert(4, " yo"); System.out.println(h3); The above insert() method inserts the String literal " yo" into the StringBuilder literal at index 4. The original value at index 4 gets pushed to index 7 making way for the insertion of the String literal " yo" Old chars: Index 0 = H Index 1 = e Index 2 = l Index 3 = l Index 4 = o New chars: Index 0 = H Index 1 = e Index 2 = l Index 3 = l Index 4 = ' ' Index 5 = y Index 6 =o Index 7 = o The output is: Hell yoo

Given: public class A { public static void main(String args[]) { int i = 4; int iA[][][] = new int[i][i=3][i]; System.out.println(iA.length); System.out.println(iA[0].length); System.out.println(iA[0][0].length); }} What is the result? a) Compiler error b) Compile and print: 4 3 4 c) Compile and print: 4 3 3 d) None of the answers are correct

c) is correct. As stated, the program will compile and print: 4 3 3 This is a two-dimensional array initialization question. In order to undertake this question you need to be know the Operator Order of Precedence (or Rules of Precedence) -See Note below. The following explains the code in further detail: ===Code Step Through=== 1: public class A { 2: public static void main(String args[]) 3: { 4: int i = 4; 5: int iA[ ][ ][ ] = new int[i][i=3][i]; 6: System.out.println(iA.length); 7: System.out.println(iA[0].length); 8: System.out.println(iA[0][0].length); 9: }} On the line 4, the number 4 is assigned to an int variable named ' i ' ========2======== 1: public class A { 2: public static void main(String args[]) 3: { 4: int i = 4; 5: int iA[ ][ ][ ] = new int[ i ][i=3][i]; 6: System.out.println(iA.length); 7: System.out.println(iA[0].length); 8: System.out.println(iA[0][0].length); 9: }} On the line 5, a three-dimensional array is initialized in size. The question is: how do we know which value? Based on the operator order of precedence and associativity rules (outlined in the note below), the square brackets highlighted above on the left hand side of the expression get initialized first with the value 4: int iA[ ][ ][ ] = new int [4][i=3][i]; ========3======== 1: public class A { 2: public static void main(String args[]) 3: { 4: int i = 4; 5: int iA[ ][ ][ ] = new int[i][ i = 3 ][i]; 6: System.out.println(iA.length); 7: System.out.println(iA[0].length); 8: System.out.println(iA[0][0].length); 9: }} On the line 5, the int variable i gets reassigned the digit 3 and this is then automatically stored in the second square brackets above: int iA[ ][ ][ ] = new int[4][ 3 ][i]; ========4======== 1: public class A { 2: public static void main(String args[]) 3: { 4: int i = 4; 5: int iA[ ][ ][ ] = new int[i][i=3][ i ]; 6: System.out.println(iA.length); 7: System.out.println(iA[0].length); 8: System.out.println(iA[0][0].length); 9: }} Continuing on the line in 5, and the final square brackets gets initialized with the current value stored in int variable ' i '. As the int variable ' i ' has been reassigned a value 3, then the int value 3 is assigned to the last square brackets of this tree dimensional array: int iA[ ][ ][ ] = new int[4][3][ 3 ]; ========5======== 1: public class A { 2: public static void main(String args[]) 3: { 4: int i = 4; 5: int iA[ ][ ][ ] = new int [ i ][i=3][i]; 6: System.out.println(iA.length); 7: System.out.println(iA[0].length); 8: System.out.println(iA[0][0].length); 9: }} On the line 6, the length of the first array is printed to the screen: 4 int iA[ ][ ][ ] = new int [ 4 ][3][3]; ========6======== 1: public class A { 2: public static void main(String args[]) 3: { 4: int i = 4; 5: int iA[ ][ ][ ] = new int[i][i=3][i]; 6: System.out.println(iA.length); 7: System.out.println(iA[ 0 ].length); 8: System.out.println(iA[0][0].length); 9: }} On the line 7, the length of the second aspect of this Three-dimensional array is printed to the screen: 3 int iA[ ][ ][ ] = new int[4][ 3 ][3]; ========7======== 1: public class A { 2: public static void main(String args[]) 3: { 4: int i = 4; 5: int iA[ ][ ][ ] = new int[i][i=3][ i ]; 6: System.out.println(iA.length); 7: System.out.println(iA[0].length); 8: System.out.println(iA[ 0 ][ 0 ].length); 9: }} On the line 8, the length of the third aspect of this Three-dimensional array is printed to the screen: 3 int iA[ ][ ][ ] = new int[4][3][ 3 ]; 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) startwhen 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 Rulessolves 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 operatorsthat 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: public class A { public String toString(){ return null; } public static void main(String[] args) { A a1 = new A(); System.out.println(a1); }} What is the result? a) Compiler error b) Runtime error c) Compile and print null d) None of the answers are correct

c) is correct. Compile and print null. Let's step through the program to explain the answer: ===Code Step Through=== 1: public class A { 2: public String toString(){ 3: return null; 4: } 5: public static void main(String[] args) { 6: A a1 = new A(); 7: System.out.println(a1); 8: }} On the line 6, a reference to an object A is created. ========2======== 1: public class A { 2: public String toString(){ 3: return null; 4: } 5: public static void main(String[] args) { 6: A a1 = new A(); 7: System.out.println(a1); 8: }} On line 7, an implicit call to the method toString() is made which returns null.

Given: public class A { public static void main(String[] args) { int [][] a1 = {{1,2},{3,4}}; System.out.println(a1[0][0]); System.out.println(a1[1][1]); int []a2 = (int[]) a1[0]; System.out.println(a2[1]); }} What is the result? a) Compiler error b) Runtime error c) Compile and print: 1 4 2 d) None of the answers are correct e) f) g)

c) is correct. Compile and print: 1 4 2 Let's step through the program to explain the answer: ===Code Step Through=== 1: public class A { 2: public static void main(String[] args) { 3: int [][] a1 = {{1,2},{3,4}}; 4: System.out.println(a1[0][0]); 5: System.out.println(a1[1][1]); 6: int []a2 = (int[]) a1[0]; 7: System.out.println(a2[1]); 8: }} On line 3, a two dimensional array is declared with the following elements stored in distinct addresses: a1[0][0] = 1 a1[0][1] = 2 a1[1][0] = 3 a1[1][1] = 4 In essence, a two dimensional array is comprised of two singular arrays: a1[0] = {1,2} a1[1] = {3,4} ========2======== 1: public class A { 2: public static void main(String[] args) { 3: int [][] a1 = {{1,2},{3,4}}; 4: System.out.println(a1[0][0]); 5: System.out.println(a1[1][1]); 6: int []a2 = (int[]) a1[0]; 7: System.out.println(a2[1]); 8: }} On line 4, the value stored at address a1[0][0] is 1 based on the two dimensional address table of the array below: a1[0][0] = 1 a1[0][1] = 2 a1[1][0] = 3 a1[1][1] = 4 ========3======== 1: public class A { 2: public static void main(String[] args) { 3: int [][] a1 = {{1,2},{3,4}}; 4: System.out.println(a1[0][0]); 5: System.out.println(a1[1][1]); 6: int []a2 = (int[]) a1[0]; 7: System.out.println(a2[1]); 8: }} On line 5, the value stored at address a1[1][1] is 4 based on the two dimensional address table of the array below: a1[0][0] = 1 a1[0][1] = 2 a1[1][0] = 3 a1[1][1] = 4 ========4======== 1: public class A { 2: public static void main(String[] args) { 3: int [][] a1 = {{1,2},{3,4}}; 4: System.out.println(a1[0][0]); 5: System.out.println(a1[1][1]); 6: int [ ]a2 = ( int[] ) a1[0]; 7: System.out.println(a2[1]); 8: }} As stated above, a two dimensional array is comprised of two arrays. On line 6, the singular array containing elements {1,2} is stored at a1[0]. A copy of this particular array is created and this copy has a new reference pointing to it (i.e. int [ ]a2). In memory a copy of single array: a2 🠚 {1,2} ========5======== 1: public class A { 2: public static void main(String[] args) { 3: int [][] a1 = {{1,2},{3,4}}; 4: System.out.println(a1[0][0]); 5: System.out.println(a1[1][1]); 6: int []a2 = (int[]) a1[0]; 7: System.out.println(a2[ 1 ]); 8: }} On line 7, the value stored at address a2[ 1 ] is printed. Below is an depiction of the single array in memory: a2 🠚 {1,2} Where the values at the particular addresses are: a2[0] = 1 a2[1] = 2 From the above, you can see that the value stored in a2[1] is 2.

Given: import java.util.ArrayList; public class A { public static void main(String[] args) { ArrayList<String> myList = new ArrayList<String>(); myList.add("apple") ; myList.add("carrot"); myList.add("banana"); myList.add(1, "plum"); System.out.print(myList); }} What is the result? A. [apple, banana, carrot, plum] B. [apple, plum, carrot, banana] C. [apple, plum, banana, carrot] D. [plum, banana, carrot, apple] E. [plum, apple, carrot, banana] F. [banana, plum, carrot, apple] G. Compilation fails

B is correct. The program prints: [apple, plum, carrot, banana] Array List elements are automatically inserted in the order of entry; They are not automatically sorted. ArrayLists use zero-based indexes and the last add() method inserts a new element and shifts the remaining elements back. Let's step through the code: ===Code Step Through=== 1: import java.util.ArrayList; 2: public class A { 3: public static void main(String[] args) { 4: ArrayList<String> myList = new ArrayList<String>(); 5: myList.add("apple") ; 6: myList.add("carrot"); 7: myList.add("banana"); 8: myList.add(1, "plum"); 9: System.out.print(myList); 10: }} On the line 4, a new array list which will contain String object types is created. =======2======= 1: import java.util.ArrayList; 2: public class A { 3: public static void main(String[] args) { 4: ArrayList<String> myList = new ArrayList<String>(); 5: myList.add("apple"); 6: myList.add("carrot"); 7: myList.add("banana"); 8: myList.add(1, "plum"); 9: System.out.print(myList); 10: }} On the line 5, the string containing "apple" is added to the array list at index 0. The following outlines a pseudocode depiction of the array list 'myList' object in memory after the string "apple" is added to the array list. All objects have unique memory addresses in the heap including the object referenced by 'myList' which has an arbitrary heap address &4327. The heap is an area of memory storing objects. ===Memory Snapshot=== myList 🠆 Object ArrayList( Heap Address &4327) { myList[ 0 ] 🠢 "apple" } =======3======= 1: import java.util.ArrayList; 2: public class A { 3: public static void main(String[] args) { 4: ArrayList<String> myList = new ArrayList<String>(); 5: myList.add("apple") ; 6: myList.add("carrot"); 7: myList.add("banana"); 8: myList.add(1, "plum"); 9: System.out.print(myList); 10: }} On the line 6, the string object "carrot" is next added to the array list at index 1. Below is a pseudocode description in memory which outlines the state of the array list object referenced by 'myList' after the execution of line 6. ===Memory Snapshot=== myList 🠆 Object ArrayList( Heap Address &4327) { myList[ 0 ] 🠢 "apple" myList[ 1 ] 🠢 "carrot" } =======4======= 1: import java.util.ArrayList; 2: public class A { 3: public static void main(String[] args) { 4: ArrayList<String> myList = new ArrayList<String>(); 5: myList.add("apple") ; 6: myList.add("carrot"); 7: myList.add("banana"); 8: myList.add(1, "plum"); 9: System.out.print(myList); 10: }} On the line 7, the string object "banana" is next added to the array list at index 2. Below is a pseudocode description in memory which outlines the current state of the array list object referenced by 'myList'. ===Memory Snapshot=== myList 🠆 Object ArrayList( Heap Address &4327) { myList[ 0 ] 🠢 "apple" myList[ 1 ] 🠢 "carrot" myList[ 2 ] 🠢 "banana" } =======5======= 1: import java.util.ArrayList; 2: public class A { 3: public static void main(String[] args) { 4: ArrayList<String> myList = new ArrayList<String>(); 5: myList.add("apple") ; 6: myList.add("carrot"); 7: myList.add("banana"); 8: myList.add(1, "plum"); 9: System.out.print(myList); 10: }} On the line 8, the string object "plum" is next inserted to the array list at index 1. This pushes the rest of the String objects down in the array list by one. Below is a pseudocode description in memory which outlines the current state of the array list object referenced by 'myList'. ===Memory Snapshot=== myList 🠆 Object ArrayList( Heap Address &4327) { myList[ 0 ] 🠢 "apple" myList[ 1 ] 🠢 "plum" myList[ 2 ] 🠢 "carrot" myList[ 3 ] 🠢 "banana" } =======6======= 1: import java.util.ArrayList; 2: public class A { 3: public static void main(String[] args) { 4: ArrayList<String> myList = new ArrayList<String>(); 5: myList.add("apple") ; 6: myList.add("carrot"); 7: myList.add("banana"); 8: myList.add(1, "plum"); 9: System.out.print(myList); 10: }} On the line 9, an implicit method call is made toString() which print off all of the String objects in the array list myList to the print stream. Namely: [apple, plum, carrot, banana]

Consider the following code: import java.util.AbstractList; import java.util.ArrayList; public class A { public static void main(String args[]) { AbstractList<String> list = new ArrayList<String>(); list.add('Hi'); list.add(5); System.out.println(list); }} What is the result? a) Compiler error b) Runtime error c) Compile and print: Hi 5 d) None of the answers are correct.

a) is correct. As stated, the program will give a compiler error. ===Code Step Through=== 1: import java.util.AbstractList; 2: import java.util.ArrayList; 3: public class A { 4: public static void main(String args[]) 5: { 6: AbstractList<String> list = new ArrayList<String>(); 7: list.add('Hi'); 8: list.add(5); 9: System.out.println(list); 10: } 11: } On the line 7, a primitive char 'Hi' is stored in an ArrayList. Likewise, on the line 8, the primitive int variable 5 is attempted to be stored in the ArrayList. You cannot store primitives in an ArrayList. Therefore, a compiler error occurs on the line 7 and also 8 The above shows that ArrayList is type safe as it is expecting an object on the line 7 and 8.

Given: String h1 = "Hello"; String h2 = h1.concatenate(" there"); System.out.println(h2); What is the result? a) Compiler error b) Runtime error c) Compile and print "Hello" d) None of the answers are correct

a) is correct. As stated, the program will give a compiler error. String h1 = "Hello"; String h2 = h1.concatenate(" there"); System.out.println(h2); The method concatenate() does not exist in String class therefore the code does not compile. Solution: String h1 = "Hello"; String h2 = h1.concat(" there"); System.out.println(h2); The above returns a new string joined (concatenated) together with the output "Hello there" String reference h2 is pointing to a new String literal (object) in the String pool i.e. "Hello there" h1 🠚"Hello there" String reference h1 is still pointing to the String literal (object) in the String pool i.e. "Hello" h1 🠚 "Hello"

Which of the following statements are true? a) keyword "break" can only be used to break out of a current loop or switch block or labelled block. b) keyword "break" can only be used to break out of a current loop or switch block. c) keyword "break" can only be used to break out of a current loop. d) None of the answers are correct.

a) is correct. Keyword "break" can only be used to break out of a current loop or switch block or labelled block.

Given: for (int i = 0, j=0; j < 2; i++,j++) { System.out.println(i+" "+j); } Which of the following will give the same output as the above? a) int i=0; int j=0; while (j<2) { System.out.println(i+" "+j); i++; j++; } b) int i=0, int j=0; while (j<2) { System.out.println(i+" "+j); i++; j++; } c) int i=0, int j=0; while (j<2) { System.out.println(i+" "+j); i++ j++; } d) None of the answers are correct

a) is correct. Looking at the original program into question again: for (int i = 0, j =0; j < 2; i++, j++) { System.out.println( i +" "+ j ); } The above is the same as: int i =0; int j =0; while( j <2) { System.out.println( i +" "+ j ); i++; j++; } The output is: 0 0 1 1 The Following Is Incorrect: b) 1: int i=0 , int j=0; 2: while (j<2) { 3: System.out.println(i+" "+j); 4: i++; 5: j++; 6: } On line 1, there is a syntax error as there should be a ' ; ' between the declared variable i and j. Alternatively, the variable j should have 'int' removed before it. ============== c) 1: int i=0 , int j=0; 2: while (j<2) { 3: System.out.println(i+" "+j); 4: i++ 5: j++; 6: } On line 1, there is a syntax error as there should be a ' ; ' between the declared variable i and j. Alternatively, the variable j should have 'int' removed before it. Also, there is a missing ' ; ' at the end of line 4.

Given: import java.time.LocalDate; import java.time. Period; public class A { public static void main(String[] args) { LocalDate date1 = LocalDate.of(1977, 10, 15); Period z = ______ .______(date1, LocalDate.now()); System.out.println("You lived for:"); System.out.println("days: "+z.getDays()); System.out.println("Months: "+z.getMonths()); System.out.println("Years: "+z.getYears()); }} What code inserted above, will calculate the amount of days months and years from the date 15 October 1977? a) Period.between b) LocalDate.between c) Period.getPeriod d) DateTimes.getPeriod e) None of the answers are correct

a) is correct. The code 'Period.between' will calculate the amount of days months and years from the date 15 October 1977 import java.time.LocalDate; import java.time.Period; public class A { public static void main(String[] args) { LocalDate date1 = LocalDate.of(1977, 10, 15); Period z = Period.between(date1, LocalDate.now() ) ; System.out.println("You lived for:"); System.out.println("days: "+z.getDays()); System.out.println("Months: "+z.getMonths()); System.out.println("Years: "+z.getYears()); }} The above will output: You lived for: days: 16 Months: 1 Years: 41 Note: java.time.Period This class is used to create immutable objects that represent a period of time between two dates. e.g. "one year, two months, and three days from/after today"

Which of the following classes are not related to the Calendar collection? a) java.time.temporal.TemporalTime b) java.time.Period c) java.time.LocalTime d) java.time.temporal.TemporalAmount

a) is correct. The following class is a fictitious class and is not related to the Calendar collection: java.time.temporal.TemporalTime Classes Related to the Calendar Collection: ➤ java.time.Period This class is used to create immutable objects that represent a period of time between two dates, for instance: "one year, two months, and three days before/after today" The following gives an example of java.time.Period LocalDate date1 = LocalDate.of(1976, 10, 15); Period z = Period.between(date1, LocalDate.now()); System.out.println("You lived for:"); System.out.println("days: "+z.getDays()); System.out.println("Months: "+z.getMonths()); System.out.println("Years: "+z.getYears()); The above will output: You lived for: days: 14 Months: 1 Years: 42 ➤ java.time.LocalTime This class is used to create immutable objects each which represents a specific time for certain area (time-zone) in the world, for instance: Berlin Time Now: 11:28:04.865 Dublin Time Now: 10:28:04.865 The following outlines an example of using java.time.LocalTime: import java.time.ZoneId; ZoneId zone1 = ZoneId.of("Europe/Berlin"); ZoneId zone2 = ZoneId.of("Europe/Dublin"); LocalTime now1 = LocalTime.now(zone1); LocalTime now2 = LocalTime.now(zone2); System.out.println("Berlin Time: "+now1); System.out.println("Dublin Time: "+now2); The above will output: Berlin Time: 11:28:04.865 Dublin Time: 10:28:04.865 ➤ java.time.temporal.TemporalAmount This interface is implemented by the Period class to define an amount (quantity) of time, for instance: "6 hours", "8 days" or "2 years and 3 months". This is usually used to establish the period of time before or after a certain date. An example would be as follows: java.time.temporal.TemporalAmount LocalDate date1 = LocalDate.of(2018, 11, 15); TemporalAmount t = Period.ofDays(2); LocalDate date2 = date1 .minus(t); System.out.println(date2); The above will output: 2018-11-13 Which is 2 days before (amount of days before) the date specified date 2018, 11, 15. Note: Calendar classes are Factory classes i.e. they do not have constructors in order to create a new object. These classes do not use the word 'new' to create new objects. Instead these classes invoke public static methods to create a new object. e.g. ZoneId zone1 = ZoneId.of("Europe/Berlin"); The above creates a new ZoneId object using factory method of() LocalTime now1 = LocalTime.now(zone1); The above creates a new LocalTime object using factory method now().

Which of the following are true? a) java.lang.StringBuilder is not thread safe. b) java.lang.StringBuilder is synchronized. c) java.lang.StringBuffer is not thread safe. d) None of the answers are correct

a) is correct. The java.lang.StringBuilder is not thread safe. That means StringBuilder methods are not synchronized Note: Oracle recommends that you use StringBuilder instead of StringBuffer whenever possible because StringBuilder will run faster than StringBuffer.

Given: 1: class A { 2: int size; 3: A(int s) { size = s; } 4: } 5: public class B { 6: public static void main(String[] args) { 7: A b1 = new A(5); 8: A[] ba = go(b1, new A(6)); 9: ba[0] = b1; 10: for(A b : ba) System.out.print(b.size + " "); 11: } 12: static A[] go(A b1, A b2) { 13: b1.size = 4; 14: A[] ma = {b2, b1}; 15: return ma; 16: }} What is the result? a) 4 4 b) 5 4 c) 6 4 d) 4 5 e) 5 5 f) Compilation fails

a) is correct. The program prints: 4 4 Although the main() method b1 is a different reference variable than go()'s b1, they refer to the same Box object. ===Code Step Through=== 1: class A { 2: int size; 3: A(int s) { size = s; } 4: } 5: public class B { 6: public static void main(String[] args) { 7: A b1 = new A(5); 8: A[] ba = go(b1, new A(6)); 9: ba[0] = b1; 10: for(A b : ba) System.out.print(b.size + " "); 11: } 12: static A[] go(A b1, A b2) { 13: b1.size = 4; 14: A[] ma = {b2, b1}; 15: return ma; 16: }} On the line 7, a new object reference of type is created. A pseudocode depiction of the newly created object is outlined below with its own unique memory address: Current object stored in memory: b1 🠆 Object A(Heap Address &643) { size = 5 } ========2======== 1: class A { 2: int size; 3: A(int s) { size = s; } 4: } 5: public class B { 6: public static void main(String[] args) { 7: A b1 = new A(5); 8: A[] ba = go(b1, new A(6)); 9: ba[0] = b1; 10: for(A b : ba) System.out.print(b.size + " "); 11: } 12: static A[] go(A b1, A b2) { 13: b1.size = 4; 14: A[] ma = {b2, b1}; 15: return ma; 16: }} On the line 8, a method call is made to go(). The parameters passed into this method go() would be comprised of: • The reference to the object of type A created online 7 with reference b1 pointing to the object with memory address &643. • A newly created object of type A with an arbitrary memory address @092 and which does not have a reference. A pseudocode description of the current objects in memory is outlined below. Current object stored in memory: b1 🠆 Object A(Heap Address &643) { size = 5 } Object A(Heap Address @092) { size = 6 } Note: The A object, which was created on line 8 with memory address @092 has no reference as it was created within the parameters of the go() method. This means that when the go() method completes execution, this object is available for garbage collection i.e. it gets destroyed. ========3======== 1: class A { 2: int size; 3: A(int s) { size = s; } 4: } 5: public class B { 6: public static void main(String[] args) { 7: A b1 = new A(5); 8: A[] ba = go(b1, new A(6)); 9: ba[0] = b1; 10: for(A b : ba) System.out.print(b.size + " "); 11: } 12: static A[] go(A b1, A b2) { 13: b1.size = 4; 14: A[] ma = {b2, b1}; 15: return ma; 16: } } On the line 12, the go() method is entered with reference b1 which is pointing to an object of type A with memory address &643 and reference b2 pointing to another object of type A with memory address @092. ========4======== 1: class A { 2: int size; 3: A(int s) { size = s; } 4: } 5: public class B { 6: public static void main(String[] args) { 7: A b1 = new A(5); 8: A[] ba = go(b1, new A(6)); 9: ba[0] = b1; 10: for(A b : ba) System.out.print(b.size + " "); 11: } 12: static A[] go(A b1, A b2) { 13: b1.size = 4; 14: A[] ma = {b2, b1}; 15: return ma; 16: } } On the line 13, the object referred to by b1 is assigned a new size of 4. This particular object has the memory address &643. Below you see the pseudocode description of the objects in memory: Current objects stored in memory: b1 🠆 Object A(Heap Address &643) { size = 4 } b2 🠆 Object A(Heap Address @092) { size = 6 } ========5======== 1: class A { 2: int size; 3: A(int s) { size = s; } 4: } 5: public class B { 6: public static void main(String[] args) { 7: A b1 = new A(5); 8: A[] ba = go(b1, new A(6)); 9: ba[0] = b1; 10: for(A b : ba) System.out.print(b.size + " "); 11: } 12: static A[] go(A b1, A b2) { 13: b1.size = 4; 14: A[ ] ma = {b2, b1}; 15: return ma; 16: } } On the line 14, a new array object is created of type A which contains references to the two objects of type A, namely, b2 and b1. Reference b2 is pointing to the object of type A with memory address @092 and reference b1 is pointing to the object of type A with memory address &643. A pseudocode description of the current objects in memory is outlined below: b1 🠆 Object A(Heap Address &643) { size = 4 } b2 🠆 Object A(Heap Address @092) { size = 6 } ma 🠆 Object[ ] A(Heap Address &221) { ma[0] 🠢 b2 ma[1] 🠢 b1 } In the above pseudocode description, you can see that: ➤ ma[0] is the first element in the array which contains a reference that is pointing to the object that is also pointed to by b2 i.e. there are now two references to the object with memory address @092. ➤ ma[1] is the second element in the array which contains a reference that is pointing to the object that is also pointed to by b1 i.e. there are now two references to the object with memory address &643. ========6======== 1: class A { 2: int size; 3: A(int s) { size = s; } 4: } 5: public class B { 6: public static void main(String[] args) { 7: A b1 = new A(5); 8: A[] ba = go(b1, new A(6)); 9: ba[0] = b1; 10: for(A b : ba) System.out.print(b.size + " "); 11: } 12: static A[] go(A b1, A b2) { 13: b1.size = 4; 14: A[ ] ma = {b2, b1}; 15: return ma; 16: } } On the line 15, the array ma is returned to the main() method. ========7======== 1: class A { 2: int size; 3: A(int s) { size = s; } 4: } 5: public class B { 6: public static void main(String[] args) { 7: A b1 = new A(5); 8: A[ ] ba = go(b1, new A(6)); 9: ba[0] = b1; 10: for(A b : ba) System.out.print(b.size + " "); 11: } 12: static A[] go(A b1, A b2) { 13: b1.size = 4; 14: A[ ] ma = {b2, b1}; 15: return ma; 16: } } On the line 8, array ma containing {b2, b1} is returned from the method go() and a copy of this array ma is pointed to by ba. The object references ma and b2 get destroyed when the go() method is exited but not the objects they were pointing to with memory addresses &221 and @092. Current object stored in memory: b1 🠆 Object A(Heap Address &643) { size = 4 } ma[0] 🠆 Object A(Heap Address @092) { size = 6 } ba 🠆 Object[ ] A(Heap Address &221) { ma[0] 🠢 <Object with Heap Address @092 > ma[1] 🠢 b1 } ========8======== 1: class A { 2: int size; 3: A(int s) { size = s; } 4: } 5: public class B { 6: public static void main(String[] args) { 7: A b1 = new A(5); 8: A[ ] ba = go(b1, new A(6)); 9: ba[0] = b1; 10: for(A b : ba) System.out.print(b.size + " "); 11: } 12: static A[] go(A b1, A b2) { 13: b1.size = 4; 14: A[] ma = {b2, b1}; 15: return ma; 16: }} This line 9, is the crucial line of the entire code. This line overites the previous element at index address 0, within array ba with the reference b1. Looking at the pseudocode depiction above, you can see that reference b1 is pointing to an object of type A with memory address &643. Therefore, following the execution of this line 9, a pseudocode depiction of the current objects in memory is outlined below with the said changes: b1 🠆 Object A(Heap Address &643) { size = 4 } Object A(Heap Address @092) { size = 6 } ba 🠆 Object[ ] A(Heap Address &221) { ma[0] 🠢 b1 ma[1] 🠢 b1 } As you can see in the above pseudocode depiction, the array ba contains two elements ma[0] and ma[1] which are pointing to the same object with address &643 in memory. ========9======== 1: class A { 2: int size; 3: A(int s) { size = s; } 4: } 5: public class B { 6: public static void main(String[] args) { 7: A b1 = new A(5); 8: A[] ba = go(b1, new A(6)); 9: ba[0] = b1; 10: for(A b : ba) System.out.print(b.size + " "); 11: } 12: static A[] go(A b1, A b2) { 13: b1.size = 4; 14: A[] ma = {b2, b1}; 15: return ma; 16: }} On the line 10, the compiler simply extracts each element (object) in the array ba and prints the contents of the object (its variable size) to the screen. As all elements within this particular array ba are pointing to the same object in memory, with address &643, therefore size is the same. Therefore 4 gets printed to the screen twice. A pseudocode description of the variables printed the screen is highlighted below: b1 🠆 Object A(Heap Address &643) { size = 4 } Object A(Heap Address @092) { size = 6 } ba 🠆 Object[ ] A(Heap Address &221) { ma[0] 🠢 b1 ma[1] 🠢 b1 }

Given: import java.util.ArrayList; import java.util.List; public class A { public static void main(String args[]) { List<String> list = new ArrayList<String>(2); System.out.println(list.length()); } } What is the result? a) Compiler error b) Runtime error c) Compile and print HERE d) None of the answers are correct

a) is correct. The program will give a compiler error. 1: import java.util.ArrayList; 2: import java.util.List; 3: 4: public class A { 5: public static void main(String args[]) 6: { 7: List<String> list = new ArrayList<String>(2); 8: System.out.println(list.length()); 9: } 10: } There is no method length() in the ArrayList or List. To get the number of elements within a list you use the size() that has outlined below: import java.util.ArrayList; import java.util.List; public class A { public static void main(String args[]) { List<String> list = new ArrayList<String>(2); list.add("Hi"); System.out.println(list.size()); } } The above method called to size() would output 1 as there is one element of type String in the said list.

Given: public class A { public static void main(String[] args) { int [][] a1 = {{1,2},{3,4}}; System.out.println(a1[0][0]); System.out.println(a1[1][1]); int []a2 = (int[]) a1; System.out.println(a2[1]); }} What is the result? a) Compiler error b) Runtime error c) Compile and print: 1 4 2 d) None of the answers are correct

a) is correct. The program will give a compiler error. ===Code Step Through=== 1: public class A { 2: public static void main(String[] args) { 3: int [][] a1 = {{1,2},{3,4}}; 4: System.out.println(a1[0][0]); 5: System.out.println(a1[1][1]); 6: int []a2 = (int[]) a1; 7: System.out.println(a2[1]); 8: }} On line 3, a two dimensional array is declared with the following elements stored in distinct addresses: a1[0][0] = 1 a1[0][1] = 2 a1[1][0] = 3 a1[1][1] = 4 In essence, a two dimensional array is comprised of two singular arrays: a1[0] = {1,2} a1[1] = {3,4} ========2======== 1: public class A { 2: public static void main(String[] args) { 3: int [][] a1 = {{1,2},{3,4}}; 4: System.out.println(a1[0][0]); 5: System.out.println(a1[1][1]); 6: int []a2 = (int[]) a1; 7: System.out.println(a2[1]); 8: }} On line 4, the value stored at address a1[0][0] is 1 based on the two dimensional address table of the array below: a1[0][0] = 1 a1[0][1] = 2 a1[1][0] = 3 a1[1][1] = 4 ========3======== 1: public class A { 2: public static void main(String[] args) { 3: int [][] a1 = {{1,2},{3,4}}; 4: System.out.println(a1[0][0]); 5: System.out.println(a1[1][1]); 6: int []a2 = (int[]) a1; 7: System.out.println(a2[1]); 8: }} On line 5, the value stored at address a1[1][1] is 4 based on the two dimensional address table of the array below: a1[0][0] = 1 a1[0][1] = 2 a1[1][0] = 3 a1[1][1] = 4 ========4======== 1: public class A { 2: public static void main(String[] args) { 3: int [][] a1 = {{1,2},{3,4}}; 4: System.out.println(a1[0][0]); 5: System.out.println(a1[1][1]); 6: int []a2 = (int[ ]) a1; 7: System.out.println(a2[1]); 8: }} On line 6, the two dimensional array a1 is cast to a single array and has a new reference a2 pointing to it. However, you cannot have a two dimensional array referenced by a single dimensional array. Therefore, this will give a compiler error as the compiler will know there are incompatible types on the line 6.

Given: String h = "Hello"; int len = h.size(); System.out.println(len); What is the result? a) Compiler error b) Runtime error c) Compile and print: 5 d) None of the answers are correct

a) is correct. The program will give a compiler error. String h = "Hello"; int len = h.size(); System.out.println(len); The method size() does not exist in the String class. To find to the size (length) of a String literal, use: length() instead.

Given: public class A { public static void main(String args[]) { int[ ] array1,array2[ ]; array1=array2; }} What is the result? a) Compiler error b) Runtime error c) Compile and run fine d) None of the answers are correct

a) is correct. The program will give a compiler error. When you assign an array to previously declared array reference, the array you're assigning must be in the same dimension as the reference your assigning it to. Below explains further: ===Code Step Through=== 1: public class A { 2:public static void main(String args[]) 3: { 4: int[ ] array1, array2[ ]; 5: array1=array2; 6: }} One the line 4, a one-dimensional array is declared of type int named array1. This is undertaken by using the single '[ ]' brackets highlighted in bold above. ========2======== 1: public class A { 2:public static void main(String args[]) 3: { 4: int [ ] array1, array2[ ]; 5: array1=array2; 6: }} On the same line 4, a two-dimensional array is declared of type int named array2. This is a shortcut to declare a two-dimensional array on the same line as a one-dimensional array. This is undertaken by using the double pair '[ ]' brackets, highlighted in bold, and a comma separating the variable names. See note 1 below for further information on the syntax of declaring arrays. ========3======== 1: public class A { 2:public static void main(String args[]) 3: { 4: int[ ] array1,array2[ ]; 5: array1 = array2; 6: }} On the line 5, array2 is assigned to array1. However, array1 is a one-dimensional array and array2 is a two-dimensional array. This gives a compiler error as you cannot assign two arrays of different dimensions together: int[ ] array1; int [ ]array2[ ]; array1 = array2; Note 1: Syntax for Declaring Arrays You can declare a two-dimensional array in the following ways: int [ ][ ] array2; or int [ ] array2 [ ]; or int array2 [ ][ ]; You can declare a one-dimensional array in the following ways: int [ ] array1; or int array1 [ ]; Note 2: In order to answer questions of this type, it would be important to know the Rules for Multidimensional Array Assignments. The following may help to quickly remember multidimensional array assignment rules: Two-Dimensional Arrays: The first square brackets are pointing to a one-dimensional array: int[ ][ ] twoD = {some 2 d array}; 🠇 [ ] 🠆 [ ] one-dimensional array e.g. int[ ][ ] twoD = {{1,2},{3,4,5}}; twoD[ 0 ] 🠆 [ ] 🠆 {1,2} twoD[ 1 ] 🠆 [ ] 🠆 {3,4,5} Two square bracket pairs are pointing to an element: int[ ][ ] twoD = = {some 2 d array}; 🠇 [ ][ ] 🠆 element. e.g. int[ ][ ] twoD = {{1,2},{3,4,5}}; twoD[0][0] 🠆 element 🠆 1 twoD[0][1] 🠆 element 🠆 2 twoD[1][0] 🠆 element 🠆 3 twoD[1][1] 🠆 element 🠆 4 twoD[1][2] 🠆 element 🠆 5 Three Dimensional Arrays: The first square brackets are pointing to a two-dimensional array: int[ ][ ][ ] threeD = {some 3 d array}; 🠇 [ ] 🠆 [ ][ ] two-dimensional array e.g. int[ ][ ][ ] threeD = { { {1,2},{3,4} }, { {5,6} } }; threeD[ 0 ] 🠆 [ ][ ]🠆 { {1,2}, {3,4} } threeD[ 1 ] 🠆 [ ][ ] 🠆 { {5,6} } The first two square bracket pairs are pointing to a one-dimensional array: int[ ][ ][ ] threeD = {some 3 d array}; 🠇 [ ][ ] 🠆 [ ] one-dimensional array e.g. int[ ][ ][ ] threeD = { { {1,2},{3,4} }, { {5,6} } }; threeD[0][0] 🠆 [ ] 🠆 {1,2} threeD[0][1] 🠆 [ ] 🠆 {3,4} threeD[1][0] 🠆 [ ] 🠆 {5,6} All of square bracket pairs of a three-d array are pointing to an element: int[ ][ ][ ] threeD = {some 3 d array}; 🠇 [ ][ ][ ] 🠆 element e.g. int [ ][ ][ ] threeD = { { {1, 2},{3,4} }, { {5,6} } }; threeD [0][0][0] 🠆 element 🠆 1 threeD [0][0][1] 🠆 element 🠆 2 threeD [0][1][0] 🠆 element 🠆 3 threeD [0][1][1] 🠆 element 🠆 4 threeD [1][0][0] 🠆 element 🠆 5 threeD [1][0][1] 🠆 element 🠆 6

Which of the following lines of code will not compile? a) String[] sB = new String[]{"Hello"}; b) String[] sA = new String[1]{"Hello"}; c) Compile and print HERE d) None of the answers are correct

b) is correct. The following line of code will not compile: String[ ] sA = new String[1]{"Hello"}; The size of the array cannot be declared as highlighted in bold above, as the array is initialized in the declaration (i.e. {"Hello"}) and therefore will give a compiler error. The following will compile fine: a) String[] sB = new String[]{"Hello"}; c) String[] sC = {"Hello"};

Which of the following will compile? a) LabelB: for (int i = 0; i < 2; i++) { System.out.println("LabelB"); } break LabelB; b) LabelB: for (int i = 0; i < 2; i++) { System.out.println("LabelB"); break LabelB; } c) LabelB: for (int i = 0; i < 2; i++) { System.out.println("LabelB"); break; } d) None of the answers are correct

b) and c) are correct. b) Looking at the program: 1: LabelB: for (int i = 0; i < 2; i++) { 2: System.out.println("LabelB"); 3: break LabelB; 4: } In order to break out of a label block, it is necessary to have the break label inside the said block label as above. c) The correct answer is as follows: 1: LabelB: for (int i = 0; i < 2; i++) { 2: System.out.println("LabelB"); 3: break; 4: } To use the keyword 'break', you do not explicitly need to write the label name (e.g. LabelB) at the end of the break as above. Incorrect Answers: a) Observing the program: LabelB: for (int i = 0; i < 2; i++) { System.out.println("LabelB"); } break LabelB; In order to break out of a label block, it is necessary to have the break label inside the said block label. In the above code, the break is outside of the labelled block. This causes the compiler error.

Given: 1: import java.time.*; 2: public class A { 3: public static void main(String[] args) { 4: LocalDate d = LocalDate.of(2018, 8, 15); 5: d = d.plusDays(1); 6: LocalDate d2 = d.plusDays(1); 7: LocalDate d3 = d2; 8: d2 = d2.plusDays(1); 9: System.out.println(d + " " + d2 + " " + d3); 10: }} Which are true? (choose all that apply) a) The output is: 2018-08-16 2018-08-17 2018-08-18 b) The output is: 2018-08-16 2018-08-18 2018-08-17 c) The output is: 2018-08-16 2018-08-17 2018-08-17 d) At line 9, zero LocalDate objects are eligible for garbage collection e) At line 9, one LocalDate object is eligible for garbage collection f) At line 9, two LocalDate objects are eligible for garbage collection g) Compilation fails

b) and e) are correct. ➤ The output is: 2018-08-16 2018-08-18 2018-08-17 ➤ At line 9, one LocalDate object is eligible for garbage collection This question tests your knowledge of immutability in the context of Date classes. Remember that the following Date classes are immutable (i.e. you cannot change them): • java.time.LocalDateTime • java.time.LocalDate • java.time.LocalTime A total of four LocalDate objects are created but the one created using the of() method, on line 4, is abandoned on the next line and therefore available for garbage collection. Let's step through the code, line for line: ===Code Step Through=== 1: import java.time.*; 2: public class A { 3: public static void main(String[] args) { 4: LocalDate d = LocalDate.of(2018, 8, 15); 5: d = d.plusDays(1); 6: LocalDate d2 = d.plusDays(1); 7: LocalDate d3 = d2; 8: d2 = d2.plusDays(1); 9: System.out.println(d + " " + d2 + " " + d3); 10: }} On the line 4, a new LocalDate object is created with reference 'd' and assigned an arbitrary memory address e.g. &332 in the memory heap. Following the execution of line 4, a pseudocode depiction of the object in memory is outlined below: d 🠆 Object LocalDate(Memory Address &332) { '2018, 8, 15' } ========2======== 1: import java.time.*; 2: public class A { 3: public static void main(String[] args) { 4: LocalDate d = LocalDate.of(2018, 8, 15); 5: d = d.plusDays(1); 6: LocalDate d2 = d.plusDays(1); 7: LocalDate d3 = d2; 8: d2 = d2.plusDays(1); 9: System.out.println(d + " " + d2 + " " + d3); 10: }} On the line 5, because of the immutability of LocalDate, a copy of the contents of the LocalDate object that is currently referred to by the reference 'd' is made. As 'd' is currently referring to the object stored at memory address &332, its date, (i.e. date: '2018, 8, 15'), is added by '1' day. This newly created LocalDate object now contains the date '2018, 8, 16'. It is assigned its own arbitrary but distinct memory address e.g. @773 in the memory heap. Following the execution of line 5, a pseudocode description of the objects in memory is outlined below: Object LocalDate(Memory Address &332) { '2018, 8, 15' } d 🠆 Object LocalDate(Memory Address @773) { '2018, 8, 16' } Note: In the above pseudocode description, following the execution of line 5, we can see that the object reference 'd' gets dereferenced from the LocalDate object with memory address &332 and is now pointing to the LocalDate object with memory address @773 (whose contents contains '2018, 8, 16'). ========3======== 1: import java.time.*; 2: public class A { 3: public static void main(String[] args) { 4: LocalDate d = LocalDate.of(2018, 8, 15); 5: d = d.plusDays(1); 6: LocalDate d2 = d.plusDays(1); 7: LocalDate d3 = d2; 8: d2 = d2.plusDays(1); 9: System.out.println(d + " " + d2 + " " + d3); 10: }} On the line 6, a copy of the contents of the LocalDate object that is currently referred to by the reference 'd' is made. As 'd' is currently referring to the object stored at memory address @773. Therefore, date: '2018, 8, 16' is added by '1' day. This newly created LocalDate object now contains the date '2018, 8, 17'. It assigned its own arbitrary but distinct memory address e.g. @223 in the memory heap. Following the execution of line 6, a pseudocode description of the objects in memory is outlined below: Object LocalDate(Memory Address &332) { '2018, 8, 15' } d 🠆 Object LocalDate(Memory Address @773) { '2018, 8, 16' } d2 🠆 Object LocalDate(Memory Address @223) { '2018, 8, 17' } ========4======== 1: import java.time.*; 2: public class A { 3: public static void main(String[] args) { 4: LocalDate d = LocalDate.of(2018, 8, 15); 5: d = d.plusDays(1); 6: LocalDate d2 = d.plusDays(1); 7: LocalDate d3 = d2; 8: d2 = d2.plusDays(1); 9: System.out.println(d + " " + d2 + " " + d3); 10: }} On the line 7, a new LocalDate reference is assigned (pointing to) the same LocalDate object that reference 'd2' is pointing to (i.e. LocalDate object with memory address @223). Remember you can have multiple references pointed to the same object. Following the execution of line 7, a pseudocode description of the current objects in memory is outlined below: Object LocalDate(Memory Address &332) { '2018, 8, 15' } d 🠆 Object LocalDate(Memory Address @773) { '2018, 8, 16' } d3 🠆 d2 🠆 Object LocalDate(Memory Address @223) { '2018, 8, 17' } ========5======== 1: import java.time.*; 2: public class A { 3: public static void main(String[] args) { 4: LocalDate d = LocalDate.of(2018, 8, 15); 5: d = d.plusDays(1); 6: LocalDate d2 = d.plusDays(1); 7: LocalDate d3 = d2; 8: d2 = d2.plusDays(1); 9: System.out.println(d + " " + d2 + " " + d3); 10: }} On the line 8, a copy of the contents of the LocalDate object that is currently referred to by the reference 'd2' is made. As 'd2' is currently referring to the object stored at memory address @223, therefore, '2018, 8, 17' is added by '1' day. This newly created LocalDate object now contains the date '2018, 8, 18'. It assigned its own arbitrary but distinct memory address e.g. @554 in the memory heap. Following the execution of line 6, a pseudocode description of the objects in memory is outlined below: Object LocalDate(Memory Address &332) { '2018, 8, 15' } d 🠆 Object LocalDate(Memory Address @773) { '2018, 8, 16' } d3 🠆 Object LocalDate(Memory Address @223) { '2018, 8, 17' } d2 -> Object LocalDate(Memory Address @554) { '2018, 8, 18' } ========6======== 1: import java.time.*; 2: public class A { 3: public static void main(String[] args) { 4: LocalDate d = LocalDate.of(2018, 8, 15); 5: d = d.plusDays(1); 6: LocalDate d2 = d.plusDays(1); 7: LocalDate d3 = d2; 8: d2 = d2.plusDays(1); 9: System.out.println(d + " " + d2 + " " + d3); 10: }} On the line 9, contents of the objects referred to by d, d2 and d3 are printed to the screen. Let's look at the pseudocode description state at this stage of the code run: Object LocalDate(Memory Address &332) { '2018, 8, 15' } d 🠆 Object LocalDate(Memory Address @773) { '2018, 8, 16' } d3 🠆 Object LocalDate(Memory Address @223) { '2018, 8, 17' } d2 🠆 Object LocalDate(Memory Address @554) { '2018, 8, 18' } From looking at the above pseudocode description we can see that: • Reference 'd' is pointing to the memory address @773 which contains: '2018, 8, 16' • Reference 'd2' is pointing to the memory address @554 which contains: '2018, 8, 18' • Reference 'd3' is pointing to the memory address @223 which contains: '2018, 8, 17' Therefore the following is output to the screen in this order: '2018, 8, 16 2018, 8, 18 2018, 8, 17' Also note from the above pseudocode description, the LocalDate with memory address &332 has no references to it and so it is the only object available for garbage collection out of the four LocalDate objects.

Given: String h1 = "Hello"; System.out.println(h1.charAt(5)); What is the result? a) Compiler error b) Runtime error c) Compile and print: "H" d) None of the answers are correct

b) is correct. As stated, the program will give a runtime error. The method charAt(): Returns the character located at the specified index String h1 = "Hello"; System.out.println(h1.charAt(5)); String literal "Hello" contains 5 chars but it is indexed to 4. Index 0 = H Index 1 = e Index 2 = l Index 3 = l Index 4 = 0 index 5 is outside the bounds of the String literal therefore, the following is thrown: java.lang.StringIndexOutOfBoundsException

Given: 1: public class A { 2: public static void main(String args[]) 3: { 4: int[][] twoD = {{1,2},{3,4,5}}; 5: for (int i : INSERT CODE) { 6: System.out.print(i); 7: } 8: }} What code, inserted on line 5, will print all the elements of the array within the twoD array (i.e. 1,2)? a) twoD[1] b) twoD[0] c) twoD[0][0] d) None of the answers are correct

b) is correct. Below outlines the code inserted on line 5 which prints all the elements stored in the first array of this two-dimensional array: 1: public class A { 2: public static void main(String args[]) 3: { 4: int[ ][ ] twoD = {{1,2},{3,4,5}}; 5: for (int i : twoD[0]) { 6: System.out.print(i); 7: } 8: }} In order to answer questions of this type, it would be important to know the Rules for Multidimensional Array Assignments. The following may help to quickly remember multidimensional array assignment rules: Two-Dimensional Arrays: The first square brackets are pointing to a one-dimensional array: int[ ][ ] twoD = {some 2 d array}; 🠇 [ ] 🠆 [ ] one-dimensional array e.g. int[ ][ ] twoD = {{1,2},{3,4,5}}; twoD[ 0 ] 🠆 [ ] 🠆 {1,2} twoD[ 1 ] 🠆 [ ] 🠆 {3,4,5} Two square bracket pairs are pointing to an element: int[ ][ ] twoD = = {some 2 d array}; 🠇 [ ][ ] 🠆 element. e.g. int[ ][ ] twoD = {{1,2},{3,4,5}}; twoD[0][0] 🠆 element 🠆 1 twoD[0][1] 🠆 element 🠆 2 twoD[1][0] 🠆 element 🠆 3 twoD[1][1] 🠆 element 🠆 4 twoD[1][2] 🠆 element 🠆 5 Three Dimensional Arrays: The first square brackets are pointing to a two-dimensional array: int[ ][ ][ ] threeD = {some 3 d array}; 🠇 [ ] 🠆 [ ][ ] two-dimensional array e.g. int[ ][ ][ ] threeD = { { {1,2},{3,4} }, { {5,6} } }; threeD[ 0 ] 🠆 [ ][ ]🠆 { {1,2}, {3,4} } threeD[ 1 ] 🠆 [ ][ ] 🠆 { {5,6} } The first two square bracket pairs are pointing to a one-dimensional array: int[ ][ ][ ] threeD = {some 3 d array}; 🠇 [ ][ ] 🠆 [ ] one-dimensional array e.g. int[ ][ ][ ] threeD = { { {1,2},{3,4} }, { {5,6} } }; threeD[0][0] 🠆 [ ] 🠆 {1,2} threeD[0][1] 🠆 [ ] 🠆 {3,4} threeD[1][0] 🠆 [ ] 🠆 {5,6} All of square bracket pairs of a three-d array are pointing to an element: int[ ][ ][ ] threeD = {some 3 d array}; 🠇 [ ][ ][ ] 🠆 element e.g. int [ ][ ][ ] threeD = { { {1, 2},{3,4} }, { {5,6} } }; threeD [0][0][0] 🠆 element 🠆 1 threeD [0][0][1] 🠆 element 🠆 2 threeD [0][1][0] 🠆 element 🠆 3 threeD [0][1][1] 🠆 element 🠆 4 threeD [1][0][0] 🠆 element 🠆 5 threeD [1][0][1] 🠆 element 🠆 6

Given: public class A { public static void main(String[] args) { String s = "MINI"; System.out.println(s.indexOf('I')); System.out.println(s.indexOf('I',2)); System.out.println(s.indexOf('I',3)); }} What is the result? a) compiler error b) Compile and print: 1 3 3 c) Compile and print: 1 1 3 d) None of the answers are correct

b) is correct. Compile and print: 1 3 3 Lets step through the program to explain the correct answer: ===Code Step Through=== 1: public class A { 2: public static void main(String[] args) { 3: String s = "MINI"; 4: System.out.println(s.indexOf('I')); 5: System.out.println(s.indexOf('I',2)); 6: System.out.println(s.indexOf('I',3)); 7: }} On line 3, a new String object is created ("MINI") which has a reference named 's' ================ 1: public class A { 2: public static void main(String[] args) { 3: String s = "MINI"; 4: System.out.println(s.indexOf('I')); 5: System.out.println(s.indexOf('I',2)); 6: System.out.println(s.indexOf('I',3)); 7: }} On line 4, the index of the first 'I' character is printed to the screen i.e. 1 Observing the index positions of each of the characters in the string 'MINI', outlined below, you can see that character 'I' is first located at index 1: 'M' = Index 0 'I' = Index 1 'N' = Index 2 'I' = Index 3 ================ 1: public class A { 2: public static void main(String[] args) { 3: String s = "MINI"; 4: System.out.println(s.indexOf('I')); 5: System.out.println(s.indexOf('I',2)); 6: System.out.println(s.indexOf('I',3)); 7: }} On line 5, the index of the first character starting on or after the specified index 2 is printed to the screen i.e. 3 An outline of the index positions of each of the characters within the string 'MINI' are shown below: 'M' = Index 0 'I' = Index 1 'N' = Index 2 'I' = Index 3 ================ 1: public class A { 2: public static void main(String[] args) { 3: String s = "MINI"; 4: System.out.println(s.indexOf('I')); 5: System.out.println(s.indexOf('I',2)); 6: System.out.println(s.indexOf('I',3)); 7: }} On line 6, the index of the first character starting on or after the specified index 3 is printed to the screen i.e. 3 An outline of the index positions of each of the characters within the string 'MINI' are shown below: 'M' = Index 0 'I' = Index 1 'N' = Index 2 'I' = Index 3 The final output: 1 3 3

Given: 1: import java.util.function.Predicate; 2: class A { 3: public static void main(String[] args) { 4: A a1 = new A(); 5: a1.go(INSERT CODE HERE); 6: } 7: void go(Predicate<A> a){ 8: A a2 = new A(); 9: System.out.println(a.test(a2)); 10: } 11: static int adder(int x, int y){return x+y;} 12: } Which code, inserted on line 5 above, will compile and run fine? a) p->7-4 b) (A u)->{int z = 3; int i = 1; return adder(z, i) >2;} c) A u->{int z = 3; return adder(z, 1) >2;} d) None of the answers are correct

b) is correct. For the OCA 8 exam, all that you need to know in regards to Java Lambda questions will be the Predicate interface and its method test() as well as the Java Lambda Syntax Rules. (A u) -> {int z = 3; int i = 1; return adder(z, i) >2;} The Java Lambda syntax rules state that: ➤ The Lambda parameter can be just a variable name or it can be a type followed by a variable name, all in parenthesis '()'. This answer fulfils this syntax rule. The lambda parameter contains a variable with a type which is surrounded by parenthesis '()': (A u)->{int z = 3; int i = 1; return adder(z, i) >2;} Introduction to Simple Lambdas In this section we're going to outline a basic introduction to Lambdas. Firstly The benefits of Lambdas: • Easier to Read Code • More Concise Code • Faster Running Code (More Efficient). The core aspect of lambdas is that you can pass complex expressions (calculations that result in a boolean) as an argument into a method. This is as opposed to the traditional manner of passing variables into a method i.e. primitive types or object type variables. So instead of having a Java class that contains many different methods that perform separate and distinct responsibilities (functions), you could have one method that can perform ALL of those separate and distinct responsibilities. The benefit would be in the area of memory efficiency so that, instead of having multiple different methods allocated memory, you could have one method allocated memory. Also, the class containing the lambda expression would make the class more cohesive in performing a particular task. Predicate Interface For the OCA exam, you will only need to know about the Predicate interface and its method test(). Predicate, in general meaning, is a statement about something that is either true or false. In programming, predicates represent single argument functions that return a boolean value. The Predicate interface is located here: java.util.function.Predicate The test() method evaluates a predicate on the given argument 't'. Its signature is as follows: boolean test(T t) Where parameter t represents the input argument which will result in the boolean value true being returned if the input argument matches the predicate, otherwise false. There is a simple example of the use of the Predicate interface and its method test(): import java.util.function.Predicate; public class Main { public static void main(String[] args) { Predicate<String> i = (s)-> s.length() > 5; System.out.println( i.test("java2s.com ")); } } As you can see in the above code, the Java Lambda expression is: s.length() > 5 and this is 'tested' utilising the test() method with a string literal "java2s.com ". As "java2s.com " has a length greater than 5, 'true' is printed to the screen. In summary, for the OCA exam, you will be tested on the very basics of Java lambdas e.g. on the syntax of Java Lambda expressions, the use of the Predicate interface and also its test() method. The Lambda questions for the OCA exam may also be mixed with other aspects that will be tested e.g. objects and data structures like a array lists. Syntax Rules for Predicate Lambda ➤ The predicate parameter can be just a variable name or it can be the type followed by the variable name, all in parethesis. e.g. s.go((x) -> adder(5,1) < 7); s.go(u -> adder(6,2) < 9); ➤ The body must return a boolean. e.g. s.go((x) -> 3 < 7); s.go(u -> adder(6,2) < 9); ➤The body can be a single expression which cannot have a return statement. e.g. s.go((x) -> 3 < 7); ➤ The body can be a code block surrounded by curly brackets containing one or more valid statements, each ending with a semicolon and the block must end with a return statement. e.g. s.go(u -> { int x = 1; return adder(x,2) < 9 } );

Given: public class A { public static void main(String args[]) { Integer i1 = 1; Integer i2 = 1; if (i1==i2) System.out.println("Same Object Address"); if (i1.equals(i2)) System.out.println("Same value"); }} What is the result? a) Compiler error b) Compile and print: Same Object Address Same value c) Compile and print: Same value d) None of the answers are correct

b) is correct. Has stated, the program will compile and print: Same Object Address Same value Let's see what happens when we step into the code: ===Code Step Through=== 1: public class A { 2: public static void main(String args[]) 3: { 4: Integer i1 = 1; 5: Integer i2 = 1; 6: if (i1==i2) 7: System.out.println("Same Object Address"); 8: if (i1.equals(i2)) 9: System.out.println("Same value"); 10: }} On the line 4 and 5, two int primitive types are auto-boxed (wrapped) into objects of type Integer: Integer i1 = new Integer( 1 ) Integer i2 = new Integer( 2 ) ========2======== 1: public class A { 2: public static void main(String args[]) 3: { 4: Integer i1 = 1; 5: Integer i2 = 1; 6: if (i1 ==i2 ) 7: System.out.println("Same Object Address"); 8: if (i1.equals(i2)) 9: System.out.println("Same value"); 10: }} On the line 6, the '==' operator compares the memory addresses of the two objects referenced by i1 and i2. Apart from String object, all objects have unique addresses when created in memory. So, it should be the case that the two addresses of i1 and i2 are not equal and therefore "Same Object Address" should not be printed to the screen. However, in order to save memory, two instances of the following wrapper objects created through boxing (i.e. Integer i1 = 1) will always be equal when their primitive values are the same. • Boolean • Byte • Character • Short • Integer This results in the if block, on the line 6, being true and the following outputted to the screen on line 7: "Same Object Address" If line 4 and 5 were replaced with: Integer i1 = new Integer( 1 ) Integer i2 = new Integer( 2 ) Then, the if block on the 6 would be false and "Same Object Address" would not have been printed to the screen. ========3======== 1: public class A { 2: public static void main(String args[]) 3: { 4: Integer i1 = 1; 5: Integer i2 = 1; 6: if (i1==i2) 7: System.out.println("Same Object Address"); 8: if (i1.equals(i2)) 9: System.out.println("Same value"); 10: }} On the line 8, the equals() method compares the contents of the two objects to see if they are equal. In this case they are equal as the both contain the number 1 and therefore the if block is entered and "Same value" is printed to the screen on line 8.

Given: String h1 = " Hello "; String h2 = h1.replace("l", "f"); System.out.println(h2); What is the result? a) Compiler error b) Compile and print "Heffo" c) Compile and print "Heflo" d) None of the answers are correct

b) is correct. The program will compile and print "Heffo" String h1 = " Hello "; String h2 = h1.replace("l", "f"); System.out.println(h2); In the code, replace(char oldChar, char newChar): Returns a String resulting from replacing all occurrences of oldChar in this string with newChar. Old chars: Index 0 = H Index 1 = e Index 2 = l Index 3 = l Index 4 = 0 New chars: Index 0 = H Index 1 = e Index 2 = f Index 3 = f Index 4 = 0 If the character oldChar does not occur in the character sequence represented by this String object, then a reference to this String object is returned.

Given: 1: public class A { 2: public static void main(String args[]) 3: { 4: char[][] twoD = {{'a','b','c'},{'d','e','f'}}; 5: System.out.println(INSERT CODE HERE); 6: System.out.println(INSERT CODE HERE); 7: } What code, inserted on lines 5 and 6 independently above, print the length of the row and length of the column of the two-dimensional array twoD? a) twoD[].length twoD.length b) twoD.length twoD[0].length c) twoD[0].length twoD.length d) None of the answers are correct

b) is correct. Looking at the highlighted aspects of the program: 1: public class A { 2: public static void main(String args[]) 3: { 4: char[][] twoD = { {'a','b','c'} , { 'd','e','f' } }; 5: System.out.println(twoD.length); 6: System.out.println(twoD[0].length); 7: } The above will output: 2 3 Where: twoD.length gets the length of the row of this two-dimensional array. twoD[0].length gets the length of the column of this two-dimensional array. The above can be explained in further detail by stepping through the code line by line: ===Code Step Through=== 1: public class A { 2: public static void main(String args[]) 3: { 4: char[][] twoD = { {'a','b','c'} , { 'd','e','f' } }; 5: System.out.println(twoD.length); 6: System.out.println(twoD[0].length); 7: } On the line 4, the total number of arrays stored in this two-dimensional array is highlighted i.e. 2 On the line 5, the code to retrieve the total number of arrays is shown i.e. twoD.length ========2======== 1: public class A { 2: public static void main(String args[]) 3: { 4: char[][] twoD = { {'a','b','c'} , { 'd','e','f' } }; 5: System.out.println(twoD.length); 6: System.out.println(twoD[0].length); 7: } On the line 6 above, total number of char values stored in the first array (represented by index 0) of this two-dimensional array get printed to the screen i.e. 3 Note 1: If line 6 had the code: twoD[1].length Then it would also print 3 as the length of the second array in this two-dimensional array contains 3 values results i.e. char[][] twoD = {{'a','b','c'},{'d','e','f'}}; If the second array contained only two values then it would print 2 and so on and so forth. Note 2: Basically, a two-dimensional array is comprised of two separate arrays stored in an bigger array. Indeed, all multidimensional arrays, be a two-dimensional, three-dimensional and so forth, are basically a collection (set) of arrays stored in a bigger array.

Which of the following are true? a) StringBuilder class methods are not synchronized b) StringBuffer class methods are synchronized c) StringBuilder class methods are synchronized d) StringBuffer class methods are not synchronized

b) is correct. StringBuffer class methods are synchronized. The Java synchronized keyword is an essential tool in concurrent programming in Java. Its overall purpose is to only allow one thread at a time into a particular section of code thus allowing us to protect, for example, variables or data from being corrupted by simultaneous modifications from different threads.

Given: import java.time.LocalDateTime; import java.time.format. ______ ; public class A { public static void main(String[] args) { LocalDateTime now = LocalDateTime.now(); System.out.println("Before : " + now); ______ formatter = ______ .______ ("dd-MM-yyyy HH:mm:ss"); String formatDateTime = now.format(formatter); System.out.println("After : " + formatDateTime); }} What class, inserted in the above empty spaces, formats the date and time to output like "dd-MM-yyyy HH:mm:ss"? a) TimeFormatter b) DateTimeFormatter c) DateFormatter d) DateTimes e) LocalDate

b) is correct. The class DateTimeFormatter is used to format the date and time to output like the following: "dd-MM-yyyy HH:mm:ss" e.g. 17-10-2018 10:23:45 import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; public class A { public static void main(String[] args) { LocalDateTime now = LocalDateTime.now(); System.out.println("Before : " + now); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss"); String formatDateTime = now.format(formatter); System.out.println("After : " + formatDateTime); }} The above output would look something like: Before : 2018-12-01T10:59:31.625 After : 10:59:31 01-12-2018 Note 1: You can change the format pattern: DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss"); or DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern(""HH:mm:ss dd-MM-yyyy"); Note 2: java.time.format.DateTimeFormatter This immutable class is used by the class above to format date/time objects for output and to parse input strings and convert them to date/time objects.

Given that 'e' refers to an object that implements Predicate, which could be considered invalid code snippets or statements? a) if (e.test(m)) b) String result = e.test(m); switch(result){...} c) while(e.test(m)) d) e.test(m) ? "yes" : "no"; e) do{ }while(e.test(m)); f) boolean b = e.test(m));

b) is correct. The code containing the method test() resolves a boolean and a boolean cannot be stored in a String variable: String result = e.test(m); switch(result){...} The Predicate class contains the method test(). Predicates in Java are implemented with interfaces. Predicate<T> is a generic functional interface representing a single argument function that returns a boolean value. It is located in the java.util.function package. It contains a test(T t) method that evaluates the predicate on the given argument. e.g. 1: import java.util.function.Predicate; 2: public class A { 3: public static void main(String[] args) 4: { 5: // Creating predicate 6: Predicate<Integer> lesserthan = i -> (i < 18); 7: 8: // Calling Predicate method 9: System.out.println(lesserthan.test(10)); 10: }} On the line 6 is the Predicate Lambda expression (i < 18). This is 'tested' with the argument 10 on the line 9. On the line 9, the (i < 18) expression resolves to testing whether or not 10 is less than 18. As 10 is less than 18, the test() method resolves to true. The following are valid statements: a) if (e.test(m)) This is a valid code snippet. c) while(e.test(m)) This is a valid code snippet. The code e.test(m) resolves to a boolean which is acceptable type in a while loop. code e.test(m) resolves to a boolean which is acceptable type in a while loop. d) e.test(m) ? "yes" : "no"; This is a valid code snippet. It contains the ternary operator, which is a shortcut way of doing if/else code block. The ternary operator: e.test(m) ? "yes" : "no"; resolves to a boolean. If the boolean is true, string "yes" is returned by the code block, otherwise, string "no" is returned by the code block. e) do{ }while(e.test(m)); This is a valid code snippet. The code e.test(m) resolves to a boolean which is acceptable type in a do while loop. f) boolean b = e.test(m)); This is a valid code snippet. The code e.test(m) resolves to a boolean which is acceptable type.

Given: StringBuilder h2 = new StringBuilder("Hello"); h2.append(" you"); System.out.println(h2); What is the result? a) Compiler error b) Compile and print "Hello you" c) Compile and print "Hello" d) None of the answers are correct

b) is correct. The code will compile and print "Hello you" StringBuilder is mutable therefore you can add the original StringBuilder literal object. StringBuilder h2 = new StringBuilder("Hello"); h2.append(" you"); System.out.println(h2); The above will output: "Hello you" ===Code Step Through=== StringBuilder h2 = new StringBuilder("Hello"); h2.append(" you"); System.out.println(h2); StringBuilder reference h2 is pointing to a newly created StringBuilder object containing string literal "Hello" h2 🠚 "Hello" ===========2============ StringBuilder h2 = new StringBuilder("Hello"); h2.append(" you"); System.out.println(h2); The call to h2 is actually appending " you" to the end of the original StringBuilder literal object "Hello". h2 🠚 "Hello you" Output is: "Hello you"

Given: public class A { public static void main(String args[ ]) { char[ ][ ][ ] threeD = {{{'a','b'},{'d','e'}}, {{'f','g'},{'h'}}}; System.out.println(INSERT CODE HERE); } What code, inserted above, would enable the character 'f' to be printed to the screen? a) threeD[1][0] b) threeD[1][0][0] c) threeD[1][2][0] d) None of the answers are correct

b) is correct. The following code will enable the character 'f' to be printed to the screen: threeD[1][0][0] = 'f' Three-dimensional arrays are probably the most complex multidimensional array you will see in the exam. It would be highly advisable to sketch out the three-dimensional array contents like below in order to make it easier to derive the array indexes. The array indexes are essential in order to complete this question: char[][][] threeD = { {{'a','b'},{'d','e'}}, {{'f','g'},{'h'}} }; In the above we can see that the three-dimensional array, 'threeD', is composed of a collection of arrays. In order to derive the answer, it would be necessary to step through the code to explain how the three-dimensional array indexes are derived: ===Code Step Through=== char[][][] threeD = { {{'a','b'},{'d','e'}}, {{'f','g'},{'h'}} }; The above highlights the two-dimensional array at index [0] i.e. threeD[0] = {'a','b'},{'d','e'}} (2-D Array) ========2======== char[][][] threeD = { {{'a','b'},{'d','e'}}, {{'f','g'},{'h'}} }; The above highlights the two-dimensional array at index [1] i.e. threeD[ 1 ] = {{'f','g'},{'h'}} (2-D Array) ========3======== char[][][] threeD = { {{'a','b'},{'d','e'}}, {{'f','g'},{'h'}} }; The above highlights the one-dimensional array at index [0][0] i.e. threeD[ 0 ][ 0 ] = {'a','b'} (1-D Array) ========4======== char[][][] threeD = { {{'a','b'},{'d','e'}}, {{'f','g'},{'h'}} }; The above highlights the one-dimensional array at index [0][1] i.e. threeD[ 0 ][ 1 ] = {'d','e'} (1-D Array) ========5======== char[][][] threeD = { {{'a','b'},{'d','e'}}, {{'f','g'},{'h'}} }; The above highlights the one-dimensional array at index [1][0] i.e. threeD[ 1 ][ 0 ] = {'f','g'} (1-D Array) ========6======== char[][][] threeD = { {{'a','b'},{'d','e'}}, {{'f','g'},{'h'}} }; The above highlights the one-dimensional array at index [1][1] i.e. threeD[ 1 ][ 1 ] = {'h'} (1-D Array with one value). ========7======== char[][][] threeD = { {{'a','b'},{'d','e'}}, {{'f','g'},{'h'}} }; The above highlights the value at index [0][0][0] i.e. threeD[ 0 ][ 0 ][ 0 ] = 'a' ========8======== char[][][] threeD = { {{'a','b'},{'d','e'}}, {{'f','g'},{'h'}} }; The above highlights the value at index [0][0][1] i.e threeD[ 0 ][ 0 ][ 1 ] = 'b' ========9======== char[][][] threeD = { {{'a','b'},{'d','e'}}, {{'f','g'},{'h'}} }; The above highlights the value at index [0][1][0] i.e threeD[ 0 ][ 1 ][ 0 ] = 'd' ========10======== char[][][] threeD = { {{'a','b'},{'d','e'}}, {{'f','g'},{'h'}} }; The above highlights the value at index [0][1][0] i.e threeD[ 0 ][ 1 ][ 1 ] = 'e' ========11======== char[][][] threeD = { {{'a','b'},{'d','e'}}, {{'f','g'},{'h'}} }; The above highlights the value at index [1][0][0] i.e threeD[ 1 ][ 0 ][ 0 ] = 'f' ========12======== char[][][] threeD = { {{'a','b'},{'d','e'}}, {{'f','g'},{'h'}} }; The above highlights the value at index [1][0][1] i.e threeD[ 1 ][ 0 ][ 1 ] = 'g' ========13======== char[][][] threeD = { {{'a','b'},{'d','e'}}, {{'f','g'},{'h'}} }; The above highlights the value at index [1][1][1] i.e threeD[ 1 ][ 1 ][ 1 ] = 'h' The above provides a full run through of the for the indexes of the three-dimensional array.

Given: StringBuilder h4 = new StringBuilder("Hello"); h4.reverse(); System.out.println(h4); What is the result? a) Compile and print "olleh" b) Compile and print "olleH" c) Compile and print HERE d) None of the answers are correct

b) is correct. The program will compile and print "olleH" StringBuilder h4 = new StringBuilder("Hello"); h4.reverse(); System.out.println(h4); The above outputs: "olleH"

Given: import java.time.LocalDate; import java.time.Period; public class A { public static void main(String[] args) { LocalDate date1 = LocalDate.of(2018, 11, 15); Period p1 = Period.ofMonths(1); date1.plus(p1); System.out.println(date1); LocalDate date2 = date1.plus(p1); System.out.println(date2); }} What is the result? a) Compiler error b) Compile and print: 2018-11-15 2018-12-15 c) Compile and print: 2018-12-15 2018-12-15 d) None of the answers are correct

b) is correct. The program will compile and print: 2018-11-15 2018-12-15 ===Code Step Through=== LocalDate date1 = LocalDate.of(2018, 11, 15); Period p1 = Period.ofMonths(1); date1.plus(p1); System.out.println(date1); LocalDate date2 = date1.plus(p1); System.out.println(date2); A date is created: 2018, 11, 15 LocalDate reference date1 is referring to (pointing to) the LocalDate object 2018, 11, 15 with an arbitrary memory address &324. Memory Heap Snapshot: date1 🠆 LocalDate Object(Address &324){ 2018, 11, 15 } Note: Calendar classes are Factory classes i.e. they do not have constructors in order to create a new object. These classes do not use the word 'new' to create new LocaDate objects. Instead these classes invoke public static methods to create a new object. In the case of LocalDate instantiation (object creation), this class uses the factory method LocalDate.of() to create the date object (2018, 11, 15) ============2============= LocalDate date1 = LocalDate.of(2018, 11, 15); Period p1 = Period.ofMonths(1); date1.plus(p1); System.out.println(date1); LocalDate date2 = date1.plus(p1); System.out.println(date2); The above creates a period unit of 1 month. ============3============ LocalDate date1 = LocalDate.of(2018, 11, 15); Period p1 = Period.ofMonths(1); date1.plus(p1); System.out.println(date1); LocalDate date2 = date1.plus(p1); System.out.println(date2); As Calendar related objects are immutable, the above creates a new LocalDate object. This new LocalDate object is comprised of a copy of the object that date1 reference is pointing to (2018, 11, 15) and adds a period unit of 1 month to that newly created LocalDate object. This results in a new local date object (2018, 12, 15) which has no reference (i.e. no reference represented by the character 'Ø') with an arbitrary address in memory &567. This null referenced object is available for garbage collection. Below outlines a pseudocode depiction of the objects in memory: Memory Heap Snapshot: date1 🠆 LocalDate Object(Address &324){ 2018, 11, 15 } Ø 🠚 LocalDate Object(Address &567) {2018, 12, 15} ============4============ LocalDate date1 = LocalDate.of(2018, 11, 15); Period p1 = Period.ofMonths(1); date1.plus(p1); System.out.println(date1); LocalDate date2 = date1.plus(p1); System.out.println(date2); The above will output 2018, 11, 15 to the screen as this is the original LocalDate object that has a reference to it (date1). Memory Heap Snapshot: date1 🠆 LocalDate Object(Address &324){ 2018, 11, 15 } ============5============ LocalDate date1 = LocalDate.of(2018, 11, 15); Period p1 = Period.ofMonths(1); date1.plus(p1); System.out.println(date1); LocalDate date2 = date1.plus(p1); System.out.println(date2); A newly created LocalDate object is created which is comprised of the object referred to by the reference date1 added with period unit 1 month. it is assigned an arbitrary address in memory &158. This has a LocalDate reference (date2) pointing to it. Memory Heap Snapshot: date1 🠆 LocalDate Object(Address &324){ 2018, 11, 15 } date2 🠆 LocalDate Object(Address &158){ 2018, 12, 15 } ============6=========== LocalDate date1 = LocalDate.of(2018, 11, 15); Period p1 = Period.ofMonths(1); date1.plus(p1); System.out.println(date1); LocalDate date2 = date1.plus(p1); System.out.println(date2); The above outputs: 2018, 12, 15 Final output will be: 2018-11-15 2018-12-15

Given: public class A { public static void main(String[] args) { String s = "Hello"; System.out.println(s.substring(4, 6)); }} What is the result? a) Compiler error b) Runtime error c) Compile and print "Hello" indefinitely d) None of the answers are correct

b) is correct. The program will throw a: java.lang.StringIndexOutOfBoundsException 1: public class A { 2: public static void main(String[] args) { 3: String s = "Hello"; 4: System.out.println(s.substring(4, 6)); 5: }} Index: 0-1-2-3-4 String: H-e-l-l-o In the above: Index 0 contains "H". Index 1 contains "e". etc. On the line 4, the method substring() attempts to return a substring starting at index 4 to (6-1) 5. However, index 5 is outside of the bounds of the string s. Therefore it throws a runtime error.

Given: public class A { public static void main(String[] args) { StringBuilder sb = new StringBuilder("Hello"); System.out.println(sb.delete(0, "Hel")); }} What is the result? a) Compiler error b) Runtime error c) Compile and print "Say Hello" d) None of the answers are correct

b) is correct. The program will throw a: java.lang.RuntimeException 1: public class A { 2: public static void main(String[] args) { 3: StringBuilder sb = new StringBuilder("Hello"); 4: System.out.println(sb.delete(0, "Hel")); 5: }} On line 4, there is no such delete() method with an int and String as parameters. Solution: 1: public class A { 2: public static void main(String[] args) { 3: StringBuilder sb = new StringBuilder("Hello"); 4: System.out.println(sb.delete(0, 2)); 5: }} The above will delete chars from index 0 to 2-1 (1) within the StringBuilder object and result in printing: "llo" Index: 0-1-2-3-4 String: H-e-l-l-o In the above: Index 0 contains "H". Index 1 contains "e". etc.

Given: public class A { public static void main(String[] args) { StringBuilder sb = new StringBuilder("Hello"); System.out.println(sb.delete(6, 7)); }} What is the result? Which are true? (choose all that apply) a) Compiler error b) Runtime error c) Compile and print Hello d) None of the answers are correct e) f) g)

b) is correct. The program will throw: java.lang.StringIndexOutOfBoundsException 1: public class A { 2: public static void main(String[] args) { 3: StringBuilder sb = new StringBuilder("Hello"); 4: System.out.println(sb.delete(6, 7)); 5: }} On line 4, it will throw the above exception as the size of the string "Hello" is less than the starting point of the subset to be deleted in the StringBuilder object. Index: 0-1-2-3-4 String: H-e-l-l-o In the above: Index 0 contains "H". Index 1 contains "e". etc.

Given: public class A { public static void main(String[] args) { int str = "123".charAt(4); System.out.println(str); }} What is the result? a) Compiler error b) Runtime error c) Compile and print 3 d) None of the answers are correct

b) is correct. public class A { public static void main(String[] args) { int str = "123".charAt(4); System.out.println(str); }} The program will throw a: java.lang.StringIndexOutOfBoundsException The size of the String str is 3 so a charAt(4) call will result in a StringIndexOutOfBoundsException.

Given: 1: import java.util.function.Predicate; 2: class A { 3: public static void main(String[] args) { 4: A a1 = new A(); 5: a1.go(INSERT CODE HERE); 6: } 7: void go(Predicate<A> a){ 8: A a2 = new A(); 9: System.out.println(a.test(a2)); 10: } 11: static int adder(int x, int y){return x+y;} 12: } Which code, inserted on line 5 above, will compile and run fine? a) t->{ adder(z, i) >2;} b) t-> adder(z, i) >2 c) y->{ int y =1; return adder(y, i) >2;} d) None of the answers are correct

b) is correct. t-> adder(z, i) >2 This is a Java Lambda question. For the OCA 8 exam, all that you need to know, in regards to Java Lambda questions, will be the Predicate interface and its method test() as well as the Java Lambda Syntax Rules. Incorrect Answers: a) t->{ adder(z, i) >2;} The Java Lambda Syntax rule states that the lambda body can be a code block surrounded by curly brackets {} containing one or more valid statements, each ending with a semi colon and the block must end with a return statement. The expression does not have return statement therefore it gives a compiler error. Solution: t->{ return adder(z, i) >2;} ============== c) y->{ int y =1; return adder(y, i) >2;} Looking at the highlighted aspects of the program: y->{ int y =1; return adder(y, i) >2;} You cannot declare the Java Lambda variable parameter the same name as a variable declared inside the Lambda body as this will give a compiler error. This is a slight trick question but nonetheless a good one. Solution: Change the name of the Lambda parameter or the variable declared inside the Lambda body i.e. q->{ int y =1; return adder(y, i) >2;} The following will also give a compile error: y->{ int z =1; adder(z, 2) >2;} The Java Lambda syntax rule states that the body can be a code block surrounded by curly brackets {} containing one or more valid statements, each ending with a semi colon and the block must end with a return statement. In the above Lambda body, there is a missing return statement at the end of the block. Solution: y->{ int z =1; return adder(z, 2) >2;} Note: Introduction to Simple Lambdas In this section we're going to outline a basic introduction to Lambdas. Firstly The benefits of Lambdas: • Easier to Read Code • More Concise Code • Faster Running Code (More Efficient). The core aspect of lambdas is that you can pass complex expressions (calculations that result in a boolean) as an argument into a method. This is as opposed to the traditional manner of passing variables into a method i.e. primitive types or object type variables. So instead of having a Java class that contains many different methods that perform separate and distinct responsibilities (functions), you could have one method that can perform ALL of those separate and distinct responsibilities. The benefit would be in the area of memory efficiency so that, instead of having multiple different methods allocated memory, you could have one method allocated memory. Also, the class containing the lambda expression would make the class more cohesive in performing a particular task. Predicate Interface For the OCA exam, you will only need to know about the Predicate interface and its method test(). Predicate, in general meaning, is a statement about something that is either true or false. In programming, predicates represent single argument functions that return a boolean value. The Predicate interface is located here: java.util.function.Predicate The test() method evaluates a predicate on the given argument 't'. Its signature is as follows: boolean test(T t) Where parameter t represents the input argument which will result in the boolean value true being returned if the input argument matches the predicate, otherwise false. There is a simple example of the use of the Predicate interface and its method test(): import java.util.function.Predicate; public class Main { public static void main(String[] args) { Predicate<String> i = (s)-> s.length() > 5; System.out.println( i.test("java2s.com ")); } } As you can see in the above code, the Java Lambda expression is: s.length() > 5 and this is 'tested' utilising the test() method with a string literal "java2s.com ". As "java2s.com " has a length greater than 5, 'true' is printed to the screen. In summary, for the OCA exam, you will be tested on the very basics of Java lambdas e.g. on the syntax of Java Lambda expressions, the use of the Predicate interface and also its test() method. The Lambda questions for the OCA exam may also be mixed with other aspects that will be tested e.g. objects and data structures like a array lists. Syntax Rules for Predicate Lambda ➤ The predicate parameter can be just a variable name or it can be the type followed by the variable name, all in parethesis. e.g. s.go((x) -> adder(5,1) < 7); s.go(u -> adder(6,2) < 9); ➤ The body must return a boolean. e.g. s.go((x) -> 3 < 7); s.go(u -> adder(6,2) < 9); ➤The body can be a single expression which cannot have a return statement. e.g. s.go((x) -> 3 < 7); ➤ The body can be a code block surrounded by curly brackets containing one or more valid statements, each ending with a semicolon and the block must end with a return statement. e.g. s.go(u -> { int x = 1; return adder(x,2) < 9 } );

Given: public class A { public static void main(String[] args) { StringBuilder sb = new StringBuilder(); String s = new String(); for(int i = 0; i < 1000; i++) { s = " " + i ; sb.append(s); } }} If the garbage collector does NOT run while this code is executing, approximately how many objects will exist in memory when the loop is complete? a) Less than 10 b) About 1000 c) About 2000 d) About 3000 e) About 4000

b) is correct. ➤ StringBuilders are mutable (changeable), so all of the append() invocations are acting on the same StringBuilder object over and over. ➤ Strings, however, are immutable (not changeable), so every String concatenation operation results in a new String object. ➤ Also, the string " " is created once and reused in every loop iteration. ===Code Step Through=== 1: public class A { 2: public static void main(String[] args) { 3: StringBuilder sb = new StringBuilder(); 4: String s = new String(); 5: for(int i = 0; i < 1000; i++) { 6: s = " " + i ; 7: sb.append(s); 8: } 9: }} On the line 3, a StringBuilder object with reference sb is created and with a unique arbitrary address assigned to it e.g. @9982 A pseudocode description of this object in memory as outlined below: sb 🠆 Object StringBuilder(Memory Address @9982) { "" } =======2======= 1: public class A { 2: public static void main(String[] args) { 3: StringBuilder sb = new StringBuilder(); 4: String s = new String(); 5: for(int i = 0; i < 1000; i++) { 6: s = " " + i ; 7: sb.append(s); 8: } 9: }} On the line 4, a new string object is created with reference s in the String Constant Pool. It would have an arbitrary address in memory also. A pseudocode description of the current objects in memory is outlined below: sb 🠆 Object StringBuilder(Memory Address @9982) { "" } s 🠆 Object String(Memory Address @3324) { "" } =======3======= 1: public class A { 2: public static void main(String[] args) { 3: StringBuilder sb = new StringBuilder(); 4: String s = new String(); 5: for(int i = 0; i < 1000; i++) { 6: s = " " + i ; 7: sb.append(s); 8: } 9: }} On the line 5, the for loop block is executed and the int variable i is initialised to 0. At this point in the code, a pseudocode description of the current objects and variables in memory would look like this: i = 0 sb 🠆 Object StringBuilder(Memory Address @9982) { "" } s 🠆 Object String(Memory Address @3324) { "" } =======4======= 1: public class A { 2: public static void main(String[] args) { 3: StringBuilder sb = new StringBuilder(); 4: String s = new String(); 5: for(int i = 0; i < 1000; i++) { 6: s = " " + i ; 7: sb.append(s); 8: } 9: }} On the line 5, a comparison is made between the current value stored in the variable i and the number 1000. If the current value stored in the variable i is less than 1000, the postfix expression i++ is executed and the for block is entered. Looking at the current variables and objects in memory above, we can see that the current value stored in variable i is 0 and as 0 is less than 1000: • The postfix expression i++ is executed. • The for block is entered. Note: The postfix expression i++ will not increment (by 1) until the control flow of the code gets to line 8 (i.e. the end of the for bock current iteration) =======5======= 1: public class A { 2: public static void main(String[] args) { 3: StringBuilder sb = new StringBuilder(); 4: String s = new String(); 5: for(int i = 0; i < 1000; i++) { 6: s = " " + i ; 7: sb.append(s); 8: } 9: }} On the line 6, the current value of i is appended to an empty String " " which results in a new String object being created (" 0") with its own unique arbitrary memory address e.g. &5643. The String reference 's' no longer references the String object would memory address @3324 and instead, is reassigned to the new String object with memory address &5643. Remember, Strings are immutable, therefore they cannot change that is why a new string object is created above with memory address &5643. This is important to understand for this line of the code. The following outlines a pseudocode description of the current objects and variables in memory when line 6 is executed: i = 0 sb 🠆 Object StringBuilder(Memory Address @9982) { "" } Object String(Memory Address @3324) { "" } s 🠆 Object String(Memory Address &5643) { " 0" } =======6======= 1: public class A { 2: public static void main(String[] args) { 3: StringBuilder sb = new StringBuilder(); 4: String s = new String(); 5: for(int i = 0; i < 1000; i++){ 6: s = " " + i ; 7: sb.append(s); 8: } 9: }} On the line 7, the contents of the String object referenced by 's' (with memory address &5643) is appended to the StringBuilder object referenced by 'sb' (with memory address @9982). As StringBuilder is mutable, a new object is not created. The following pseudocode description outlines the current objects and variables in memory at this particular point of the code: i = 0 sb 🠆 Object StringBuilder(Memory Address @9982) { " 0" } Object String(Memory Address @3324) { "" } s 🠆 Object String(Memory Address &5643) { " 0" } =======7======= 1: public class A { 2: public static void main(String[] args) { 3: StringBuilder sb = new StringBuilder(); 4: String s = new String(); 5: for(int i = 0; i < 1000; i ++) { 6: s = " " + i ; 7: sb.append(s); 8: } 9: }} On the line 8, the i ++ gets incremented by 1 and the flow control jumps back up to line 5. The following pseudocode description outlines the current objects and variables in memory at this particular point of the code: i = 1 sb 🠆 Object StringBuilder(Memory Address @9982) { " 0" } Object String(Memory Address @3324) { "" } s 🠆 Object String(Memory Address &5643) { " 0" } =======8======= 1: public class A { 2: public static void main(String[] args) { 3: StringBuilder sb = new StringBuilder(); 4: String s = new String(); 5: for(int i = 0; i < 1000; i++){ 6: s = " " + i ; 7: sb.append(s); 8: } 9: }} On the line 5, the expression i < 1000 is executed. Looking at the current variables and objects in memory above, we can see that the current value stored in variable i is 1 and as 1 is less than 1000: • The postfix expression i++ is executed. • The for block is entered. Note: The postfix expression i++ will not increment (by 1) until the control flow of the code gets to line 8 (i.e. the end of the for bock current iteration) =======9======= 1: public class A { 2: public static void main(String[] args) { 3: StringBuilder sb = new StringBuilder(); 4: String s = new String(); 5: for(int i = 0; i < 1000; i++) { 6: s = " " + i ; 7: sb.append(s); 8: } 9: }} On the line 6, the current value of i is appended to an empty String " " which results in a new String object being created (" 1") with its own unique arbitrary memory address e.g. &2232. The following outlines a pseudocode description of the current objects and variables in memory when line 6 is executed: i = 1 sb 🠆 Object StringBuilder(Memory Address @9982) { " 0" } Object String(Memory Address @3324) { "" } Object String(Memory Address &5643) { " 0" } s 🠆 Object String(Memory Address &2232) { " 1" } The String reference 's' no longer references the String object with memory address &5643 and instead, is reassigned to the new String object with memory address &2232. As you can see, the for loop will continue to execute until the expression i < 1000 is no longer true. Therefore, when ' i ' finally increments to 1000, there will be approximately 1000 new String objects created in memory. Note: To make Java more memory efficient, the Java Virtual Machine sets aside a special area of memory called the String Constant Pool. When the compiler encounters a String literal (e.g. "Hello"), it checks the pool to see if the same identical String literal already exists. If a match is found, the reference to the new literal is directed to the existing String, and no new String literal object is created. This is why string objects are immutable i.e. they cannot be changed and are final constants. The key concept for you to understand is that once a String object is created, it can never be changed.

Given that addIt() returns an int, which are valid Predicate lambdas? a) x, y -> 7 < 5 b) x -> { return addIt(2, 1) >5; } c) x -> return addIt(2, 1) > 5; d) x -> { int y = 5; int z = 7; addIt(y, z) > 8; } e) (MyClass x) -> 7 > 13 f) x -> { int y = 5; int z = 7; return addIt(y, z) >8; } g) (MyClass x) -> 5+4

b), e) and f) are correct. b) x -> { return addIt(2, 1) >5; } According to the rules of lambda expressions, the keyword 'return' must be wrapped in brackets '{}'. The method addIt(2, 1) passes in two ints into its parameters, it adds these numbers and returns 3. The number 3 is then compared to see if it is greater than the number 5. This expression resolves to a boolean false. e) ( MyClass x ) -> 7 > 13 According to the rules of lambda expressions, the lambda single parameter can be cast using parenthesis. f) x -> { int y = 5; int z = 7; return addIt(y, z) >8; } According to the rules of lambda expressions, variables can be declared inside and outside the block. The method addIt(5, 7) passes in two ints into its parameters, it adds these numbers and returns 12. The number 12 is then compared to see if it is greater than the number 8. This expression resolves to a boolean true Incorrect Answers: a) x, y -> 7 < 5 Incorrect syntax: x, y -> 7 < 5 The java lambda uses a Single Parameter. In the above, it has two parameters which gives a compiler error. c) x -> return addIt(2, 1) > 5; The 'return' keyword must be encapsulated in a code block using '{ }'. Therefore the above code give a compiler error. d) x -> { int y = 5; int z = 7; addIt(y, z) > 8; } A 'return' keyword must be encapsulated in a code block using '{}'. As this keyword is missing in the above expression, it gives compiler error. g) (MyClass x) ->5+4 According to the rules of lambda expressions, the body of the lambda expression must return a boolean. In the expression above, it does not resolve to a boolean but simply adds two numbers together. This gives a compiler error.

Which of the following will compile? a) while (true) { LABELA: System.out.println("Label A"); break LABELA; } b) while (true) { {LABELA: System.out.println("Label A"); break LABELA;} } c) while (true) { LABELA:{ System.out.println("Label A"); break LABELA;} } d) None of the answers are correct

c) is correct. In order to break out of a label block, it is necessary to have the break label inside the said block label i.e. 1: while (true) { 2: LABELA: { System.out.println("Label A"); 3: break LABELA; } 4: } On the line 2 and 3, you see the label block named LABELA. Inside this label block online 3 you will see the break key word. Incorrect Answers: a) Looking at the suggested program: 1: while (true) { 2: LABELA: System.out.println("Label A"); 3: break LABELA; 4: } On the 2, LABELA block contains a single line of code therefore does not require parenthesis i.e {}. This block ends at the end of line 2. On the line 3, break LABELA; is outside of the LABELA block and therefore this gives a compiler error. b) Looking at the suggested program answer: while (true) { {LABELA: System.out.println("Label A"); break LABELA; } } The above as incorrect placement of parenthesis {} therefore this gives a compiler error. Note: keyword "break" can only be used to break out of a current loop or switch block or labelled block.

Given: import java.util.ArrayList; import java.util.List; public class A { public static void main(String args[]) { List<String> list = new ArrayList<String>(2); list.add("Hi"); list.add("Lo"); System.out.println(list.subList(0, 1)); }} What is the result? a) Compiler error b) Runtime error c) Compile and print [Hi] d) None of the answers are correct

c) is correct. It will compile and print [Hi]. Let's step through the code to explain the answer: ===Code Step Through=== 1: import java.util.ArrayList; 2: import java.util.List; 3: 4: public class A { 5: public static void main(String args[]) 6: { 7: List<String> list = new ArrayList<String>(2); 8: list.add("Hi"); 9: list.add("Lo"); 10: System.out.println(list.subList(0, 1)); 11: } 12: } On the line 7, a new ArrayList object is created which will contain only objects of type String. Its initial size is 2. An ArrayList is a re-sizable array, also called a dynamic array. It grows its size to accommodate new elements and shrinks the size when the elements are removed. The above ArrayList object instance is referred to by a List reference. List is an interface and ArrayList implements List. ========2======== 1: import java.util.ArrayList; 2: import java.util.List; 3: 4: public class A { 5: public static void main(String args[]) 6: { 7: List<String> list = new ArrayList<String>(2); 8: list.add("Hi"); 9: list.add("Lo"); 10: System.out.println(list.subList(0, 1)); 11: } 12: } On the line 8 and 9, the two String objects, named are added to the ArrayList. Therefore, the ArrayList grows in size by two. ========3======== 1: import java.util.ArrayList; 2: import java.util.List; 3: 4: public class A { 5: public static void main(String args[]) 6: { 7: List<String> list = new ArrayList<String>(2); 8: list.add("Hi"); 9: list.add("Lo"); 10: System.out.println(list.subList(0, 1)); 11: } 12: } On the line 10, a sublist of the 'list' is created at starting index 0 and ending a index 1-1 (i.e. subList(0, 0)). This results in the the substring containing 'Hi' output to the screen.

Which of the following will compile? a) String[] s = {"H","i"}; for (String arg : s) { System.out.print(arg); } b) String[] s = {"H","i"}; for ( String arg : s) { s = new String[]{"l","o"}; } c) String[] s = {"H","i"}; for (final String arg : s) { System.out.print(arg); } d) None of the answers are correct

c) is correct. Looking at the code: String[] s = {"H","i"}; for (final String arg : s) { System.out.print(arg); } The above is an enhanced for loop which prints the contents of string array to the screen i.e. 'hi' Note: if the code was the following, it would not compile: String[] s = {"H","i"}; for (final String arg : s) { arg = new String[]{"l","o"}; } The above does not compile as the String arg is declared final (constant) and therefore cannot be reassigned to another object as is the case within the body of the for loop. This causes the compiler error. Incorrect Answers: a) Looking at the highlighted aspects of the program: String[] s = {"H","i"}; for (String arg : s) { System.out.print(arg); } The above is an enhanced for loop which prints the contents of string array to the screen i.e. 'hi' b) Looking at the highlighted aspects of the program: String[] s = {"H","i"}; for ( String arg : s ) { s = new String[]{"l","o"}; } The above enhanced for loop contains an array reference s which is reassigned to another String object containing strings "l" ,"o". Nothing gets printed to the screen.

Which of the following will not compile? a) String[] s = {"H","i"}; String arg; for ( arg : s) { System.out.println(arg); } b) String[] s = {"H","i"}; for ( String arg : s) { System.out.println(arg); } c) String[] s = {"H","i"}; String arg = "lo"; for ( arg : s) { System.out.println(arg); } d) None of the answers are correct

c) is correct. Looking at the highlighted aspect of the answer: 1: String[] s = {"H","i"}; 2: String arg = "lo"; 3: for (arg : s) { 4: System.out.println(arg); 5: } On line 2 above, variable String arg is declared. On the line 3, the variable arg is used (inside the enhanced for loop). This cannot be undertaken and causes a compiler error. Solution: Declare the String variable inside the enhanced for loop. 1: String[] s = {"H","i"}; 2: 3: for (String arg : s) { 4: System.out.println(arg); 5: } Incorrect Answers: a) In looking at the highlighted aspect of the program: 1: String[] s = {"H","i"}; 2: String arg; 3: for(arg : s) { 4: System.out.println(arg); 5: } On line 2 above, variable String arg is declared. On the line 3, the variable arg is used (inside the enhanced for loop). This cannot be undertaken and causes a compiler error. Solution: Declare the String variable inside the enhanced for loop. b) String[] s = {"H","i"}; for (String arg : s) { System.out.println(arg); }

Given: 1: import java.util.function.Predicate; 2: class A { 3: public static void main(String[] args) { 4: A a1 = new A(); 5: a1.go(INSERT CODE HERE); 6: } 7: void go(Predicate<A> a){ 8: A a2 = new A(); 9: System.out.println(a.test(a2)); 10: } 11: static int adder(int x, int y){return x+y;} 12: } Which code, inserted on line 5 above, will compile and run fine? a) p->7<4 b) p<->5<6 c) u->{return adder(2, 1) >2;} d) None of the answers are correct

c) is correct. Looking at the highlighted aspects of the correct answer: u-> {return adder(2, 1) >2; } The syntax rules for Java Lambda states that the body of a Lambda expression can be a code block surrounded by curly brackets {} ending with a return statement. In the above Lambda expression, the body '{return adder(2, 1) >2;}' fulfils this syntax rule. Note that the adder() method call returns a boolean which is then compared with the number 2. Incorrect Answers: a) p->7<4 Looking at the highlighted aspects of the program: p->7<4 The syntax rules for Java Lambda states that the body of a Lambda expression must return a boolean. In the above Lambda expression, the body '7<4' resolves to a boolean which is 'false'. b) p<->5<6 Looking at the highlighted aspects of the program: p <-> 5<6 The Java Lambda arrow token is written as ->. The symbol '<->' is not recognised in Java and gives a compiler error. Note: Introduction to Simple Lambdas In this section we're going to outline a basic introduction to Lambdas. Firstly The benefits of Lambdas: • Easier to Read Code • More Concise Code • Faster Running Code (More Efficient). The core aspect of lambdas is that you can pass complex expressions (calculations that result in a boolean) as an argument into a method. This is as opposed to the traditional manner of passing variables into a method i.e. primitive types or object type variables. So instead of having a Java class that contains many different methods that perform separate and distinct responsibilities (functions), you could have one method that can perform ALL of those separate and distinct responsibilities. The benefit would be in the area of memory efficiency so that, instead of having multiple different methods allocated memory, you could have one method allocated memory. Also, the class containing the lambda expression would make the class more cohesive in performing a particular task. Predicate Interface For the OCA exam, you will only need to know about the Predicate interface and its method test(). Predicate, in general meaning, is a statement about something that is either true or false. In programming, predicates represent single argument functions that return a boolean value. The Predicate interface is located here: java.util.function.Predicate The test() method evaluates a predicate on the given argument 't'. Its signature is as follows: boolean test(T t) Where parameter t represents the input argument which will result in the boolean value true being returned if the input argument matches the predicate, otherwise false. There is a simple example of the use of the Predicate interface and its method test(): import java.util.function.Predicate; public class Main { public static void main(String[] args) { Predicate<String> i = (s)-> s.length() > 5; System.out.println( i.test("java2s.com ")); } } As you can see in the above code, the Java Lambda expression is: s.length() > 5 and this is 'tested' utilising the test() method with a string literal "java2s.com ". As "java2s.com " has a length greater than 5, 'true' is printed to the screen. In summary, for the OCA exam, you will be tested on the very basics of Java lambdas e.g. on the syntax of Java Lambda expressions, the use of the Predicate interface and also its test() method. The Lambda questions for the OCA exam may also be mixed with other aspects that will be tested e.g. objects and data structures like a array lists. Syntax Rules for Predicate Lambda ➤ The predicate parameter can be just a variable name or it can be the type followed by the variable name, all in parethesis. e.g. s.go((x) -> adder(5,1) < 7); s.go(u -> adder(6,2) < 9); ➤ The body must return a boolean. e.g. s.go((x) -> 3 < 7); s.go(u -> adder(6,2) < 9); ➤The body can be a single expression which cannot have a return statement. e.g. s.go((x) -> 3 < 7); ➤ The body can be a code block surrounded by curly brackets containing one or more valid statements, each ending with a semicolon and the block must end with a return statement. e.g. s.go(u -> { int x = 1; return adder(x,2) < 9 } );

Which of the following are correct? a) The String and StringBuilder class are immutable i.e. you cannot change them anyway. b) The StringBuilder class is immutable i.e. you cannot change it in any way. c) The String class is immutable i.e. you cannot change it in anyway. d) None of the answers are correct.

c) is correct. The String class is immutable i.e. you cannot change an existing String object instance in anyway. On the other hand, the StringBuilder class is mutable i.e. you can change an existing StringBuilder object instance. Note: To make Java more memory efficient, the Java Virtual Machine sets aside a special area of memory called the String Constant Pool. When the compiler encounters a String literal (e.g. "Hello"), it checks the pool to see if the same identical String literal already exists. If a match is found, the reference to the new literal is directed to the existing String, and no new String literal object is created. This is why string objects are immutable i.e. they cannot be changed and are final constants. The key concept for you to understand is that once a String object is created, it can never be changed.

Given: public class A { public static void main(String [] args) { StringBuilder sb = new StringBuilder("abc"); String s = "abc"; sb.reverse().append("d"); s.toUpperCase().concat("d"); System.out.println("." + sb + " . . " + s + "."); }} Which two substrings will be included in the result? a) . abc. b) . ABCd. c) .ABCD. d) . cbad.

d) is correct. The output will contain the following: . abc. and . cbad. Incorrect Answers: a) . abc. This question tests your knowledge of the String class and also StringBuilder class. Let's step to the code to see how it runs: ===Code Step Through=== 1: public class A { 2: public static void main(String [] args) { 3: StringBuilder sb = new StringBuilder("abc"); 4: String s = "abc"; 5: sb.reverse().append("d"); 6: s.toUpperCase().concat("d"); 7: System.out.println("." + sb + " . . " + s + "."); 8: }} On the line 3, a new StringBuilder object is created containing the string literal "abc". The StringBuilder is a mutable class. In other words, StringBuilder objects can be changed. A pseudocode depiction of this StringBuilder object in memory with an arbitrary memory address is outlined below. In the depiction below, we can see the StringBuilder reference 'sb' is referring to ('pointing to') the StringBuilder object which is stored at a unique address in memory. Current Object stored in heap memory: sb 🠆 Object StringBuilder(Heap Address $2453) { "abc" } ========2======== 1: public class A { 2: public static void main(String [] args) { 3: StringBuilder sb = new StringBuilder("abc"); 4: String s = "abc"; 5: sb.reverse().append("d"); 6: s.toUpperCase().concat("d"); 7: System.out.println("." + sb + " . . " + s + "."); 8: }} On the line 4, a String object is created with another string literal "abc". The String class is immutable. In other words, String objects cannot be changed when created. A snapshot of the two objects created so far in memory is outlined below. All objects, when created in memory, have unique memory addresses in the Heap. The String object is stored in the String Object Pool which is a special area of memory for storing Strings. Current Objects stored in memory: sb 🠆 Object StringBuilder(Heap Address $2453) { "abc" } s 🠆 Object String(Heap Address &5423) { "abc" } ========3======== 1: public class A { 2: public static void main(String [] args) { 3: StringBuilder sb = new StringBuilder("abc"); 4: String s = "abc"; 5: sb.reverse().append("d"); 6: s.toUpperCase().concat("d"); 7: System.out.println("." + sb + " . . " + s + "."); 8: }} On the line 5, the StringBuilder method reverse() is applied to the StringBuilder object 'sb'. This results in the StringBuilder object, referenced by 'sb', getting changed (edited) to the following: "cba". Current Objects stored in memory: sb 🠆 Object StringBuilder(Heap Address $2453) { "cba" } s 🠆 Object String(Heap Address &5423) { "abc" } ========4======== 1: public class A { 2: public static void main(String [] args) { 3: StringBuilder sb = new StringBuilder("abc"); 4: String s = "abc"; 5: sb.reverse().append("d"); 6: s.toUpperCase().concat("d"); 7: System.out.println("." + sb + " . . " + s + "."); 8: }} On the line 5, the string literal "d" is added to the StringBuilder object referenced by 'sb'. The new string literal is appended to the StringBuilder object 'sb' which results in the current StringBuilder object looking like: "cbad". Following the execution of line 5, the heap memory snapshot of objects looks like this: Current Objects stored in memory: sb 🠆 Object StringBuilder(Heap Address $2453) { "cbad" } s 🠆 Object String(Heap Address &5423) { "abc" } ========5======== 1: public class A { 2: public static void main(String [] args) { 3: StringBuilder sb = new StringBuilder("abc"); 4: String s = "abc"; 5: sb.reverse().append("d"); 6: s.toUpperCase().concat("d"); 7: System.out.println("." + sb + " . . " + s + "."); 8: }} On the line 6, a new unreferenced String object (null depicted by the character 'Ø') is created which contains the contents of the String object 's'. The object the assigned an arbitrary address in heap memory (e.g. @8273) This new String object is converted to uppercase characters which results in the unreferenced String object containing the string literal: "ABC". Current Objects stored in memory: sb 🠆 Object StringBuilder(Heap Address $2453) { "cbad" } s 🠆 Object String(Heap Address &5423) { "abc" } Ø 🠆 Object String(Heap Address @8273) { "ABC" } ========6======== 1: public class A { 2: public static void main(String [] args) { 3: StringBuilder sb = new StringBuilder("abc"); 4: String s = "abc"; 5: sb.reverse().append("d"); 6: s.toUpperCase().concat("d"); 7: System.out.println("." + sb + " . . " + s + "."); 8: }} On the line 6, the method concat() is executed which appends "d" to the String object "ABC". As a consequence of String objects being immutable, this concat() method call results in the creation of a new String object containing the String literal: "ABCd". From looking at the heap memory snapshot below, we can now see there are four objects created in memory, one StringBuilder object, along with three String objects. Current Objects stored in memory: sb 🠆 Object StringBuilder(Heap Address $2453) { "cbad" } s 🠆 Object String(Heap Address &5423) { "abc" } Ø 🠆 Object String(Heap Address @8273) { "ABC" } Ø 🠆 Object String(Heap Address &2086) { "ABCd" } ========7======== 1: public class A { 2: public static void main(String [] args) { 3: StringBuilder sb = new StringBuilder("abc"); 4: String s = "abc"; 5: sb.reverse().append("d"); 6: s.toUpperCase().concat("d"); 7: System.out.println("." + sb + " . . " + s + "."); 8: }} On the line 7, the String literal "." and StringBuilder object 'sb' containing "cbad" are joined together. Note: You can join String and StringBuilder objects together. This results in the print stream parameters currently in the state: System.out.println(".cbad"+ " . . " + s + "."); ========8======== 1: public class A { 2: public static void main(String [] args) { 3: StringBuilder sb = new StringBuilder("abc"); 4: String s = "abc"; 5: sb.reverse().append("d"); 6: s.toUpperCase().concat("d"); 7: System.out.println(".cbad"+ " . . " + s + "."); 8: }} On the line 7, the string literal ".cbad" and " . . " are joined together. This results in the print stream parameters currently in the state: System.out.println(".cbad . . " + s + "."); The Current Objects stored in heap memory: sb 🠆 Object StringBuilder(Heap Address $2453) { "cbad" } s 🠆 Object String(Heap Address &5423) { "abc" } Ø 🠆 Object String(Heap Address @8273) { "ABC" } Ø 🠆 Object String(Heap Address &2086) { "ABCd" } ========9======== 1: public class A { 2: public static void main(String [] args) { 3: StringBuilder sb = new StringBuilder("abc"); 4: String s = "abc"; 5: sb.reverse().append("d"); 6: s.toUpperCase().concat("d"); 7: System.out.println(".cbad . . " + s + "."); 8: }} Continuing on the line 7, the string literal ".cbad . . " is joined with the contents of the String object referenced by 's'. Looking at the snapshot of objects in heap memory above, we can see that the String object referenced by 's' has the literal "abc". Therefore, the following two string literals are joined together: ".cbad . . " and "abc". This results in the print stream parameters currently in the state: System.out.println(".cbad . . abc"+"."); ========10======== 1: public class A { 2: public static void main(String [] args) { 3: StringBuilder sb = new StringBuilder("abc"); 4: String s = "abc"; 5: sb.reverse().append("d"); 6: s.toUpperCase().concat("d"); 7: System.out.println(".cbad . . abc"+"."); 8: }} Continuing again on the line 7, the two string literals ".cbad . . abc" and "." are joined together. This results in the final output: ".cbad . . abc" Note: It's important to know some core String and StringBuilder methods. Also the difference between mutable and immutable in the context of string and StringBuilder. The String class has a number of methods and whilst it would not be practical memorise all of them, it would be advisable to memorise some of them. Below is an abbreviation to help you memorise some methods of the String class that you may see in the exam: lc-ss-tr • length() • concat(String str) • substring(int beginIndex) • substring(int beginIndex, int endIndex) • trim() • replace(char oldChar, char newChar) The above methods are explained in more detail below: ➤ public int length(): The above method returns the length of this string. E.g. String h = "Hello"; int i = h.length(); System.out.println(i); The above will output 5. ➤ public String concat(String str): The above method returns a new String with both strings joined together. E.g. String h = "Hello"; String newString = h.concat(" There!"); System.out.println(newString); The above will print: "Hello There!" Note: The concat() method has the same result as adding two strings together e.g. "Hello" +" There!" ➤ public String substring(int beginIndex) The above method returns a string that is a substring of the original string, starting at the index 'beginIndex'. E.g. String h = "Hello"; String newString = h.substring(3); System.out.println(newString); The above will output: "lo" In the above, the beginning index of the string "Hello" is 3. A new String object is created containing the substring "lo" and is assigned to the new reference 'newString'. The original string object "Hello" with reference 'h' remains unchanged. Note: The index values of the string are: "H" = index 0 "e" = index 1 "l" = index 2 "l" = index 3 "o" = index 4 ➤public String substring(int beginIndex, int endIndex) The above method returns a string that is a substring of the original string. This substring starts at the index named 'beginIndex' and ends at the index named 'endIndex' -1. Make sure to subtract -1 from the ending index as this is not explicitly stated in the method signature. E.g. String h = "Hello"; String newString = h.substring(4,5); System.out.println(newString); The above will output: "o" In the above, the beginning index of the string "Hello" is 4. The ending index is 'endIndex', which is 5 - 1, which results in 4 Where the index values of the string are: "H" = index 0 "e" = index 1 "l" = index 2 "l" = index 3 "o" = index 4 Note 1: A new String object is created containing the substring "o" and is assigned to the new reference 'newString'. The original string object "Hello" with reference 'h' remains unchanged. Note 2: The following would give a java.lang.StringIndexOutOfBoundsException String h = "Hello"; String newString = h.substring(4,6); The ending index is 'endIndex', which is 6 - 1, which results in 5. As index 5 is outside of the bounds of the "Hello" string (because the last index value of the string is 4), this will give StringIndexOutOfBoundsException ➤ public String trim() The above method returns a string whose value is this string, with any leading and trailing whitespace removed. E.g. String h = " Hello "; String newString = h.trim(); System.out.println(newString); The above will output "Hello" ➤ public String replace(char oldChar, char newChar) The above returns a string resulting from replacing all occurrences of oldChar in this string with newChar. E.g. String h = "Hello"; String newString = h.replace('H', 'F'); System.out.println(newString); The above replaces the character 'H' with the character 'F' in the string "Hello" and stores this changed string in a new string named 'newString' This results in the output: "Fello" Note: As a consequence of String immutability, the result of the replace() method on the original string object "Hello" (with reference 'h') gets assigned a new reference which is a new object entirely independent of the original string 'h'.

Given: import java.time. ______ ; import java.time.ZoneId; public class A { public static void main(String[] args) { ZoneId zone1 = ZoneId.of("Europe/Berlin"); ZoneId zone2 = ZoneId.of("Europe/Dublin"); ______ now1 = ______ .now(zone1); ______ now2 = ______ .now(zone2); System.out.println("Berlin Time: "+now1); System.out.println("Dublin Time: "+now2); }} What class, inserted in the above empty spaces, will return the current local time for Berlin and Dublin? a) DateTime b) LocalDateTimes c) LocalTime d) DateTimes e) LocalDate

c) is correct. The class LocalTime will return the current local time for Berlin and Dublin. import java.time.LocalTime; import java.time.ZoneId; public class A { public static void main(String[] args) { ZoneId zone1 = ZoneId.of("Europe/Berlin"); ZoneId zone2 = ZoneId.of("Europe/Dublin"); LocalTime now1 = LocalTime.now(zone1); LocalTime now2 = LocalTime.now(zone2); System.out.println("Berlin Time: "+now1); System.out.println("Dublin Time: "+now2); }} The above will output: Berlin Time: 11:51:19.238 Dublin Time: 10:51:19.254 Note: java.time.LocalTime This class is used to create immutable objects each which represents a specific time for certain area (time-zone) in the world. e.g. Berlin Time Now: 11:28:04.865 Dublin Time Now: 10:28:04.865

Given: public class A { public static void main(String args[]) { int[ ] array1,array2[ ]; int[ ][ ] array3; int [ ] array4[ ], array5[ ]; }} Which of the above arrays are two-dimensional? a) array1, array2, array3 and array4 only b) array3 only c) array2, array3, array4 and array5 only d) None of the answers are correct

c) is correct. The following are the two-dimensional arrays initializations: array2, array3, array4 and array5 only. To explain the above answer, a code step through would help. ===Code Step Through=== 1: public class A { 2: public static void main(String args[]) 3: { 4: int[ ] array1, array2[ ]; 5: int[ ][ ] array3; 6: int [ ] array4[ ], array5[ ]; 7: }} On the line 4, array1 is declared a one-dimensional array while array2 is a declared two-dimensional array which could be alternatively have been declared as: int[ ][ ]array2; or int[ ]array2[ ]; or int array2[ ][ ]; =======2========= 1: public class A { 2: public static void main(String args[]) 3: { 4: int[ ] array1,array2[]; 5: int[ ][ ] array3; 6: int [ ] array4[ ], array5[ ]; 7: }} On the line 5, it's clear that array3 is declared a two-dimensional array as highlighted. ========3======== 1: public class A { 2: public static void main(String args[ ]) 3: { 4: int[ ] array1,array2[]; 5: int[ ][ ] array3; 6: int [ ] array4[ ], array5[ ]; 7: }} On the line 6, array4 is declared a two-dimensional array as highlighted. ========4======== 1: public class A { 2: public static void main(String args[]) 3: { 4: int[ ] array1,array2[ ]; 5: int[ ][ ] array3; 6: int [ ] array4[ ], array5[ ]; 7: }} Also on the line 6, array5 is declared a two-dimensional array with the two highlighted square brackets. The end result is that the following are declared two-dimensional arrays: array2, array3, array4 and array5 only. While the following is declared a one-dimensional array in the code: array1.

Which of the following are not methods of the java.lang.StringBuilder class? a) insert(int startIndex, Object obj) b) append(String aStr) c) replace(char oldChar, char newChar) d) reverse() e) delete(int startIndex, int endIndex) f) None of the answers are correct.

c) is correct. The method replace() is contained within the String class and not StringBuilder class. It would be advisable to memorize the core methods of the StringBuilder class as as these type of questions pop up in the exam regularly. StringBuilder Methods The following is a suggested abbreviation abbreviation to help memorize some of the methods of the StringBuilder class: airr-d ➤ append(String aStr): The characters of the String argument are appended into the character sequence (StringBuilder object). ➤ insert(int startIndex, Object obj): Inserts the string obj into this character sequence (StringBuilder object) at startIndex. ➤ replace(int startIndex, int endIndex, String str): Replaces the characters in a substring of this sequence with characters in the specified String. The substring begins at the specified startIndex and extends to the character at endIndex end - 1 ➤ reverse(): Causes this character sequence to be replaced by the reverse of the sequence. ➤ delete(int startIndex, int endIndex): Removes the characters in a substring of this sequence. The substring begins at the specified start and extends to the character at index end - 1 or to the end of the sequence if no such character exists. The following outlines examples of using the above methods: ➤➤➤ Sample Code: append()➤➤➤ StringBuilder h2 = new StringBuilder("Hello"); h2.append(" you"); System.out.println(h2); The above will output: "Hello you" ===Code Step Through=== StringBuilder h2 = new StringBuilder("Hello"); h2.append(" you"); System.out.println(h2); StringBuilder ref h2 is pointing to a newly created StringBuilder object containing string literal "Hello" h2 🠆 "Hello" ===========2============ StringBuilder h2 = new StringBuilder("Hello"); h2.append(" you"); System.out.println(h2); The call to h2 is actually appending the string " you" to the end of the original StringBuilder literal object "Hello". h2 🠆 "Hello you" Output is: "Hello you" ➤➤➤Sample Code: insert() ➤➤➤ StringBuilder h3 = new StringBuilder("Hello"); h3.insert(4, " yo"); System.out.println(h3); The above will output: "Hell yoo" ===Code Step Through=== StringBuilder h3 = new StringBuilder("Hello"); h3.insert(4, " yo"); System.out.println(h3); StringBuilder ref h3 is pointing to a newly created StringBuilder object containing string literal "Hello" h3 🠆 "Hello" ======================= StringBuilder h3 = new StringBuilder("Hello"); h3.insert(4, " yo"); System.out.println(h3); The above insert() method inserts the String literal " yo" into the StringBuilder literal at index 4. The value at index 4 gets pushed to Index 7 making way for the insertion of the String literal " yo" Old chars: Index 0 = H Index 1 = e Index 2 = l Index 3 = l Index 4 = o New chars: Index 0 = H Index 1 = e Index 2 = l Index 3 = l Index 4 = ' ' Index 5 = y Index 6 = o Index 7 = o The output is: Hell yoo ➤➤➤Sample Code: replace() ➤➤➤ StringBuilder h1 = new StringBuilder("Hello"); h1.replace(0, 2, "b"); System.out.println(h1); The output is: "bllo" ===Code Step Through=== StringBuilder h1 = new StringBuilder("Hello"); h1.replace(0, 2, "b"); System.out.println(h1); The above replace() method replaces the String literal starting at index 0 and ending at index 2-1 with "b". Old chars: Index 0 = H Index 1 = e Index 2 = l Index 3 = l Index 4 = o New chars: Index 0 = b Index 1 = l Index 2 = l Index 3 = o The output is: bllo ➤➤➤Sample Code: reverse() ➤➤➤ StringBuilder h4 = new StringBuilder("Hello"); h4.reverse(); System.out.println(h4); The above outputs: "olleH" ➤➤➤Sample Code: delete() ➤➤➤ StringBuilder h4 = new StringBuilder("Hello"); h4.delete(4, 5); System.out.println(h4); The output: "Hell" ============================= StringBuilder h4 = new StringBuilder("Hello") h4.delete(4, 5); System.out.println(h4); StringBuilder ref h4 is pointing to a newly created StringBuilder object containing string literal "Hello" h4 🠆 "Hello" ============================ StringBuilder h4 = new StringBuilder("Hello") h4.delete(4, 5); System.out.println(h4); The above delete() method deletes the character literals at at start index 4 and ending at index 5-1 Old chars: Index 0 = H Index 1 = e Index 2 = l Index 3 = l Index 4 = deleted New chars: Index 0 = H Index 1 = e Index 2 = l Index 3 = l The output is: "Hell"

Given: 1: import java.util.*; 2: public class Dat { 3: public static void main(String[] args) { 4: List<Integer> myList = new ArrayList<>(); 5: myList.add(new Integer(5)); 6: myList.add(42); 7: myList.add("113"); 8: myList.add(new Integer("7")); 9: System.out.println(myList); 10: }} What is the result? a) [5, 42, 113, 7] b) Compilation fails due only to an error on line 4. c) Compilation fails due only to an error on line 7. d) Compilation fails due only to errors on lines 4 and 7. e) Compilation fails due only to errors on lines 6 and 7 f) Compilation fails due only to errors on lines 4, 6, and 7 g) Compilation fails due only to errors on lines 4, 6, 7, and 8

c) is correct. The only error in this code is the attempt to add a String to an ArrayList of Integer wrapper objects on line 7. Line 6 uses autoboxing, and lines 5 and 8 demonstrate using a wrapper class's two constructors. ===Code Step Through=== 1: import java.util.*; 2: public class Dat { 3: public static void main(String[] args) { 4: List<Integer> myList = new ArrayList<>(); 5: myList.add(new Integer(5)); 6: myList.add(42); 7: myList.add("113"); 8: myList.add(new Integer("7")); 9: System.out.println(myList); 10: }} On the line 4, a new ArrayList object is created. This ArrayList object has a reference named 'mylist' of type List<Integer>. List is an interface and ArrayList implements the List interface. One of the methods in the List interface is add(). Therefore, it's perfectly okay to have an object be referenced by the interface it is implements. List<Integer> myList = new ArrayList<>(); The above highlights the diamond syntax which contains Integer. This means that this ArrayList object (declared on the line 4) will only store objects of type Integer. Any other type of object (other than Integer) that is attempted to be stored in this ArrayList will give a compiler error. ========2======== 1: import java.util.*; 2: public class Dat { 3: public static void main(String[] args) { 4: List<Integer> myList = new ArrayList<>(); 5: myList.add(new Integer(5)); 6: myList.add(42); 7: myList.add("113"); 8: myList.add(new Integer("7")); 9: System.out.println(myList); 10: }} On the line 5, the Integer object 'new Integer(5)' is added to the ArrayList referenced by 'myList'. ========3======== 1: import java.util.*; 2: public class Dat { 3: public static void main(String[] args) { 4: List<Integer> myList = new ArrayList<>(); 5: myList.add(new Integer(5)); 6: myList.add(42); 7: myList.add("113"); 8: myList.add(new Integer("7")); 9: System.out.println(myList); 10: }} On the line 6, the primitive int type '42' is auto boxed to Integer object (i.e. new Integer(42)) and then added to the ArrayList referenced by 'myList'. ========4======== 1: import java.util.*; 2: public class Dat { 3: public static void main(String[] args) { 4: List<Integer> myList = new ArrayList<>(); 5: myList.add(new Integer(5)); 6: myList.add(42); 7: myList.add("113"); 8: myList.add(new Integer("7")); 9: System.out.println(myList); 10: }} On the line 7, a String object "113" is attempted to be added to the ArrayList referenced by 'myList'. However, as the ArrayList referenced by 'myList' takes only objects of type Integer, its gives a compiler error. Solution: Wrap the said String object in an Integer class: myList.add(new Integer("113")); ========5======== 1: import java.util.*; 2: public class Dat { 3: public static void main(String[] args) { 4: List<Integer> myList = new ArrayList<>(); 5: myList.add(new Integer(5)); 6: myList.add(42); 7: myList.add("113"); 8: myList.add(new Integer("7")); 9: System.out.println(myList); 10: }} On the line 8, if line 7 contained myList.add(new Integer("113")) instead of myList.add("113"), then the Integer object 'new Integer("7")' would be added to the ArrayList referenced by 'myList'. ========6======== 1: import java.util.*; 2: public class Dat { 3: public static void main(String[] args) { 4: List<Integer> myList = new ArrayList<>(); 5: myList.add(new Integer(5)); 6: myList.add(42); 7: myList.add("113"); 8: myList.add(new Integer("7")); 9: System.out.println(myList); 10: }} On the line 9, again, if line 7 contained myList.add(new Integer("113")) instead of myList.add("113"), then the contents of the ArrayList would be printed to the screen using an implicit call to the method toString(). This would result in the following output: [5, 42, 113, 7]

Given: 1: public class A { 2: public static void main(String[] args) { 3: String s1 = "abc"; 4: String s2 = s1; 5: s1 += "d"; 6: System.out.println(s1 + " " + s2 + " " + (s1 == s2)); 7: StringBuilder sb1 = new StringBuilder("abc"); 8: StringBuilder sb2 = sb1; 9: sb1.append("d"); 10: System.out.println(sb1 + " " + sb2 + " " + (sb1==sb2)); 11: }} Which are true? (choose all that apply) a) Compilation fails b) The first line of output is: abc abc true c) The first line of output is: abc abc false d) The first line of output is: abed abc false e) The second line of output is: abed abed true f) The second line of output is: abed abed false

d) and e) are true The following are correct: ➤ d) The first line of output is: abed abc false ➤ e) The second line of output is: abed abed true Although String objects are immutable, references to Strings are mutable. Therefore, you can change the name of references to a String object or you can have multiple different String references to the same String object but the said String object that the references are referring to is still unchanged (immutable). The code si += "d"; creates a new String object. StringBuilder objects are mutable, so the append() is changing the single StringBuilder object to which both StringBuilder references refer. ===Code Step Through=== 1: public class A { 2: public static void main(String[] args) { 3: String s1 = "abc"; 4: String s2 = s1; 5: s1 += "d"; 6: System.out.println(s1 + " " + s2 + " " + (s1 == s2)); 7: StringBuilder sb1 = new StringBuilder("abc"); 8: StringBuilder sb2 = sb1; 9: sb1.append("d"); 10: System.out.println(sb1 + " " + sb2 + " " + (sb1==sb2)); 11: }} On the line 3, a new String object with reference s1 is created. String objects are stored in a special area of memory named the String Object Pool. A pseudocode the description of this String object stored in memory is outlined below, along with its unique memory address. s1 🠆 Object String(Memory Address @7356) { "abc" } =======2======= 1: public class A { 2: public static void main(String[] args) { 3: String s1 = "abc"; 4: String s2 = s1; 5: s1 += "d"; 6: System.out.println(s1 + " " + s2 + " " + (s1 == s2)); 7: StringBuilder sb1 = new StringBuilder("abc"); 8: StringBuilder sb2 = sb1; 9: sb1.append("d"); 10: System.out.println(sb1 + " " + sb2 + " " + (sb1==sb2)); 11: }} On the line 4, a new reference is pointing to the same String object that reference s1 is pointing to. Below, you'll see the pseudocode description of the String object along with its references pointing to it (s1 and s2): s2🠆s1 🠆 Object String(Memory Address @7356) { "abc" } =======3======= 1: public class A { 2: public static void main(String[] args) { 3: String s1 = "abc"; 4: String s2 = s1; 5: s1 += "d" ; 6: System.out.println(s1 + " " + s2 + " " + (s1 == s2)); 7: StringBuilder sb1 = new StringBuilder("abc"); 8: StringBuilder sb2 = sb1; 9: sb1.append("d"); 10: System.out.println(sb1 + " " + sb2 + " " + (sb1==sb2)); 11: }} On the line 5, the letter "d" is added to a copy of the contents of the String object referenced by s1 (i.e the String object "abc" at address @7356). This results in a new String object containing "abcd" stored in memory. The operator '+=' adds operands together. In this question, the operands are String objects. Also, the String reference s1 is deallocated from the String object with memory address @7356. This means reference s1 is no longer referring to String object with memory address @7356 and is now is pointing to the new String object with memory address &9364. Following the execution of line 5, a pseudocode description outlining the current state of the String objects in memory is outlined below: s2🠆 Object String(Memory Address @7356) { "abc" } s1 🠆 Object String(Memory Address &9364) { "abcd" } In the above pseudocode description we can see the new String object at memory address &9364 with its String reference s1. Also note above that the first String object with memory address @7356 still has a String reference pointing to it, namely s2. =======4======= 1: public class A { 2: public static void main(String[] args) { 3: String s1 = "abc"; 4: String s2 = s1; 5: s1 += "d"; 6: System.out.println(s1 + " " + s2 + " " + (s1 == s2)); 7: StringBuilder sb1 = new StringBuilder("abc"); 8: StringBuilder sb2 = sb1; 9: sb1.append("d"); 10: System.out.println(sb1 + " " + sb2 + " " + (sb1==sb2)); 11: }} On the line 6, the contents of the String object referenced by s1 and s2 are printed to the screen. From looking at the pseudocode description above, we can see that s1 refers to the String object at memory address &9364 which contains the string value "abcd". Also, s2 refers to the String object at memory address @7356 which contains the string value "abc". Therefore the current print stream on line 6 would look like: System.out.println("abcd" + " " + "abc" + " " + (s1 == s2)); =======5======= 1: public class A { 2: public static void main(String[] args) { 3: String s1 = "abc"; 4: String s2 = s1; 5: s1 += "d"; 6: System.out.println(s1 + " " + s2 + " " + (s1 == s2)); 7: StringBuilder sb1 = new StringBuilder("abc"); 8: StringBuilder sb2 = sb1; 9: sb1.append("d"); 10: System.out.println(sb1 + " " + sb2 + " " + (sb1==sb2)); 11: }} On the line 6, the memory address of the String object that is referred to by s1 is compared to see if it is equal to the memory address of the String object that is referred to by s2. As s1 is referring to String object with address &9364 and s2 is referring to String object with address @7356 then the resultant is false Therefore the output on the line 6, after it executes is: abcd abc false =======6======= 1: public class A { 2: public static void main(String[] args) { 3: String s1 = "abc"; 4: String s2 = s1; 5: s1 += "d"; 6: System.out.println(s1 + " " + s2 + " " + (s1 == s2)); 7: StringBuilder sb1 = new StringBuilder("abc"); 8: StringBuilder sb2 = sb1; 9: sb1.append("d"); 10: System.out.println(sb1 + " " + sb2 + " " + (sb1==sb2)); 11: }} On the line 7, a new StringBuilder object is created with reference sb1. Following the execution of line 7, a pseudocode depiction of the current objects stored in memory, along with this new StringBuilder object with address @0989 is outlined below: s2🠆 Object String(Memory Address @7356) { "abc" } s1 🠆 Object String(Memory Address &9364) { "abcd" } sb1 🠆 Object StringBuilder(Memory Address @0989) { "abc" } =======7======= 1: public class A { 2: public static void main(String[] args) { 3: String s1 = "abc"; 4: String s2 = s1; 5: s1 += "d"; 6: System.out.println(s1 + " " + s2 + " " + (s1 == s2)); 7: StringBuilder sb1 = new StringBuilder("abc"); 8: StringBuilder sb2 = sb1; 9: sb1.append("d"); 10: System.out.println(sb1 + " " + sb2 + " " + (sb1==sb2)); 11: }} On the line 8, a new StringBuilder reference named sb2 is created and is pointing to (assigned) the same object that StringBuilder reference sb1 is pointing to i.e. the StringBuilder object with heap memory address: @0989. Following the execution of line 8, a pseudocode depiction of the current objects stored in memory is outlined below: s2🠆 Object String(Memory Address @7356) { "abc" } s1 🠆 Object String(Memory Address &9364) { "abcd" } sb2🠆sb1 🠆 Object StringBuilder(Memory Address @0989) { "abc" } As you can see above, StringBuilder with memory address @0989 has two references, namely, sb2 and sb1. =======8======= 1: public class A { 2: public static void main(String[] args) { 3: String s1 = "abc"; 4: String s2 = s1; 5: s1 += "d"; 6: System.out.println(s1 + " " + s2 + " " + (s1 == s2)); 7: StringBuilder sb1 = new StringBuilder("abc"); 8: StringBuilder sb2 = sb1; 9: sb1.append("d"); 10: System.out.println(sb1 + " " + sb2 + " " + (sb1==sb2)); 11: }} On the line 9, the String object "d" is appended to the StringBuilder object referenced by sb1 i.e. StringBuilder object with memory address @0989. As StringBuilder objects are mutable (editable), the contents of the StringBuilder object at memory address @0989 gets changed to the following which the 'd' appended: "abcd". Following the execution of line 9, a pseudocode depiction of the current objects stored in memory is outlined below: s2🠆 Object String(Memory Address @7356) { "abc" } s1 🠆 Object String(Memory Address &9364) { "abcd" } sb2🠆sb1 🠆 Object StringBuilder(Memory Address @0989) { "abcd" } =======9======= 1: public class A { 2: public static void main(String[] args) { 3: String s1 = "abc"; 4: String s2 = s1; 5: s1 += "d"; 6: System.out.println(s1 + " " + s2 + " " + (s1 == s2)); 7: StringBuilder sb1 = new StringBuilder("abc"); 8: StringBuilder sb2 = sb1; 9: sb1.append("d"); 10: System.out.println(sb1 + " " + sb2 + " " + (sb1==sb2)); 11: }} On the line 10, the contents of the StringBuilder object referred to by sb1 and sb2 get appended to the String in the parameters of the System.out.println() method. Looking at the pseudocode description above, we can see that the StringBuilder references sb1 and sb2 are pointing to the same StringBuilder object with memory address @0989. Therefore, when the call is made to sb1, an implicit call to StringBuilder toString() is made which appends "abcd" onto the String parameters of the System.out.println() method. i.e. System.out.println("abcd" + " " + sb2 + " " + (sb1==sb2)); Likewise, when a call is made to sb2, an implicit call to StringBuilder toString() is made which appends "abcd" onto the String parameters of the System.out.println() method: System.out.println("abcd" + " " + "abcd"+ " " + (sb1==sb2)); Current objects stored in memory is outlined below: s2🠆 Object String(Memory Address @7356) { "abc" } s1 🠆 Object String(Memory Address &9364) { "abcd" } sb2🠆sb1 🠆 Object StringBuilder(Memory Address @0989) { "abcd" } =======10====== 1: public class A { 2: public static void main(String[] args) { 3: String s1 = "abc"; 4: String s2 = s1; 5: s1 += "d"; 6: System.out.println(s1 + " " + s2 + " " + (s1 == s2)); 7: StringBuilder sb1 = new StringBuilder("abc"); 8: StringBuilder sb2 = sb1; 9: sb1.append("d"); 10: System.out.println(sb1 + " " + sb2 + " " + (sb1 ==sb2)); 11: }} Continuing on the line in 10, the expression sb1 ==sb2 gets executed which essentially gets the memory address of the StringBuilder object referred to by sb1 and gets the address of the StringBuilder object referred to by sb2. A comparison is then made to see if the memory addresses of sb1 and sb2 are equal and if they are, the expression resolves to true. Looking at the pseudocode description below, we can see that StringBuilder references sb1 and sb2 are pointing to the same StringBuilder object in memory, therefore the expression sb1 ==sb2 will be resolve to true: s2🠆 Object String(Memory Address @7356) { "abc" } s1 🠆 Object String(Memory Address &9364) { "abcd" } sb2🠆sb1 🠆 Object StringBuilder(Memory Address @0989) { "abcd" } Therefore the final output from line 10 will be: abcd abcd true In summary, the total output of the program will be: abcd abc false abcd abcd true Note: To make Java more memory efficient, the Java Virtual Machine sets aside a special area of memory called the String Constant Pool. When the compiler encounters a String literal (e.g. "Hello"), it checks the pool to see if the same identical String literal already exists. If a match is found, the reference to the new literal is directed to the existing String, and no new String literal object is created. This is why string objects are immutable i.e. they cannot be changed and are final constants. The key concept for you to understand is that once a String object is created, it can never be changed.

Given: public class A { public static void main(String[] args) { String s1 = "Pop"; s1 = s1.concat(" Eye"); System.out.println(s1); }} What is the result? a) Compiler error b) Compile and print: Pop Pop Eye c) Compile and print: Pop Eye d) None of the answers are correct

c) is correct. The program compiles and prints: Pop Eye The following explains the code in further details: ===Code Step Through=== public class A { public static void main(String[] args) { String s1 = "Pop"; s1 = s1.concat(" Eye"); System.out.println(s1); }} An object string "Pop" is created and located on the heap. There is one reference to the object i.e. s1 s1 🠚 "Pop" =========2=========== public class A { public static void main(String[] args) { String s1 = "Pop"; s1 = s1.concat(" Eye"); System.out.println(s1); }} Rememeber: String objects are immutable - they cannot be changed. s1.concat(" Eye"); String object " Eye" is appended (concatinated) to a copy of "Pop" This new object contains "Pop Eye". This is completely seperate to the other string object "Pop" which was referenced by s1 and is no longer referenced (i.e. null represented by the character Ø). Ø 🠚"Pop" s1 🠚 "Pop Eye" Above, there are two objects. The object s1 has dereferenced "Pop" object and references (points to) the object "Pop" instead. As a consequence the other object "Pop" which is now represented by the character Ø, has no reference to it and is available for garbage collection. =========3========== public class A { public static void main(String[] args) { String s1 = "Pop"; s1.concat(" Eye"); System.out.println(s1); }} Ø 🠚"Pop" s1 🠚 "Pop Eye" The output is the object referenced by s1 i.e. "Pop Eye"

Given: import java.util.*; public class Baker { public static void main(String[] args) { ArrayList<String> steps = new ArrayList<String>(); steps.add("knead"); steps.add("oil pan"); steps.add("turn on oven"); steps.add("roll"); steps.add("turn on oven"); steps.add("bake"); System.out.println(steps); }} What is the result? (choose all that apply) a) [knead, oil pan, roll, turn on oven, bake] b) [knead, oil pan, turn on oven, roll, bake] c) [knead, oil pan, turn on oven, roll, turn on oven, bake] d) The output is unpredictable e) Compilation fails f) An exception is thrown at runtime

c) is correct. The program will compile and output: [knead, oil pan, turn on oven, roll, turn on oven, bake] ArrayLists can have duplicate entries. As you can see below, on line 7 and 9 have the same duplicate entry "turn on oven". 1: import java.util.*; 2: public class Baker { 3: public static void main(String[] args) { 4: ArrayList<String> steps = new ArrayList<String>(); 5: steps.add("knead"); 6: steps.add("oil pan"); 7: steps.add("turn on oven"); 8: steps.add("roll"); 9: steps.add("turn on oven"); 10: steps.add("bake"); 11: System.out.println(steps); 12: }} Note: HashMap data structure does not allow duplicate keys but allows duplicate values: Even though HashMap is somewhat likely to be on the OCP exam, not the OCA exam, you'll find below an example: 1: import java.util.*; 2: public class Baker { 3: public static void main(String[] args) { 4: HashMap<Integer,String> steps = new HashMap<>(); 5: steps.put(1,"knead"); 6: steps.put(2,"oil pan"); 7: steps.put(3,"turn on oven"); 8: steps.put(4,"roll"); 9: steps.put(3,"turn on oven"); 10: steps.put(6,"bake"); 11: System.out.println(steps); 12: }} The above outputs the following non-duplicate values with the second "turn on oven" not included: {1=knead, 2=oil pan, 3=turn on oven, 4=roll, 6=bake}

Given: StringBuilder h4 = new StringBuilder("Hello"); h4.delete(4, 5); System.out.println(h4); What is the result? a) Compiler error b) Runtime error c) Compile and print "Hell" d) None of the answers are correct

c) is correct. The program will compile and print "Hell" Inside the program we can see the method in action: StringBuilder h4 = new StringBuilder("Hello"); h4.delete(4, 5); System.out.println(h4); The output: "Hell" =============2================ StringBuilder h4 = new StringBuilder("Hello"); h4.delete(4, 5); System.out.println(h4); StringBuilder ref h4 is pointing to a newly created StringBuilder object containing string literal "Hello" h4 🠚"Hello" ==============3============== StringBuilder h4 = new StringBuilder("Hello"); h4.delete(4, 5); System.out.println(h4); The above delete() method deletes the character literals at at start index 4 and ending at index 5-1. Old chars: Index 0 = H Index 1 = e Index 2 = l Index 3 = l Index 4 = deleted New chars: Index 0 = H Index 1 = e Index 2 = l Index 3 = l The output is: "Hell"

Given: public class A { public static void main(String[] args) { String s = "MINI"; System.out.println(s.length()); System.out.println(s.substring(1)); System.out.println(s.substring(0,2)); }} What is the result? a) Compiler Error b) Compile and print: 4 INI MIN c) Compile and print: 4 INI MI d) None of the answers are correct

c) is correct. The program will compile and print: 4 INI MI ===Code Step Through=== 1: public class A { 2: public static void main(String[] args) { 3: String s = "MINI"; 4: System.out.println(s.length()); 5: System.out.println(s.substring(1)); 6: System.out.println(s.substring(0,2)); 7: }} On the line 3, the new string object is created with reference named 's'. ================ 1: public class A { 2: public static void main(String[] args) { 3: String s = "MINI"; 4: System.out.println(s.length()); 5: System.out.println(s.substring(1)); 6: System.out.println(s.substring(0,2)); 7: }} On the line 4, the length of the string is printed to the screen i.e. 4 ================ 1: public class A { 2: public static void main(String[] args) { 3: String s = "MINI"; 4: System.out.println(s.length()); 5: System.out.println(s.substring(1)); 6: System.out.println(s.substring(0,2)); 7: }} On the line 5, a substring of the string "MINI" beginning at index 1 is printed to the screen i.e. INI An outline of the characters in the string and their indexes are outlined below: 'M' = index 0 'I' = index 1 'N' = index 2 'I' = index 3 In the above outline, the characters stored at index 1, 2 and 3 are printed to screen. ================ 1: public class A { 2: public static void main(String[] args) { 3: String s = "MINI"; 4: System.out.println(s.length()); 5: System.out.println(s.substring(1)); 6: System.out.println(s.substring(0,2)); 7: }} On the line 6, a substring of the string "MINI" beginning at index 0 and ending at index 1 (2-1) is printed to the screen i.e. "MI" An outline of the characters in the string and their indexes are outlined below: 'M' = index 0 'I' = index 1 'N' = index 2 'I' = index 3 In the above outline, the characters stored at index 0 and 1 are printed to screen. The resultant final output would be: 4 INI

Given: public class A { public static void main(String[] args) { String h1 = "Hello"; String h2 = h1.substring(3,5); System.out.println(h2); }} What is the result? a) Compiler error b) Runtime error c) Compile and print: "lo" d) None of the answers are correct

c) is correct. The program will compile and print: "lo" public class A { public static void main(String[] args) { String h1 = "Hello"; String h2 = h1.substring(3,5); System.out.println(h2); }} In the above code, substring(int startIndex, int endIndex): Returns a part of the string commencing at startIndex and finishing at the char stored at endIndex-1 h1.substring(3,5); The above returns the substring from startIndex (3) to the index the endIndex i.e. 5-1 (h1.substring(3,4)). Output is: "lo" Index 0 = H Index 1 = e Index 2 = l Index 3 = l 🠘 startIndex Index 4 = 0 🠘 endIndex Note: if the endindex was 6 (i.e. h1.substring(3,4)) it would output a runtime error. Namely: java.lang.StringIndexOutOfBoundsException

Given: public class A { public static void main(String[] args) { StringBuilder sb = new StringBuilder("Hello"); System.out.println(sb.delete(4, 4)); }} What is the result? a) Compiler error b) Runtime error c) Compile and print Hello d) None of the answers are correct

c) is correct. The program will not delete anything as end index (i.e. 4-1) 3 is less than the starting next 4. 1: public class A { 2: public static void main(String[] args) { 3: StringBuilder sb = new StringBuilder("Hello"); 4: System.out.println(sb.delete(4, 4)); 5: }} Therefore the output is the original StringBuilder object: "Hello"

What is the name of the special area of memory used to store strings? a) StringBuilder Constant Pool b) Character Constant Pool c) String Constant Pool d) None of the answers are correct

c) is correct. The special area of memory used to store strings is called the String Constant Pool. To make Java more memory efficient - the JVM (Java virtual machine) sets aside a special area of memory called the String Constant Pool. When the compiler encounters a String literal - it checks the pool to see if an identical String already exists. If a match is found - the reference to the new literal is pointed to the existing String and no new String literal is created. The existing String literal simply has an additional reference. e.g. String s1 = "Hello"; String s2 = "Hello"; Below explains how the above String objects are stored in memory: ====Code Step Through==== String s1 = "Hello"; String s2 = "Hello"; String literal "Hello" as an object that is stored in the Java String Pool and has one String reference pointing to it. s1 🠚 "Hello" ==========2========== String s1 = "Hello"; String s2 = "Hello"; A new String reference is created. The JVM checks the String Pool to identify if the exact same String literal already exists. In this case the String literal "Hello" does exist in the pool and therefore the String reference s2 is pointed to "Hello": s1 🠚 "Hello" 🠘 s2 Therefore there are two references (s1 and s2) to this string literal. This is for the purposes of efficient memory management.

Given: import java.util.ArrayList; import java.util.List; public class A { public static void main(String args[]) { List<String> list = new ArrayList<String>(2); System.out.println(list.size()); } } What is the result? a) Compiler error b) Compile and print 2 c) Compile and print 0 d) None of the answers are correct

c) is correct. import java.util.ArrayList; import java.util.List; public class A { public static void main(String args[]) { List<String> list = new ArrayList<String>(2); System.out.println(list.size()); } } As stated, the program will compile and print: 0 As there are zero elements added to the list, zero is outputted to the screen. Note: Method size() returns the number of elements in the list.

Given: public class A { public static void main(String[] args) { StringBuilder sb = new StringBuilder("Hello"); System.out.println(sb.insert(5, " World")); }} What is the result? a) Compiler error b) Runtime error c) Compile and print "Hello World" d) None of the answers are correct

c) is correct. public class A { public static void main(String[] args) { StringBuilder sb = new StringBuilder("Hello"); System.out.println(sb.insert(5, " World")); }} The compiler will insert the string " World" at index 5, where index 5 is at the end of the string "Hello". Index: 0-1-2-3-4 String: H-e-l-l-o In the above: Index 0 contains "H". Index 1 contains "e". etc. Note: following would give a java.lang.StringIndexOutOfBoundsException public class A { public static void main(String[] args) { StringBuilder sb = new StringBuilder("Hello"); System.out.println(sb.insert(6, " World")); }} This is because 6 index is outside of the bounds of the StringBuilder object containing "Hello"

Given: 1: public class A { 2: public static void main(String[] args) { 3: int [ ] [ ] a = { {1,2}, {3,4}}; 4: int [ ] b = (int[ ]) a[1] ; 5: Object o1 = a; 6: int [ ][ ] a2 = (int [ ][ ]) o1; 7: int [ ] b2 = (int[ ] ) o1; 8: System.out.println(b[1] ) ; 9: }} What is the result? a) It prints: 2 b) It prints: 4 c) An exception is thrown at runtime d) Compilation fails due to an error on line 4 e) Compilation fails due to an error on line 5 f) Compilation fails due to an error on line 6 g) Compilation fails due to an error on line 7

c) is correct. An exception is thrown at runtime. A ClassCastException is thrown at line 7 because o1 refers to a two-dimensional array (int[ ][ ]) not a one-dimensional array (int[ ]). if line 7 were removed, the output would be 4. Let's step through the code: ===Code Step Through=== 1: public class A { 2: public static void main(String[] args) { 3: int [ ] [ ] a = { {1,2}, {3,4}}; 4: int [] b = (int[ ]) a[1] ; 5: Object o1 = a; 6: int [ ][ ] a2 = (int [][]) o1; 7: int [ ] b2 = (int[] ) o1; 8: System.out.println(b[1] ) ; 9: }} On line 3, a two dimensional array is declared with the following elements stored in distinct addresses: a[ 0 ][ 0 ] = 1 a[ 0 ][ 1 ] = 2 a[ 1 ][ 0 ] = 3 a[ 1 ][ 1 ] = 4 In essence, a two dimensional array is comprised of two singular arrays: a[ 0 ] = {1,2} a[ 1 ] = {3,4} All objects, when created in memory, have unique memory addresses in the Heap and arrays are objects. A pseudocode depiction of the 2D array 'a' object currently in heap memory is outlined below: ===Memory Snapshot=== [ ][ ]a 🠆 Object 2D Array( Heap Address &2313) { a[ 0 ] 🠢 {1,2}, a[ 1 ] 🠢 {3,4} } As you can see from the above depiction, there is a two-dimensional reference named 'a' to this array object and its pointing to the unique address of the 2D array, namely: &2313. There are also two one-dimensional references which can access the two one-dimensional arrays within the 2D array i.e. a[ 0 ] 🠢 {1,2}, a[ 1 ] 🠢 {3,4} =======2======= 1: public class A { 2: public static void main(String[] args) { 3: int [ ] [ ] a = { {1,2}, {3,4}}; 4: int [ ] b = (int[ ]) a[ 1 ] ; 5: Object o1 = a; 6: int [ ][ ] a2 = (int [ ][ ]) o1; 7: int [ ] b2 = (int[] ) o1; 8: System.out.println(b[ 1 ] ) ; 9: }} On the line 4, the array, located at index a[ 1 ], is pointed to by a new additional reference declared 'b'. The new references is pointing to the actual Heap address (&2313) where the original array is stored. This is very important to understand. This means that there are now two references to the said array {3,4} inside the 2D array 'a'. Namely, a[ 1 ] and b[ ]. A pseudocode depiction of the array objects currently in heap memory is outlined below: ===Memory Snapshot=== [ ][ ]a 🠆 Object 2D Array( Heap Address &2313) { a[ 0 ] 🠢 {1,2}, b[ ] 🠢 a[ 1 ] 🠢 {3,4} } =======3======= 1: public class A { 2: public static void main(String[] args) { 3: int [] [] a = { {1,2}, {3,4}}; 4: int [] b = (int[]) a[1] ; 5: Object o1 = a; 6: int [][] a2 = (int [][]) o1; 7: int [] b2 = (int[] ) o1; 8: System.out.println(b[1] ) ; 9: }} On the line 5, a new additional reference of type Object is referring to the two-dimensional array that is pointed to by 'a'. As Object is the mother of all objects, they can refer to any type of object. This means there are now two references to the two-dimensional array containing { {1,2}, {3,4} }. Namely, reference 'a' and 'o1'. This 2D array has a Heap memory address &2313. A pseudocode depiction of the array objects currently in heap memory is outlined below: ===Memory Snapshot=== o1 🠆 [ ][ ]a 🠆 Object 2D Array( Heap Address &2313) { a[ 0 ] 🠢 {1,2}, b[ ] 🠢 a[ 1 ] 🠢 {3,4} } =======4======= 1: public class A { 2: public static void main(String[] args) { 3: int [] [] a = { {1,2}, {3,4}}; 4: int [] b = (int[]) a[1] ; 5: Object o1 = a; 6: int [][] a2 = (int [][]) o1; 7: int [] b2 = (int[] ) o1; 8: System.out.println(b[1] ) ; 9: }} On the line 6, reference 'o1' is cast to a two-dimensional array. Then a new additional 2D reference named 'a2' is referred to the same two-dimensional array as 'o1' is pointing to, namely, 2D array with heap memory &2313. Note: 2D reference named 'a' is also pointing to the same object in heap memory. A pseudocode depiction of the array objects currently in heap memory is outlined below: ===Memory Snapshot=== [ ] [ ] a2 🠆 o1 🠆 [ ][ ]a 🠆 Object 2D Array( Heap Address &2313) { a[ 0 ] 🠢 {1,2}, b[ ] 🠢 a[ 1 ] 🠢 {3,4} } =======5======= 1: public class A { 2: public static void main(String[] args) { 3: int [] [] a = { {1,2}, {3,4}}; 4: int [] b = (int[]) a[1] ; 5: Object o1 = a; 6: int [][] a2 = (int [ ][ ]) o1; 7: int [] b2 = (int[ ]) o1; 8: System.out.println(b[1] ) ; 9: }} On the line 7, reference 'o1' is cast to a one-dimensional array. However, 'o1' is referring to a 2D array and not a 1D array. Therefore, the compiler throws a: ClassCastException

Given: public class A { public static void main(String[] args){ byte[ ] [ ] ba = {{1,2,3,4}, {1,2,3} }; System.out.println(ba[1].length+" "+ba.length); }} What is the result? a) 2 4 b) 2 7 c) 3 2 d) 3 7 e) 4 2 f) 4 7 g) Compilation fails

c) is correct. A two-dimensional array (2D) is an array comprised of two one-dimensional arrays. The length of the 2D array referenced by 'ba' is 2 because it contains 2 one-dimensional arrays. Array indexes are zero-based, so ba[ 1 ] refers to ba's second array. Arrays, or indeed variables, of primitive type byte can store int values. ===Code Step Through=== 1: public class A { 2: public static void main(String[] args){ 3: byte[ ] [ ] ba = {{1,2,3,4}, {1,2,3} }; 4: System.out.println(ba[1].length+" "+ba.length); 5: }} On the line 3, a two-dimensional array of type byte is created containing two one-dimensional arrays. The first one-dimensional array {1,2,3,4} in this two-dimensional array is referred to by ba[ 0 ]: ba[ 0 ] = {1,2,3,4} The second one-dimensional array {1,2,3} in this two-dimensional array is referred to by ba[ 1 ] i.e. ba[ 1 ] = {1,2,3} Looking at the two-dimensional array again If you wish to access '1' highlighted in bold below: byte[ ] [ ] ba = {{1,2,3,4}, {1,2,3} }; You would call: ba[ 0 ][ 0 ] If you wish to access 2 highlighted in bold below: byte[ ] [ ] ba = {{1,2,3,4}, {1,2,3} }; You would call: ba[ 0 ][ 1 ] To access any of the elements within this two-dimensional array 'ba' you would use the following 2D array 'address calls': ba[ 0 ][ 0 ] = 1 ba[ 0 ][ 1 ] = 2 ba[ 0 ][ 1 ] = 3 ba[ 0 ][ 2 ] = 4 ba[ 1 ][ 0 ] = 1 ba[ 1 ][ 1 ] = 2 ba[ 1 ][ 2 ] = 3 =======2======= 1: public class A { 2: public static void main(String[] args){ 3: byte[ ] [ ] ba = {{1,2,3,4}, {1,2,3} }; 4: System.out.println(ba[ 1 ].length+" "+ba.length); 5: }} On the line 4, ba[ 1 ].length retrieves the length of the second one-dimensional array of the 2D array 'ba'. As the total number of elements in the second 1D array is 3, this equates to the length of the said array and as a consequence, 3 is what gets printed. =======3======= 1: public class A { 2: public static void main(String[] args){ 3: byte[ ] [ ] ba = {{1,2,3,4}, {1,2,3} }; 4: System.out.println(ba[1].length+" "+ba.length); 5: }} On the line 4, ba.length retrieves the length of the 2D array 'ba' i.e. ba.length retrieves the total number of 1D arrays that comprise of the 2D array 'ba'. As the total number of elements (1D arrays) in the 2D array is 2, this equates to the length of the said array and as a consequence, 2 is what gets printed. Final output: 3 2

Which of the following are not methods of the String class? a) substring(int startIndex) b) trim() c) charAt() d) size() e) reverse()

d) and e) are correct. The methods size() and reverse() are not methods within the String class. It is important to be familiar with core methods of the String class. The following is an abbreviation to help remember methods: LCCSSTR • length() • concat() • charAt() • substring(int startindex) • substring(int startindex, int endIndex) • trim() • replace() ➤ length(): Returns the number of characters in a string e.g. String h = "Hello"; int len = h.length(); System.out.println(len); The above outputs 5. ➤ concat(): Appends one string to the end of another (+ also works). e.g. String h1 = "Hello"; String h2 = h1.concat(" there"); System.out.println(h2); The above returns a new string joined together with the output "Hello there" ➤ charAt(): Returns the character located at the specified index E.g. String h1 = "Hello"; System.out.println(h1.charAt(0)); The above returns the character located at index 0 that is H. Index 0 = H Index 1 = e Index 2 = l Index 3 = l Index 4 = 0 Total number of chars in this String is: 5 ➤ substring(int startIndex): Returns a part of the string commencing at startIndex E.g. String h1 = "Hello"; String h2 = h1.substring(3); System.out.println(h2); The above returns part of the string literal "Hello" starting at the index 3 to the last char value: Index 0 = H Index 1 = e Index 2 = l Index 3 = l Index 4 = 0 🠄 last char The output is: "lo" ➤ substring(int startIndex, int endIndex): Returns a part of the string commencing at startIndex and finishing at the char stored at endIndex-1 e.g. String h1 = "Hello"; String h2 = h1.substring(3,4); System.out.println(h2); The above returns part of the string literal "Hello" starting at the index 3 to the char value stored at index 4-1 (i.e. 3): Index 0 = H Index 1 = e Index 2 = l Index 3 = l Index 4 = 0 The output is: "l" ➤ trim(): Removes whitespace from both ends of the string E.g. String h1 = " Hello "; String h2 = h1.trim(); System.out.println(h2); The above will remove the whitespace (empty space) on both ends of h1 from " Hello " to "Hello" Output is: "Hello" ➤ replace(char oldChar, char newChar): Returns a String resulting from replacing all occurrences of oldChar in this string with newChar. e.g. String h1 = " Hello "; String h2 = h1.replace("l", "f"); System.out.println(h2); Tha above would output: Heffo Old chars: Index 0 = H Index 1 = e Index 2 = l Index 3 = l Index 4 = 0 New chars: Index 0 = H Index 1 = e Index 2 = f Index 3 = f Index 4 = 0 If the character oldChar does not occur in the character sequence represented by this String object, then a reference to this String object is returned. Also h1.replace('l', 'f'); would also work. Note: As stated, it would be advisable to remember the core methods of the String class. In the exam you may come across questions which test your knowledge of whether or not a method is contained within the String class.

Given: 1: public class A { 2: public static void main (String [ ] args) { 3: Dozens [ ] da = new Dozens[3] ; 4: da[0] = new Dozens(); 5: Dozens d = new Dozens(); 6: da[1] = d; d = null; 7: da[1] = null; 8: // do stuff 9: }} 10: class Dozens { 11: int [ ] dz = {1,2,3,4,5,6,7,8,9,10,11,12}; 12: } Which two are true about the objects created within main(), and which are eligible for garbage collection (GC) when line 8 is reached? a) Three objects were created b) Four objects were created c) Five objects were created d) Zero objects are eligible for GC e) One object is eligible for GC f) Two objects are eligible for GC

d) and f) are correct. • Five objects were created • Two objects are eligible for Garbage Collection 'da' refers to an object of type "Dozens array" and each Dozens object that is created comes with its own "int array" object. When line 8 is reached, only the second Dozens object (and its internal int array object) are not reachable and therefore available for garbage collection. ===Code Step Through=== 1: public class A { 2: public static void main (String [ ] args) { 3: Dozens [ ] da = new Dozens[3]; 4: da[0] = new Dozens(); 5: Dozens d = new Dozens(); 6: da[1] = d; d = null; 7: da[1] = null; 8: // do stuff 9: }} 10: class Dozens { 11: int [ ] dz = {1,2,3,4,5,6,7,8,9,10,11,12}; 12: } On the line 3, an array of type Dozens is created. All arrays and objects are stored in heap memory. A pseudocode depiction of the array object is outlined below with its own unique memory address: Current object stored in memory: da 🠆 Object [ ] Dozens(Heap Address &221) { da[0] 🠢 null da[1] 🠢 null da[2] 🠢 null } ========2======== 1: public class A { 2: public static void main (String [ ] args) { 3: Dozens [ ] da = new Dozens[3] ; 4: da[0] = new Dozens(); 5: Dozens d = new Dozens(); 6: da[1] = d; d = null; 7: da[1] = null; 8: // do stuff 9: }} 10: class Dozens { 11: int [ ] dz = {1,2,3,4,5,6,7,8,9,10,11,12}; 12: } On the line 4, a new object of type Dozens is created and is placed at address 0 in the Dozens array 'da'. Current objects stored in memory: da 🠆 Object [ ] Dozens(Heap Address &221) { da[0] 🠢 Object Dozens(Heap Address &4327) { [ ] dz 🠢 Object int(Heap Address &6295) { dz[0] = 1; dz[1] = 2; dz[2] = 3; dz[3] = 4; .................. dz[11] = 12; } } da[1] 🠢 null da[2] 🠢 null } From the above pseudocode description, we can see now that there are three objects created with separate and unique addresses in heap memory: ➤ Dozens array object with reference da and unique heap address &221. ➤ Inside the Dozens object object with reference da, we have an object referenced by da[0] with unique heap address &4327. ➤ Nested inside the object referenced by da[0], we have an int array object referenced by dz with unique heap address &6295. ========3======== 1: public class A { 2: public static void main (String [ ] args) { 3: Dozens [ ] da = new Dozens[3] ; 4: da[0] = new Dozens(); 5: Dozens d = new Dozens(); 6: da[1] = d; d = null; 7: da[1] = null; 8: // do stuff 9: }} 10: class Dozens { 11: int [ ] dz = {1,2,3,4,5,6,7,8,9,10,11,12}; 12: } On the line 5, another object is created of type Dozens and with reference 'd'. The current snapshot of objects in heap memory now looks like: da 🠆 Object[ ] Dozens(Heap Address &221) { da[0] 🠢 Object Dozens(Heap Address &4327) { [ ] dz 🠢 Object int(Heap Address &6295) { dz[0] = 1; dz[1] = 2; dz[2] = 3; dz[3] = 4; .................. dz[11] = 12; } } da[1] 🠢 null da[2] 🠢 null } d 🠆 Object Dozens(Heap Address &5543) { [ ] dz 🠢 Object int(Heap Address &4356) { dz[0] = 1; dz[1] = 2; dz[2] = 3; dz[3] = 4; .................. dz[11] = 12; } } From looking at the above pseudocode we can see there are now five objects created in memory with separate heap memory addresses. ➤ Dozens array object with reference da and unique heap address &221. ➤ A Dozens object referenced by da[0] with unique heap address &4327. ➤ An int array object referenced by dz with unique heap address &6295. ➤ A new Dozens object referenced by d with unique heap address &5543. ➤ An int array object referenced by dz with unique heap address &4356. ========4======== 1: public class A { 2: public static void main (String [ ] args) { 3: Dozens [ ] da = new Dozens[3]; 4: da[0] = new Dozens(); 5: Dozens d = new Dozens(); 6: da[1] = d; d = null; 7: da[1] = null; 8: // do stuff 9: }} 10: class Dozens { 11: int [ ] dz = {1,2,3,4,5,6,7,8,9,10,11,12}; 12: } On the line 6, object Dozens with reference da[ 1 ] is pointing to the same object that object Dozens with reference 'd' is pointing to. The current snapshot of objects in heap memory now looks like: da 🠆 Object [ ] Dozens(Heap Address &221) { da[0] 🠢 Object Dozens(Heap Address &4327) { [ ] dz 🠢 Object int(Heap Address &6295) { dz[0] = 1; dz[1] = 2; dz[2] = 3; dz[3] = 4; .................. dz[11] = 12; } } da[1] 🠢 d da[2] 🠢 null } da[1] 🠢 d 🠆 Object Dozens(Heap Address &5543) { [ ] dz 🠢 Object int(Heap Address &4356) { dz[0] = 1; dz[1] = 2; dz[2] = 3; dz[3] = 4; .................. dz[11] = 12; } } Note: In the above pseudocode description, we still have five objects with unique addresses in heap memory. Namely: ➤ Reference da with heap address &221. ➤ Reference da[0] with heap address &4327. ➤ Nested reference dz with heap address &6295. ➤ Reference d with heap address &5543. ➤ Nested reference dz with heap address &5543. ========5======== 1: public class A { 2: public static void main (String [ ] args) { 3: Dozens [ ] da = new Dozens[3]; 4: da[0] = new Dozens(); 5: Dozens d = new Dozens(); 6: da[1] = d; d = null; 7: da[1] = null; 8: // do stuff 9: }} 10: class Dozens { 11: int [ ] dz = {1,2,3,4,5,6,7,8,9,10,11,12}; 12: } On the line 6, object reference d is no longer pointing to the object heap address &5543 and instead is pointing to null. All other references to the object Dozens with heap address &5543 are unchanged, namely, reference da[1]. The current snapshot of objects in heap memory now looks like: da 🠆 Object[ ] Dozens(Heap Address &221) { da[0] 🠢 Object Dozens(Heap Address &4327) { [ ] dz 🠢 Object int(Heap Address &6295) { dz[0] = 1; dz[1] = 2; dz[2] = 3; dz[3] = 4; .................. dz[11] = 12; } } da[1] 🠢 d da[2] 🠢 null } da[1] 🠢 Object Dozens(Heap Address &5543) { [ ] dz 🠢 Object int(Heap Address &4356) { dz[0] = 1; dz[1] = 2; dz[2] = 3; dz[3] = 4; .................. dz[11] = 12; } } d 🠆 null ========6======== 1: public class A { 2: public static void main (String [ ] args) { 3: Dozens [ ] da = new Dozens[3]; 4: da[0] = new Dozens(); 5: Dozens d = new Dozens(); 6: da[1] = d; d = null; 7: da[1] = null; 8: // do stuff 9: }} 10: class Dozens { 11: int [ ] dz = {1,2,3,4,5,6,7,8,9,10,11,12}; 12: } On the line 7, object reference da[1] is no longer pointing to the object heap address &5543 and instead is pointing to null. The current snapshot of objects in heap memory now looks like: da 🠆 Object[ ] Dozens(Heap Address &221) { da[0] 🠢 Object Dozens(Heap Address &4327) { [ ] dz 🠢 Object int(Heap Address &6295) { dz[0] = 1; dz[1] = 2; dz[2] = 3; dz[3] = 4; .................. dz[11] = 12; } } da[1] 🠢 null da[2] 🠢 null } Object Dozens(Heap Address &5543) { [ ] dz 🠢 Object int(Heap Address &4356) { dz[0] = 1; dz[1] = 2; dz[2] = 3; dz[3] = 4; .................. dz[11] = 12; } } d 🠆 null ========7======== 1: public class A { 2: public static void main (String [ ] args) { 3: Dozens [ ] da = new Dozens[3] ; 4: da[0] = new Dozens(); 5: Dozens d = new Dozens(); 6: da[1] = d; d = null; 7: da[1] = null; 8: // do stuff 9: }} 10: class Dozens { 11: int [ ] dz = {1,2,3,4,5,6,7,8,9,10,11,12}; 12: } When we reach the line 8 the pseudocode of objects in memory will look like this: da 🠆 Object[ ] Dozens(Heap Address &221) { da[0] 🠢 Object Dozens(Heap Address &4327) { [ ] dz 🠢 Object int(Heap Address &6295) { dz[0] = 1; dz[1] = 2; dz[2] = 3; dz[3] = 4; .................. dz[11] = 12; } } da[1] 🠢 null da[2] 🠢 null } Object Dozens(Heap Address &5543) { [ ] dz 🠢 Object int(Heap Address &4356) { dz[0] = 1; dz[1] = 2; dz[2] = 3; dz[3] = 4; .................. dz[11] = 12; } } d 🠆 null In the above pseudocode description of objects, we can see two objects are available for garbage collection: ➤ The object of type Dozens with heap address &5543. ➤ The internal nested array object with heap address &4356. Note: With questions of such nature it's imperative that you have your nonpermanent pen and paper ready to sketch out the objects in memory as you go through each line of the code. I'd recommend that you laminate a square box page, have a nonpermanent marker and also some alcohol ready to wipe out rough work as you practice exam questions. You will not be allowed to bring anything to the exam as everything will be provided.

Given: import java.util.ArrayList; import java.util.List; public class A { public static void main(String args[]) { List<String> list = new ArrayList<String>(2); list.add("Hi"); list.add("Lo"); System.out.println(list.subList(1, 1)); }} What is the result? a) Compiler error b) Runtime error c) Compile and print [Lo] d) None of the answers are correct

d) is correct The program will compile and print [ ]. Let's go through the code to explain how this works: ===Code Step Through=== 1: import java.util.ArrayList; 2: import java.util.List; 3: 4: public class A { 5: public static void main(String args[]) 6: { 7: List<String> list = new ArrayList<String>(2); 8: list.add("Hi"); 9: list.add("Lo"); 10: System.out.println(list.subList(1, 1)); 11: } 12: } On the line 7, a new ArrayList object is created which will contain only objects of type String. Its initial size is 2. An ArrayList is a re-sizable array, also called a dynamic array. It grows its size to accommodate new elements and shrinks the size when the elements are removed. The above ArrayList object instance is referred to by a List reference. List is an interface and ArrayList implements List. ========2======== 1: import java.util.ArrayList; 2: import java.util.List; 3: 4: public class A { 5: public static void main(String args[]) 6: { 7: List<String> list = new ArrayList<String>(2); 8: list.add("Hi"); 9: list.add("Lo"); 10: System.out.println(list.subList(1, 1)); 11: } 12: } On the line 8 and 9, the two String objects, named are added to the ArrayList. Therefore, the ArrayList grows in size by two. ========3======== 1: import java.util.ArrayList; 2: import java.util.List; 3: 4: public class A { 5: public static void main(String args[]) 6: { 7: List<String> list = new ArrayList<String>(2); 8: list.add("Hi"); 9: list.add("Lo"); 10: System.out.println(list.subList(1, 1)); 11: } 12: } On the line 10, a sublist of the 'list' is created at starting index 1 and ending a index 1-1 (i.e. subList(1, 0)). This means that the substring(1, 0) has a starting index (1) which is after the ending index (0) which creates an empty substring. This results in [ ] printed to the screen.

Which of the following are true? a) All primitive types are passed to methods by value b) All primitive types and Strings are passed to methods by value c) All objects and Strings are passed to methods by value d) All references to objects and Strings are passed to methods by value

d) is correct. All references to objects and Strings are passed to methods by value. Pass by Value: The method parameter values are copied to another variable and then the copied object is passed, that's why it's called pass by value.

Given: import java.time.*; import java.time.format.*; public class A { public static void main(String[] args) { DateTimeFormatter f1 = DateTimeFormatter.ofPattern("MMM dd, yyyy"); LocalDate d = LocalDate.of(2018, Month.JANUARY, 15); LocalDate d2 = d.plusDays(1); System.out.print(f1.format(d) + " "); System.out.println(d2.format(f1)); }} What is the result? a) 2018-01-15 2018-01-15 b) 2018-01-15 2018-01-16 c) Jan 15, 2018 Jan 15, 2018 d) Jan 15, 2018 Jan 16, 2018 e) Compilation fails f) An exception is thrown at runtime

d) is correct. As stated, the program prints: Jan 15, 2018 Jan 16, 2018 Invoking the plusDays() method creates a new object, and both LocalDate and DateTimeFormatter have format() methods. ===Code Step Through=== 1: import java.time.*; 2: import java.time.format.*; 3: public class A { 4: public static void main(String[] args) { 5: DateTimeFormatter f1 = DateTimeFormatter.ofPattern("MMM dd, yyyy"); 7: LocalDate d = LocalDate.of(2018, Month.JANUARY, 15); 8: LocalDate d2 = d.plusDays(1); 9: System.out.print(f1.format(d) + " "); 10: System.out.println(d2.format(f1)); }} On the line 5, the DateTimeFormatter class is used to format date/time objects for output. It is also used to parse input strings and convert them to date/time objects. The following immutable classes use DateTimeFormatter: • java.time.LocalDateTime • java.time.LocalDate • java.time.LocalTime The ofPattern() method will create a formatter based on a simple pattern of letters and symbols as described in the class documentation. In the above code: DateTimeFormatter.ofPattern("MMM dd, yyyy"); will format: '15 January 2018' as 'Jan 15, 2018'. ========2======== 1: import java.time.*; 2: import java.time.format.*; 3: public class A { 4: public static void main(String[] args) { 5: DateTimeFormatter f1 = DateTimeFormatter.ofPattern("MMM dd, yyyy"); 7: LocalDate d = LocalDate .of(2018, Month.JANUARY, 15); 8: LocalDate d2 = d.plusDays(1); 9: System.out.print(f1.format(d) + " "); 10: System.out.println(d2.format(f1)); }} On the line 7, a LocalDate object is created for the date 15 January 2018. ========3======== 1: import java.time.*; 2: import java.time.format.*; 3: public class A { 4: public static void main(String[] args) { 5: DateTimeFormatter f1 = DateTimeFormatter.ofPattern("MMM dd, yyyy"); 7: LocalDate d = LocalDate .of(2018, Month.JANUARY, 15); 8: LocalDate d2 = d.plusDays(1); 9: System.out.print(f1.format(d) + " "); 10: System.out.println(d2.format(f1)); }} On the line 8, a new LocalDate object is created taking the LocalDate object referenced by d and adding 1 day to it. This creates a new LocalDate object (16 January 2018) which is referenced by LocalDate d2. ========4======== 1: import java.time.*; 2: import java.time.format.*; 3: public class A { 4: public static void main(String[] args) { 5: DateTimeFormatter f1 = DateTimeFormatter.ofPattern("MMM dd, yyyy"); 7: LocalDate d = LocalDate.of(2018, Month.JANUARY, 15); 8: LocalDate d2 = d.plusDays(1); 9: System.out.print(f1.format(d) + " "); 10: System.out.println(d2.format(f1)); }} On the line 9, the LocalDate object referenced by 'd' (which contains 2018, Month.JANUARY, 15) is formatted to the pattern "MMM dd, yyyy" (which was declared on line 5). This is undertaken using the DateTimeFormatter method format(). When line 9 is executed the following is outputted to the screen: Jan 15, 2018 ========5======== 1: import java.time.*; 2: import java.time.format.*; 3: public class A { 4: public static void main(String[] args) { 5: DateTimeFormatter f1 = DateTimeFormatter.ofPattern("MMM dd, yyyy"); 7: LocalDate d = LocalDate.of(2018, Month.JANUARY, 15); 8: LocalDate d2 = d.plusDays(1); 9: System.out.print(f1.format(d) + " "); 10: System.out.println(d2.format(f1)); }} On the line 10, the LocalDate object referenced by 'd2' (which contains 2018, Month.JANUARY, 16) is formatted to the pattern "MMM dd, yyyy" (which was declared on line 5). This is undertaken using the LocalDate method format(). The resultant output when line 9 is executed is: Jan 16, 2018 The above is appended to the previous print stream which results in the final output: Jan 15, 2018 Jan 16, 2018 Note: In the above line 10, we see the method call format() from the LocalDate class. However, on line 9, we see the method format() called from DateTimeFormatter class. How can this be? The format() method, which performs the exact same function, is located in DateTimeFormatter and LocalDate classes. In fact, the format() method is sourced in the following classes: • java.time.LocalDateTime • java.time.LocalDate • java.time.LocalTime The format() method is important for the exam.

Given: 1: import java.util.function.Predicate; 2: class A { 3: public static void main(String[] args) { 4: A a1 = new A(); 5: a1.go(INSERT CODE HERE); 6: } 7: void go(Predicate<A> a){ 8: A a2 = new A(); 9: System.out.println(a.test(a2)); 10: } 11: static int adder(int x, int y){return x+y;} 12: } Which code, inserted on line 5 above, will compile and run fine? a) (A u)->return adder(z, i) >2; b) A u->{int z = 3; return adder(z, 1) >2;} c) ()->adder(z, i) >2 d) None of the answers are correct

d) is correct. Incorrect Answer: a) (A u)->return adder(z, i) >2; According to the Java Lambda syntax rules, the Lambda body has a return statement without curly brackets. This causes the compiler error. b) A u->{int z = 3; return adder(z, 1) >2;} Java Lambda syntax rules state that the Lambda parameter can be just a variable name or it can be a type followed by a variable name, all in parenthesis '()'. In the above, the Lambda parameter should have a parenthesis '()' surrounding it. As a consequence a compiler error occurs. Solution: (A u) ->{int z = 3; return adder(z, 1) >2;} c) ()->adder(z, i) >2 The Java Lambda syntax rule states that the Lambda parameter must have an arbitrary argument name e.g. 'x' or 'y' or 'SomeName' etc. Solution: (x)->adder(z, i) >2 Note: Introduction to Simple Lambdas In this section we're going to outline a basic introduction to Lambdas. Firstly The benefits of Lambdas: • Easier to Read Code • More Concise Code • Faster Running Code (More Efficient). The core aspect of lambdas is that you can pass complex expressions (calculations that result in a boolean) as an argument into a method. This is as opposed to the traditional manner of passing variables into a method i.e. primitive types or object type variables. So instead of having a Java class that contains many different methods that perform separate and distinct responsibilities (functions), you could have one method that can perform ALL of those separate and distinct responsibilities. The benefit would be in the area of memory efficiency so that, instead of having multiple different methods allocated memory, you could have one method allocated memory. Also, the class containing the lambda expression would make the class more cohesive in performing a particular task. Predicate Interface For the OCA exam, you will only need to know about the Predicate interface and its method test(). Predicate, in general meaning, is a statement about something that is either true or false. In programming, predicates represent single argument functions that return a boolean value. The Predicate interface is located here: java.util.function.Predicate The test() method evaluates a predicate on the given argument 't'. Its signature is as follows: boolean test(T t) Where parameter t represents the input argument which will result in the boolean value true being returned if the input argument matches the predicate, otherwise false. There is a simple example of the use of the Predicate interface and its method test(): import java.util.function.Predicate; public class Main { public static void main(String[] args) { Predicate<String> i = (s)-> s.length() > 5; System.out.println( i.test("java2s.com ")); } } As you can see in the above code, the Java Lambda expression is: s.length() > 5 and this is 'tested' utilising the test() method with a string literal "java2s.com ". As "java2s.com " has a length greater than 5, 'true' is printed to the screen. In summary, for the OCA exam, you will be tested on the very basics of Java lambdas e.g. on the syntax of Java Lambda expressions, the use of the Predicate interface and also its test() method. The Lambda questions for the OCA exam may also be mixed with other aspects that will be tested e.g. objects and data structures like a array lists. Syntax Rules for Predicate Lambda ➤ The predicate parameter can be just a variable name or it can be the type followed by the variable name, all in parethesis. e.g. s.go((x) -> adder(5,1) < 7); s.go(u -> adder(6,2) < 9); ➤ The body must return a boolean. e.g. s.go((x) -> 3 < 7); s.go(u -> adder(6,2) < 9); ➤The body can be a single expression which cannot have a return statement. e.g. s.go((x) -> 3 < 7); ➤ The body can be a code block surrounded by curly brackets containing one or more valid statements, each ending with a semicolon and the block must end with a return statement. e.g. s.go(u -> { int x = 1; return adder(x,2) < 9 } );

Given: public class A { public static void main(String[] args) { String[] horses = new String[5]; horses [4] = null; for(int i = 0; i < horses.length; i++) { if(i < args.length) horses[i] = args [i]; System.out.print(horses[i].toUpperCase()+" "); } }} And, if the code compiles the command line: java A hope all is well What is the result? a) HOPE ALL IS WELL b) HOPE ALL IS WELL null c) An exception is thrown with no other output. d) HOPE ALL IS WELL, and then a NullPointerException e) It prints: 'HOPE ALL IS WELL' and then a ArrayIndexOutOfBoundsException. f) Compiler Error.

d) is correct. It prints: 'HOPE ALL IS WELL' and then a throws a NullPointerException. 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: String[] horses = new String[5]; 4: horses [4] = null; 5: for(int i = 0; i < horses.length; i++) { 6: if(i < args.length) 7: horses[i] = args [i]; 8: System.out.print(horses[i].toUpperCase()+" "); 9: } 10: } } The user runs the program and inputs their arguments as follows: java A hope all is well This results in the array String[] 'args' getting populated with the following strings: args[0] = "hope" args[1] = "all" args[2] = "is" args[3] = "well" =======2======= 1: public class A { 2: public static void main(String[] args) { 3: String[] horses = new String[5]; 4: horses [4] = null; 5: for(int i = 0; i < horses.length; i++) { 6: if(i < args.length) 7: horses[i] = args [i]; 8: System.out.print(horses[i].toUpperCase()+" "); 9: } 10: }} On the line 3, an array of String objects is created of size 5 and it gets initialised to 'null': horses [0] = null horses [1] = null horses [2] = null horses [3] = null horses [4] = null =======3======= 1: public class A { 2: public static void main(String[] args) { 3: String[] horses = new String[5]; 4: horses[4] = null; 5: for(int i = 0; i < horses.length; i++) { 6: if(i < args.length) 7: horses[i] = args [i]; 8: System.out.print(horses[i].toUpperCase()+" "); 9: } 10: }} On the line 4, the array index at address 4 gets assigned 'null' but since it's already 'null' from its initialisation on the line 3, there is no change in the 'horses' array: horses [0] = null horses [1] = null horses [2] = null horses [3] = null horses [4] = null =======4======= 1: public class A { 2: public static void main(String[] args) { 3: String[] horses = new String[5]; 4: horses [4] = null; 5: for(int i = 0; i < horses.length; i++) { 6: if(i < args.length) 7: horses[i] = args [i]; 8: System.out.print(horses[i].toUpperCase()+" "); 9: } 10: }} On the line 5, the variable i gets initialized to 0. Then the current value of i , which is 0, is compared to see if it less than the the size of the array horses, which is 5 (i < horses.length). As i (which is 0) is less than horses.length (which is 5), the for block is entered. Below is the current snapshot of variables in memory: ===Memory Snapshot=== args[0] = "hope" args[1] = "all" args[2] = "is" args[3] = "well" horses [0] = null horses [1] = null horses [2] = null horses [3] = null horses [4] = null i = 0 =======5======= 1: public class A { 2: public static void main(String[] args) { 3: String[] horses = new String[5]; 4: horses [4] = null; 5: for(int i = 0; i < horses.length; i++) { 6: if( i < args.length) 7: horses[i] = args [i]; 8: System.out.print(horses[i].toUpperCase()+" "); 9: } 10: }} On the line 6, the current value stored in variable i , which is 0, is checked to see if it is less than the length of the args array which is 4. As there are 4 string tokens entered by the user (i.e. java A hope all is well) , the length of the args array is 4. Therefore, on the line 6, we are currently comparing: if(0 < 4) As the above is true the line 7 gets executed. ===Memory Snapshot=== args[0] = "hope" args[1] = "all" args[2] = "is" args[3] = "well" horses [0] = null horses [1] = null horses [2] = null horses [3] = null horses [4] = null i = 0 =======6======= 1: public class A { 2: public static void main(String[] args) { 3: String[] horses = new String[5]; 4: horses [4] = null; 5: for(int i = 0; i < horses.length; i++) { 6: if(i < args.length) 7: horses[ i ] = args [ i ]; 8: System.out.print(horses[i].toUpperCase()+" "); 9: } 10: }} On the line 7, the contents of the 'horses' array string at index '0' receives a copy of the contents of the 'args' array string at index 0: horses[ 0 ] = args [ 0 ] Looking at the last memory snapshot, we can see that "hope" is in args [ 0 ] and a copy of this gets stored in the horses string array at index 0: horses[ 0 ] = "hope" =======7======= 1: public class A { 2: public static void main(String[] args) { 3: String[] horses = new String[5]; 4: horses [4] = null; 5: for(int i = 0; i < horses.length; i++){ 6: if(i < args.length) 7: horses[i] = args [i]; 8: System.out.print(horses[ i ].toUpperCase()+" "); 9: } 10: }} On the line 8, a new unreferenced String object is created containing a copy of the string at index horses[ 0 ] i.e. "hope". This unreferenced String object is converted to upper case: horses[ 0 ].toUpperCase() This results in "HOPE" getting printed to the output stream. Note: As String objects are immutable, the original string "hope" at index horses[0] does not get changed i.e. it remains as "hope". =======8======= 1: public class A { 2: public static void main(String[] args) { 3: String[] horses = new String[5]; 4: horses [4] = null; 5: for(int i = 0; i < horses.length; i++) { 6: if(i < args.length) 7: horses[i] = args [i]; 8: System.out.print(horses[i].toUpperCase()+" "); 9: } 10: }} On the line 9, variable i gets incremented to 1. Note: i++ is a postfix operator which means the variable gets incremented AFTER the loop completes on line 9. The variables in memory now look like the following: ===Memory Snapshot=== args[0] = "hope" args[1] = "all" args[2] = "is" args[3] = "well" horses[0] = "hope" horses [1] = null horses [2] = null horses [3] = null horses [4] = null i = 1 =======9======= To speed up the repetitive loop process, lets fast forward the code step through so that all the string 'args' are copied to the 'horses' array and the following is successfully output to the print stream: HOPE ALL IS WELL ===Memory Snapshot=== args[0] = "hope" args[1] = "all" args[2] = "is" args[3] = "well" horses [0] = "hope" horses [1] = "all" horses [2] = "is" horses [3] = "well" horses [4] = null i = 4 =======10======= 1: public class A { 2: public static void main(String[] args) { 3: String[] horses = new String[5]; 4: horses [4] = null; 5: for(int i = 0; i < horses.length; i++) { 6: if(i < args.length) 7: horses[i] = args [i]; 8: System.out.print(horses[i].toUpperCase()+" "); 9: } 10: }} On the line 5, the current value stored in variable i i.e. is checked to see that it is less than horses.length. Looking at the current values in memory, we can see i is 4 and horses.length is 5. This means 1<5 is true and the for loop block is entered. ===Memory Snapshot=== args[0] = "hope" args[1] = "all" args[2] = "is" args[3] = "well" horses [0] = "hope" horses [1] = "all" horses [2] = "is" horses [3] = "well" horses [4] = null i = 4 =======11======= 1: public class A { 2: public static void main(String[] args) { 3: String[] horses = new String[5]; 4: horses [4] = null; 5: for(int i = 0; i < horses.length; i++) { 6: if(i < args.length) 7: horses[i] = args [i]; 8: System.out.print(horses[i].toUpperCase()+" "); 9: } 10: }} On the line 6, i < args.length. As i is currenty 4 and args.length is 4, as 4 < 4 is false, the if block resolves to false and is skipped. ===Memory Snapshot=== args[0] = "hope" args[1] = "all" args[2] = "is" args[3] = "well" horses [0] = "hope" horses [1] = "all" horses [2] = "is" horses [3] = "well" horses [4] = null i = 4 =======12======= 1: public class A { 2: public static void main(String[] args) { 3: String[] horses = new String[5]; 4: horses [4] = null; 5: for(int i = 0; i < horses.length; i++) { 6: if(i < args.length) 7: horses[i] = args [i]; 8: System.out.print(horses[ i ].toUpperCase()+" "); 9: } 10: }} On the line 8, the contents currently stored at horses[ 4 ] is retrieved. Namely, 'null'. When toUpperCase()' gets called, it is expecting a string but instead gets a 'null' variable which throws: NullPointerException Final overall output: HOPE ALL IS WELL, and then a NullPointerException.

Given: public class A { public static void main(String[] args) { StringBuilder sb = new StringBuilder(100); sb.ensureCapacity(300); System.out.println(sb.length()); }} What is the result? a) Compiler error b) Runtime error c) Compile and print HERE d) None of the answers are correct

d) is correct. None of the answers are correct. Looking at the program: public class A { public static void main(String[] args) { StringBuilder sb = new StringBuilder(100); sb.ensureCapacity(300); System.out.println(sb.length()); }} It will print 0 as there are no elements inside this StringBuilder . ensureCapacity(300) - Ensures that the capacity is at least equal to the specified minimum of 300.

Given: 1: import java.util.ArrayList; 2: import java.util.function.Predicate; 3: public class A { 4: public static void main(String[] args) { 5: ArrayList<Student> sList = new ArrayList<>(); 6: sList.add(new Student(12312, 56, 2019)); 7: sList.add(new Student(53562, 39, 2019)); 8: System.out.println(runStudentQuery(sList, s -> s.getGrade()>40)); 9: 10: } 11: static int runStudentQuery(ArrayList<Student> studentList, Predicate<Student> expr){ 12: int total = 0; 13: for (Student s : studentList) { 14: if(expr.test(s)) 15: total++; 16: } 17: return total; 18: }} class Student{ int theStudNum; int theGrade; int theYear; public Student(int aStudNum, int aGrade, int aYear) { theStudNum = aStudNum; theGrade = aGrade; theYear = aYear; } int getGrade(){ return theGrade; } int getYear(){ return theYear; } public String toString(){ Integer grade = this.getGrade(); return grade.toString(); }} What will happen when the above code is compiled? a) Compiler Error on line 8 b) Compiler error on line 11 c) Compiler error on line 14 d) None of the answers are correct

d) is correct. The number '1' will be output to the screen. This is a Java Lambda question. ===Code Step Through=== 1: import java.util.ArrayList; 2: import java.util.function.Predicate; 3: public class A { 4: public static void main(String[] args) { 5: ArrayList<Student> sList = new ArrayList<>(); 6: sList.add(new Student(12312, 56, 2019)); 7: sList.add(new Student(53562, 39, 2019)); 8: System.out.println(runStudentQuery(sList, s -> s.getGrade()>40)); 9: 10: } 11: static int runStudentQuery(ArrayList<Student> studentList, Predicate<Student> expr){ 12: int total = 0; 13: for (Student s : studentList) { 14: if(expr.test(s)) 15: total++; 16: } 17: return total; 18: }} On the line 5, a data structure ArrayList is created which takes only Student type objects. On the lines 6 and 7, new student objects are added to the ArrayList. Student objects contain student number, grade and year. Each of these newly created Student objects are allocated addresses in memory by the Java virtual machine e.g. &221 and &432. They also have have references 'pointing' to them. In the context of the student objects being stored within an ArrayList, these references would be sList[0] and sList[1] and they would be stored as follows: sList[0] = new Student(12312, 56, 2019) sList[1] = new Student(53562, 39, 2019) A pseudocode depiction of the above Student objects stored in memory is outlined below: sList[0] 🠆 Object Student(Heap Address &221) { theStudNum = 12312; theGrade = 56; theYear = 2019; } sList[1] 🠆 Object Student(Heap Address &432) { theStudNum = 53562; theGrade = 39; theYear = 2019; } Even though the heap address is not required for this question, it's still outlined to give an overall picture of how objects are stored in memory. You will be asked questions in regards to this in the exam. ========2======== 1: import java.util.ArrayList; 2: import java.util.function.Predicate; 3: public class A { 4: public static void main(String[] args) { 5: ArrayList<Student> sList = new ArrayList<>(); 6: sList.add(new Student(12312, 56, 2019)); 7: sList.add(new Student(53562, 39, 2019)); 8: System.out.println( runStudentQuery(sList, s -> s.getGrade()>40)); 9: 10: } 11: static int runStudentQuery(ArrayList<Student> studentList, Predicate<Student> expr){ 12: int total = 0; 13: for (Student s : studentList) { 14: if(expr.test(s)) 15: total++; 16: } 17: return total; 18: }} On the line 8, the runStudentQuery() method is called which passes two parameters into it. Namely, an ArrayList of students with reference sList and the lambda expression: s -> s.getGrade()>40 ========3======== 1: import java.util.ArrayList; 2: import java.util.function.Predicate; 3: public class A { 4: public static void main(String[] args) { 5: ArrayList<Student> sList = new ArrayList<>(); 6: sList.add(new Student(12312, 56, 2019)); 7: sList.add(new Student(53562, 39, 2019)); 8: System.out.println( runStudentQuery(sList, s -> s.getGrade() > 40)); 9: 10: } 11: static int runStudentQuery(ArrayList<Student> studentList, Predicate<Student> expr){ 12: int total = 0; 13: for (Student s : studentList) { 14: if(expr.test(s)) 15: total++; 16: } 17: return total; 18: }} On the line 8, you see the lambda expression body containing the calculation to be executed. All lambda expressions must resolve to a boolean of true or false: s -> s.getGrade() > 40 This expression checks the current student grade to see if it is greater than 40 and if it is, the expression will return true. On the left-hand side of the lambda arrow token ( '->') is the single lambda parameter argument 's'. This s argument stores the lambda expression result of s -> s.getGrade() > 40 which will be either true or false. Again, it is imperative to understand that the expression s -> s.getGrade() > 40 will be passed into a method. In other words we are passing code as an argument into a method. ========4======== 1: import java.util.ArrayList; 2: import java.util.function.Predicate; 3: public class A { 4: public static void main(String[] args) { 5: ArrayList<Student> sList = new ArrayList<>(); 6: sList.add(new Student(12312, 56, 2019)); 7: sList.add(new Student(53562, 39, 2019)); 8: System.out.println( runStudentQuery(sList, s -> s.getGrade() > 40)); 10: } 11: static int runStudentQuery(ArrayList<Student> studentList, Predicate<Student> expr){ 12: int total = 0; 13: for (Student s : studentList) { 14: if(expr.test(s)) 15: total++; 16: } 17: return total; 18: } } On the line 11, the runStudentQuery() method is entered. This method contains the parameters studentList and also the lambda expression reference expr where the expr is: s -> s.getGrade() > 40 ========5======== 1: import java.util.ArrayList; 2: import java.util.function.Predicate; 3: public class A { 4: public static void main(String[] args) { 5: ArrayList<Student> sList = new ArrayList<>(); 6: sList.add(new Student(12312, 56, 2019)); 7: sList.add(new Student(53562, 39, 2019)); 8: System.out.println( runStudentQuery(sList, s -> s.getGrade() > 40)); 9: 10: } 11: static int runStudentQuery(ArrayList<Student> studentList, Predicate<Student> expr){ 12: int total = 0; 13: for (Student s : studentList) { 14: if(expr.test(s)) 15: total++; 16: } 17: return total; 18: }} On the line 12, inside the runStudentQuery() method, a local variable named 'total' is initialised to 0. This 'total' variable stores the total number of student grades greater than 40. A snapshot of the current variables and objects stored in memory is shown below. Current Values Stored in Memory: total🠆 0 sList[0] 🠆 Object Student(Heap Address &221) { theStudNum = 12312; theGrade = 56; theYear = 2019; } sList[1] 🠆 Object Student(Heap Address &432) { theStudNum = 53562; theGrade = 39; theYear = 2019; } ========6======== 1: import java.util.ArrayList; 2: import java.util.function.Predicate; 3: public class A { 4: public static void main(String[] args) { 5: ArrayList<Student> sList = new ArrayList<>(); 6: sList.add(new Student(12312, 56, 2019)); 7: sList.add(new Student(53562, 39, 2019)); 8: System.out.println( runStudentQuery(sList, s -> s.getGrade() > 40)); 9: 10: } 11: static int runStudentQuery(ArrayList<Student> studentList, Predicate<Student> expr){ 12: int total = 0; 13: for (Student s : studentList) { 14: if(expr.test(s)) 15: total++; 16: } 17: return total; 18: }} On the line 13, an enhanced for loop is entered which iterates through the array list 'studentList', retrieving each student object ('s') stored within that array list. It's important to note that ArrayList 'studentList' is 'pointing' to the same ArrayList 'sList'. This is depicted below in the pseudocode memory snapshot. Current Values Stored in Memory: total🠆 0 studentList[0] 🠆 sList[0] 🠆 Object Student(Heap Address &221) { theStudNum = 12312; theGrade = 56; theYear = 2019; } studentList[1]🠆 sList[1] 🠆 Object Student(Heap Address &432) { theStudNum = 53562; theGrade = 39; theYear = 2019; } ========7======== 1: import java.util.ArrayList; 2: import java.util.function.Predicate; 3: public class A { 4: public static void main(String[] args) { 5: ArrayList<Student> sList = new ArrayList<>(); 6: sList.add(new Student(12312, 56, 2019)); 7: sList.add(new Student(53562, 39, 2019)); 8: System.out.println( runStudentQuery(sList, s -> s.getGrade() > 40)); 9: 10: } 11: static int runStudentQuery(ArrayList<Student> studentList, Predicate<Student> expr){ 12: int total = 0; 13: for (Student s : studentList) { 14: if(expr.test(s)) 15: total++; 16: } 17: return total; 18: }} On the line 14, the Predicate's test() method executes the Lambda expression that was passed in via the method parameter 'expr': 's.getGrade() > 40'. The reference 's' is referring to the current Student object stored in the array list: studentList[0] 🠆 sList[0] 🠆 Object Student(Heap Address &221) { theStudNum = 12312; theGrade = 56; theYear = 2019; } (See memory snapshot above). The grade of this particular object with Heap Address &221 is retrieved i.e. 56. As the current Student object grade '56' is greater than 40, the if block on the line 14 is entered and the variable 'total' is incremented by 1 The for loop then loops back up to line 14 to check the next student object in the array list. (The compiler will continue to loop back to line 14 until all objects assessed within the ArrayList). Current Values Stored in Memory: total🠆 0 studentList[0] 🠆 sList[0] 🠆 Object Student(Heap Address &221) { theStudNum = 12312; theGrade = 56; theYear = 2019; } studentList[1]🠆 sList[1] 🠆 Object Student(Heap Address &432) { theStudNum = 53562; theGrade = 39; theYear = 2019; } ========8======== 1: import java.util.ArrayList; 2: import java.util.function.Predicate; 3: public class A { 4: public static void main(String[] args) { 5: ArrayList<Student> sList = new ArrayList<>(); 6: sList.add(new Student(12312, 56, 2019)); 7: sList.add(new Student(53562, 39, 2019)); 8: System.out.println( runStudentQuery(sList, s -> s.getGrade() > 40)); 9: 10: } 11: static int runStudentQuery(ArrayList<Student> studentList, Predicate<Student> expr){ 12: int total = 0; 13: for (Student s : studentList) { 14: if(expr.test(s)) 15: total++; 16: } 17: return total; 18: }} On the line 14, the test() executes the Lambda expression 's.getGrade() > 40'. The reference 's' is referring to the current Student object stored: studentList[1]🠆 sList[1] 🠆 Object Student(Heap Address &432) { theStudNum = 53562; theGrade = 39; theYear = 2019; } The grade of this particular object with Heap Address &432 is retrieved i.e. 39. As grade '39' is not greater than 40, the if block condition on the line 14 is false and program flow control jumps to the end of the enhanced for loop. The for loop then loops back up to line 14 to check the next student object in the array list. (The compiler will continue to loop back to line 14 until all objects assessed within the ArrayList). As there are no more Student objects within the ArrayList studentList, the for loop block is exited. Current Values Stored in Memory: total🠆 0 studentList[0] 🠆 sList[0] 🠆 Object Student(Heap Address &221) { theStudNum = 12312; theGrade = 56; theYear = 2019; } studentList[1]🠆 sList[1] 🠆 Object Student(Heap Address &432) { theStudNum = 53562; theGrade = 39; theYear = 2019; } ========9======== 1: import java.util.ArrayList; 2: import java.util.function.Predicate; 3: public class A { 4: public static void main(String[] args) { 5: ArrayList<Student> sList = new ArrayList<>(); 6: sList.add(new Student(12312, 56, 2019)); 7: sList.add(new Student(53562, 39, 2019)); 8: System.out.println( runStudentQuery(sList, s -> s.getGrade()>40) ); 9: 10: } 11: static int runStudentQuery(ArrayList<Student> studentList, Predicate<Student> expr){ 12: int total = 0; 13: for (Student s : studentList) { 14: if(expr.test(s)) 15: total++; 16: } 17: return total; 18: } } On the line 17, the value stored within the variable 'total' is returned to the main method i.e. 1. On the line 8, the value stored within the variable 'total' is printed to the screen i.e. 1. The program then completes. Note 1: Introduction to Simple Lambdas In this section we're going to outline a basic introduction to Lambdas. Firstly The benefits of Lambdas: • Easier to Read Code • More Concise Code • Faster Running Code (More Efficient). The core aspect of lambdas is that you can pass complex expressions (calculations that result in a boolean) as an argument into a method. This is as opposed to the traditional manner of passing variables into a method i.e. primitive types or object type variables. So instead of having a Java class that contains many different methods that perform separate and distinct responsibilities (functions), you could have one method that can perform ALL of those separate and distinct responsibilities. The benefit would be in the area of memory efficiency so that, instead of having multiple different methods allocated memory, you could have one method allocated memory. Also, the class containing the lambda expression would make the class more cohesive in performing a particular task. Predicate Interface For the OCA exam, you will only need to know about the Predicate interface and its method test(). Predicate, in general meaning, is a statement about something that is either true or false. In programming, predicates represent single argument functions that return a boolean value. The Predicate interface is located here: java.util.function.Predicate The test() method evaluates a predicate on the given argument 't'. Its signature is as follows: boolean test(T t) Where parameter t represents the input argument which will result in the boolean value true being returned if the input argument matches the predicate, otherwise false. There is a simple example of the use of the Predicate interface and its method test(): import java.util.function.Predicate; public class Main { public static void main(String[] args) { Predicate<String> i = (s)-> s.length() > 5; System.out.println( i.test("java2s.com ")); } } As you can see in the above code, the Java Lambda expression is: s.length() > 5 and this is 'tested' utilising the test() method with a string literal "java2s.com ". As "java2s.com " has a length greater than 5, 'true' is printed to the screen. In summary, for the OCA exam, you will be tested on the very basics of Java lambdas e.g. on the syntax of Java Lambda expressions, the use of the Predicate interface and also its test() method. The Lambda questions for the OCA exam may also be mixed with other aspects that will be tested e.g. objects and data structures like a array lists. Syntax Rules for Predicate Lambda ➤ The predicate parameter can be just a variable name or it can be the type followed by the variable name, all in parethesis. e.g. s.go((x) -> adder(5,1) < 7); s.go(u -> adder(6,2) < 9); ➤ The body must return a boolean. e.g. s.go((x) -> 3 < 7); s.go(u -> adder(6,2) < 9); ➤The body can be a single expression which cannot have a return statement. e.g. s.go((x) -> 3 < 7); ➤ The body can be a code block surrounded by curly brackets containing one or more valid statements, each ending with a semicolon and the block must end with a return statement. e.g. s.go(u -> { int x = 1; return adder(x,2) < 9 } );

Which of the following methods are not inside the StringBuilder class? a) public StringBuilder reverse() b) public StringBuilder append(String str) c) public StringBuilder insert(int offset, Object obj) d) public String trim() e) public StringBuilder replace(int start, int end, String str)

d) is correct. The StringBuilder class does not have a trim() method as this is located in the String class. The StringBuilder objects are mutable. That means that when you create a String object, it can be changed (you can write to it). On the other hand, String objects are immutable and therefore cannot be changed when created (you cannot write to it). The StringBuilder class has a number of methods and whilst it would not be practical memorise all of them, it would be advisable to memorise some of them. Below is an abbreviation to help you memorise the methods of the String class that may appear in the exam: airr-d • append(String str) • insert(int offset, Object obj) • replace(int start, int end, String str) • reverse() • delete(int start, int end) The above methods are explained in more detail below: ➤ public StringBuilder append(String str): The above method appends the specified string to the end of the StringBuilder object. e.g. StringBuilder h = new StringBuilder("Hello"); System.out.println(h.append(" There!")); In the above example, the append() method appends the string " There!" to the end of the original string object using StringBuilder. ➤ public StringBuilder insert(int offset, Object obj): The above method inserts a string representation of the Object argument to the end of the StringBuilder object. e.g. StringBuilder h = new StringBuilder("Hello"); System.out.println(h.insert(4," There!")); In the above example, the insert() method inserts the string " There!" at index 4 of the string "Hello" Each of the characters of the string "Hello" have the following index addresses: 'H' = index 0 'e' = index 1 'l' = index 2 'l' = index 3 'o' = index 4 The character 'o', located at index 4 is moved up to make way for the inserted string " There!" Note: If the index was outside of the bounds of string "Hello" e.g. h.insert(6," There!"), then a StringIndexOutOfBoundsException will be thrown. ➤ public StringBuilder replace(int start, int end, String str): The above replaces the characters in a substring of this string with characters in the specified String 'str'. e.g. StringBuilder h = new StringBuilder("Hello"); System.out.println(h.replace(3, 5, "icopter")); In the above example, the string "icopter" replaces the characters located between index 3 and index 4 (5-1). The original string would now be: "Helicopter" Below outlines the changes to the original string "Hello": "Hello" string before replace() method executed: 'H' = index 0 'e' = index 1 'l' = index 2 'l' = index 3 'o' = index 4 "Hello" string after replace() method executed: 'H' = index 0 'e' = index 1 'l' = index 2 'i' = index 3 'c' = index 4 'o' = index 5 'p' = index 6 't' = index 7 'e' = index 8 'r' = index 9 In the above, you can see there are additional characters ("icopter") included which essentially increases the size of the original string after the replace() method it is executed. ➤ public StringBuilder reverse(): The above causes this string to be replaced by the reverse of the string. e.g. StringBuilder h = new StringBuilder("Hello"); System.out.println(h.reverse()); In the above example, the string "Hello" is reversed with the resultant output: "olleH" ➤ public StringBuilder delete(int start, int end): The above method removes the characters in a substring of this original string starting at index 'start' and finishing at index 'end' -1 e.g. StringBuilder h = new StringBuilder("Hello"); System.out.println(h.delete(2, 5)); In the above example, the string characters beginning at index 2 and finishing at index 4 (5-1) are deleted from the string resulting in the output: "He" Below outlines the changes to the original string "Hello": "Hello" string before delete() method executed: 'H' = index 0 'e' = index 1 'l' = index 2 'l' = index 3 'o' = index 4 "Hello" string after delete() method executed: 'H' = index 0 'e' = index 1

Given: public class A { public static void main(String args[]) { char[][] twoD = {{'a','b','c'},{'d','e','f'}}; System.out.println(INSERT CODE HERE); } What code inserted above would enable the character 'e' to be printed to the screen? a) twoD[1][0] b) twoD[0][2] c) twoD[1,2] d) None of the answers are correct

d) is correct. The answer is: twoD[1][1] This is an example of a two-dimensional array. That is, two separate one-dimensional arrays stored together. Below is a step through of the code which will explain in further detail: ===Code Step Through=== 1: public class A { 2: public static void main(String args[]) 3: { 4: char[][] twoD = {{'a','b','c'},{'d','e','f'}}; 5: System.out.println(twoD[1][1]); 6: } To help understand two-dimensional arrays, it's advisable to write out a pseudocode 'depiction' of the values stored in memory. On the line 4 above, the values stored in the two-dimensional array can be depicted as follows (where Col means Column): ====== Col 0 === Col 1 === Col 2 === Row 0: ---'a'--------'b'--------'c'---- Row 1: ----'d'-------'e'---------'f'---- Then: Column 0 (Col 0) contains the char value 'a' and 'd'. Column 1 contains the char values 'b' and 'e'. Column 2 contains the char values 'c' and 'f'. ====== Col 0 === Col 1 === Col 2 === Row 0: ---'a'--------'b'--------'c'---- Row 1: ----'d'-------'e'---------'f'---- Likewise, from looking at the two-dimensional depiction above: Row 0 contains the char values 'a','b','c'. Row 1 contains the char values 'd','e','f'. Once we have derived this table, it is now easy to locate and retrieve any char value stored in the two-dimensional array. ====== Col 0 === Col 1 === Col 2 === Row 0: ---'a'--------'b'--------'c'---- Row 1: ----'d'-------'e'---------'f'---- Remembering that the first square brackets in a two-dimensional array represents the ROW in the second square brackets represents the COLUMN as below: twoD[ROW][COLUMN] We can see from the above table depiction that the char value 'e' is located in ROW 1 COLUMN 1. Therefore, in Java the answer is: twoD[1][1] Note: An alternative initialization of the two-dimensional array above can be as follows: 1: public class A { 2: public static void main(String args[]) 3: { 4: char[][] twoD = new char[2][3]; 5: twoD[0][0]='a'; 6: twoD[0][1]='b'; 7: twoD[0][2]='c'; 8: twoD[1][0]='d'; 9: twoD[1][1]='e'; 10: twoD[1][2]='f'; 11: } On the line 4 above, a two-dimensional array is initialized with row size 2 and column size 3.

Given: public class A { public static void main(String args[]) { float[] b1 = new float[2]; for (float c : b1) { System.out.println(c); } }} What is the result? a) Compiler error b) Runtime error c) Compile and print: 0 0 d) None of the answers are correct

d) is correct. The code will compile and print: 0.0 0.0 An array of primitive types will have default values when initialized. In the case of float arrays, the default value is 0.0 and not 0. ===Code Step Through=== 1: public class A { 2: public static void main(String args[]) 3: { 4: float[] f1 = new float[2]; 5: for (float c : b1) { 6: System.out.println(c); 7: } 8: }} On the line 4, an array of float is declared with size 2. The default values of this float array will be 0.0. Therefore the compiler automatically assigns 0.0 to each of the index 'cells' in the array i.e. f1[0] = 0.0 f1[1] = 0.0 ========2======== 1: public class A { 2: public static void main(String args[]) 3: { 4: float[] f1 = new float[2]; 5: for (float c : b1) { 6: System.out.println(c); 7: } 8: }} On the lines 5-7 is declared an enhanced for loop which iterates through the float array and prints all of the values stored in the array to the screen. i.e. 0.0 0.0 Note 1: Default Values of Primitive Types Below is a list of default values of primitive types. The following abbreviation may help to remember all of the primitive types: dbs-cilf-b double default value is: false byte default value is: 0 short default value is: 0 char default value is: \u0000 int default value is: 0 long default value is: 0 float default value is: 0.0 boolean default value is: false Note 2: Objects have a default value of null e.g. String, Integer, Double all have null as the default value

Given: public class A { public static void main(String args[]) { String[] s1 = new String[2]; for (String c : s1) { System.out.println(c); } }} What is the result? a) Compiler error b) Runtime error c) Compile and print an empty string. d) None of the answers are correct

d) is correct. The code will compile and print: null null An array of object types will have default values of null when initialized. ===Code Step Through=== 1: public class A { 2: public static void main(String args[]) 3: { 4: String[] s1 = new String[2]; 5: for (String c : s1) { 6: System.out.println(c); 7: } 8: }} On the line 4, an array of object String is declared with size 2. The default values of all objects will be null. Therefore the compiler automatically assigns null to each of the index 'cells' in the array i.e. s1[0] = null s1[1] = null ========2======== 1: public class A { 2: public static void main(String args[]) 3: { 4: String[] s1 = new String[2]; 5: for (String c : s1) { 6: System.out.println(c); 7: } 8: }} On the lines 5-7 is declared an enhanced for loop which iterates through the String array and prints all of the values stored in the array to the screen. i.e. null null Note 1: Default Values of Primitive Types Below is a list of default values of primitive types. The following abbreviation may help to remember all of the primitive types: dbs-cilf-b double default value is: false byte default value is: 0 short default value is: 0 char default value is: \u0000 int default value is: 0 long default value is: 0 float default value is: 0.0 boolean default value is: false Note 2: Objects have a default value of null e.g. String, Integer, Double all have null as the default value

Given: String h = "Hello"; int len = h.length(); System.out.println(len); What is the result? a) Compiler error b) Runtime error c) Compile and print: 4 d) None of the answers are correct

d) is correct. The output will be 5 (The length of the String object) String h = "Hello"; int len = h.length(); System.out.println(len); Index 0 = H Index 1 = e Index 2 = l Index 3 = l Index 4 = 0 Consider the String object is in essence as a String array data structure whose start Index is 0. There are 5 chars (letters) in the Hello String object. Therefore the length of the said String literal is 5. Note: arrays start at index 0. Java uses zero-based indexing because C lanaguage uses zero-based indexing. C uses zero-based indexing because an array index is nothing more than a memory offset.

Given: public class A { public static void main(String[] args) { String s1 = "Pop"; String s2 = s1; s1 = s1.concat(" Eye"); System.out.println(s1); System.out.println(s2); }} What is the result? a) Compiler error b) Compile and print: Pop Pop Eye c) Compile and print: Pop Eye d) None of the answers are correct

d) is correct. The program compiles and prints: Pop Eye Pop Below explains the code step-by-step to better understand how the answer is derived: ===Code Step Through=== public class A { public static void main(String[] args) { String s1 = "Pop"; String s2 = s1; s1 = s1.concat(" Eye"); System.out.println(s1); System.out.println(s2); }} An object string "Pop" is created and located on the memory heap. There is one reference to the object i.e. s1 s1 🠚 "Pop" =========2:=========== public class A { public static void main(String[] args) { String s1 = "Pop"; String s2 = s1; s1 = s1.concat(" Eye"); System.out.println(s1); System.out.println(s2); }} A new String reference called s2 is created. This s2 reference is pointing to string object the same string reference s1 is pointing to i.e. "Pop" s1 🠚"Pop"🠘 s2 ==========3:========= public class A { public static void main(String[] args) { String s1 = "Pop"; String s2 = s1; s1 = s1.concat(" Eye"); System.out.println(s1); System.out.println(s2); }} Remember: String objects are immutable - they cannot be changed. s1.concat(" Eye"); String object " Eye" is appended (concatenated) to a copy of "Pop" This new object contains "Pop Eye". This is completely seperate to the other string object "Pop" s1 🠚"Pop"🠘 s2 "Pop Eye" =========4:========= s1 = s1.concat(" Eye"); String s1 reference is dereferenced from string object "Pop" and now referencing "Pop Eye" "Pop" 🠘 s2 s1 🠚"Pop Eye" ========5:========= public class A { public static void main(String[] args) { String s1 = "Pop"; String s2 = s1; s1 = s1.concat(" Eye"); System.out.println(s1); System.out.println(s2); }} Outputs the object referenced to s1 i.e. Pop Eye ========6:========= public class A { public static void main(String[] args) { String s1 = "Pop"; String s2 = s1; s1 = s1.concat(" Eye"); System.out.println(s1); System.out.println(s2); }} Outputs the object referenced to s2 i.e. Pop

Given: public class A { public static void main(String[] args) { String s = "JAVA"; s = s + "rocks"; s = s.substring(4,8); s.toUpperCase(); System.out.println(s); }} Which are true? (choose all that apply) a) JAVA b) JAVAROCKS c) rocks d) rock e) ROCKS f) ROCK g) Compilation fails

d) is correct. The program prints: rock The substring() method call uses a zero-based index and the second argument is exclusive, so the character at index 8 is NOT included. The toUpperCase() method call makes a new string object that is instantly lost. The toUpperCase() method call does NOT affect the String referred to by 's'. ===Code Step Through=== 1: public class A { 2: public static void main(String[] args) { 3: String s = "JAVA"; 4: s = s + "rocks"; 5: s = s.substring(4,8); 6: s.toUpperCase(); 7: System.out.println(s); 8: }} On the line 3, a new string object with reference s is created in the String Pool. The string pool is a special area of memory that stores Strings objects. String objects are immutable therefore you cannot change them. The following outlines a pseudocode description of the current string object and in memory when line 3 is executed: s 🠆 Object String(Memory Address @9982) { "JAVA" } ========2======== 1: public class A { 2: public static void main(String[] args) { 3: String s = "JAVA"; 4: s = s + "rocks"; 5: s = s.substring(4,8); 6: s.toUpperCase(); 7: System.out.println(s); 8: }} On the line 4, two String objects ("JAVA" + "rocks") are joined together to create a new String object with a seperate distinct address in memory (e.g. &523). The reference s, which was originally pointing to the string object with memory address @9982, is dereferenced and is now pointing to the &523. There is a null reference (represented by the character 'Ø') to the object with memory address @9982. Is pseudocode description of the objects in memory at this point in time is outlined below. : Ø 🠚 Object String(Memory Address @9982) { "JAVA" } s 🠆 Object String(Memory Address &523) { "JAVArocks" } Note, the String object, with memory address @9982 above, has not changed i.e. it is immutable. ========3======== 1: public class A { 2: public static void main(String[] args) { 3: String s = "JAVA"; 4: s = s + "rocks"; 5: s = s.substring(4,8); 6: s.toUpperCase(); 7: System.out.println(s); 8: }} On the line 5, a new String object is created in memory based on the sub string of the object located at memory address &523 (i.e. "JAVArocks"). Looking at the "JAVArocks" string we derive the following indexes: Index 0 = J Index 1 = A Index 2 = V Index 3 = A Index 4 = r Index 5 = o Index 6 = c Index 7 = k Index 8 = s The method s.substring(4,8) is in fact s.substring(4,8-1) which is s.substring(4,7) when executed. This results in a new string object created, with arbitrary memory address &187, which is comprised of the following highlighted subset: Index 0 = J Index 1 = A Index 2 = V Index 3 = A Index 4 = r Index 5 = o Index 6 = c Index 7 = k Index 8 = s There is a null reference (represented by the character 'Ø') to the object with memory address @9982 and &523. A pseudocode description of the current objects in memory is outlined below after the execution of line 5: Ø 🠚 Object String(Memory Address @9982) { "JAVA" } Ø 🠚 Object String(Memory Address &523) { "JAVArocks" } s 🠆 Object String(Memory Address &187) { "rock" } Note, in the above pseudocode description, string reference s dereferences string object with memory address &523 and is now pointing to the new string object created with memory address &187 containing the string "rock". ========4======== 1: public class A { 2: public static void main(String[] args) { 3: String s = "JAVA"; 4: s = s + "rocks"; 5: s = s.substring(4,8); 6: s.toUpperCase(); 7: System.out.println(s); 8: }} On the line 6, a new string object is created without a reference, containing the string "ROCK". Remember string objects are immutable, and therefore the method call toUpperCase() causes a new string object to be created with an arbitrary memory address @332. There is a null reference (represented by the character 'Ø') to the object with memory addresses @9982, &523 and @332. The pseudocode description of the objects in memory is outlined below: Ø 🠚 Object String(Memory Address @9982) { "JAVA" } Ø 🠚 Object String(Memory Address &523) { "JAVArocks" } s 🠆 Object String(Memory Address &187) { "rock" } Ø 🠚 Object String(Memory Address @332) { "ROCK" } ========5======== 1: public class A { 2: public static void main(String[] args) { 3: String s = "JAVA"; 4: s = s + "rocks"; 5: s = s.substring(4,8); 6: s.toUpperCase(); 7: System.out.println(s); 8: }} On the line 7, as the string referenced by 's' is referring to the string object with memory address &187, therefore the contents of this particular string object with this particular memory address gets printed to the screen i.e. "rock" From looking at the pseudocode description below we can see the current state of the objects in memory: Ø 🠚 Object String(Memory Address @9982) { "JAVA" } Ø 🠚 Object String(Memory Address &523) { "JAVArocks" } s 🠆 Object String(Memory Address &187) { "rock" } Ø 🠚 Object String(Memory Address @332) { "ROCK" }

Given: String h1 = " Hello "; String h2 = h1.trim(); System.out.println(h2); What is the result? a) Compiler error b) Runtime error c) Compile and print " Hello" d) None of the answers are correct

d) is correct. The program was compile and print: "Hello"; String h1 = " Hello "; String h2 = h1.trim(); System.out.println(h2); The trim() method will remove the whitespace (empty space) on both ends of h1 from " Hello " to "Hello"

Given: public class A { public static void main(String[] args) { String h1 = "Hello"; String h2 = h1.substring(3,3); System.out.println(h2); }} What is the result? a) Compiler error b) Runtime error c) Compile and print: "l" d) None of the answers are correct

d) is correct. public class A { public static void main(String[] args) { String h1 = "Hello"; String h2 = h1.substring(3,3); System.out.println(h2); }} In the above code, substring(int startIndex, int endIndex): Returns a part of the string commencing at startIndex and finishing at the char stored at endIndex-1 h1.substring(3,3); The above attempts to return the substring from startIndex (3) to the index the endIndex i.e. 3-1 (substring(3,2)). As endIndex is before the startIndex - it compiles and runs fine but nothing gets printed. Index 0 = H Index 1 = e Index 2 = l 🠘 endIndex Index 3 = l 🠘 startIndex Index 4 = 0

Which of the following statements are true? a) keyword "continue" can only be used to continue the iteration of a loop or switch block. b) keyword "continue" can only be used to continue the iteration of a while loop. c) keyword "continue" can only be used to continue the iteration of a for loop and if block. d) None of the answers are correct.

d) is correct. Keyword "continue" can only be used to continue the iteration of any loop (for/while/do while) otherwise it will give a compiler error.

Given: 1: import java.time. ______ ; 2: public class A { 3: public static void main(String[] args) { 4: ______ date = ______ .now(); 5: ______ yesterday = date.minusDays(1); 6: ______ tomorrow = yesterday.plusDays(2); 7: System.out.println("Today date: "+date); 8: System.out.println("Yesterday date: "+yesterday); 9: System.out.println("Tommorow date: "+tomorrow); 10: }} What class, inserted in the above empty spaces, will return the date, one day from now and two days after now? a) DateTime b) LocalDateTime c) LocalDatesTimes d) DateTimes e) LocalDate

e) is correct. The class LocalDate ( inserted below on lines 1, 4, 5 and 6) will return the date only, one day from now and two days after now import java.time.LocalDate; public class A { public static void main(String[] args) { LocalDate date = LocalDate.now(); LocalDate yesterday = date.minusDays(1); LocalDate tomorrow = yesterday.plusDays(2); System.out.println("Today date: "+date); System.out.println("Yesterday date: "+yesterday); System.out.println("Tommorow date: "+tomorrow); }} The above will output: Today date: 2018-12-01 Yesterday date: 2018-11-30 Tommorow date: 2018-12-02 Note: java.time.LocalDate This class is used to create immutable objects each of which represents a specific date. e.g. 2018-11-29

Which of the following classes are not part of the Calendar collection? a) LocalDateTime b) LocalDate c) LocalTime d) DateTimeFormatter e) TimeDateFormatter f) TemporalAmount

e) is correct. There is no such class as TimeDateFormatter. Calendar Collection It would be advisable to memorize certain classes of the Calendar collection as these will pop up in the exam. Below is a suggested abbreviation to help memorize some of the core classes of the calendar collection: LLL-DPT ➤ java.time.LocalDateTime This class is used to create immutable objects each of which represents a specific date and time. ➤ java.time.LocalDate This class is used to create immutable objects each of which represents a specific date. ➤ java.time.LocalTime This class is used to create immutable objects each of which represents a specific time. ➤ java.time.format.DateTimeFormatter This immutable class is used by the class above to format date/time objects for output and to parse input strings and convert them to date/time objects. ➤ java.time.Period This class is used to create immutable objects that represent a period of time for example "one year, two months, and three days" ➤ java.time.temporal.TemporalAmount This interface is implemented by the Period class.

Given: 1: import java.util.function.Predicate; 2: public class A { 3: public static void main(String[] args) { 4: A s = new A(); 5: s.go(() -> adder(5,1) < 7); 6: s.go(x -> adder(6,2) < 9); 7: s.go(x, y -> adder(3,2) < 4); 8: } 9: void go(Predicate<A> e) { 10: A s2 = new A(); 11: if(e.test(s2)) 12: System.out.print("true "); 13: else 14: System.out.print("false "); 15: } 16: static int adder(int x, int y) { 17: return x + y; 18: }} What is the result? (choose all that apply) a) true true false b) Compilation fails due only to an error at line 5 c) Compilation fails due only to an error at line 6 d) Compilation fails due only to an error at line 7 e) Compilation fails due only to errors at lines 5 and 6 f) Compilation fails due only to errors at lines 5 and 7 g) Compilation fails due only to errors at lines 5, 6, and 7

f) is correct. Compilation fails due only to errors at lines 5 and 7. Predicate lambdas take exactly one parameter. Lets have a look at the code: 1: import java.util.function.Predicate; 2: public class A { 3: public static void main(String[] args) { 4: A s = new A(); 5: s.go(() -> adder(5,1) < 7); 6: s.go(x -> adder(6,2) < 9); 7: s.go(x, y -> adder(3,2) < 4); 8: } 9: void go(Predicate<A> e) { 10: A s2 = new A(); 11: if(e.test(s2)) 12: System.out.print("true "); 13: else 14: System.out.print("false "); 15: } 16: static int adder(int x, int y) { 17: return x + y; 18: }} On line 5, Predicate needs one argument and this is missing. On line 7, you can only have a single paramter for a lambda Note: Introduction to Simple Lambdas In this section we're going to outline a basic introduction to Lambdas. Firstly The benefits of Lambdas: • Easier to Read Code • More Concise Code • Faster Running Code (More Efficient). The core aspect of lambdas is that you can pass complex expressions (calculations that result in a boolean) as an argument into a method. This is as opposed to the traditional manner of passing variables into a method i.e. primitive types or object type variables. So instead of having a Java class that contains many different methods that perform separate and distinct responsibilities (functions), you could have one method that can perform ALL of those separate and distinct responsibilities. The benefit would be in the area of memory efficiency so that, instead of having multiple different methods allocated memory, you could have one method allocated memory. Also, the class containing the lambda expression would make the class more cohesive in performing a particular task. Predicate Interface For the OCA exam, you will only need to know about the Predicate interface and its method test(). Predicate, in general meaning, is a statement about something that is either true or false. In programming, predicates represent single argument functions that return a boolean value. The Predicate interface is located here: java.util.function.Predicate The test() method evaluates a predicate on the given argument 't'. Its signature is as follows: boolean test(T t) Where parameter t represents the input argument which will result in the boolean value true being returned if the input argument matches the predicate, otherwise false. There is a simple example of the use of the Predicate interface and its method test(): import java.util.function.Predicate; public class Main { public static void main(String[] args) { Predicate<String> i = (s)-> s.length() > 5; System.out.println( i.test("java2s.com ")); } } As you can see in the above code, the Java Lambda expression is: s.length() > 5 and this is 'tested' utilising the test() method with a string literal "java2s.com ". As "java2s.com " has a length greater than 5, 'true' is printed to the screen. In summary, for the OCA exam, you will be tested on the very basics of Java lambdas e.g. on the syntax of Java Lambda expressions, the use of the Predicate interface and also its test() method. The Lambda questions for the OCA exam may also be mixed with other aspects that will be tested e.g. objects and data structures like a array lists. Syntax Rules for Predicate Lambda ➤ The predicate parameter can be just a variable name or it can be the type followed by the variable name, all in parethesis. e.g. s.go((x) -> adder(5,1) < 7); s.go(u -> adder(6,2) < 9); ➤ The body must return a boolean. e.g. s.go((x) -> 3 < 7); s.go(u -> adder(6,2) < 9); ➤The body can be a single expression which cannot have a return statement. e.g. s.go((x) -> 3 < 7); ➤ The body can be a code block surrounded by curly brackets containing one or more valid statements, each ending with a semicolon and the block must end with a return statement. e.g. s.go(u -> { int x = 1; return adder(x,2) < 9 } );

Given: 1: import java.uti1.*; 2: import java.util.ArrayList; 3: class A { 4: private String name; 5: private ArrayList<Integer> list; 6: A() { list = new ArrayList<Integer>() ; } 7: String getName(){ return name; } 8: void addToList(int x) { list.add(x);} 9: ArrayList getList() { return list;} 10: } Which lines of code (if any) break encapsulation? a) Line 3 b) Line 4 c) Line 5 d) Line 7 e) Line 8 f) Line 9 g) The class is already well encapsulated

f) is correct. Line 9 breaks encapsulation. When encapsulating a mutable object like an ArrayList, the getter method must return a reference to a copy of the object, not just the reference to the original object as is the case on the line 9 below. 1: import java.uti1.*; 2: import java.util.ArrayList; 3: class A { 4: private String name; 5: private ArrayList<Integer> list; 6: A() { list = new ArrayList<Integer>() ; } 7: String getName(){ return name; } 8: void addToList(int x) { list.add(x);} 9: ArrayList getList() {return list;} 10: } Solution 1: Create a shallow copy of the ArrayList as follows by placing the original ArrayList (list) into the parameters of a new ArrayList: 1: import java.uti1.*; 2: import java.util.ArrayList; 3: class A { 4: private String name; 5: private ArrayList<Integer> list; 6: A() { list = new ArrayList<Integer>() ; } 7: String getName(){ return name; } 8: void addToList(int x) { list.add(x);} 9: ArrayList getList(){ return new ArrayList(list);} 10: } Solution 2: Use the targetList.addAll(sourceList) method. 1: import java.uti1.*; 2: import java.util.ArrayList; 3: class A { 4: private String name; 5: private ArrayList<Integer> list; 6: A() { list = new ArrayList<Integer>() ; } 7: String getName(){ return name; } 8: void addToList(int x) { list.add(x);} 9: ArrayList getList(){ 10: ArrayList alCopy = new ArrayList(); 11: alCopy.addAll(list); 12: return alCopy; 13: } 14: }

Which of the following methods are not inside the String class? a) public int length() b) public String concat(String str) c) public String substring(int beginIndex) d) public String substring(int beginIndex, int endIndex) e) public String trim() f) public String reverse()

f) is correct. There is no such method as reverse() in the String class as this method is located in the StringBuilder class. The String objects are immutable. That means that when you create a String object, it cannot be changed. The String class has a number of methods and whilst it would not be practical memorise all of them, it would be advisable to memorise some of them. Below is an abbreviation to help you memorise some methods of the String class that you may see in the exam: lc-ss-tr • length() • concat(String str) • substring(int beginIndex) • substring(int beginIndex, int endIndex) • trim() • replace(char oldChar, char newChar) The above methods are explained in more detail below: ➤ public int length(): The above method returns the length of this string. E.g. String h = "Hello"; int i = h.length(); System.out.println(i); The above will output 5. ➤ public String concat(String str): The above method returns a new String with both strings joined together. E.g. String h = "Hello"; String newString = h.concat(" There!"); System.out.println(newString); The above will print: "Hello There!" Note: The concat() method has the same result as adding two strings together e.g. "Hello" +" There!" ➤ public String substring(int beginIndex) The above method returns a string that is a substring of the original string, starting at the index 'beginIndex'. E.g. String h = "Hello"; String newString = h.substring(3); System.out.println(newString); The above will output: "lo" In the above, the beginning index of the string "Hello" is 3. A new String object is created containing the substring "lo" and is assigned to the new reference 'newString'. The original string object "Hello" with reference 'h' remains unchanged. Note: The index values of the string are: "H" = index 0 "e" = index 1 "l" = index 2 "l" = index 3 "o" = index 4 ➤public String substring(int beginIndex, int endIndex) The above method returns a string that is a substring of the original string. This substring starts at the index named 'beginIndex' and ends at the index named 'endIndex' -1. Make sure to subtract -1 from the ending index as this is not explicitly stated in the method signature. E.g. String h = "Hello"; String newString = h.substring(4,5); System.out.println(newString); The above will output: "o" In the above, the beginning index of the string "Hello" is 4. The ending index is 'endIndex', which is 5 - 1, which results in 4 Where the index values of the string are: "H" = index 0 "e" = index 1 "l" = index 2 "l" = index 3 "o" = index 4 Note 1: A new String object is created containing the substring "o" and is assigned to the new reference 'newString'. The original string object "Hello" with reference 'h' remains unchanged. Note 2: The following would give a java.lang.StringIndexOutOfBoundsException String h = "Hello"; String newString = h.substring(4,6); The ending index is 'endIndex', which is 6 - 1, which results in 5. As index 5 is outside of the bounds of the "Hello" string (because the last index value of the string is 4), this will give StringIndexOutOfBoundsException ➤ public String trim() The above method returns a string whose value is this string, with any leading and trailing whitespace removed. E.g. String h = " Hello "; String newString = h.trim(); System.out.println(newString); The above will output "Hello" ➤ public String replace(char oldChar, char newChar) The above returns a string resulting from replacing all occurrences of oldChar in this string with newChar. E.g. String h = "Hello"; String newString = h.replace('H', 'F'); System.out.println(newString); The above replaces the character 'H' with the character 'F' in the string "Hello" and stores this changed string in a new string named 'newString' This results in the output: "Fello" Note: As a consequence of String immutability, the result of the replace() method on the original string object "Hello" (with reference 'h') gets assigned a new reference which is a new object entirely independent of the original string 'h'.


Conjuntos de estudio relacionados

3.1.10 spanish written assignment

View Set

Survey of the Criminal Justice System Exam 1

View Set

Compensations-Benefits Topic 4-5

View Set

AI-102: Designing and Implementing a Microsoft Azure AI Solution

View Set

Principles of Accounting Chapter 5

View Set

Nursing Management: Patients With Urinary Disorders

View Set