├── .gitignore ├── LICENSE ├── README.md └── src ├── oca └── chapter │ ├── one │ ├── Chick.java │ ├── InstanceInitializer.java │ ├── README.md │ └── Zoo.java │ └── two │ ├── BinaryArithmetic.java │ ├── JavaStatements.java │ └── README.md └── ocp └── chapter ├── eight ├── HidingExample.java ├── InitializationExample.java ├── PolymorphismOverridingExample.java └── README.md ├── eighteen ├── AtomicSheepManager.java ├── CheckResults.java ├── CyclicBarrierLionPenManager.java ├── LionPenManager.java ├── README.md ├── SheepManager.java └── SyncSheepManager.java ├── eleven ├── README.md ├── care │ ├── module-info.java │ └── zoo │ │ └── animal │ │ └── care │ │ ├── details │ │ └── HippoBirthday.java │ │ └── medical │ │ └── Diet.java ├── feeding │ ├── module-info.java │ └── zoo │ │ └── animal │ │ └── feeding │ │ └── Task.java ├── mods │ ├── zoo.animal.care.jar │ ├── zoo.animal.feeding.jar │ ├── zoo.animal.talks.jar │ └── zoo.staff.jar ├── staff │ ├── module-info.java │ └── zoo │ │ └── staff │ │ └── Jobs.java └── talks │ ├── module-info.java │ └── zoo │ └── animal │ └── talks │ ├── content │ ├── ElephantScript.java │ └── SeaLionScript.java │ ├── media │ ├── Announcement.java │ └── Signage.java │ └── schedule │ ├── Weekday.java │ └── Weekend.java ├── fifteen └── README.md ├── five ├── ManipulatingArrays.java ├── ManipulatingStrings.java └── README.md ├── fourteen ├── ComparatorExample.java ├── ListExamples.java ├── MapExamples.java ├── README.md └── SetExamples.java ├── nine ├── AbstractExample.java └── README.md ├── seven ├── README.md ├── StaticExamples.java └── VarargsExample.java ├── six ├── Animal.java ├── ComparatorExample.java ├── ConsumerExample.java ├── LambdaApiUsage.java ├── PredicateSearch.java ├── README.md └── SupplierExample.java ├── sixteen └── README.md ├── ten ├── ExceptionExamples.java └── README.md ├── thirteen └── README.md └── twelve ├── README.md ├── Season.java └── TraditionalSearch.java /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | *.class 8 | 9 | ### STS ### 10 | .apt_generated 11 | .classpath 12 | .factorypath 13 | .project 14 | .settings 15 | .springBeans 16 | .sts4-cache 17 | 18 | ### IntelliJ IDEA ### 19 | .idea 20 | *.iws 21 | *.iml 22 | *.ipr 23 | out/ 24 | 25 | ### NetBeans ### 26 | /nbproject/private/ 27 | /nbbuild/ 28 | /dist/ 29 | /nbdist/ 30 | /.nb-gradle/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Java Certification - 1Z0-819 Java SE 11 Developer 2 | 3 | Repository dedicated to **my** studies of the needed content to obtain a Java 11 certification. It contains notes and chapter code from the OCA (Java 8) and OCP (Java 11) books. The certification exam that was the focus of this repo is the Oracle Certified Professional 1Z0-819 Java SE 11 Developer, for this exam you are expected to be familiar with all the topics in the OCP book. 4 | 5 | > **Note:** This content can be used in Java 8 and Java 17 certifications, since most of the content is the same, just make sure to search for key changes on Java objects/libs while studying. 6 | 7 | ## [OCA-BOOK](./src/oca/chapter) 8 | 9 | - [Java Building Blocks](./src/oca/chapter/one) 10 | - [Operators and Statements](./src/oca/chapter/two) 11 | 12 | ## [OCP-BOOK](./src/ocp/chapter) 13 | 14 | - [Core Java APIs](./src/ocp/chapter/five) 15 | - [Lambdas and Functional Interfaces](./src/ocp/chapter/six) 16 | - [Methods and Encapsulation](./src/ocp/chapter/seven) 17 | - [Class Design](./src/ocp/chapter/eight) 18 | - [Advanced Class Design](./src/ocp/chapter/nine) 19 | - [Exceptions](./src/ocp/chapter/ten) 20 | - [Modules](./src/ocp/chapter/eleven) 21 | - [Java Fundamentals](./src/ocp/chapter/twelve) 22 | - [Annotations](./src/ocp/chapter/thirteen) 23 | - [Generics and Collections](./src/ocp/chapter/fourteen) 24 | - [Functional Programming](./src/ocp/chapter/fifteen) 25 | - [Exceptions, Assertions and Localization](./src/ocp/chapter/sixteen) 26 | - [Concurrency](./src/ocp/chapter/eighteen) 27 | -------------------------------------------------------------------------------- /src/oca/chapter/one/Chick.java: -------------------------------------------------------------------------------- 1 | package oca.chapter.one; 2 | 3 | public class Chick { 4 | 5 | private void printName() { 6 | System.out.println("Field 'name' has the value: " + name); 7 | } 8 | 9 | private String name = "Fluffy"; 10 | private long number = 2_147_483_648l; 11 | 12 | { System.out.println("Setting field 'name' with value: " + name); } 13 | 14 | public Chick() { 15 | name = "Tiny"; 16 | System.out.println("Setting Contructor..."); 17 | } 18 | 19 | public static void main(String[] args) { 20 | Chick chick = new Chick(); 21 | 22 | System.out.println(chick.name); 23 | System.out.println(chick.number); 24 | 25 | chick.printName(); 26 | } 27 | } -------------------------------------------------------------------------------- /src/oca/chapter/one/InstanceInitializer.java: -------------------------------------------------------------------------------- 1 | package oca.chapter.one; 2 | 3 | public class InstanceInitializer { 4 | 5 | public static void main(String[] args) { 6 | { System.out.println("Inside Main Method Code Block"); } 7 | 8 | new InstanceInitializer(); 9 | } 10 | 11 | { System.out.println("Instance Initializer"); } 12 | } -------------------------------------------------------------------------------- /src/oca/chapter/one/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 1 - Java Building Blocks 2 | 3 | ## Java Basics 4 | 5 | - Define the scope of variables; 6 | - Define the structure of a Java class; 7 | - Create executable Java applications with a main method; run a Java program from the command line; including console output; 8 | - Import other Java packages to make them accessible in your code; 9 | - Compare and contrast the features and components of Java such as platform independence, object orientation, encapsulation and etc; 10 | 11 | ## Working with Java Data Types 12 | 13 | - Declare and initialize variables (including casting or primitive types); 14 | - Differentiate between object reference variables and primitive variables; 15 | - Know how to read or write to object fiels; 16 | - Explain an Object's Lifecycle (creation, "dereference by reassignment" and garbage collection); 17 | 18 | Obs.: This chapter covers the same subjects as the Chapters 1 and 2 of the OCP-11 book, but it covers them in Java 8. 19 | 20 | ## Java comment types: 21 | 22 | //comment until end of line - single line comment 23 | 24 | /* Multiple 25 | * line comment 26 | */ 27 | 28 | /** 29 | * Javadoc multiple-line comment 30 | * @author Marcelo 31 | */ 32 | 33 | ## Compile commands: 34 | 35 | - javac Zoo.java -> Generates bytecode file (.class) 36 | - WITHOUT PACKAGE - java Zoo -> Executes generated file (Zoo.class) 37 | - p.14-15 - WITH PACKAGE - java chapter.one.Zoo from the \src (because the package is underneath him) -> Executes generated file (Zoo.class) 38 | - Obs.: Filename needs to match the name of a public class in the .java file to compile 39 | 40 | \*\* Rules for what a java code file content (p.6-10) 41 | 42 | - Each file can contain only one class; 43 | - The filename must match the class name, including case, and have a .java extension; 44 | - String[] args, String args[] or String...args - Compiler accepts any of these declarations of the main() parameters 45 | - Java only looks for class names in the packages 46 | - `import java.util.*;` -> \* is a 'wildcard' 47 | - When wildcards are used, java imports only the classes within a package 48 | - A wildcard only matches class names - ex: GOOD - `java.nio.file.*;` / NO GOOD - `java.nio.*;` 49 | - If there is a 'package' (folder) without any .java files inside declaring it as a package, Java wont compile any .java classes that import something from this non declared package. 50 | - `java.lang` package is automatically imported by Java. 51 | - Tip -> Always question yourself when reading a code in the exam, the question is `What imports would work to get this code to compile?` 52 | 53 | ## Naming conflicts (imports) - (p.12-19) 54 | 55 | - java.util and java.sql have a class with same name, which is Date 56 | 57 | import java.util.*; 58 | import java.sql.*; // DOES NOT COMPILE 59 | 60 | - When classes with the same name are found in multiple packages and imported inside one, Java gives you a compiler error: The type date is ambiguous 61 | - But if we explicitly import a class name it will take precedence over any wildcards present, for example, if we have a `import java.util.Date;` with a `import.java.sql.*;` in the same file, the `util.Date` will take precendence over the `sql.*`. 62 | - Another way to use the class, is importing one class as usual and the other one you can write down like this inside a method or class: `java.sql.Date sqlDate;` 63 | 64 | - Make sure that the exam question gives you the imports if there are no lines or they start at 1, 65 | if they start at something bigger than 1, you can assume that the imports are OK. 66 | - If there is no main() method on the code, assume that the main() method, 67 | class definition and all the necessary imports are present 68 | 69 | ## Order of Initialization Rules (p.19) 70 | 71 | - Fields and instance initializer blocks are run in the order in which they appear in the file; 72 | - The constructor runs after all fields and instance initializer blocks have run; 73 | 74 | ## Primitive Types Key Points (p.21-23) 75 | 76 | - A byte can hold a value from -128 to 127. 77 | 78 | Java allows you to specify digits in several other formats: 79 | 80 | - octal (digits 0-7), which uses the number 0 as a prefix - for ex., 017; 81 | - hexadecimal (digits 0-9 and letters A-F), which uses the number 0 followed by x or X as a prefix - for ex., 0xFF; 82 | - binary (digits 0-1), which uses the number 0 followed by b or B as a prefix - for ex., 0b101. You can add underscores anywhere except at the beginning of a literal, the end of a literal, right before a decimal point or right after a decimal point. 83 | 84 | ## Reference Types (p.24-34) 85 | 86 | - Reference types can be assigned null, which means they do not currently refer to an object. 87 | - Primitive types will give you a compiler error if you attempt to assign them null. Example: 88 | 89 | int value = null; // DOES NOT COMPILE - String s = null; COMPILE 90 | 91 | - You can declare and initialize as many variables you want in a single line (same statement), as long as they share the same type declaration and not repeat it. 92 | - Local variables must be initialized, if not, you'll get a compiler error when you try to read its value; 93 | - Instance variables are those that can be declared inside a class, without being static. 94 | - A class variable has the static keyword in its declaration; 95 | - Instance and class variables do not require you to initialize them. As soon as they are declared, they are given a default value. 96 | - Default values: 97 | - boolean = false; 98 | - byte, short, int, long = 0; 99 | - float, double = 0.0; 100 | - char = '\u0000' (NUL); 101 | - All object references (everything else) = null. 102 | 103 | ## Variables Scope Rules (p.34-35) 104 | 105 | - Local variables: in scope from declaration to end of block; 106 | - Instance variables: in scope from declaration until object garbage collected; 107 | - Class variables: in scope from declaration until the program ends. 108 | - Multiple classes can be defined in the same file, but only one of them is allowed to be public. 109 | 110 | ## Garbage Collection (p.36-38) 111 | 112 | The heap, also known as free store, represents a giant pool of unused memory allocated to your Java application; 113 | 114 | - System.gc() suggests that now might be a good time for Java to kick off a garbage collection run, but is not guaranteed that Java will run it; An object is no longer reachable when one of two situations occurs: 115 | - The object no longer has any references pointing to it; 116 | - All references to the object have gone out of scope. 117 | The method finalize() might not be called and it definitely won't be called twice to collect the object from the heap. 118 | 119 | > Obs.: Objects are always on the heap. 120 | -------------------------------------------------------------------------------- /src/oca/chapter/one/Zoo.java: -------------------------------------------------------------------------------- 1 | package oca.chapter.one; 2 | import java.util.Random; 3 | 4 | //After compiling the .java file, to execute this class type java oca.chapter.one.Zoo "San Diego" Zoo from the \src folder 5 | public class Zoo { 6 | 7 | public Zoo() { 8 | System.out.println("Contructor"); 9 | } 10 | 11 | public static void main(String[] args) { 12 | System.out.println("Welcome!"); 13 | 14 | System.out.println(args[0]); 15 | System.out.println(args[1]); 16 | 17 | System.out.println(new Random().nextInt(100)); 18 | 19 | Zoo zoo = new Zoo(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/oca/chapter/two/BinaryArithmetic.java: -------------------------------------------------------------------------------- 1 | package oca.chapter.two; 2 | 3 | public class BinaryArithmetic { 4 | 5 | public static void main(String[] args) { 6 | 7 | // Numeric promotion rules examples, this rules applies to any binary arithmetic operations (+, -, /, %). 8 | 9 | short a = 1; 10 | short b = 2; 11 | 12 | /* Smaller data types (byte, short and char) are promoted to int, 13 | / so the result of a + b is a int value. 14 | */ 15 | int c = a + b; 16 | 17 | System.out.println(c); 18 | 19 | short x = 14; 20 | float y = 14; 21 | double z = 4; 22 | 23 | /* Promotes x to int, then promotes x to float and multiplies x and y, 24 | / then promotes x and y result (float type) to double, so it can finnaly 25 | / be divided with z, resulting in a double value. 26 | */ 27 | double r = x * y / z; 28 | 29 | System.out.println(r); 30 | 31 | /* Obs.: Applying a unary operator (ex.: ++ or --) to a short value results in a short value, 32 | / unary operators are excluded from the third rule. 33 | */ 34 | short u = 1; 35 | 36 | System.out.println(++u); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/oca/chapter/two/JavaStatements.java: -------------------------------------------------------------------------------- 1 | package oca.chapter.two; 2 | 3 | public class JavaStatements { 4 | 5 | public static void main(String[] args) { 6 | int x = 5; 7 | 8 | if (x == 5) { 9 | System.out.println("if-then block"); 10 | } 11 | 12 | if (x == 5) 13 | System.out.println("if-then single line"); 14 | 15 | if (x == 5) { 16 | System.out.println("if-then-else true branch"); 17 | } else { 18 | System.out.println("if-then-else false branch"); 19 | } 20 | 21 | if (x != 5) 22 | System.out.println("if-then-else single line true branch"); 23 | else 24 | System.out.println("if-then-else single line false branch"); 25 | 26 | if (x != 5) 27 | System.out.println("if-then-else single line true branch"); 28 | else { 29 | System.out.println("if-then-else single line false branch"); 30 | } 31 | 32 | if (x > 5) { 33 | System.out.println("if-then-else-if-then first if true branch"); 34 | } else if (x == 5) { 35 | System.out.println("if-then-else-if-then second if true branch"); 36 | } else { 37 | System.out.println("if-then-else-if-then block false branch"); 38 | } 39 | 40 | int y = x == 5 ? 10 : 0; // () on the operands are optional; 41 | 42 | System.out.println("ternary result = " + y); 43 | 44 | System.out.println("\n----------------------------------------\n"); 45 | 46 | switch(y) { 47 | case 0: // If the value is 0, it will print all the cases 48 | System.out.println("Monday..."); // until it finds a break statement or finishes the structure. 49 | default: 50 | System.out.println("Weekday."); // Prints only Friday because the value of y is 10, but if the default block was called, 51 | case 10: // in case of no match, Weekday and Friday would be printed (no break on the default). 52 | System.out.println("Friday!"); 53 | break; 54 | } 55 | 56 | System.out.println("\n----------------------------------------\n"); 57 | 58 | int bitesOfCheese = 10; 59 | int roomInBelly = 5; 60 | 61 | while (bitesOfCheese > 0 && roomInBelly > 0) { 62 | --bitesOfCheese; 63 | --roomInBelly; 64 | } 65 | 66 | System.out.println(bitesOfCheese + " pieces of cheese left."); 67 | 68 | int chips = 10; 69 | int roomInPackage = 5; 70 | 71 | do { 72 | --chips; 73 | --roomInPackage; 74 | } while (chips > 0 && roomInPackage > 0); 75 | 76 | System.out.println(chips + " chips left."); 77 | 78 | System.out.println("\n----------------------------------------\n"); 79 | 80 | int f = 0; 81 | 82 | for(long i = 0, p = 4; f < 5 && i < 10; f++, i++) { 83 | System.out.println(i + " "); 84 | } 85 | 86 | String[] names = new String[3]; 87 | 88 | // Prints 3 null values 89 | for (String name : names) { 90 | System.out.println(name + " "); 91 | } 92 | 93 | java.util.List values = new java.util.ArrayList<>(); 94 | 95 | // Doesn't iterate over this empty ArrayList. 96 | for (String value : values) { 97 | System.out.println(value + " "); 98 | } 99 | 100 | System.out.println("\n----------------------------------------\n"); 101 | 102 | int [][] myComplexArray = new int[][] {{5,2,1,3}, {3,9,8,9}, {5,7,12,7}}; 103 | // int [][] myComplexArray = {{5,2,1,3}, {3,9,8,9}, {5,7,12,7}}; Both compile 104 | 105 | for (int[] mySimpleArray : myComplexArray) { 106 | for (int i = 0; i < mySimpleArray.length; i++) { 107 | System.out.println(mySimpleArray[i] + "\t"); 108 | } 109 | System.out.println(); 110 | } 111 | 112 | int nestedWhileX = 20; 113 | 114 | while (nestedWhileX > 0) { 115 | 116 | do { 117 | nestedWhileX -= 2; 118 | } while (nestedWhileX > 5); 119 | 120 | nestedWhileX--; 121 | System.out.println(nestedWhileX + "\t"); 122 | } 123 | } 124 | } -------------------------------------------------------------------------------- /src/oca/chapter/two/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 2 - Operators and Statements 2 | 3 | - Using Operators and Decision Constructs (decision-making controls structures) 4 | 5 | - Use Java operators; including parentheses to override operator precedence; 6 | - Create if, if/else and ternary constructs; 7 | - Use a switch statement; 8 | 9 | - Using Loop Constructs (repetion control structures) 10 | - Create and use while loops; 11 | - Create and use for loops, including the enhanced for loop; 12 | - Create and use do/while loops; 13 | - Compare loop constructs; 14 | - Use break and continue; 15 | 16 | Ps.: This chapter covers the same subjects as the Chapters 3 and 4 of the OCP-11 book, but it covers them in Java 8. 17 | 18 | ## Operators (p.52-55) 19 | 20 | - Three types of operators are available in Java: unary (++, --), binary(+, -, \*, /, %) and ternary(a ? b : c); 21 | - Unless overridden with parentheses, Java operators follow order of operation; 22 | - If two operators have the same level of precedence, then Java guarantees left-to-right evaluation; 23 | - All of the arithmetic operators may be applied to any Java primitives, except boolean; 24 | - To String values, only the addition operators + and += may be applied, which results in String concatenation; 25 | - Modulus operation (%) may also be applied to negative integers and floating-point integers; 26 | 27 | * Order of operator precedence (decreasing order of precedence): 28 | 29 | - Post-unary operators - expression++, expression-- 30 | - Pre-unary operators - ++expression, --expression 31 | - Other unary operators - ~, + (positive), - (negative/negates a expression), ! (inverts a boolean's logical value) 32 | - Multiplication/Division/Modulus - \*, /, % 33 | - Addition/Subtraction - +,- 34 | - Shift operators - <<, >>, >>> 35 | - Relational operators - <, >, <=, >=, instanceof 36 | - Equal to/not equal to - ==, != 37 | - Logical operators - &, ^, | - (Evaluates all conditions) 38 | - Short-circuit logical operators - &&, || (Short circuit on the first true) 39 | - Ternary operators - boolean expression ? expression1 : expression2 40 | - Assignment operators - =, +=, -=, \*=, /=, %=, &=, ^=, <<=, >>=, >>>= 41 | 42 | ## Numeric promotion rules (p.55-56) 43 | 44 | - If two values have different data types, Java will automatically promote one of the values 45 | to the larger of the two data types (ex.: short -> int or long); 46 | - If one of the values is integral and other is floating-point, Java will automatically promote 47 | the integral value to the floating-point value's data type; 48 | - Smaller data types, namely byte, short and char, are first promoted to int any time they're 49 | used with a Java binary arithmetic operator, even if neither of the operands is int; 50 | - After all promotion has occurred and the operands have the same data type, the resulting value 51 | will have the same data type as its promoted operands; 52 | 53 | ## Increment and Decrement Operators (p.59) 54 | 55 | There are two orders that can be applied when using these operators: 56 | PRE (++x or --x) and POST (x++ or x--); 57 | Examples of the distinction (code snippet): 58 | 59 | int counter = 0; 60 | System.out.print(counter); // Outputs 0 61 | System.out.print(++counter); // Outputs 1 62 | System.out.print(counter); // Outputs 1 63 | System.out.print(counter--); // Outputs 1 64 | System.out.print(counter); // Outputs 0 65 | 66 | int x = 3; 67 | int y = ++x * 5 / x-- + --x; 68 | System.out.println("x is " + x); 69 | System.out.println("y is " + y); 70 | 71 | Simplify this: 72 | 73 | int y = 4 * 5 / x-- + --x; // x assigned value of 4 74 | then 75 | int y = 4 * 5 / 4 + --x; // x assigned value of 3 76 | then 77 | int y = 4 * 5 / 4 + 2; // x assigned value of 2 then the result is `x is 2` and `y is 7` 78 | 79 | ## Overflow and Underflow (p.61) 80 | 81 | Overflow is when a number is so large that it will no longer fit within the data type, so the system "wraps around" to the next lowest value and counts up from there. There is a analogous Underflow, when the number is too low to fit in the data type. For example: 82 | 83 | - `System.out.print(2147483647+1); // -2147483648` 84 | Since 2147483647 is the maximum int value, adding any strictly positive value to it will cause it to wrap to the next negative number. 85 | 86 | ## Relational Operators (p.63) 87 | 88 | The instanceof operator is the fifth relational operator, and it's applied to object references and classes or interfaces. 89 | 90 | - `a instanceof b` - True if the reference that 'a' points to is an instance of a class, subclass or class that implements a particular interface, as named in 'b'. 91 | 92 | ## Equality Operators (p.65) 93 | 94 | The equality operators (== and !=) are used in one of three scenarios: 95 | 96 | 1. Comparing two numeric primitive types. If the numeric values are of different data types, the values are automatically promoted as previously described. For example, 5 == 5.00 returns true since the left side is promoted to a double. 97 | 2. Comparing two boolean values. 98 | 3. Comparing two objects, including null and String values. 99 | 100 | - For object comparison, the equality operator is applied to the references to the objects, not the objects they point to; 101 | - Two references are equal if and only they point to the same object or both point to null. 102 | 103 | ## The if-then Statement (p.67-68) 104 | 105 | - For readability, it is considered good coding practice to put blocks around the execution component of if-then 106 | statements, as well as many other control flow statements, although it is not required: 107 | - Single line statement: 108 | - `if (boolean condition) expression //branch if true;`. 109 | 110 | ## The if-then-else Statement (p.69-70) 111 | 112 | - The else operator takes a statement or block of statements, in the same manner 113 | as the if statement does (`if (b) {} else {}` or `if (b) {} else if (b2) {}`); 114 | 115 | - Using a if-then-else statement in a single line works, but remember to guarantee that all the semicolons (;) are written: 116 | 117 | if (x != 5) System.out.println("if-then-else single line true branch") // DOES NOT COMPILE 118 | else System.out.println("if-then-else single line false branch"); 119 | 120 | ## Ternary Operator (p.71) 121 | 122 | - It takes 3 operands, a boolean expression (condition) and two expressions of any kind that returns a value; 123 | - Note that it is often helpful for readability to add parentheses around the expressions in ternary operators, although it is certainly not required; 124 | - In the exam, pay extra attention to any cases which a variable can be modified by the right-hand side expressions of a ternary; 125 | 126 | ## The switch Statement (p.72-75) 127 | 128 | - Supported data types are byte, short, char, int, enum values, String, Byte, Short, Character and Integer. 129 | - A switch statement may contain 0 or more case branches, break inside the case is optional, and the default is optional and it may appear anywhere within the switch statement. 130 | - The values in each case statement must be compile-time constant values of the same data type as the switch value, this means that you can use only literals, enum constants or final constant variables of the same data type. A final constant is a variable that is marked with the final modifier and initialized with a literal value in the same expression in which it is declared. 131 | - If there isn't a break statement on the default or case block, flow will continue to the next proceeding case or default block automatically until it finds a break statement or finishes the structure. 132 | 133 | ## The while Statement (p.77) 134 | 135 | - Curly braces are required for block of multiple statements and optional for single statement. 136 | - The loop may terminate after its first evaluation of the boolean expression (returning a false), in this manner, the statement block may never be executed (while evaluates before continuing execution). 137 | 138 | ## The do-while Statement (p.78) 139 | 140 | - Curly braces are required for block of multiple statements and optional for single statement. 141 | - Unlike a while loop, a do-while loop guarantees that the statement or block will be executed at least once. 142 | 143 | ## The Basic for Statement (p.80-83) 144 | 145 | - Curly braces are required for block of multiple statements and optional for single statement. 146 | - Its composed of 3 sections, an initialization block, boolean expression and an update statement (`for (initialization; booleanExpression; updateStatement)). 147 | 148 | * Basic for steps are: 149 | 150 | 1. Initialization statement executes. 151 | 2. If booleanExpression is true continue, else exit loop. 152 | 3. Body executes. 153 | 4. Execute updateStatement. 154 | 5. Return to Step 2. 155 | 156 | - The initialization and update sections may contain multiple statements, separated by commas (,). 157 | 158 | * Some examples of exam basic for variations and edge cases: 159 | 160 | 1. Creating an Infinite Loop 161 | 162 | - `for( ; ; ) { ... }` 163 | - This example will compile, it is an infinite loop that will run the body repeatedly. 164 | - `for( ; )` or `for( )` will not compile. 165 | 166 | 2. Adding Multiple Terms to the for Statement 167 | 168 | - `int x = 0; for(long y = 0, z = 4; x < 5 && y < 10; x++, y++) { ... } // COMPILES` 169 | - This example will compile, since you can add multiple terms into basic for sections. 170 | 171 | 3. Redeclaring a Variable in the Initialization Block 172 | 173 | - `int x = 0; for(long y = 0, x = 4; x < 5 && y < 10; x++, y++) { ... } // DOES NOT COMPILE` 174 | 175 | - Does not compile because x is repeated in the initialization block after being already being declared before the loop, resulting the compiler stopping because of a duplicate variable declaration, we can fix this removing the declaration on the for and only assigning the values to x and a pre declared y. 176 | 177 | - `int x = 0; long y = 10; for(y = 0, x = 4; x < 5 && y < 10; x++, y++) { ... } // COMPILES` 178 | 179 | 4. Using Incompatible Data Types in the Initialization Block 180 | 181 | - `for(long y = 0, int x = 4; x < 5 && y < 10; x++, y++) { ... } // DOES NOT COMPILES` 182 | - The variables in the initialization block must all be of the same type. 183 | 184 | 5. Using Loop Variables Outside the Loop 185 | - `for(long y = 0, x = 4; x < 5 && y < 10; x++, y++) { ... } System.out.println(x); // DOES NOT COMPILE` 186 | 187 | ## The for-each Statement (enhanced for) (p.83) 188 | 189 | - Curly braces are required for block of multiple statements and optional for single statement. 190 | - The for-each loop declaration is composed of an initialization section and an object to be iterated over. 191 | - The right-hand side of the loop (iterable collection of objects) must be a built-in Java array or an object whose class implements java.lang.Iterable (includes most of the Java Collections framework). 192 | - The left-hand side of the loop (collection member) must include a declaration for an instance of a variable, whose type matches the type of a member of the array or collection in the right-hand side of the statement. 193 | 194 | ## Optional Labels, break Statement and continue Statement (p.87-91) 195 | 196 | - if-then statements, switch statements and loops can all have optional labels. 197 | - A label is an optional pointer to the head of a statement that allows the application flow to jump to it or break from it. 198 | - It is rarely considered good coding practice to use this labels to control and block structures, 199 | they are mostly used in loop structures. 200 | Ex.: `OUTER_LOOP: for(long y = 0, z = 4; x < 5 && y < 10; x++, y++) { break OUTER_LOOP; } // COMPILES` 201 | - Not using a label on a 'break' statement (`break` instead of `break LOOP:`) will make the break statement terminate the nearest inner loop it is currently on the process of executing. 202 | - 'continue' statement syntax and usage mirrors the break statement, but has different results. 203 | - Difference between 'break' and 'continue' statements: While the break statement transfers control to the enclosing statement, terminating the execution of a loop, the continue statement transfers control to the boolean expression that determines if the loop should continue. In other words, it ends the current iteration of the loop. 204 | 205 | > Obs.: The if-then statement does not allow the usage of unlabeled break statement. The if-then and switch statements, both don't allow the continue statement usage. 206 | -------------------------------------------------------------------------------- /src/ocp/chapter/eight/HidingExample.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.eight; 2 | 3 | class Penguin { 4 | public static int getHeight() { return 3; } 5 | 6 | public void printInfo() { 7 | System.out.println(this.getHeight()); // Prints 3 - since the getHeight method isn't overridden, it's hidden. We can remove the this keyword in this case 8 | // since getHeight is static. 9 | } 10 | } 11 | 12 | public class HidingExample extends Penguin { 13 | public static int getHeight() { return 8; } 14 | 15 | public static void main(String... fish) { 16 | new HidingExample().printInfo(); 17 | } 18 | } -------------------------------------------------------------------------------- /src/ocp/chapter/eight/InitializationExample.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.eight; 2 | 3 | public class InitializationExample { 4 | 5 | public InitializationExample() { 6 | super(); 7 | System.out.println(test1 + test2); // Will print Test X, since the static members are initialized before the instance is. 8 | } 9 | 10 | { 11 | test2 = "X"; 12 | } 13 | 14 | private static String test1 = "Test "; 15 | 16 | private static String test2 = "this one too"; 17 | 18 | static { 19 | test2 = "Y"; 20 | } 21 | 22 | public static void main(String[] args) { 23 | 24 | new InitializationExample(); 25 | } 26 | } -------------------------------------------------------------------------------- /src/ocp/chapter/eight/PolymorphismOverridingExample.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.eight; 2 | 3 | class Penguin { 4 | public int getHeight() { return 3; } 5 | 6 | public void printInfo() { 7 | System.out.println(this.getHeight()); 8 | } 9 | } 10 | 11 | public class PolymorphismOverridingExample extends Penguin { 12 | public int getHeight() { return 8; } 13 | 14 | public void printThis() { 15 | super.printInfo(); // Prints 8 - because the object is a PolymorphismExample and the method getHeight has been overridden to return 8 16 | this.printInfo(); // Prints 3 - because printInfo has been overridden on PolymorphismExample and it calls super.getHeight (3) and not the this.getHeight (8) 17 | } 18 | 19 | public void printInfo() { 20 | System.out.println(super.getHeight()); 21 | } 22 | 23 | public static void main(String []fish) { 24 | new PolymorphismExample().printThis(); 25 | } 26 | } -------------------------------------------------------------------------------- /src/ocp/chapter/eight/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 8 - Class Design 2 | 3 | - Creating and Using Methods 4 | 5 | - Create methods and contructors with arguments and return values 6 | 7 | - Reusing Implementations Through Inheritance 8 | 9 | - Create and use subclasses and superclasses 10 | - Enable polymorphism by overriding methods 11 | - Utilize polymorphism to cast and call methods, differentiating object type versus reference type 12 | - Distinguish overloading, overriding and hiding 13 | 14 | ## Understanding Inheritance (p.298-299): 15 | 16 | - Is the process by which a subclass automatically includes any public or protected members of the class, including primitives, 17 | objects or methods, that are defined in the parent class. 18 | - Package-private members are only available if the child class is in the same package as the parent class. 19 | - private members are restricted to the class they are defined in and are never available via inheritance. This means that the 20 | direct access to them is restricted, but other members with more lenient access modifiers can modify and access them. 21 | 22 | ## Single vs. Multiple Inheritance (p.299-300): 23 | 24 | - Java allows a class Z to inherit from a class X and if that class X inherit from a class Y, then class Z will inherit the members of 25 | X and Y. 26 | - But it doesn't support multiple inheritance like this: `public class C extends A, B {}`. Because it can lead to complex often 27 | difficult-to-maintain data models. 28 | - Java does allow one exception to the single inheritance rule: A class may implement multiple interfaces. 29 | - The final modifier on a class, prevents the class from being extended. // Code will not compile if you try to extend a final class 30 | 31 | ## Inheriting Object (p.300): 32 | 33 | - All classes inherit from java.lang.Object. 34 | - Object is the only class that doesn't have a parent class. 35 | - The compiler automatically inserts code into any class you write that doesn't extend a specific class, adds the syntax `extends Object`. 36 | 37 | ## Creating and Extending a Class (p.301-302): 38 | 39 | - The declaration of a class has the following members: 40 | - Access modifier: public or default (package-private). 41 | - Optional modifier: abstract or final keyword (optional). 42 | - Class keyword: class (required). 43 | - Class name: AnyNameFollowingTheRules (required). 44 | - Extends parent class: extends Class (optional). 45 | - Implements interface(s): implements A, B... (optional). 46 | - Brackets (required) and body inside (optional). 47 | Obs.: Remember that final means a class cannot be extended. 48 | - If the classes are in the same package they don't require an import statement to access each other. 49 | 50 | ## Applying Class Access Modifiers (p.303): 51 | 52 | - In Java, a "top-level" class is a class that is not defined inside another class. 53 | - Classes can only have public or package-private access. 54 | Note: An inner class is a class defined inside of another class and is the opposite of a top-level class. Inner classes can have all 55 | access modifiers. 56 | - Remember, a Java file can have many top-level classes, but at most one public top-level class. 57 | 58 | ## Accessing the `this` Reference (p.304): 59 | 60 | - The this reference refers to the current instance of the class and can be used to access any members of the class, including inherited ones. 61 | - It can be used in any instance method, contructor and instance initializer block of the class. 62 | - It cannot be used when there is no implicit instance of the class, such as in a static method or static initializer block. 63 | - this reference is optional. 64 | - If Java encounters a variable or method it cannot find, it will check the class hierarchy to see if it is available. 65 | 66 | > **Note**: You can't use this inside static members, because this refers to an instance of the class and in static contexts you will 67 | > not have access to a reference. For static variables it's better to use static reference (not using the 'this' reference). 68 | 69 | ## Calling the super Reference (p.305-306): 70 | 71 | - The super reference is similar to the this reference, except that it excludes any members found in the current class. 72 | - You can use super to call members that have the same name in a class A that extends a class B. 73 | 74 | return super.type + ":" + this.type; 75 | 76 | - Java uses the narrowest scope it can, so if you don't use the super.type, it will pick the type variable from the class that its the caller. 77 | Obs.: If you try to call a member that doesn't exist on the superclass with `super`, the code will not compile, since super only looks at the 78 | parent's scope. 79 | 80 | ## Declaring Constructors (p.307): 81 | 82 | - Contructors are special methods that matches the name of the class and has no return type. 83 | - It is called only when a new instance of the class is created. 84 | - It is the last block to execute in the instantiation of a class. 85 | - Contructor parameters are similar to method parameters (Remember that they may not include var). 86 | - A class can have multiple contructors, so long as each contructor has a unique signature (parameters must be distinct). This practice is also 87 | known as 'contructor overloading'. 88 | - Contructors can only be called by writing new before the name of the class or this()/super() inside a constructor (first line of it). 89 | 90 | ## Default Contructor (p.308-309): 91 | 92 | - Every class in Java has a contructor whether you code one or not. If you don't include one, Java will create one for you implicitly without 93 | parameters. It is created during the compile step. 94 | - This Java-created contructor is called 'default contructor', also referred as the 'default no-argument contructor'. 95 | - It is declared as a `public` contructor without parameters and an empty body ({}). 96 | - Remember, private contructors prevents other classes from instantiating the class and static methods may access private members, 97 | including private contructors. 98 | 99 | ## Calling Overloaded Contructors with this() (p.310-311): 100 | 101 | - When this() is used with parentheses, Java calls another constructor on the same instance of the class. Searching for a signature with the same 102 | parameters specified inside the parentheses. 103 | - The rules for calling this() are: 104 | 105 | - It must be the first statement in the constructor. 106 | - There can be only one call to this() in any contructor. 107 | - A constructor can't call itself infinitely. 108 | Obs.: The compiler is capable of detecting this last one, since the code can never terminate, the compiler stops and reports this as an error. 109 | 110 | public class Gopher { public Gopher() { this(5); // Does not compile } 111 | public Gopher(int dugHoles) { this(); // Does not compile } } 112 | 113 | > **Note**: Despite using the same keyword, this and this() are very different. this, refers to an instance of the class, while this(), refers to a 114 | > constructor call within the class. 115 | 116 | ## Calling Parent Contructors with super() (p.312-314): 117 | 118 | - super() is very similar to this(), but instead it refers to any and only parent constructor. 119 | - It must be the first statement and there can be only one call to super() in any contructor, just like this(). 120 | - Any valid parent contructor is acceptable to be called inside the child contructors, as long as the appropriate input parameters to the parent 121 | constructor are provided. 122 | 123 | > **Note**: Like this and this(), super and super() are unrelated in Java. 124 | 125 | ## Understanding Compiler Enhancements (p.314-315): 126 | 127 | - The first line of every constructor is a call to either this() or super(), even if you don't code it. 128 | - Java compiler automatically inserts a call to the no-argument constructor super() if you do not explicitly call this() or super() at the first 129 | line of a constructor. 130 | - For example, this three constructor definitions are equivalent, because the compiler will automatically convert them all to the last example: 131 | 132 | public class Donkey {} 133 | public class Donkey { public Donkey() {} } 134 | public class Donkey { public Donkey() { super() } } 135 | 136 | \*\> **Notes** about classes with only private constructors: 137 | 138 | - Classes with only private constructors are not considered final. Because they can be extended, but only an inner class defined in the class 139 | itself can extend it. 140 | - An inner class is the only one that would have access to a private constructor and would be able to call super(). 141 | - Other top-level classes cannot extend such a class. 142 | 143 | ## Missing a Default No-Argument Constructor (p.315-316): 144 | 145 | - If a class extends a class that has no default no-argument constructor, having at least one constructor already, if this child class doesn't have one 146 | constructor, Java will insert a default no-argument constructor on the child and call super() by default, but the code will not compile since the parent 147 | class has already a constructor declared and it's not a no-argument constructor (because it has parameters). 148 | For example: 149 | 150 | public class Mammal { public Mammal (int a) {} } 151 | public class Elephant extends Mammal {} // DOES NOT COMPILE 152 | 153 | - It doesn't because there is no superclass no-argument constructor, so the implicit super() call on Elephant will fail. 154 | - Remember that Java will automatically create a no-argument constructor for Elephant with a call to super() at the first line. 155 | - To fix this, we can create a constructor in Elephant with a explicit call of super(int a). 156 | 157 | > **Note**: super() always refers to the most direct parent. 158 | 159 | ## Constructors and final Fields (p.316-318): 160 | 161 | - final instance variables can be initialized inside constructors, instance initializers or in the same line as they are declared. 162 | - static final variables (class variables) can't be initialized inside constructors, only in the same line as the declaration or inside a static initializer. 163 | - By the time the constructor completes (last block to be executed), all final instance variables must be assigned a value. \*\* 164 | - Unlike local final variables, which are not required to have a value unless they are actually used, final instance variables must be assigned. 165 | - Default values are not used for these variables. They aren't for static final variables too. 166 | - A final instance variable can be assigned a value only once, like the static final variables. Initializing them in more than one place, will result 167 | in a compiler error. 168 | - Each constructor is considered independently in terms of assignment. The constructor must initialize all final variables if they aren't before him, 169 | even if they are initialized in another constructor. 170 | - Failure to assign a value is considered a compiler error in the CONSTRUCTOR. 171 | - We can assign a null value to final instance variables, so long as they are explicitly set. 172 | 173 | ## Order of Initialization (p.318-324): 174 | 175 | - Class Initialization: 176 | 177 | - This is often referred to as 'loading the class', the JVM controls when the class is initialized, although you can assume the class is loaded before 178 | it is used, the reality is that the class may be initialized when the program first starts, when a static member of the class is referenced, or 179 | shortly before an instance of the class is created. 180 | - First, all static members in the class hierarchy are invoked, starting with the highest superclass and working downward. 181 | - The most important rule with class initialization is that it happens at most once for each class. 182 | - A class may also never be loaded if it is not used in the program. 183 | - Summarized order of initialization of a class X: 184 | 1. If there is a superclass Y of X, then initialize Y first. 185 | 2. Process all static variable declarations in the order they appear in the class. 186 | 3. Process all static initializers in the order they appear in the class. 187 | - Following the order they appear. 188 | 189 | > **Note**: The class containing the program entry point, aka the main() method, is loaded before the main() method is executed. 190 | 191 | - Instance Initialization: 192 | - An instance is initialized anytime the new keyword is used. 193 | - Summarized order of initialization of an instance of X: 194 | 1. If there is a superclass Y of X, then initialize the instance of Y first. 195 | 2. Process all instance variable declarations in the order they appear in the class. 196 | 3. Process all instance initializers in the order they appear in the class. 197 | 4. Initialize the constructor including any overloaded constructors referenced with this(). 198 | 199 | > **Note**: super() call on the child constructor is called before the initialization of the child class. It works like this because the parent class 200 | > is instantiated before the child class. 201 | 202 | > **Note for Class and Instance Initialization**: The order of initialization of the variables and initializer blocks will follow the declaring order of the class. You can't access or modify a variable inside a initializer block before she has been declared. 203 | 204 | - Reviewing Contructor Rules: 205 | 206 | 1. The first statement of every constructor is a call to an overloaded constructor via this(), or a direct parent constructor via super(). 207 | 2. If the first statement of a constructor is not a call to this() or super(), then the compiler will insert a no-argument super() as the first statement. 208 | 3. Calling this() and super() after the first statement of a contructor results in a compiler error. 209 | 4. If the parent class doesn't have a no-argument constructor, then every constructor in the child class must start with an explicit this() or super() call. 210 | 5. If the parent class doens't have a no-argument constructor and the child doesn't define any constructors, then the child class will not compile. 211 | 6. If a class only defines private constructors, then it cannot be extended, nor be instantiated by a top-level class. 212 | 7. All final instance variables must be assigned a value exactly once, if they are not initialized before the contructor call, they must be by the end of 213 | the constructor. Any final instance variables not assigned a value will be reported as a compiler error on the line the constructor is declared. 214 | 215 | - Exam Note: Before even attempting to answer the question on the exam, check if the constructors are properly defined using the previous set of rules. 216 | Also verify if the classes include valid access modifiers for members. 217 | 218 | ## Overriding a Method in Inheritance (p.326-332): 219 | 220 | - Remember that you can't have two methods with the same signature inside a class. 221 | - Occurs when a subclass declares a new implementation for an inherited method with the same signature and compatible return type. 222 | - You may reference the parent version of the method using the super keyword. 223 | - this and super keywords allow you to select between the current and parent versions of a method, respectively. 224 | - The compiler performs the following checks when you override a method: 225 | 1. The method in the child class must have the same signature as the method in the parent class. 226 | 2. The method in the child class must be at least as accessible as the method in the parent class (same or broader access modifer only). 227 | - The subclass can't reduce the visibility of the parent method. 228 | 3. The method in the child class may not declare a checked exception that is new or broader than the class of any exception 229 | declared in the parent class method (this rule only applies for CHECKED exceptions). 230 | - Basically, the overridden method can't be more restrictive than the inherit method. 231 | 4. If the method returns a value, it must be the same or a subtype of the method return type in the parent class, known as 'covariant return types'. 232 | - If the inherited method return type is void, then the overridden must be void too, as nothing is covariant with void except itself. 233 | - To check if two types are covariant: Given an inherited return type A and an overridden return type B, can you assign an instance of B to a 234 | reference of A without a cast? If so, then they are covariant (like String and CharSequence, all Strings are CharSequence since String 235 | implements CharSequence). 236 | 237 | * Defining Subtype and Supertype: 238 | 239 | - A subtype is the relationship between two types where one type inherits the other. 240 | - If we define X to be a subtype of Y, then one of the following is true: 241 | - X and Y are classes, and X is a subclass of Y. 242 | - X and Y are interfaces, and X is a subinterface of Y. 243 | - X is a class and Y is an interface, and X implements Y (either directly or through an inherited class). 244 | - Likewise, a supertype is the reciprocal relationship between two types where one type is the ancestor of the other. 245 | - Remember, a subclass is a subtype, but not all subtypes are subclasses (subinterfaces are subtypes too). 246 | 247 | * Overloading vs. Overriding: 248 | 249 | - If two methods have the same name but different signatures, the methods are overloaded and not overridden. 250 | - Overloaded methods are considered independent and do not share the same polymorphic properties as overridden methods. 251 | - Both involve redefining a method using the same name. 252 | - On overloaded methods the return type and parameter list can change. 253 | - On overridden methods the return type must be compatible with the parent's type and the parameter list can't change. 254 | 255 | * Access Modifiers on Overridden Methods: 256 | - Java avoids ambiguity caused by access modifiers being different in the parent and child methods, by limiting overriding a method to access modifiers 257 | that are as accessible or more accessible than the version in the inherited method. 258 | - If the parent method has public access, then the overridden method must be public too, other options will not compile. 259 | 260 | ## Overriding a Generic Method (p.332-334): 261 | 262 | - Remember that you can't overload methods with generic parameters, because of type erasure. Generics are used only at compile time. 263 | - So you can't overload with two Lists of different generics for example, because they will result in the same after (`List X` and `List Y`). 264 | - But you can override a method with generic parameters, since the signatures and the generic types match exactly. 265 | 266 | ## Redeclaring private Methods (p.334-335): 267 | 268 | - You can't override private methods, since they are not inherited. 269 | - Java permits you to redeclare a new method in the child class with the same or modified signature as the method in the parent class. 270 | This method in the child class is a separate and independent method, unrelated to the parent version's method, so none of the rules of 271 | overriding methods is invoked. Child classes may override only methods that are public, protected and package-private (if they are in 272 | the same package). 273 | 274 | ## Hiding Static Methods (p.335-337): 275 | 276 | - A hidden method occurs when a child class defined a static method with the same name and signature as an inherited static method defined in a parent class. 277 | - Method hiding is similar but not exactly the same as method overriding. 278 | - The previous four rules for overriding a method must be followed when a method is hidden. In addition, a new rule is added: 5. The method defined in the child class must be marked as static if it is marked as static in a parent class. 279 | 280 | ## Creating final Methods (p.337-338): 281 | 282 | - final methods cannot be replaced. By marking a method final you forbid a child class from replacing this method. 283 | - This rule is in place both when you override a method and when you hide a method. 284 | - Remember that this rule only applies to inherited methods. So if you have a inherited method that is not final, you can use the final 285 | on the overridden method. 286 | - Using final on methods will guarantee certain behavior of a method in the parent class, regardless of which child is invoking the method. 287 | 288 | > **Note**: All the rules listed above apply on this situations. 289 | 290 | ## Hiding Variables (p.338): 291 | 292 | - Remember that Java doesn't allow variables to be overridden. Variables can be hidden, though. 293 | - A hidden variable occurs when a child class defines a variable with the same name as an inherited variable defined in the parent class. 294 | This creates two distinct copies of the variable within an instance of the child class: 295 | - One instance defined in the parent class. 296 | - One instance defined in the child class. 297 | 298 | > **Note** on Hiding Inherited Members: Hiding a method or variable replaces the member only if a child REFERENCE type is used. Java uses the REFERENCE type to 299 | > use the member (p.339). 300 | 301 | ## Understanding Polymorphism (p.339-340): 302 | 303 | - The property of an object can take on many different forms. 304 | - A Java object may be accessed using a reference with the same type as the object, a reference that is a superclass of the object, or a reference that 305 | defines an interface the object implements, either directly or through a superclass. 306 | - Once the object has been assigned to a new reference type using polymorphism, only the methods and variables available to that reference type are 307 | callable on the object without an explicit cast. 308 | 309 | ## Object vs. Reference (p.341): 310 | 311 | - The object in memory will never change depending on the reference type you assign him. What changes is our ability to access members within the object, 312 | those being only the members of the reference type. We can have access back to the object members only if we do a direct cast back to the object type. 313 | - Summarizing this principle with the following two rules: 314 | 1. The type of the object determines which properties exist within the object in memory. 315 | 2. The type of the reference to the object determines which methods and variables are accessible to the Java program. 316 | 317 | ## Casting Objects (p.342-343): 318 | 319 | - Is similar to casting primitives. You do not need a cast operator if the current reference is a subtype of the target type (implicit cast or type conversion). 320 | - Alternatively, if the current reference is not a subtype of the target type, then you need to perform an explicit cast with a compatible type. 321 | - If the underlying object is not compatible with the type, then a ClassCastException will be thrown at runtime. \* 322 | - Summarizing these concepts into a set of rules: 323 | 1. Casting a reference from a subtype to a supertype doesn't require an explicit cast. 324 | 2. Casting a reference from a supertype to a subtype requires an explicit cast. 325 | 3. The compiler disallows casts to an unrelated class. 326 | 4. At runtime, an invalid cast of a reference to an unrelated type results in a ClassCastException being thrown. 327 | > **Note**: The third rule on casting applies to class types only, not interfaces. 328 | - The fourth rule will apply in a situation that either the reference type and object type are the same as the supertype, when trying to cast this object to 329 | an subtype reference, the ClassCastException will be thrown. Keep in mind that the object created with the parent's type does not inherit the child class. 330 | - When reviewing a question on the exam that involves this topics, be sure to remember what the instance of the object actually is. Then, focus on whether 331 | the compiler will allow the object to be referenced with or without explicit casts. 332 | 333 | ## The instanceOf Operator (p.343-344): 334 | 335 | - Can be used to check whether an object belongs to a particular class or interface and to prevent ClassCastException at runtime (inside a if for example). 336 | - The compiler does not allow instanceOf to be used with unrelated types, just like casting. 337 | 338 | ## Polymorphism and Method Overriding (p.344-345): 339 | 340 | - When a method is overridden in the subclass and called by a object of its type, all calls to it are replaced at runtime, meaning that the calls will be 341 | associated with the precise object in memory, not the current reference type where is called. Even using the this reference, it does not call the parent 342 | version because the method has been replaced. // Coded example on file PolymorphismOverridingExample.java 343 | - The facet of polymorphism that replaces methods via overriding is one of the most important properties of Java. It allows to create complex inheritance 344 | models, with subclasses that have their own custom implementation of overridden methods. 345 | 346 | ## Overriding vs. Hiding Members (p.346-347): 347 | 348 | - While method overriding replaces the method everywhere it is called, method (static) and variable hiding does not. 349 | - Hiding members is not a form of polymorphism since the methods and variables maintain their individual properties. 350 | - Hiding members is very sensitive to the reference type and location where the member is used. 351 | - Contrast this with overriding a method, where it returns the same value for an object regardless of which class it is called in. 352 | 353 | * Real World Scenario Note: Hiding variables and methods is allowed by Java, but it is considered an extremely poor coding practice. 354 | 355 | ## Summary (p.348): 356 | 357 | - All instance methods, contructors and instance initializers have access to this and super. 358 | - this() and super() can only be used in constructors, following the rules of constructors. 359 | - A method is overloaded if it has the same name but a different signature as another accessible method. 360 | - A method is overridden if it has the same signature as an inherited method and has access modifiers, exceptions and a return type that are compatible. 361 | - Remember that 'covariant types' only apply to return values of overridden methods, not method parameters. 362 | - A static method is hidden if it has the same signature as an inherited static method. Remember that the four rules plus a fifth rule are applied here. 363 | - A method is redeclared if it has the same name and possibly the same signature as an uninherited method (superclass private methods). 364 | - You can access private methods (instance methods and constructors) from the main() method, if he is declared inside the same class. 365 | -------------------------------------------------------------------------------- /src/ocp/chapter/eighteen/AtomicSheepManager.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.eighteen; 2 | 3 | import java.util.concurrent.*; 4 | import java.util.concurrent.atomic.*; 5 | 6 | // Thread-safe code example using Atomic classes, discussed about from line 556. 7 | public class AtomicSheepManager { 8 | private AtomicInteger sheepCount = new AtomicInteger(0); 9 | 10 | private void incrementAndReport() { 11 | System.out.println(sheepCount.incrementAndGet() + " "); 12 | } 13 | 14 | public static void main(String[] args) { 15 | ExecutorService service = null; 16 | try { 17 | service = Executors.newFixedThreadPool(20); 18 | AtomicSheepManager manager = new AtomicSheepManager(); 19 | for (int i = 0; i < 10; i++) 20 | service.submit(() -> manager.incrementAndReport()); 21 | } finally { 22 | if (service != null) service.shutdown(); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/ocp/chapter/eighteen/CheckResults.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.eighteen; 2 | 3 | import java.util.concurrent.*; 4 | 5 | // Using ExecutorService methods (submit()) to do polling on a class. 6 | // Thus example is the essence of the Concurrency API: to do complex things with threads without having to manage them directly. 7 | // Non thread-safe example, but its using a single-thread executor. 8 | public class CheckResults { 9 | 10 | private static int counter = 0; 11 | 12 | public static void main(String[] unused) throws Exception { 13 | ExecutorService service = null; 14 | 15 | try { 16 | service = Executors.newSingleThreadExecutor(); 17 | Future result = service.submit(() -> { 18 | for(int i = 0; i < 500; i++) { 19 | CheckResults.counter++; 20 | System.out.println(CheckResults.counter); 21 | }; 22 | }); 23 | result.get(10, TimeUnit.SECONDS); // This result is async, so if it takes more than 10 seconds, it'll throw the exception, but as we 24 | // are catching her, the submit task will continue until 500 and it will never print "Reached!". 25 | System.out.println("Reached!"); 26 | } catch (TimeoutException e) { 27 | System.out.println("Not reached in time"); 28 | } finally { 29 | if(service != null) service.shutdown(); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/ocp/chapter/eighteen/CyclicBarrierLionPenManager.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.eighteen; 2 | 3 | import java.util.concurrent.*; 4 | 5 | // Thread-safe example, it contains CyclicBarrier, discussed about from line 804. 6 | public class CyclicBarrierLionPenManager { 7 | private void removeLions() { System.out.println("Removing lions"); } 8 | private void cleanPen() { System.out.println("Cleaning the pen"); } 9 | private void addLions() { System.out.println("Adding lions"); } 10 | public void performTask(CyclicBarrier cb1, CyclicBarrier cb2) { 11 | try { 12 | removeLions(); 13 | cb1.await(); 14 | cleanPen(); 15 | cb2.await(); 16 | addLions(); 17 | } catch (InterruptedException | BrokenBarrierException e) { 18 | e.printStackTrace(); 19 | } 20 | } 21 | public static void main(String... args) { 22 | ExecutorService service = null; 23 | try { 24 | service = Executors.newFixedThreadPool(4); 25 | var manager = new CyclicBarrierLionPenManager(); 26 | var cb1 = new CyclicBarrier(4); 27 | var cb2 = new CyclicBarrier(4, () -> System.out.println("*** Pen Cleaned!")); 28 | for (int i = 0; i < 4; i++) 29 | service.submit(() -> manager.performTask(cb1, cb2)); 30 | } finally { 31 | if (service != null) service.shutdown(); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/ocp/chapter/eighteen/LionPenManager.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.eighteen; 2 | 3 | import java.util.concurrent.*; 4 | 5 | // Non thread-safe example, it does not contain CyclicBarrier, discussed about from line 804. 6 | public class LionPenManager { 7 | private void removeLions() { System.out.println("Removing lions"); } 8 | private void cleanPen() { System.out.println("Cleaning the pen"); } 9 | private void addLions() { System.out.println("Adding lions"); } 10 | public void performTask() { 11 | removeLions(); 12 | cleanPen(); 13 | addLions(); 14 | } 15 | public static void main(String... args) { 16 | ExecutorService service = null; 17 | try { 18 | service = Executors.newFixedThreadPool(4); 19 | var manager = new LionPenManager(); 20 | for (int i = 0; i < 4; i++) 21 | service.submit(() -> manager.performTask()); 22 | } finally { 23 | if (service != null) service.shutdown(); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/ocp/chapter/eighteen/SheepManager.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.eighteen; 2 | 3 | import java.util.concurrent.*; 4 | 5 | // Non thread-safe code example, discussed about from line 518. 6 | public class SheepManager { 7 | private int sheepCount = 0; 8 | 9 | private void incrementAndReport() { 10 | System.out.println((++sheepCount)+" "); 11 | } 12 | 13 | public static void main(String[] args) { 14 | ExecutorService service = null; 15 | try { 16 | service = Executors.newFixedThreadPool(20); 17 | SheepManager manager = new SheepManager(); 18 | for (int i = 0; i < 10; i++) 19 | service.submit(() -> manager.incrementAndReport()); 20 | } finally { 21 | if (service != null) service.shutdown(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/ocp/chapter/eighteen/SyncSheepManager.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.eighteen; 2 | 3 | import java.util.concurrent.*; 4 | 5 | // Thread-safe code example using the synchronized block, discussed about from line 595. 6 | public class SyncSheepManager { 7 | private int sheepCount = 0; 8 | 9 | public void incrementAndReport() { 10 | synchronized(this) { 11 | System.out.println((++sheepCount)+" "); 12 | } 13 | } 14 | 15 | public static void main(String[] args) { 16 | ExecutorService service = null; 17 | try { 18 | service = Executors.newFixedThreadPool(20); 19 | SyncSheepManager manager = new SyncSheepManager(); 20 | for (int i = 0; i < 10; i++) 21 | service.submit(() -> manager.incrementAndReport()); 22 | } finally { 23 | if (service != null) service.shutdown(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/ocp/chapter/eleven/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 11 - Modules 2 | 3 | - Understanding Modules 4 | - Describe the Modular JDK. 5 | - Declare modules and enable access between modules. 6 | - Describe how a modular project is compiled and run. 7 | 8 | ## Introducing Modules (p.454-457) 9 | 10 | - Since Java 9, packages can be grouped into modules. 11 | - When you have a big project that consist of hundred or thousand of classes grouped into packages, all these packages 12 | are grouped into Java archive (JAR) files. A JAR is a zip file with some extra info, and the extension is .jar. 13 | - The main purpose of a module is to provide groups of related packages to offer a particular set of functionality to 14 | developers. It's like a JAR file except a developer chooses which packages are accessible outside the module. 15 | - A complex chain of dependencies and minimum version is often referred to by the community as JAR hell. 16 | - The Java Platform Module System (JPMS) includes the following: 17 | - A format for module JAR files. 18 | - Partitioning of the JDK into modules. 19 | - Additional command-line options for Java tools. 20 | - A module is a group of one or more packages plus a special file called module-info.java. 21 | - Modules have 'dependencies' between them, where one module can relie on code that is in another. 22 | - Using modules is optional. 23 | 24 | * Benefits of Modules 25 | - Better Access Control: Modules can act like as a fifth level of access control. They can expose packages within the 26 | modular JAR to specific packages. 27 | - Clearer Dependency Management: In a fully modular environment, each of the open source projects specify their dependencies 28 | in the module-info.java file. When launching the program, Java will complain that a library isn't in the module path in case 29 | it isn't and you'd know right away, instead of just blowing up on runtime with a message about not finding a required class 30 | if you forget to include a library in the classpath (nonmodular). 31 | - Custom Java Builds: 32 | - In the past, Java attempted to solve the size of JRE and JDK with a compact profile. The three compact profiles provided 33 | a subset of the built-in Java classes so there would be a smaller package for mobile and embedded devices. However, the 34 | compact profiles lacked flexibility, because many packages were included that developers were unlikely to use and at the 35 | same time, using other packages like Image I/O required the full JRE. 36 | - The JPMS allows developers to specify which modules they actually need. This makes it possible to create a smaller runtime 37 | image that is customized to what the application needs and nothing more. Users can run that image without having Java 38 | installed at all. 39 | - Improved Performance: Since Java now knows which modules are required, it only needs to look at those at class loading time. 40 | This improves startup time for big programs and requires less memory to run. This impacts mostly big applications. 41 | - Unique Package Enforcement: 42 | - Another manifestation of JAR hell is when the same package is in two JARs. There are number of causes of this problem 43 | including renaming JARs, or clever developers using a package name that is already taken and having two version of the 44 | same JAR on the classpath. 45 | - The JPMS prevents this scenario, by making a package allowed to be supplied by only one module. No more unpleasant surprises about 46 | a package at runtime. 47 | 48 | ## Creating, Compiling, Running and Packaging a Modular Program (p.458-464) 49 | 50 | - Note: There is lots of practice in this chapter, so the .java files are located in subpackages of packages eleven and other. 51 | 52 | - There are a few key differences between a module-info file and a regular Java class: 53 | - The module-info file must be in the root directory of your MODULE. Regular Java classes should be in packages. 54 | - The module-info file must use the keyword module instead of class, interface or enum. 55 | - The module name follows the naming rules for package names. It often includes periods (.) in its name. Regular class and package 56 | names are not allowed to have dashes (-) and module names follows the same rule. 57 | - A module-info.java file can be empty. The compiler sees there isn't a class in there and exits without creating a .class file. 58 | - A module-info file can be empty (zero-bytes), but its required to be created 59 | - You can think of module-path as replacing the classpath option when you are working on a modular program. 60 | - Some valid commands that can be used to compile a module (using package eleven or single_module_c11 as the 'root' directory to 61 | execute and feeding as the module root): 62 | 63 | - `javac --module-path mods -d feeding feeding/zoo/animal/feeding/*.java feeding/module-info.java` 64 | - `javac -p mods -d feeding feeding/zoo/animal/feeding/*.java feeding/*.java` 65 | - `javac -p mods -d feeding feeding/zoo/animal/feeding/*.java feeding/module-info.java` 66 | - `javac -p mods -d feeding feeding/zoo/animal/feeding/Task.java feeding/module-info.java` 67 | - `javac -p mods -d feeding feeding/zoo/animal/feeding/Task.java feeding/*.java` 68 | 69 | - --module-path and -p are equivalent. 70 | - The usage of classpath is still available on Java 11, with it's three forms: -cp, --class-path and -classpath. 71 | 72 | - Options you need to know for using modules with 'javac': 73 | 74 | | Use for | Abbreviation | Long form | 75 | | :------------------------- | :----------- | :------------------- | 76 | | Directory for .class files | -d | n/a | 77 | | Module path | -p | --module-path | 78 | | | | | 79 | 80 | - Running a module syntax example: 81 | 82 | - `java --module-path feeding --module zoo.animal.feeding/zoo.animal.feeding.Task` 83 | 84 | - "--module-path" is the location of modules 85 | - "zoo.animal.feeding" on the left side of the slash is the module name 86 | - "zoo.animal.feeding" on ther right side is the package name followed by the class name "Task", 87 | zoo.animal.feeding.Task (the fully qualified class name) 88 | - module name is followed by a slash (/) followed by the fully qualified class name 89 | 90 | * Note: Its common for the module name to match either the full package name or the beginning of it (convention). 91 | 92 | - "-module" has a short form too, is -m. So the following command is equivalent: 93 | 94 | - `java -p feeding -m zoo.animal.feeding/zoo.animal.feeding.Task` 95 | 96 | - Options you need to know for using modules with 'java': 97 | 98 | | Use for | Abbreviation | Long form | 99 | | :---------- | :----------- | :------------------- | 100 | | Module name | -m | --module | 101 | | Module path | -p | --module-path | 102 | | | | | 103 | 104 | - A module isn't much use if we can run it only in the folder it was created in. So we package it. Be sure to create a mods 105 | directory before running this command, because 'mods' is where the generated artifacts will be stored (.jar for example). 106 | 107 | - `jar -cvf mods/zoo.animal.feeding.jar -C feeding/ .` 108 | 109 | - With this command, we package everything under the feeding directory and store it in a JAR file named zoo.animal.feeding.jar 110 | under the mods folder. This represents how the module JAR will look to other code that wants to use it. 111 | 112 | - Note: It is possible to version your module using the --module-version option, which is good to do when you are ready to share 113 | your module with others. 114 | 115 | - Now we can run the program using the mods directory instead of the loose classes: 116 | 117 | - `java -p mods -m zoo.animal.feeding/zoo.animal.feeding.Task` 118 | 119 | - Since a module path is used, a module JAR is being run. 120 | 121 | - Note: Some commands can have their order inverted, like the 'java' command (java -m ... -p ...) 122 | 123 | ## Updating Our Example for Multiple Module (p.465-472) 124 | 125 | - Note: The first version of the code until this section is located at the directory 'other/single_module_c11', to execute those files you need 126 | to use the single_module_c11 folder as the 'root'. The multiple module example is under directory 'eleven'. 127 | 128 | - The exports keyword is used to indicate that a module intends for those packages to be used by Java code outside the module: 129 | 130 | - `exports zoo.animal.feeding;` 131 | 132 | - You can reuse the same javac and jar commands ran previously to recompile and repackage the module inside the .jar file, so it'll update the 133 | dependencies exports and requires. 134 | - Remember that all modules must have a module-info file on the module root and inside of this file are located the dependencies of the module. 135 | - The requires statement specifies that a module is needed. So a module X depends on the Y: 136 | 137 | - `requires zoo.animal.feeding;` 138 | 139 | - Its intentional that the packages names begin with the same prefix as the module name. 140 | - Compiling more than one package command example: 141 | 142 | - `javac -p mods -d care care/zoo/animal/care/details/*.java care/zoo/animal/care/medical/*.java (...) care/module-info.java` 143 | 144 | * The --module-path (-p) directory must be the path where the modules jars were compiled, so Java can require the dependencies from the other modules. 145 | 146 | * Note that order matters when compiling a module. For example, the module-info can't go first on the command to compile, because Java will not find the 147 | packages that are being exported or required from the module-info files, a compiler error will be thrown since those packages haven't been compiled yet. 148 | 149 | - Remember that you need to repackage the modules using the jar command to refresh changes. 150 | 151 | - `jar -cvf mods/zoo.animal.feeding.jar -C feeding/ .` 152 | 153 | ## Diving into the module-info File (p.472-476) 154 | 155 | - In these sections we will look at 'exports', 'requires', 'provides', 'uses' and 'opens'. All these keywords can appear in any order in the module-info file. 156 | - Java is a bit sneaky here. These 'keywords' are only keywords inside a module-info.java file. In other files, like classes and interfaces, you are free to name 157 | your variable exports for example. These special keywords are called directives. You might ask why they are like this, its all about backward compatibility. 158 | 159 | * exports: 160 | 161 | - Exports a package to other modules. It's also possible to export a package to a specific module. For example: 162 | 163 | `module zoo.animal.talks { exports zoo.animal.talks.content to zoo.staff; // Exports 'content' only to 'staff' module. exports zoo.animal.talk.media; requires zoo.animal.feeding; }` 164 | 165 | - On the module-info of zoo.staff, nothing changes (requires...). However, no other modules are allowed to access 'content' package. 166 | - When exporting a package, all public classes, interfaces and enums are exported. 167 | - Any public and protected fields and methods in those files are visible, but any fields and methods that are private or package-private are not visible. 168 | - Access control with modules: 169 | 170 | | Level | Within module code | Outside module | 171 | | :------------------------ | :--------------------------------------------- | :--------------------------------------------------- | 172 | | private | Available only within class | No access | 173 | | default (package-private) | Available only within packages | No access | 174 | | protected | Available only within package or to subclasses | Accessible to subclasses only if package is exported | 175 | | public | Available to all classes | Accessible only if package is exported | 176 | | | | | 177 | 178 | * requires and requires transitive: 179 | 180 | - requires specifies that the current module X depends on another module Y. 181 | - requires transitive specifies that any module X that requires a module Y that requires transitive Z will also depend on Z. 182 | - Example: 183 | ` 184 | module zoo.animal.feeding { 185 | exports zoo.animal.feeding; 186 | } 187 | 188 | module zoo.animal.care { 189 | exports zoo.animal.care; 190 | requires transitive zoo.animal.feeding; 191 | } 192 | 193 | module zoo.animal.talks { 194 | exports zoo.animal.talks.content to zoo.staff; 195 | exports zoo.animal.talks.media; 196 | exports zoo.animal.talks.schedule; 197 | 198 | // requires zoo.animal.feeding - no longer needed 199 | // requires zoo.animal.care - no longer needed 200 | requires transitive zoo.animal.care; 201 | } 202 | 203 | module zoo.animal.staff { 204 | // requires zoo.animal.feeding - no longer needed 205 | // requires zoo.animal.care - no longer needed; 206 | requires zoo.animal.talks; 207 | } 208 | ` 209 | 210 | - Applying the transitive modifier has the following effects: 211 | - Module zoo.animal.talks can optionally declare it requires the zoo.animal.feeding module, but is not required. Kind of reduntant. 212 | - Module zoo.animal.care cannot be compiled or executed without access to the zoo.animal.feeding module. 213 | - Module zoo.animal.talks cannot be compiled or executed without access to the zoo.animal.feeding module. 214 | - Remember that without the transitive modifier, all modules would need to explicitly use requires in order to reference any other packages. 215 | - Java doesn't allow you to repeat the same module in a requires clause at the same module (requires and requires transitive). It's reduntant. 216 | 217 | * provides, uses and opens: 218 | 219 | - For 1Z0-815 exam you only need to be aware of them, on 1Z0-816 chapters will be more content about them. 220 | - The provides keyword specifies that a class provides an implementation of a service. To use it, you supply the API and class name that 221 | implements the API: 222 | 223 | - `provides zoo.staff.ZooApi with zoo.staff.ZooImpl;` 224 | 225 | - The uses keyword specifies a module is relying on a service. To code it, you supply the API you want to call: 226 | 227 | - `uses zoo.staff.ZooApi;` 228 | 229 | - Java allows callers to inspect and call code at runtime with a technique called 'reflection'. This is a powerful approach that allows calling 230 | code that might not be available at compile time. It can even be used to subvert access control. But don't worry, you don't need to know how to 231 | write code using reflection for the exam. 232 | - Since reflection can be dangerous, the module system requires developers to explicitly allow reflection in the module-info if they want, calling 233 | modules to be allowed to use it. For example: 234 | 235 | - `opens zoo.animal.talks.schedule;` 236 | - `opens zoo.animal.talks.media to zoo.staff;` 237 | 238 | - The first example allows any module using this one to use reflection. The second example only gives that privilege to the zoo.staff package. 239 | 240 | ## Discovering Modules (p.477-482) 241 | 242 | - Since Java 9, the classes built into the JDK were modularized as well. 243 | - For this section is important to know the syntax of the commands and what they do. 244 | 245 | * The java Command: 246 | 247 | - Has three module-related options. One describes a module, another lists the available modules, and the third shows the module resolution logic. 248 | - It is also possible to add modules, exports and more at the command line with java command, but don't do that, is confusing and hard to maintain. 249 | 250 | 1. Describing a Module 251 | 252 | - If you want to to know about a module structure, you can "unjar" it and open the module-info file. But you can also use the 'java' command to describe 253 | the module. The following two commands are equivalent: 254 | 255 | - `java -p mods -d zoo.animal.feeding` 256 | - `java -p mods -describe-module zoo.animal.feeding` 257 | 258 | - Each prints information about the module. For example, it might print this: 259 | `zoo.animal.feeding file:///C:/Dev/java-certification/src/ocp/chapter/eleven/mods/zoo.animal.feeding.jar exports zoo.animal.feeding requires java.base mandated ` 260 | - The java.base module is special. It is automatically added as a dependency to all modules. This module has frequently used packages like java.util. 261 | Works like the java.lang package, that is automatically imported on classes whether you type it or not. 262 | - When printing information about a module that is structured like this: 263 | `module zoo.animal.care { exports zoo.animal.care.medical to zoo.staff; requires transitive zoo.animal.feeding; }` 264 | You'll get this result: 265 | `zoo.animal.care file:///C:/Dev/java-certification/src/ocp/chapter/eleven/mods/zoo.animal.care.jar requires zoo.animal.feeding transitive requires java.base mandated qualified exports zoo.animal.care.medical to zoo.staff contains zoo.animal.care.details` 266 | - The qualified exports is the full name of exporting to a specific module. 267 | - The contains means that there is a package in the module that is not exported at all. This is true, because our module has two packages and one is 268 | available only to code inside the module (details). 269 | 270 | 2. Listing Available Modules 271 | 272 | - The simplest form lists all the modules that are part of the JDK and their version numbers: 273 | 274 | - `java --list-modules` // Result has a lot of lines and they look like this: java.base@11.0.2 275 | 276 | - You can print all the modules of the JDK plus some custom modules: 277 | 278 | - `java -p mods --list-modules` // Will print the same result as before plus our coded modules (zoo, talks...) 279 | 280 | - This command just prints the observable modules and exits, it does not run the program. 281 | 282 | 3. Showing Module Resolution: 283 | 284 | - Using the --show-module-resolution option its kind of a way of debugging modules. It spits out a lot of output when the program starts up. Then it 285 | runs the program. Example: 286 | 287 | - `java --show-module-resolution -p feeding -m zoo.animal.feeding/zoo.animal.feeding.Task` 288 | 289 | - The output starts out by listing the root module you choose to run. Then it lists many lines of packages included by the mandatory java.base module. 290 | Then after a while, it lists modules that have dependencies. Finally, it outputs the result of the program (class Task). 291 | 292 | * The jar Command: 293 | 294 | - Can describe a module too. Both of these commands are equivalent: 295 | 296 | - `jar -f mods/zoo.animal.feeding.jar -d` 297 | - `jar --file mods/zoo.animal.feeding.jar --describe-module` 298 | 299 | - The output is slightly different from when we used the java command. It prints a `/!module-info.class` on the ending of the first line. 300 | 301 | * The jdeps Command: 302 | 303 | - Gives you info about dependencies within a module. Unlike describing a module, it looks at the code in addition to the module-file. this tells you 304 | what dependencies are actually used rather than simply declared. 305 | - Asking for a summary of the dependencies in zoo.animal.feeding. Both of these commands give the same output: 306 | 307 | - `jdeps -s mods/zoo.animal.feeding.jar` 308 | - `jdeps -summary mods/zoo.animal.feeding.jar` 309 | 310 | - Notice that the is one dash (-) before the -summary rather than two. 311 | - The output tells you that there is only one package and it depends on the built-in java.base module. 312 | 313 | `zoo.animal.feeding -> java.base` 314 | 315 | - Alternatively you can ask for the dependencies in zoo.animal.feeding without summary and get the long form of output: 316 | 317 | - `jdeps mods/zoo.animal.feeding.jar` // Outputs shows the module filename and path, lists the required java.base dependency and version number, 318 | // then finally prints the specific packages within the java.base modules that are used by feeding. 319 | 320 | - If you want to print modules that have dependencies on other custom modules, you need to specify the module path so jdeps knows where to find the info 321 | about the dependent module. We don't need to do this for modules built into the JDK like java.base. Syntax examples: 322 | 323 | - `jdeps -s --module-path mods mods/zoo.animal.care.jar` 324 | - `jdeps -summary --module-path mods mods/zoo.animal.care.jar` 325 | - `jdeps --module-path mods mods/zoo.animal.care.jar` 326 | 327 | - There is no short form of --module-path in the jdeps command. 328 | 329 | - Presenting the result of the last one in order of appearance, without -summary: 330 | 1. Filename and required dependencies. 331 | 2. Summary showing the two module dependencies with an arrow. 332 | 3. Package-level dependencies. 333 | 334 | * The jmod Command: 335 | - You might think a JMOD file is a Java module file, but not quite. Oracle recommends using JAR files for most modules. JMOD files are recommended only 336 | when you have native libraries or something that can't go inside a JAR file. This is unlikely to affect you in the real world. 337 | - The most important thing to remember is that jmod is only for working with the JMOD files. You don't need to memorize the syntax for jmod. 338 | - Some common modes using jmod: 339 | - create: Creates a JMOD file. 340 | - extract: Extracts all files from the JMOD. Works like unzipping. 341 | - describe: Prints the module details such as requires. 342 | - list: Lists all files in the JMOD file. 343 | - hash: Shows a long string that goes with the file. 344 | 345 | ## Reviewing Command-Line Options (p.483-485) 346 | 347 | - The command lines you should expect to encounter on the exam (1Z0-815): 348 | 349 | | Description | Syntax | 350 | | :---------------------- | :------------------------------------------------------------------------------------ | 351 | | Compile nonmodular code | javac -cp classpath -d directory classesToCompile | 352 | | | javac --class-path classpath -d directory classesToCompile | 353 | | | javac -classpath classpath -d directory classesToCompile | 354 | | | 355 | | Run nonmodular code | java -cp classpath package.className | 356 | | | java -classpath classpath package.className | 357 | | | java --class-path classpath package.className | 358 | | | 359 | | Compile a module | javac -p moduleFolderName -d directory classesToCompileIncludingModuleInfo | 360 | | | javac --module-path moduleFolderName -d directory classesToCompileIncludingModuleInfo | 361 | | | 362 | | Run a module | java -p moduleFolderName -m moduleName/package.className | 363 | | | java --module-path moduleFolderName --module moduleName/package.className | 364 | | | 365 | | Describe a module | java -p moduleFolderName -d moduleName | 366 | | | java --module-path moduleFolderName --describe-module moduleName | 367 | | | jar --file jarName --describe-module | 368 | | | jar -f jarName -d | 369 | | | 370 | | List available modules | java --module-path moduleFolderName --list-modules | 371 | | | java -p moduleFolderName --list-modules | 372 | | | java --list-modules | 373 | | | 374 | | View dependencies | jdeps -summary --module-path moduleFolderName jarName | 375 | | | jdeps -s --module-path moduleFolderName jarName | 376 | | | 377 | | Show module resolution | java --show-module-resolution -p moduleFolderName -m moduleName | 378 | | | java --show-module-resolution --module-path moduleFolderName --module moduleName | 379 | 380 | - Now some options that you need to know for the exam. 381 | 382 | * 'javac' options: 383 | 384 | | Option | Description | 385 | | :----------------------- | :--------------------------------------- | 386 | | -cp | Location of JARs in a nonmodular program | 387 | | -classpath | | 388 | | --class-path | | 389 | | | 390 | | -d | Directory to place generated class files | 391 | | | 392 | | -p | Location of JARs in a modular program | 393 | | --module-path | | 394 | | | 395 | 396 | - 'java' options: 397 | 398 | | Option | Description | 399 | | :----------------------- | :------------------------------------------------- | 400 | | -p | Location of JARs in a modular program | 401 | | --module-path | | 402 | | | 403 | | -m | Module name to run | 404 | | --module | | 405 | | | 406 | | -d | Describes the details of a module | 407 | | --describe-module | | 408 | | | 409 | | --list-modules | Lists observable modules without running a program | 410 | | | 411 | | --show-module-resolution | Shows modules when running a program | 412 | | | 413 | 414 | - 'jar' options: 415 | 416 | | Option | Description | 417 | | :---------------- | :------------------------------------------------------ | 418 | | -c | Create a new JAR file | 419 | | --create | | 420 | | | 421 | | -v | Prints details when working with JAR files | 422 | | --verbose | | 423 | | | 424 | | -f | JAR filename | 425 | | --file | | 426 | | | 427 | | -C | Directory containing files to be used to create the JAR | 428 | | | 429 | | -d | Describes the details of a module | 430 | | --describe-module | | 431 | | | 432 | 433 | - 'jdeps' options: 434 | 435 | | Option | Description | 436 | | :------------------- | :------------------------------------ | 437 | | --module-path | Location of JARs in a modular program | 438 | | | 439 | | -s | Summarizes output | 440 | | -summary | | 441 | | | 442 | 443 | ## Summary (p.485-486) 444 | 445 | - The JPMS organizes code at a higher level than packages. Each module contains one or more packages and a module-info file. 446 | - Advantages of the JPMS include better access control, clearer dependency management, custom runtime images, improved performance 447 | and unique package enforcement. 448 | - The module info file suports a number of keywords: 449 | - exports: Specifies that a package should be accessible outside the module. It can optionally restrict that export to a specific package (to Y). 450 | - requires: Is used when a module depends on code in another module. Additionally, 'requires transitive' can be used when all modules that require 451 | one module should always require another. 452 | - provides: Is used when exposing an API. 453 | - uses: Is used when consuming an API. 454 | - opens: Is used for allowing access via reflection. 455 | - The 'java' command can also describe a module, list available modules or show the module resolution. 456 | - The 'jar' command can also describe a module similar how the 'java' command does. 457 | - The 'jdeps' command prints details about a module and packages. 458 | - The 'jmod' command provides various modes for working with JMOD files rather than JAR files. 459 | -------------------------------------------------------------------------------- /src/ocp/chapter/eleven/care/module-info.java: -------------------------------------------------------------------------------- 1 | module zoo.animal.care { 2 | exports zoo.animal.care.medical; 3 | 4 | requires zoo.animal.feeding; 5 | } -------------------------------------------------------------------------------- /src/ocp/chapter/eleven/care/zoo/animal/care/details/HippoBirthday.java: -------------------------------------------------------------------------------- 1 | package zoo.animal.care.details; 2 | 3 | import zoo.animal.feeding.*; 4 | 5 | public class HippoBirthday { 6 | private Task task; 7 | } 8 | -------------------------------------------------------------------------------- /src/ocp/chapter/eleven/care/zoo/animal/care/medical/Diet.java: -------------------------------------------------------------------------------- 1 | package zoo.animal.care.medical; 2 | 3 | public class Diet { } -------------------------------------------------------------------------------- /src/ocp/chapter/eleven/feeding/module-info.java: -------------------------------------------------------------------------------- 1 | module zoo.animal.feeding { 2 | exports zoo.animal.feeding; 3 | } -------------------------------------------------------------------------------- /src/ocp/chapter/eleven/feeding/zoo/animal/feeding/Task.java: -------------------------------------------------------------------------------- 1 | package zoo.animal.feeding; 2 | 3 | public class Task { 4 | public static void main(String... args) { 5 | System.out.println("All fed!"); 6 | } 7 | } -------------------------------------------------------------------------------- /src/ocp/chapter/eleven/mods/zoo.animal.care.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marceloasf/java-certification/de98311b5aec3c2f1f3acac7a6985a95cac918ae/src/ocp/chapter/eleven/mods/zoo.animal.care.jar -------------------------------------------------------------------------------- /src/ocp/chapter/eleven/mods/zoo.animal.feeding.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marceloasf/java-certification/de98311b5aec3c2f1f3acac7a6985a95cac918ae/src/ocp/chapter/eleven/mods/zoo.animal.feeding.jar -------------------------------------------------------------------------------- /src/ocp/chapter/eleven/mods/zoo.animal.talks.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marceloasf/java-certification/de98311b5aec3c2f1f3acac7a6985a95cac918ae/src/ocp/chapter/eleven/mods/zoo.animal.talks.jar -------------------------------------------------------------------------------- /src/ocp/chapter/eleven/mods/zoo.staff.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marceloasf/java-certification/de98311b5aec3c2f1f3acac7a6985a95cac918ae/src/ocp/chapter/eleven/mods/zoo.staff.jar -------------------------------------------------------------------------------- /src/ocp/chapter/eleven/staff/module-info.java: -------------------------------------------------------------------------------- 1 | module zoo.staff { 2 | requires zoo.animal.talks; 3 | requires zoo.animal.feeding; 4 | requires zoo.animal.care; 5 | } -------------------------------------------------------------------------------- /src/ocp/chapter/eleven/staff/zoo/staff/Jobs.java: -------------------------------------------------------------------------------- 1 | package zoo.staff; 2 | 3 | public class Jobs { } -------------------------------------------------------------------------------- /src/ocp/chapter/eleven/talks/module-info.java: -------------------------------------------------------------------------------- 1 | module zoo.animal.talks { 2 | exports zoo.animal.talks.content; 3 | exports zoo.animal.talks.media; 4 | exports zoo.animal.talks.schedule; 5 | 6 | requires zoo.animal.feeding; 7 | requires zoo.animal.care; 8 | } -------------------------------------------------------------------------------- /src/ocp/chapter/eleven/talks/zoo/animal/talks/content/ElephantScript.java: -------------------------------------------------------------------------------- 1 | package zoo.animal.talks.content; 2 | 3 | public class ElephantScript { } -------------------------------------------------------------------------------- /src/ocp/chapter/eleven/talks/zoo/animal/talks/content/SeaLionScript.java: -------------------------------------------------------------------------------- 1 | package zoo.animal.talks.content; 2 | 3 | public class SeaLionScript { } -------------------------------------------------------------------------------- /src/ocp/chapter/eleven/talks/zoo/animal/talks/media/Announcement.java: -------------------------------------------------------------------------------- 1 | package zoo.animal.talks.media; 2 | 3 | public class Announcement { 4 | public static void main(String args[]) { 5 | System.out.println("We will be having talks"); 6 | } 7 | } -------------------------------------------------------------------------------- /src/ocp/chapter/eleven/talks/zoo/animal/talks/media/Signage.java: -------------------------------------------------------------------------------- 1 | package zoo.animal.talks.media; 2 | 3 | public class Signage { } -------------------------------------------------------------------------------- /src/ocp/chapter/eleven/talks/zoo/animal/talks/schedule/Weekday.java: -------------------------------------------------------------------------------- 1 | package zoo.animal.talks.schedule; 2 | 3 | public class Weekday { } -------------------------------------------------------------------------------- /src/ocp/chapter/eleven/talks/zoo/animal/talks/schedule/Weekend.java: -------------------------------------------------------------------------------- 1 | package zoo.animal.talks.schedule; 2 | 3 | public class Weekend { } -------------------------------------------------------------------------------- /src/ocp/chapter/five/ManipulatingArrays.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.five; 2 | 3 | import java.util.*; 4 | 5 | public class ManipulatingArrays { 6 | 7 | static int[] classIntArray; 8 | 9 | public static void main(String... args) { 10 | 11 | String [] bugs = new String[] { "cricket", "beetle", "ladybug" }; 12 | 13 | System.out.println(Arrays.toString(bugs)); 14 | 15 | var emptyList = new ArrayList<>(); 16 | String[] emptyArray = emptyList.toArray(new String[0]); 17 | 18 | System.out.println(emptyList); 19 | System.out.println(emptyArray); 20 | 21 | String[] oneArray = {"hawk", "robin"}; 22 | 23 | List oneAsList = Arrays.asList(oneArray); 24 | List oneListOf = List.of(oneArray); 25 | 26 | System.out.println(oneAsList); 27 | System.out.println(oneListOf); 28 | 29 | classIntArray = new int[] {1, 2, 3}; // Need to instantiate a new object to change the default values of the array 30 | 31 | System.out.println(Arrays.toString(classIntArray)); 32 | 33 | System.out.println("\n----------------------------------------\n"); 34 | 35 | int numbers[] = new int[] {6, 9, 1}; 36 | 37 | Arrays.sort(numbers); 38 | 39 | for(Integer i : numbers) // Autoboxing with the sorted int array 40 | System.out.println(i + " "); // 1 6 9 41 | 42 | System.out.println("\n"); 43 | 44 | String[] strings = {"123", "9", "112", "0300"}; 45 | 46 | Arrays.sort(strings); 47 | 48 | for(String s : strings) 49 | System.out.println(s + " "); // "0300", "112", "123", "9" - alphabetic order - sorts from 0 to 9, then from A to Z and finally from a to z. 50 | 51 | System.out.println("\n----------------------------------------\n"); 52 | 53 | Set set = new HashSet<>(); 54 | 55 | System.out.println("Added the value? " + set.add(21)); // true 56 | System.out.println("Added the duplicated value? " + set.add(21)); // false 57 | System.out.println("Size: " + set.size()); // 1 58 | 59 | set.remove(21); 60 | System.out.println("isEmpty? " + set.isEmpty()); // true 61 | 62 | System.out.println("\n----------------------------------------\n"); 63 | 64 | Map map = new HashMap<>(); 65 | map.put("koala", "bamboo"); 66 | 67 | String food = map.get("koala"); // bamboo 68 | String other = map.getOrDefault("ant", "leaf"); // leaf 69 | 70 | for (String key: map.keySet()) 71 | System.out.println(key + " " + map.get(key)); // koala bamboo (key | value) 72 | 73 | System.out.println("\n----------------------------------------\n"); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/ocp/chapter/five/ManipulatingStrings.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.five; 2 | 3 | public class ManipulatingStrings { 4 | 5 | public static void main(String[] args) { 6 | 7 | System.out.println("\n----------------String----------------\n"); 8 | 9 | String string = "animals"; 10 | 11 | System.out.println(string.charAt(0)); // a 12 | System.out.println(string.charAt(6)); // s 13 | 14 | // System.out.println(string.charAt(7)); // THROWS EXCEPTION 15 | 16 | System.out.println("\n----------------------------------------\n"); 17 | 18 | System.out.println(string.indexOf('a')); // 0 19 | System.out.println(string.indexOf("al")); // 4 20 | System.out.println(string.indexOf('a', 4)); // 4 21 | System.out.println(string.indexOf("al", 5)); // -1 22 | 23 | System.out.println("\n----------------------------------------\n"); 24 | 25 | /* 26 | / String 'array' structure 27 | / [a][n][i][m][a][l][s] 28 | / | | | | | | | | 29 | / 0 1 2 3 4 5 6 7 30 | / If a method specifies a starting index of 0, 0 will be considered. 31 | / If a method specifies an ending index of 6, 6 won't be considered. 32 | / Index 7 will not give an out-of-bounds exception. 33 | / It looks the characters in between. Including the starting index and stoping before the ending index. 34 | */ 35 | 36 | System.out.println(string.substring(3)); // mals 37 | System.out.println(string.substring(string.indexOf('m'))); // mals 38 | System.out.println(string.substring(3, 4)); // m 39 | System.out.println(string.substring(3, 7)); // mals 40 | System.out.println(string.substring(3, 3)); // Empty string 41 | 42 | // System.out.println(string.substring(3, 2)); // THROWS EXCEPTION 43 | // System.out.println(string.substring(3, 8)); // THROWS EXCEPTION 44 | 45 | System.out.println("\n----------------------------------------\n"); 46 | 47 | System.out.println("abcabc".replace('a', 'A')); // AbcAbc - char 48 | System.out.println("abcabc".replace("a", "A")); // AbcAbc - CharSequence 49 | 50 | System.out.println("\n----------------------------------------\n"); 51 | 52 | System.out.println("abc".strip()); // abc 53 | System.out.println("\t a b c".strip()); // a b c 54 | System.out.println("abc".trim()); // abc 55 | System.out.println("\t a b c".trim()); // a b c 56 | 57 | // _ means whitespace in the examples below 58 | 59 | String text = " abc\t "; 60 | System.out.println(text.trim().length()); // 3 - abc 61 | System.out.println(text.strip().length()); // 3 - abc 62 | System.out.println(text.stripLeading().length()); // 5 - abc\t_ 63 | System.out.println(text.stripTrailing().length()); // 4 - _abc 64 | 65 | System.out.println("\n----------------StringBuilder----------------\n"); 66 | 67 | StringBuilder sb1 = new StringBuilder("ani").append("mals"); // animals - append() is called directly after the contructor 68 | String sub = sb1.substring(sb1.indexOf("a"), sb1.indexOf("al")); 69 | int len = sb1.length(); 70 | char ch = sb1.charAt(6); 71 | System.out.println(sub + " " + len + " " + ch); // anim 7 s 72 | 73 | System.out.println("\n----------------------------------------\n"); 74 | 75 | StringBuilder sb2 = new StringBuilder("animals"); 76 | sb2.insert(7, "-"); // animals- 77 | sb2.insert(0, "-"); // -animals- 78 | sb2.insert(4, "-"); // -ani-mals- 79 | System.out.println(sb2); // Will change the indexes 80 | 81 | System.out.println("\n----------------------------------------\n"); 82 | 83 | StringBuilder sb3 = new StringBuilder("abcdef"); 84 | sb3.delete(1, 3); // adef - removes bc (1 and 2) and stops right before d (3) - similar to substring String structure. 85 | // sb3.deleteCharAt(5); // THROWS EXCEPTION, this index is out of bonds after deleting ab (1 and 2). 86 | 87 | System.out.println(sb3); // adef 88 | 89 | StringBuilder sb4 = new StringBuilder("abcdef"); 90 | 91 | // sb4.delete(2, 0); // THROWS EXCEPTION 92 | 93 | sb4.delete(1, 100); // a - will delete everything till the end of the String. 94 | sb4.delete(0, 0); // Will not delete a (identifies as an empty string like substring). 95 | 96 | System.out.println(sb4); // a 97 | 98 | System.out.println("\n----------------------------------------\n"); 99 | 100 | // replace is different in StringBuilder - it replaces more than just a specified char (uses indexes). 101 | 102 | StringBuilder builder = new StringBuilder("pigeon dirty"); 103 | builder.replace(3, 6, "sty"); 104 | System.out.println(builder); // pigsty dirty 105 | 106 | builder.replace(3, 100, ""); 107 | System.out.println(builder); // pig 108 | 109 | System.out.println("\n----------------Equality----------------\n"); 110 | 111 | StringBuilder one = new StringBuilder(); 112 | StringBuilder two = new StringBuilder(); 113 | StringBuilder three = one.append("a"); 114 | 115 | System.out.println(one == two); // false 116 | System.out.println(one == three); // true 117 | 118 | String x = "Hello"; 119 | String z = " Hello ".trim(); 120 | 121 | System.out.println(x.equals(z)); // true - since Strings equals() method checks the values inside rather than the reference. 122 | 123 | String normalString = "a"; 124 | StringBuilder normalBuilder = new StringBuilder("a"); 125 | 126 | // System.out.println(normalString == normalBuilder); // DOES NOT COMPILE - different data types 127 | System.out.println(normalString.equals(normalBuilder)); // false - stringbuilder is not equal to "a" 128 | System.out.println(normalString.equals(normalBuilder.toString())); // true 129 | 130 | System.out.println("\n----------------String-Pool----------------\n"); 131 | 132 | // The String Pool contains `LITERAL VALUES` and `CONSTANTS` that are created in memory at compile-time (or with intern() at runtime) 133 | 134 | String x1 = "Hello World"; 135 | String y1 = "Hello World"; 136 | System.out.println(x1 == y1); // true - because both point to the same location in memory, which is the string pool value "Hello World". 137 | 138 | String x2 = "Hello World"; 139 | String y2 = "Hello World ".trim(); 140 | System.out.println(x2 == y2); // false - because y2 computes it's value at runtime and creates a new String value. 141 | 142 | String x3 = "Hello World"; 143 | String y3 = "Hello "; 144 | y3 += "World"; 145 | System.out.println(x3 == y3); // false - Concatenation is just like calling a method and results in a new String. 146 | 147 | String x4 = "Hello World"; 148 | String y4 = new String("Hello World"); 149 | System.out.println(x4 == y4); // false - x4 says to use the string pool normally, the second creates a new String object. 150 | 151 | String x5 = "Hello World"; 152 | String y5 = new String("Hello World").intern(); 153 | System.out.println(x5 == y5); // true - Using the intern() tells Java to use the string pool and both values point to 154 | // the same reference in the String Pool, which is "Hello World". 155 | 156 | String x6 = "Hello World"; 157 | String y6 = "Hello World".trim(); 158 | System.out.println(x6 == y6); // true - both are pointing to the same reference in the Pool, even with the trim() method call 159 | 160 | String first = "rat" + 1; // compile-time literals 161 | String second = "r" + "a" + "t" + "1"; // compile-time literals 162 | String third = "r" + "a" + "t" + new String("1"); // runtime because we have a String contructor, creating a new object 163 | 164 | System.out.println(first == second); // true - same reference in the String Pool. 165 | System.out.println(first == second.intern()); // true - same reference in the String Pool, intern() call is useless but it works. 166 | System.out.println(first == third); // false - doesn't point to a reference in the String Pool. 167 | System.out.println(first == third.intern()); // true - intern() looks to the Pool Java notice they point to the same String and prints true. 168 | } 169 | } -------------------------------------------------------------------------------- /src/ocp/chapter/five/README.md: -------------------------------------------------------------------------------- 1 | As mentioned on c1-notes and c2-notes, I am starting this book at this chapter (5) because the OCA-8 book already covers the same subjects of the Chapters 1-4 from this book in its Chapters 1-2, they will be revisited futurely. 2 | 3 | # Chapter 5 - Core Java APIs 4 | 5 | Working with Java Primitive Data Types and String APIs 6 | 7 | - Create and manipulate Strings. 8 | - Manipulate data using the StringBuilder class and its methods. 9 | - String Pool 10 | 11 | Working with Java Arrays 12 | 13 | - Declare, instantiate, initialize and use one-dimensional and two-dimensional arrays. 14 | 15 | Programming Abstractly Through Interfaces 16 | 17 | - Declare and use List and ArrayList instances. 18 | 19 | Introduction to Wrapper Classes and Java Collections 20 | 21 | - Wrapper classes, Sets and Maps. 22 | 23 | ## String immutability (p.166-167) 24 | 25 | Once a String object is created, it is not allowed to change. It cannot be made larger or smaller, and you cannot change one of the characters inside it (Strings are immutable). You can make a reference point to a different String object or replace a char for other. Strings support Method Chaining and each time a method is called, a new String is returned. 26 | 27 | > **Note:** Immutable classes in Java are final, which prevents subclasses creation. 28 | 29 | ## Creating and Manipulating Strings (p.167-172) 30 | 31 | Some of the String methods that you should be familiar with: 32 | 33 | - `length()` returns the number of characters in the String. 34 | - `charAt(int index)` lets you query the string to find out what character is at a specific index. 35 | - `indexOf()` has multiple signatures and returns an int value, looks at the characters in the string and finds the first index that matches the desired value. indexOf can work with an individual character or a whole String as input. It can also start from a requested postion. A char can be passed to an int parameter type. Signatures are `indexOf(int ch)`, `indexOf(int ch, int fromIndex)`, `indexOf(String str)`, `indexOf(String str, int fromIndex)`. Returns -1 when the value is not found. 36 | - `substring()` has one starting index param and a ending index optional param, if the endingIndex is specified, it will stop right before the endingIndex. `"abcde".substring(1, 4);` // Result is "bcd". 37 | - Strings has two implementations of equals methods to check equality. The `equals()` that checks if the string values are the same and `equalsIgnoreCase()` that does the same thing but ignore the case, because it will converts the chars if needed. 38 | - `startsWith(Strings prefix)` and `endsWith(String suffix)` do exactly what they sound like, they check if a string is the prefix or is the suffix of a String. 39 | - `replace()` method has two signatures, one that takes a oldChar and a newChar, and another that takes a charSequence as target and charSequence as replacement to replace them left to right. 40 | - `contains()` method looks for matches in the String, using a CharSequence("ABC") - the match can be anywhere in the String. 41 | - `trim()` and `strip()` (strip was added in Java 11) removes whitespaces from the beginning and end of a String. The diference between them is that `strip()` supports unicode. 42 | - `stripLeading()` removes whitespaces only from the beginning of the String. 43 | - `stripTrailing()` removes whitespaces only from the end of the String. 44 | - The `intern()` method returns the value from the string pool if it is there, otherwise, it adds the value to the string pool. 45 | 46 | ## StringBuilder (p.174-179) 47 | 48 | StringBuilder is not immutable (`a.append("x")` concats to the same object). StringBuffer is slower and older than StringBuilder, so just use StringBuilder. 49 | 50 | When chaining StringBuilder methods, it will change its own state and returns a reference to itself (`append()` the same object), different than String that returns a new String on chaining. 51 | 52 | `charAt()`, `indexOf()`, `length()` and `substring()` all work the same way as they work with String, but `substring()` returns a String rather than a StringBuilder. 53 | 54 | Some StringBuilder methods that you should be familiar with: 55 | 56 | - `append()` will convert values (any type) into String, like true to "true". 57 | - `insert()` adds chars to the StringBuilder at the requested index and returns a reference to the current StringBuilder. 58 | - `delete()` deletes chars from a starting index to stop right before the ending index, `deleteCharAt()` deletes only one char at the indicated index. 59 | - `StringBuilder a = new StringBuilder("abc"); - a.delete(1, 100);` // Compiles because Java will just assume you meant the end, `delete()` is more flexible. 60 | - `replace(int startingIndex, int endingIndex, String newString)` works differently for StringBuilder than it did for String. Java deletes the chars between the startingIndex and stops right before endingIndex, then java inserts the replacement value. 61 | - `reverse()` does just what it sounds like, it reverse the chars in the sequences and returns a ref to the current StringBuilder. 62 | - `toString()` converts a StringBuilder to a String. Methods that expect a String will not accept a StringBuilder instance (use `sb.toString()` to work). 63 | 64 | ## Understanding equality (p.179-180) 65 | 66 | Logical equality is asserting the values (for strings, the equals() will assert the equality between the value of a and b). Object equality is asserting the references, if they are pointing to the same object (objectA == objectB, same reference is true). Primitives always assert the values when using ==. equals() depends on the implementation of the object it is being called on, the default implementation is using object equality (comparing references). If you call equals() on two Objects that doesn't implements the equals() method, it will check reference equality (StringBuilder for example). 67 | 68 | > **Note:** If you try to check Object equality between two different data type Objects, the compiler will throw an error, because he is smart enough to know that two references can't possibly point to the same Object when they are completely different types. 69 | 70 | ## String Pool (p.181-182) 71 | 72 | The string pool contains literal values and constants ("ABC") that appear in your program. Java realizes that many strings repeat in the program and solves this issue by reusing common ones, the string pool is a location in the JVM that collects all these strings. How the String Pool can impact on reference equality: 73 | 74 | String x = "Hello"; 75 | String y = "Hello"; 76 | x == y // is true, because the JVM created only one literal in memory. x and y both point to the the same location in memory; 77 | therefore, the statement outputs true. 78 | 79 | String x = "Hello"; 80 | String y = " Hello".trim(); 81 | x == y // is false, because we don't have the same String literal. Although both happen to evaluate to the same string, 82 | one is computed at runtime, since it isn't the same at compile-time, a new String object is created. 83 | 84 | 85 | - If we call the `intern()` after that `trim()`, Java will add it to the string pool and the result will be true. 86 | 87 | > **Note:** Never use `intern()` or == to compare String objects in your code. Just know how they work for the exam. 88 | 89 | ## Understanding Java arrays (p.184-186) 90 | 91 | An array is a fixed-sized area of memory on the heap, that has space for primitives or pointers to objects. Default declaration: int[] numbers = new numbers[3] -> arrays are reference (object) variables. Anonymous array is a declaration of an array that doesn't need you to specify the type and size, for example: `int[] numbers2 = {42, 45}`, since you are specifying the type of the array on the left side of the equal sign, Java already knows the type and since you are specifying the initial values, it already knows the size too. The array does not allocate space for the Objects, instead, it allocates space for a reference to where the objects are really stored. 92 | 93 | For the exam is good to know that all these statements do the exact thing (declaring arrays): 94 | 95 | int[] numAnimals; 96 | int [] numAnimals2; 97 | int []numAnimals3; 98 | int numAnimals4[]; 99 | int numAnimals5 []; 100 | int[] ids, types; // Declare both as int[]. 101 | int ids[], types; // Declare only ids as int[] and types is declared as int. 102 | 103 | We can call `equals()` because an array is an object (any type of array), but it uses reference equality because it doesn't overrides Object implementation. \*\* The `equals()` method on arrays, does not look at the elements of the array. 104 | 105 | > **Note:** Since Java 5, Java has provided a method that prints an array nicely: `String [] bugs = { "cricket", "beetle", "ladybug" };`, `java.util.Arrays.toString(bugs)` would print [cricket, beetle, ladybug] (inside of a System.out.println...). 106 | 107 | ## Using an Array (p.187-194) 108 | 109 | length does not consider what is in the array, it only considers how many slots have been allocated, and length is not a method. `String[] numbers = new String[6];` // numbers.length results in 6, even though all six elements are null. There is no direct way to remove and add elements from an array in Java. 110 | 111 | ### Sorting 112 | 113 | Arrays.sort requires an import -> `java.util.*` or `java.util.Arrays`. Numbers sort before letters, and uppercase sorts before lowercase (with Strings). 114 | 115 | ### Searching 116 | 117 | binarySearch only works if the array is already sorted. Binary search (Arrays.binarySearch) rules: 118 | 119 | - Target element found in sorted array: Index of match. 120 | - Target element not found in sorted array: Negative value showing one smaller than the negative of the index where a match needs to be inserted to preserve the sorted order. 121 | - Unsorted array: A surprise (this result isn't predictable). 122 | 123 | ### Comparing 124 | 125 | `compare()` returns -1, 0 and +1 (negative number, zero and positive number on the exam). 126 | 127 | - -1: First array is smaller than the second. 128 | - 0: Arrays are equal. 129 | - +1: First array is larger than the second. 130 | 131 | `compare()` will not compare only the length of the arrays. Rules of comparation: 132 | 133 | - If both arrays are the same length and have the same values in each spot in the same order, return 0. 134 | - If all the elements are the same but the second array has extra elements at the end, returns -1 (it returns a positive number if the first array is 'bigger'). 135 | - If the first element that differs is smaller in the first array, return a negative number (it returns a positive number if the first element to differ in the first array is'larger'). 136 | - The following rules apply to `compare()` and to `compareTo()`: 137 | - null is smaller than any other value. 138 | - For numbers, normal numeric order applies. 139 | - For strings, one is smaller if it is a prefix of another. 140 | - For strings/chars, numbers are smaller than letters. 141 | - For strings/chars, uppercase is smaller than lowercase. 142 | 143 | Arrays.`compare()` examples applying this rules: 144 | 145 | new int[] {1, 2} - new int[] {1} // Positive number; 146 | new int[] {1, 2} - new int[] {1, 2} // Zero; 147 | new String[] {"a"} - new String[] {"aa"} // Negative number; 148 | new String[] {"a"} - new String[] {"A"} // Positive number; 149 | new String[] {"a"} - new String[] {null} // Positive number; 150 | 151 | > **Note:** When comparing two arrays, they must be the same array type, otherwise, the code will not compile. 152 | 153 | `Arrays.mismatch()` (Java 9): Returns -1 if the arrays are equal, otherwise, it returns the first index where they differ. 154 | 155 | ### Multidimensional Arrays 156 | 157 | int[] a[]; // 2D array. 158 | int[][] b; // 2D array. 159 | int c [][]; // 2D array. 160 | int[] d[], e[][]; // 2D array and a 3D array. 161 | String [][] f = new String[3][2]; 162 | 163 | Assymetric Arrays: 164 | 165 | int[][] g = {{1, 4}, {3}, {9, 8, 7}}; 166 | int[][] args = new int[4][]; -> args[0] = new int[5]; -> args[1] = new int[3]; 167 | 168 | ## ArrayList (p.196-197) 169 | 170 | Default contructor slots size value is 10 (new ArrayList<>()). Implements an interface called List, so you can store an ArrayList in a List reference variable, but not vice versa, because List is an interface and interfaces can't be instantiated. If you don't specify a type for the ArrayList, it will accept any Object subclasses (not primitives), 171 | but if a type is specified, only that type can be added (add()) into the ArrayList. If a type is not specified with the diamond operator < and >, Object will be the default type for ArrayList and List. Some methods of ArrayList: 172 | 173 | - add() method can be used in two different ways, add(index, value) and add(value), one adding the value at the specified index and the other adding to the end of the ArrayList. 174 | - remove() removes the first matching value in the ArrayList (remove(Object object)) or remove the element at a specified index (remove(int index)). 175 | - set(int index, E newElement) changes one of the elements of the ArrayList without changing the size (updates a value). 176 | - isEmpty() and size() methods look at how many of the slots are in use. 177 | - contains(Object object) checks whether a certain value is in the ArrayList. 178 | - equals(Object object) compare two lists to see whether they contain the same elements in the same order. 179 | 180 | > **Note:** E appears in this chapter on some method signatures. E is used by convention in generics to mean "any class that this array can hold". If you didn't specify a type when creating the ArrayList, E means Object. 181 | 182 | Sorting ArrayList: Is similar to sorting an array, the difference is the helper class, which is `Collections`.sort(array) for an ArrayList. 183 | 184 | ## Wrapper Classes (p.201-203) 185 | 186 | Each primitive type has a wrapper class, which is an object type that corresponds to the primitive. Each wrapper class also has a contructor. It works the same way as valueOf(), but isn't recommended for new code, because the valueOf() allows object caching. The wrapper classes are immutable and take advantage of some caching as well. Only the Character class doesn't has parse/valueOf methods. The valueOf() can receive a String or the primitive value that corresponds to that wrapper class data type. String's valueOf() is different, because it can receive char, int, long, float, double and Objects as params. All the parse methods (parseInt(s), parseFloat(s)...) on the wrapper classes receive a String as the param. 187 | 188 | ### Autoboxing and Unboxing 189 | 190 | Since Java 5, you can just type the primitive value and Java will convert it to the relevant wrapper class for you (data types matter). The reverse conversion of wrapper class to primitive value is called unboxing. For example: 191 | 192 | Integer a = 50; // Autoboxing 50 (literal) to Integer. 193 | exArray.add(a); 194 | double first = exArray.get(0); // Unboxing exArray.get(0) (Integer) to double (50.0). 195 | 196 | > **Note:** In some cases the unboxing may produce a NullPointerException, since calling any method on null gives a NullPointerException. 197 | 198 | ## Converting Between array and List (p.204-205) 199 | 200 | List list = new ArrayList<>(); 201 | Object[] objectArray = list.toArray(); // Default return is an array of class Object. 202 | String[] objectArray = list.toArray(new String[0]); // Specified the type of array (corresponding to the List type). 203 | 204 | Arrays.asList(array) is an option to create a list from an array, but be careful using this method, because it generates a fixed-size list and is also known as a backed List, because the array changes with it. You can 'update' the values from the List, but you can't change the size of the List (for example using a list.remove(0)). 205 | 206 | List.of(array) is another option to create a list from an array, but this option returns an immutable List, that means you cannot change the values or the size of the List. You can change the original array, but will not be reflected in the immutable List like Arrays.asList(). 207 | 208 | None of the options allows you to change the number of elements. 209 | 210 | > **Note:** For the typed declaration, specifying a size of 0 for the parameter is an advantage, because Java will create a new array of the proper size for the return value, but you can suggest a larger array to be used instead, if the ArrayList fits in, it will be returned. Otherwise, a new one will be created (a dimension must be specified in this type of declaration). 211 | 212 | Arrays.asList and List.of can take varargs (`Arrays.asList("ABC", "DEF")`), which let you pass in an array or just type out the String values. 213 | 214 | ## Introducing Sets and Maps (p.206-208) 215 | 216 | #### Sets 217 | 218 | A Set is a collection of objects that cannot contain duplicates, the API will not fulfill a request that add a duplicate. The most common implementation of Set is HashSet. All the methods for ArrayList apply to a Set, with the exception of those taking an index as a param, because Set isn't ordered like a List, so `remove(int index)` or `set(int index, value)` will not work (obs.: `remove(Object value)` works). Methods like `add()` return a boolean because of Set. When trying to add a duplicate value, the method returns false and does not add the value. 219 | 220 | #### Maps 221 | 222 | A Map uses a key to identify values (key -> value, Map). The most common implementation of Map is HashMap. Some of the methods are the same as those in ArrayList, like `clear()`, `isEmpty()` and `size()`. There are also methods specific to dealing with key and value pairs: 223 | 224 | - V get(Object key) - Returns the value mapped by key or null if none is mapped. 225 | - V getOrDefault(Object key, V other) - Returns the value mapped by key or other if none is mapped. 226 | - V put(K key, V value) - Adds or replaces key/value pair. Returns previous value or null. 227 | - V remove(Object key) - Removes and returns value mapped to key. Returns null if none. 228 | - boolean containsKey(Object key) - Returns whether key is in Map. 229 | - boolean containsValue(Object value) - Returns whether value is in Map. 230 | - Set keySet() - Returns set of all keys. 231 | - Collection values() - Returns Collection of all values. 232 | 233 | ## Calculating with Math APIs (p.208-210) 234 | 235 | - `min(a, b)` and `max(a, b)` compare two values and return one of them (overloaded with int, long, float and double return types). `min()` returns the smaller of A and B and`max()` returns the bigger of A and B. 236 | - `round(double/float num)` method gets rid of the decimal portion of the value, choosing the next higher number if appropriate (.5 or higher will round up). 237 | - `pow(double num, double exponent)` handles exponents (fractional too). 238 | - `random()` generates a value greater or equal to 0 and less than 1.0 (returns a double). 239 | -------------------------------------------------------------------------------- /src/ocp/chapter/fourteen/ComparatorExample.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.fourteen; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.Comparator; 6 | 7 | public class ComparatorExample implements Comparable { 8 | private String name; 9 | private int weight; 10 | 11 | public ComparatorExample(String name, int weight) { 12 | this.name = name; 13 | this.weight = weight; 14 | } 15 | public int getWeight() { 16 | return this.weight; 17 | } 18 | public String toString() { 19 | return name; 20 | } 21 | public int compareTo(ComparatorExample d) { 22 | return this.name.compareTo(d.name); 23 | } 24 | public static void main(String[] args) { 25 | Comparator byWeight = Comparator.comparingInt(ComparatorExample::getWeight); 26 | var ducks = new ArrayList(); 27 | ducks.add(new ComparatorExample("Quack", 7)); 28 | ducks.add(new ComparatorExample("Puddles", 10)); 29 | Collections.sort(ducks); // sorts by name 30 | System.out.println(ducks); // [Puddles, Quack] 31 | Collections.sort(ducks, byWeight); // sorts by weight with Comparator 32 | System.out.println(ducks); // [Quack, Puddles] 33 | } 34 | } -------------------------------------------------------------------------------- /src/ocp/chapter/fourteen/ListExamples.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.fourteen; 2 | 3 | import java.util.*; 4 | 5 | public class ListExamples { 6 | 7 | public static void main(String... args) { 8 | 9 | List list = new ArrayList<>(); 10 | list.add("SD"); 11 | list.add(0, "NY"); 12 | System.out.println(list.get(0)); 13 | 14 | list.set(1, "FL"); 15 | System.out.println(list); 16 | 17 | list.remove("NY"); 18 | list.remove(0); 19 | System.out.println(list); 20 | 21 | List numbers = Arrays.asList(1, 2, 3); 22 | numbers.replaceAll(x -> x * 3); 23 | System.out.println(numbers); 24 | } 25 | } -------------------------------------------------------------------------------- /src/ocp/chapter/fourteen/MapExamples.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.fourteen; 2 | 3 | import java.util.*; 4 | import java.util.function.*; 5 | 6 | public class MapExamples { 7 | 8 | public static void main(String... args) { 9 | 10 | Map map1 = new HashMap<>(); 11 | map1.put("koala", "bamboo"); 12 | map1.put("lion", "meat"); 13 | map1.put("giraffe", "leaf"); 14 | String food1 = map1.get("koala"); 15 | for (String key: map1.keySet()) System.out.print(key + ","); 16 | 17 | System.out.println(); 18 | 19 | Map map2 = new TreeMap<>(); 20 | map2.put("koala", "bamboo"); 21 | map2.put("lion", "meat"); 22 | map2.put("giraffe", "leaf"); 23 | map2.put("dolphin", "water"); 24 | String food2 = map2.get("koala"); 25 | for (String key: map2.keySet()) System.out.print(key + ","); 26 | 27 | System.out.println(); 28 | 29 | Map forEachMap = new HashMap<>(); 30 | forEachMap.put(1, "a"); 31 | forEachMap.put(2, "b"); 32 | forEachMap.put(3, "c"); 33 | forEachMap.forEach((k, v) -> System.out.println(v)); 34 | forEachMap.values().forEach(System.out::println); 35 | forEachMap.entrySet().forEach((e) -> System.out.println(e.getKey() + e.getValue())); 36 | 37 | System.out.println(); 38 | 39 | Map map3 = new HashMap<>(); 40 | map3.put(1, 2); 41 | map3.put(2, 4); 42 | Integer original = map3.replace(2, 10); 43 | System.out.println(map3); 44 | map3.replaceAll((k, v) -> k + v); 45 | System.out.println(map3); 46 | 47 | Map favorites = new HashMap<>(); 48 | favorites.put("Jenny", "Bus Tour"); 49 | favorites.put("Tom", null); 50 | favorites.putIfAbsent("Jenny", "Tram"); 51 | favorites.putIfAbsent("Sam", "Tram"); 52 | favorites.putIfAbsent("Tom", "Tram"); 53 | System.out.println(favorites); 54 | 55 | System.out.println(); 56 | 57 | BiFunction mapper = (v1, v2) -> v1.length() > v2.length() ? v1 : v2; 58 | 59 | Map favorites2 = new HashMap<>(); 60 | favorites2.put("Jenny", "Bus Tour"); 61 | favorites2.put("Tom", "Tram"); 62 | 63 | String jenny = favorites2.merge("Jenny", "Skyride", mapper); 64 | String tom = favorites2.merge("Tom", "Skyride", mapper); 65 | 66 | System.out.println(favorites2); 67 | System.out.println(jenny); 68 | System.out.println(tom); 69 | } 70 | } -------------------------------------------------------------------------------- /src/ocp/chapter/fourteen/SetExamples.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.fourteen; 2 | 3 | import java.util.*; 4 | 5 | public class SetExamples { 6 | 7 | public static void main(String... args) { 8 | 9 | Set set1 = new HashSet<>(); 10 | boolean b11 = set1.add(66); 11 | boolean b12 = set1.add(10); 12 | boolean b13 = set1.add(66); 13 | boolean b14 = set1.add(8); 14 | set1.forEach(System.out::println); 15 | 16 | System.out.println(); 17 | 18 | Set set2 = new TreeSet<>(); 19 | boolean b21 = set2.add(66); 20 | boolean b22 = set2.add(10); 21 | boolean b23 = set2.add(66); 22 | boolean b24 = set2.add(8); 23 | set2.forEach(System.out::println); 24 | } 25 | } -------------------------------------------------------------------------------- /src/ocp/chapter/nine/AbstractExample.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.nine; 2 | 3 | interface Fly { } 4 | 5 | abstract class Animal { 6 | 7 | protected abstract void makeNoise(String a); 8 | } 9 | 10 | abstract class Bird extends Animal implements Fly { // This class isn't instantiable 11 | 12 | public abstract String getName(); 13 | 14 | protected void makeNoise(String a) { // The first concrete subclass of Bird and Animal (Stork) will not need to override this method, since it's 15 | // overridden here as a nonabstract method. It could be redeclared here as an abstract method too. 16 | System.out.println(a); 17 | } 18 | 19 | public void printName() { 20 | System.out.println(getName()); 21 | } 22 | } 23 | 24 | class Stork extends Bird { 25 | 26 | public String getName() { // Must override the parent's abstract methods, or else the class will not compile (l.12). 27 | return "STORK!"; 28 | } 29 | } 30 | 31 | public class AbstractExample { 32 | 33 | public static void main(String... args) { 34 | Stork stork = new Stork(); 35 | stork.printName(); 36 | stork.makeNoise("Piu piu"); 37 | } 38 | } -------------------------------------------------------------------------------- /src/ocp/chapter/nine/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 9 - Advanced Class Design 2 | 3 | - Reusing Implementations Through Inheritance 4 | 5 | - Create and extend abstract classes 6 | 7 | - Programming Abstractly Through interfaces 8 | - Create and implement interfaces 9 | - Distinguish class inheritance from interface inheritance including abstract classes 10 | 11 | ## Introducing Abstract Classes (p.367) 12 | 13 | - An abstract class is a class that cannot be instantiated and may contain abstract methods. 14 | - An abstract method is a method that does not define an implementation when it is declared. 15 | - Both abstract classes and methods are denoted with the 'abstract' modifier. 16 | - A class that inherits an abstract class, must override the abstract methods of the superclass (all override rules from the last chapter apply). 17 | - An abstract class can be initialized, but only as part of the instantiation of a nonabstract subclass. 18 | - Only at runtime that the methods of an abstract class that have been overridden can be defined. 19 | - Abstract classes can extends nonabstract classes. 20 | 21 | ## Defining Abstract Methods (p.368-370) 22 | 23 | - An abstract class may include all of the same members as a nonabstract class (even constructors). 24 | - It is not required to include any abstract methods in an abstract class. 25 | - An abstract method can only be defined in an abstract class (or an interface). 26 | - Remember that optional modifiers, such as abstract and final, can be placed before or after the access modifier in a class and method declarations. 27 | - It is not possible to define an abstract method that has a body or default implementation. 28 | - Abstract classes constructors work just like nonabstract classes constructors. The only difference is that an abstract class constructor can only 29 | be called when it is being initialized by a nonabstract class (super()). 30 | - Even with abstract methods, all the rules for overriding methods must be followed. 31 | 32 | * Note: Remember that abstract methods can't have a body and must be declared with at least like this: 33 | - access modifier - abstract modifier (the order between these first two can vary, abstract is REQUIRED) - return type - method name and (); 34 | 35 | ## Invalid Modifiers (p.371-372) 36 | 37 | - abstract and final modifiers are an invalid combination of optional modifiers, since the final modifier won't let a class be extended and a method overridden. 38 | - A method cannot be marked as both abstract and private, since a private method can't be inherited/overridden. 39 | - abstract and static modifiers are an invalid combination of optional modifiers, since a static method is defined as belonging to the class, not an instance of 40 | the class, so it cannot be overridden (only hidden). 41 | - The compiler recognizes all this invalid combinations in the parent class and reports an error as soon as the invalid combinations are applied. 42 | 43 | ## Creating a Concrete Class (p.372-374) 44 | 45 | - A concrete class is a nonabstract class. 46 | - The first concrete subclass that extends an abstract class is required to implement all inherited abstract methods. 47 | - If the first concrete subclass extends an abstract class that extends another abstract class too and that overrides an abstract method to being a nonabstract 48 | method, the first concrete class is not required to override this method, since is not abstract anymore and already has an implementation. 49 | 50 | ## Reviewing Abstract Class Rule (p.374-375)s 51 | 52 | - Abstract Class Definition Rules: 53 | 1. Abstract classes cannot be instantiated. 54 | 2. All top-level types, including abstract classes, cannot be marked protected or private. 55 | 3. Abstract classes cannot be marked final. 56 | 4. Abstract classes may include zero or more abstract and nonabstract methods. 57 | 5. An abstract class that extends another abstract class inherits all of its abstract methods. 58 | 6. The first concrete class that extends an abstract class must provide an implementation for all of the inherited abstract methods. 59 | 7. Abstract class constructors follow the same rules for initialization as regular constructors, except they can be called only as part of the 60 | initialization of a subclass. 61 | 62 | * The following rules for abstract methods apply regardless of whether the abstract method is defined in an abstract class or interface. 63 | 64 | - Abstract Method Definition Rules: 65 | 1. Abstract methods can be defined only in abstract classes or interfaces. 66 | 2. Abstract methods cannot be declared private, final or static (in all cases). 67 | 3. Abstract methods must not provide a method body/implementation in the abstract supertype in which they are declared. 68 | 4. Implementing an abstract method in a subclass follows the same rules for overriding a method, including covariant return types, exception 69 | declarations, etc. 70 | 71 | ## Implementing Interfaces (p.375-379) 72 | 73 | - An interface is an abstract data type that declares a list of abstract methods that any concrete class implementing the interface must provide. 74 | - An interface can also include constant variables. 75 | - An interface can also include private, private static, static and default methods (they have a body). 76 | - A default method is one in which the interface method has a body and is not marked abstract, it doesn't need to be overridden. 77 | - private, private static, static and default methods in interfaces will be covered in 1Z0-816 topics of the book. 78 | - Both abstract methods and constant variables included within an INTERFACE are always implicitly assumed to be public. 79 | - Java allows a class to implement any number of interfaces. 80 | Interface declaration in order of appearance: 81 | - Access modifier: public or default (package-private). 82 | - `Implicit` modifier: abstract. 83 | - Interface keyword: interface. 84 | - Interface name and brackets. 85 | Interface members: 86 | - For methods: 87 | - `Implicit` modifiers: public abstract 88 | - Return type: Integer or int for example. 89 | - Method name. 90 | - Parentheses, parameter list (optional) and semicolon. // (); or (int a); 91 | - For constant variables: 92 | - `Implicit` modifiers: public static final 93 | - Variable type: Integer or int for example. 94 | - Variable name. 95 | - Variable constant value assignment. 96 | * Notes on interface constants: 97 | - Since they are all public and static, they can be used outside the interface declaration without requiring 98 | an instance of the interface. 99 | - An instance of the interface, means the instance of a class that implements the interface. 100 | - Remember that interface constants must be initialized inside the interface. 101 | - Interfaces are not required to define any methods. 102 | - The abstract modifier is optional, because the compiler will insert it implicitly in the declaration if there is no explicit declaration of it. 103 | - Interfaces can't be final for the same reason as abstract classes, since they are always abstract too. 104 | - The concrete class that implements an interface, must declare the overridden methods as public, since they are all public (the ones without a body). 105 | - Interfaces can extends other interfaces. Unlike a class, an interface can extend multiple interfaces. 106 | - Interfaces are not part of instance initialization. 107 | - Many of the rules for class declarations also apply to interfaces, including the following: 108 | 1. A Java file may have at most one public top-level class or interface (top-level types), and it must match the name of the file. 109 | 2. A top-level class or interface can only be declared with public or package-private access. 110 | 111 | ## Implicit Modifiers (p.379) 112 | 113 | - The compiler will automatically insert these modifiers on the interface and interface methods declarations. 114 | - You can choose to insert this implicit modifiers yourself or let the compiler insert them for you. 115 | - List of implicit modifiers for the exam (1Z0-815): 116 | - Interfaces are assumed to be abstract. 117 | - Interface variables are assumed to be public, static and final. 118 | - Interface methods without a body are assumed to be abstract and public. // They must be overridden with an explicit public access modifier. 119 | * Note: Only interfaces have these implicit modifiers. 120 | 121 | ## Conflicting Modifiers (p.380-381) 122 | 123 | - Examples of conflicts: 124 | 125 | private final interface Crawl { 126 | String distance; 127 | private int MAXIMUM = 1000; 128 | protected abstract boolean UNDERWATER = false; 129 | private void dig(int depth); 130 | protected abstract double depth(); 131 | public final void surface(); 132 | } // Every single line does not compile, since some modifiers aconflicting with the implicit modifiers and interface rules... 133 | 134 | * Note for difference between interfaces and classes (p.381): Remember that ONLY interfaces make use of implicit modifiers. 135 | 136 | ## Inheriting an Interface (p.382-383) 137 | 138 | - An interface can be inherited in one of three ways: 139 | - An interface can extends another interface(s). 140 | - A class can implements an interface(s). 141 | - A class can extend another class whose ancestor implements an interface. 142 | - Just like abstract classes, the first concrete class (nonabstract) that inherits the interface, must implement all of the inherited ABSTRACT methods. 143 | 144 | ## Mixing Class and Interface Keywords (p.383) 145 | 146 | - The following, are the only valid syntaxes for relating classes and interfaces in their declaration: 147 | - class1 extends class2 148 | - interface1 extends interface2, interface3, ... 149 | - class1 implements interface1, interface2, ... 150 | - class1 extends class 2 implements interface1, interface2 ... 151 | 152 | ## Duplicate Interface Method Declarations (p.384-386) 153 | 154 | - When two methods have identical declaration on two (or more) implemented interfaces, they are considered compatible. By that, we mean that the compiler 155 | can resolve the differences between the two (or more) declarations without finding any conflicts. 156 | - If two (or more) interface methods have identical behaviors (the same method declaration), you just need to be able to create a single method that 157 | overrides both inherited abstract methods at the same time. 158 | - If two (or more) interface methods have the same name but different signatures, it is considered a method overload and there is no conflict. 159 | When overload happens, all the methods must be implemented by the concrete class, since they are considered separate methods. 160 | - If the return types are different in interface methods, they must be covariant, or else the class that implements them will not compile. The compiler 161 | would also throw an exception if you define an abstract class or interface that inherits from two conflicting abstract types. 162 | 163 | ## Casting Interfaces (p.387) 164 | 165 | - When casting two classes that implement the same interface but don't have any kind of relation between them, Java will not throw a compiler error, but 166 | will throw a ClassCastException after. This is one of the rules of casting discussed in Chapter 8, that the compiler does not allow casts to unrelated 167 | types, like String casting to Long, but with interfaces there are limitations to what the compiler can validate. 168 | 169 | - For ex.: 170 | 171 | interface Canine {} 172 | class Dog implements Canine {} 173 | class Wolf implements Canine {} 174 | 175 | ... method() { 176 | Canine canine = new Wolf(); 177 | Canine badDog = (Dog)canine; 178 | } // Compiles, but will throw a ClassCastException at runtime, because both classes don't have any kind of relation. 179 | 180 | - But the compiler can enforce one rule around interface casting. The compiler does not allow a cast from an interface reference to an object reference if 181 | the object type does not implement the interface. 182 | - For ex.: `Object badDog = (String)canine; // Since String does not implements Canine, the compiler recognizes that this cast is not possible.` 183 | 184 | ## Interfaces and the instanceof Operator (p.388) 185 | 186 | - With interfaces, the compiler has limited ability to enforce the rule of unrelated classes when using the intanceOf operator too, because even though a 187 | reference type may not implement an interface, one of its subclasses could. 188 | - But the compiler can check for unrelated interfaces if the reference is a class that is marked final, like Integer. 189 | 190 | ## Reviewing Interface Rule (p.388-389) 191 | 192 | - Interface Definition Rules: 193 | 194 | 1. Interfaces cannot be instantiated. 195 | 2. All top-level types, including interfaces, cannot be marked protected or private. 196 | 3. Interfaces are assumed to be abstract and cannot be marked final. 197 | 4. Interfaces may include zero or more abstract methods. 198 | 199 | - Note that this four rules are similar to the abstract class declaration rules that were seen before. 200 | 201 | 5. An interface can extend any number of interfaces. 202 | 6. An interface reference may be cast to any reference that inherits the interface, although this may produce an exception at runtime if the classes aren't 203 | related (ClassCastException). 204 | 7. The compiler will only report an unrelated type error for an instanceof operation with an interface on the RIGHT side if the reference on the LEFT side 205 | is a final class that does not inherit the interface. Remember that the right side is composed by a supertype and the left side is a reference. 206 | 8. An interface method with a body must be marked default, private, static or private static (covered on 1Z0-816). 207 | 208 | - Abstract Interface Method Rules: 209 | 210 | 1. Abstract methods can be defined only in abstract classes and interfaces. 211 | 2. Abstract methods cannot be declared private, static or final. 212 | 3. Abstract methods must not provide a method body/implementation in the abstract class/interface in which it's declared. 213 | 4. Implementing an abstract method in a subclass follows the same rules for overriding a method, including covariant return types, exception declarations, etc. 214 | 215 | - Note that this four rules are similar to the abstract methods rules seen before. 216 | 217 | 5. Interface methods without a body are assumed to be abstract and public. 218 | 219 | - Interface Variable Rules: 220 | 221 | 1. Interface variables are assumed to be public, static and final (public constants). 222 | 2. Because interface variables are marked final, they must be initialized with a value when they are declared. 223 | 224 | - Note: Remember that the primary differences between interfaces and abstract classes are that only interfaces include implicit modifiers, do not contain constructors, 225 | do not participate in the instance initialization process, and support multiple inheritance (classes only support single inheritance), remember that this isn't a true 226 | multiple inheritance, since Java enables only limited multiple inheritance for interfaces and classes can't extend multiple classes directly. 227 | 228 | ## Introducing Inner Classes (p.390-391) 229 | 230 | - A member inner class is a class defined at the member level of a class (same level as methods, instance variables, etc). It can be declared only inside 231 | another class. 232 | - For the 1Z0-816 exam, there are four types of nested classes you will need to know about (they will be covered further) member inner classes, local classes, 233 | anonymous classes and static nested classes. 234 | - A class can have many inner classes and interfaces. 235 | - While top-level classes and interfaces can only be set with public or package-private access, member inner classes do not have the same restriction. A member 236 | inner class, can be declared with all of the same access modifiers as a class member (even private abstract is allowed for the inner class declaration). 237 | - A member inner class can contain many of the same methods and variables as a top-level class, but it cannot contain some members, such as static members. 238 | 239 | - Notes after taking the review exam: 240 | - Remember that an abstract class may include all of the same members as a nonabstract class (even constructors). 241 | - The main() method can be included inside an abstract class. 242 | - Note that the methods can be overloaded inside instead of overridden, so there are some tricky questions that do this in the exam and the concrete will not compile, 243 | since the concrete class doesn't override all the abstract inherited methods. Abstract methods can be overloaded on abstract classes too, causing the same problem if 244 | the concrete class doesn't override the abstract method. 245 | -------------------------------------------------------------------------------- /src/ocp/chapter/seven/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 7 - Methods and Encapsulation 2 | 3 | Creating and Using Methods 4 | 5 | - Create methods and contructors with arguments and return values 6 | - Create and invoke overloaded methods 7 | - Apply the static keyword to methods and fields 8 | 9 | Applying Encapsulation 10 | 11 | - Apply access modifiers 12 | - Apply encapsulation principles to a class 13 | 14 | ## Designing Methods (p.250-251) 15 | 16 | A method declaration is composed by, respectively, an access modifier (public), _optional_ specifier (final), return type (void), method name (any name that starts with a letter, $ or \_), list of parameters (which must be wrapped in parentheses), exceptions(optional) and the method body (must have braces). 17 | 18 | > **Note:** The method name and parameter list are called the method signature. 19 | 20 | Parts of a method declaration: 21 | 22 | | Element | Required? | 23 | | :---------------------- | :------------------------ | 24 | | Access modifier | No | 25 | | Optional modifier | No | 26 | | Return type | Yes | 27 | | Method name | Yes | 28 | | Parameter list | Yes, but can be empty ( ) | 29 | | Optional exception list | No | 30 | | Method body \* | Yes, but can be empty { } | 31 | 32 | > **Table Note:** The full body can be omitted for abstract methods. 33 | 34 | ## Access Modifiers (p.251-252) 35 | 36 | Java offers four choices of access modifiers: 37 | 38 | - private: The private modifier means the method can be called only from within the same class. 39 | - Default (package-private) Access: With default access, the method can be called only from classes in the same package. There is no keyword for default access. You simply omit the access modifier. 40 | - protected: The protected modifier means the method can be called only from classes in the same package or subclasses. 41 | - public: The public modifier means the method can be called from any class. 42 | 43 | > **Note:** The default keyword exists in Java, but it's not used for access control (Chapter 9 will cover interfaces). 44 | 45 | Some tricky method declarations that may appear in the exam: 46 | 47 | `public void walk1() { }` // VALID 48 | `default void walk2() { }` // DOES NOT COMPILE 49 | `void public walk3() { }` // DOES NOT COMPILE 50 | `void walk4() { }` // VALID 51 | 52 | ## Optional Specifiers (p.252-253) 53 | 54 | Different than access modifiers, you can have multiple specifiers in the same method (although not all combinations are legal). Multiple specifiers can be specified in any order. Optional specifiers list: 55 | 56 | - static: The static modifier is used for class methods (will cover more later in this Chapter). 57 | - abstract: The abstract modifier is used when a method body is not provided (Chapter 9 will cover it). 58 | - final: The final modifier is used when a method is not allowed to be overridden by a subclass (Chapter 8 will cover it). 59 | - synchronized: The synchronized modifier is used with multithreaded code (1Z0-816 Chapters will cover it). 60 | - native: The native modifier is used when interacting with code written in another language such as C++. It is not on either OCP 11 exam. 61 | - strictfp: The strictfp modifier is used for making floating-point calculations portable. It is not on either OCP 11 exam. 62 | 63 | Some tricky method declarations with specifiers that can appear in the exam: 64 | 65 | `public void walk1() { }` // VALID 66 | `public final void walk2() { }` // VALID 67 | `public static final void walk3() { }` // VALID 68 | `public final static void walk4() { }` // VALID 69 | `public modifier void walk5() { }` // DOES NOT COMPILE 70 | `public void final walk6() { }` // DOES NOT COMPILE - It's not allowed to declare the optional specifiers after the return type. 71 | `final public void walk7() { }` // VALID - Java allows the optional specifiers to appear before the access modifier. 72 | 73 | ## Return Type (p.253-254) 74 | 75 | Methods with a return type other than void are required to have a return statement (returning the same data type) inside their body. Methods that have a return type of void are permitted to have a return statement with no value returned or omit the return statement. Some examples of wrong method declaration: 76 | 77 | `public String walk1() { }` // DOES NOT COMPILE - No return statement 78 | `public walk2() { }` // DOES NOT COMPILE - No return type specified 79 | `public String int walk3() { }` // DOES NOT COMPILE - Two return types are specified (only one can be specified) 80 | `String walk4(int a) { if (a == 4) return ""; }` // DOES NOT COMPILE - Missing a default return statement, in case of a !== 4 81 | 82 | ## Method Name (p.254-255) 83 | 84 | Review of some rules: 85 | 86 | - An identifier may only contain letters, numbers, $ or \_. 87 | - The first character is not allowed to be a number. 88 | - An identifier is not allowed to contain special characters (%,#,&,@...). 89 | - Reserved words are not allowed (public), but remember that Java is camelcase, for example public !== Public. 90 | - Single underscore (\_) character is not allowed as an identifier. 91 | - By convention, methods begin with a lowercase letter, but are not required to. 92 | 93 | ## Working with Varargs (p.256-257) 94 | 95 | A varargs parameter must be the last element in a method's parameter list. Only one varargs parameter is allowed per method: 96 | 97 | `public void walk1(int... nums) { }` // COMPILES 98 | `public void walk2(int start, int... nums) { }` // COMPILES 99 | `public void walk3(int... nums, int start) { }` // DOES NOT COMPILES - The varargs parameter isn't the last parameter on the list. 100 | `public void walk4(int... start, int... nums) { }` // DOES NOT COMPILES - There are two varargs parameters on the list (only one allowed). 101 | 102 | You can call a method with varargs parameter in more than a way: 103 | 104 | - Pass in an array with the values. 105 | - List the elements of the array and let Java create if for you. 106 | - Omit the varargs values in the method call, Java will create an array of length zero (empty array). 107 | - It is possible to pass null explicitly, but you can get a nullpointer exception in the usage of this null varargs array. 108 | 109 | > Note.: Remember that a member of a class, is an instance variable or instance method. 110 | 111 | ## Applying Access Modifiers (p.258-266) 112 | 113 | Access Modifiers in order from most restrictive to least restrictive: 114 | 115 | - private: Only code in the same class can call private methods or access private fields. 116 | `private String name;` or `private String getName() { ... }` 117 | - Default (package-private) access: Only classes in the same package may call these methods or access these fields. 118 | 119 | `String name;` or `String getName() { ... }` 120 | 121 | - protected: Allows everything that package-private allows, plus adds the ability to access members of a parent class (subclasses). Not allowed to refer to protected members of a parent class if they are not in the same package and the reference type used is an object that is not a subclass of the parent class. You can only access the protected members with the reference of the subclass from inside the subclass. 122 | 123 | `protected String name;` or `protected String getName() { ... }` 124 | 125 | - public: Anyone can access the member from anywhere. 126 | `public String name;` or `public String getName() { ... }` 127 | 128 | > **Note:** Extending means creating a subclass that has access to any protected and public members of the parent class. Modules redefine public access, making possible to restrict access to public code. 129 | 130 | Access modifiers rules: 131 | 132 | | A method in X can access a Y member | private | Default (package-private) | protected | public | 133 | | :------------------------------------------- | :------ | :------------------------ | :-------- | :----- | 134 | | in the same class | Yes | Yes | Yes | Yes | 135 | | in another class in the same package | No | Yes | Yes | Yes | 136 | | in a subclass in a different package | No | No | Yes | Yes | 137 | | in an unrelated class in a different package | No | No | No | Yes | 138 | 139 | ## Applying the static Keyword (p.266-274) 140 | 141 | When the static keyword is applied to a variable, method or class, it applies to the class rather than a specific instance of the class. 142 | 143 | ### Designing static Methods and Fields 144 | 145 | - static methods don't require an instance of the class. 146 | - They are shared among all users of the class. 147 | - Is a member of the single class object that exists independently of any instances of that class. 148 | - main(String... args) method is a static method, that can be called like any other static method. `TestClass.main(new String[0]);` 149 | 150 | static methods have two main purposes: 1. For utility or helper methods that don't require any object state. Since there is no need to access instance variables, having static methods eliminates the need for the caller to instantiate an object just to call the method. 1. For state that is shared by all instances of a class, like a counter. All instances must share the same state. Methods that merely use that should be static as well. 151 | 152 | ### Accessing a static Variable or Method 153 | 154 | - You don't need an instance of the object to call a static member. `System.out.println(Koala.count);`. If the static member is declared inside the same class you're calling, you just call him directly. `System.out.println(count);` - inside Koala class. 155 | 156 | You can use an instance of the object to call a static member. The compiler checks for the type of the REFERENCE and uses that instead of the OBJECT. 157 | 158 | `Koala k = new Koala();` 159 | `System.out.println(k.count);` // k is a Koala, so print 0 160 | `k = null` 161 | `System.out.println(k.count);` // k is still a Koala, so print 0 too 162 | 163 | > **Note:** This works since we're looking for a static member. 164 | 165 | ### Static vs. Instance 166 | 167 | - A static member cannot call an instance member without referencing an instance of the class. 168 | - A static or instance member can call a static member because static doesn't require an object to use. 169 | - Only an instance member can call another instance member on the same class without using a reference variable (instance of the object), because instance objects do require an object. 170 | - Method params can be used inside static methods to access nonstatic members of a class. 171 | - Each object has a copy of the instance variables. 172 | - There is only one copy of the code for the instance methods. 173 | - Parameters and local variables go on the stack. 174 | 175 | ### static Variables 176 | 177 | - Constants are variables that are meant to never change during the program. It uses the final modifier to ensure the variable never changes. 178 | - Constants use the modifier static final and a different naming convention than other variables. They use all upercase letters with underscores. 179 | - Constants must be set exactly once, in the same line as the declaration or inside a static initializer block. 180 | between "words". `private static final int NUM_BUCKETS = 45;` - If you try to change this value the code will note compile. 181 | - The compiler can only check if we don't try to reassign the final value to point to a different object. So adding a element to a final ArrayList will compile. 182 | 183 | ### Static Initialization 184 | 185 | - They are like instance initializers, just code inside braces, but they add the static keyword to specify they should be run when the class is first loaded. 186 | - All static initializers run when the class is first used in the order they are defined. 187 | - You can initialize a constant variable (static final) inside an static initializer, without initializing it before the block, if you initialize in the same line as the declaration and inside the static initializer, the code will not compile. 188 | - Try to avoid static and instance initializers. One case that a static initializer is usefull, is when the code needed to initialize a constant variable required more than one line of code. 189 | 190 | ### Static Imports 191 | 192 | This imports are only for static members, like "import static java.util.Arrays.asList" // will import only the static method asList, and it can be used directly without Arrays. If we create an asList method in our coding class. Java would give it preference over the imported one, and the method we coded would be used. 193 | 194 | Some exam cases of static import usage: 195 | 196 | `import static java.util.Arrays;` // Does not compile 197 | `import static java.util.Arrays.asList;` // Compile 198 | `static import java.util.Arrays.*;` // Does not compile 199 | `import static java.util.Arrays.*;` // Compile 200 | 201 | > **Note:** If we try to use Arrays.asList() it will not compile, since we didn't imported the class, we imported only the static member asList(). Regular imports are for classes and Static imports are for static members of a class. 202 | 203 | ## Passing Data among Methods (p.274-277) 204 | 205 | Java is a "pass-by-value" language. This means that a copy of the variable is made and the method receives that copy. Assignments made in the method do not affect the caller. If the change made on the other method changes a value of the object, like StringBuilder `append()` method, the change will be available to both references, but in a case of trying to assign a new value to the copy, it will not mirror the change. So remember, assigning a new primitive or reference to a parameter doesn't change the caller. Calling methods on a reference to an object can affect the caller. 206 | 207 | > **Note:** _pass-by-reference_ is another approach, which Java don't utilize, that the values can be affected if they are passed as params and modified. 208 | 209 | ## Overloading Methods (p.277-283) 210 | 211 | Method overloading occurs when methods have the same name but different method signatures, which means they differ by method parameters. Everything other than the method name can vary for overloading methods. 212 | 213 | You cannot have methods where the only difference is that one is an instance method and the other is a static method. It's not allowed to overload methods with the same parameter list. They must differ in at least one of the parameters. Java will always pick the most specific version of a method that it can. So it will not autobox if we have two methods with the corresponding param type, one being a Wrapper and the other a primitive. It would call the primitive method in this case: `a(1)` -> `a(int a)` instead of `a(Integer a)`. Remember that Java only accept wider types, it will not automatically convert to a narrower type. If you want so, you'll need to explicitly cast the wider to a narrower type. 214 | 215 | Java has a concept called "type erasure", where generics are used only at compile time. So you can't overload with two Lists of different generics. 216 | 217 | - `List strings` and `List integers` look like this in compiled code `List strings` and `List integers`, so they are considered equal. 218 | 219 | Normal arrays will work just fine with overload (`int[] ints` and `Integers[] integers`), they don't participate in type erasure. 220 | 221 | > **Note:** Java will always do only one conversion. Java can convert a 4 (int) to a long or autobox it to an Integer 4, but it will not convert a 4 (int) to a long and then autobox it to a Long 4. 222 | 223 | The order that Java uses to choose the right overloaded method: 224 | 225 | | Rule | Example of what will be chosen for glide(1, 2) | 226 | | :-------------------- | :--------------------------------------------- | 227 | | Exact match by type | String glide(int i, int j) | 228 | | Larger primitive type | String glide(long i, long j) | 229 | | Autoboxed type | String glide(Integer i, Integer j) | 230 | | Varargs | String glide(int... nums) | 231 | 232 | ## Encapsulation (p.283-285) 233 | 234 | Means that only methods in the class with the same variables can refer to the instance variables. Callers are required to use these methods. The getter and setter methods are also known as, respectively, 'accessor method' and 'mutator method'. Conventions for getters and setters: 235 | 236 | - Getter methods most frequently begin with 'is' if the property is a boolean. 237 | - Getter methods most frequently begin with 'get' if the property is not a boolean. 238 | - Setter methods begin with 'set'. 239 | 240 | > **Notes after the review exam:** Some exam questions try tricking you with the type 'var' in method declaration. Remember that 'var' can only be used with local variables. 241 | -------------------------------------------------------------------------------- /src/ocp/chapter/seven/StaticExamples.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.seven; 2 | 3 | public class StaticExamples { 4 | 5 | private static final int NUM_SECOND_PER_MINUTE; 6 | private static final int NUM_MINUTES_PER_HOUR; 7 | private static final int NUM_SECONDS_PER_HOUR; 8 | 9 | static { 10 | NUM_SECOND_PER_MINUTE = 60; 11 | NUM_MINUTES_PER_HOUR = 60; 12 | } 13 | 14 | static { 15 | NUM_SECONDS_PER_HOUR = NUM_SECOND_PER_MINUTE * NUM_MINUTES_PER_HOUR; 16 | } 17 | 18 | private String name = "Static class"; 19 | public static void first() { } 20 | public static void second() { } 21 | public void third() { System.out.println(name); } 22 | 23 | public static void main(String... args) { 24 | 25 | first(); 26 | second(); 27 | // third(); // - Does not compile because main() is static and is trying to access a nonstatic method. 28 | // - If we add the static specifier to third(), it will only change the problem. 29 | // - Because third is trying to access an Instance variable (nonstatic). Adding static 30 | // to name would solve the problem. Another solution would have been to call third using an instance of the object 31 | 32 | new StaticExamples().third(); // Will compile normally 33 | 34 | System.out.println(NUM_SECONDS_PER_HOUR); 35 | } 36 | } -------------------------------------------------------------------------------- /src/ocp/chapter/seven/VarargsExample.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.seven; 2 | 3 | public class VarargsExample { 4 | 5 | public static void walk(int start, int... nums) { 6 | 7 | System.out.println(nums.length); 8 | } 9 | 10 | public static void run(int... nums) { 11 | 12 | System.out.println(nums[1]); // Accessing a varargs parameter is just like accessing an array. 13 | } 14 | 15 | public static void main(String... args) { 16 | 17 | walk(1); // 0 18 | walk(1, 2); // 1 19 | walk(1, 2, 3); // 2 20 | walk(1, new int [] {4, 5}); // 2 21 | 22 | run(11, 22); // 22 23 | } 24 | } -------------------------------------------------------------------------------- /src/ocp/chapter/six/Animal.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.six; 2 | 3 | public class Animal { 4 | private String name; 5 | private boolean canHop; 6 | 7 | public Animal(String name, boolean canHop) { 8 | this.name = name; 9 | this.canHop = canHop; 10 | } 11 | 12 | public boolean canHop() { 13 | return this.canHop; 14 | } 15 | 16 | public String toString() { 17 | return this.name; 18 | } 19 | } -------------------------------------------------------------------------------- /src/ocp/chapter/six/ComparatorExample.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.six; 2 | 3 | import java.util.*; 4 | 5 | // p.230-231 6 | // Comparator interface - this is a functional interface since it has only one unimplemented method. 7 | // It has many static and default methods to facilitate writing complex comparators. 8 | // public interface Comparator { 9 | // int compare(T o1, T 02); - Most important method for the exam. 10 | // } 11 | 12 | public class ComparatorExample { 13 | 14 | public static void main(String args[]) { 15 | 16 | Comparator ints = (i1, i2) -> i1 - i2; 17 | 18 | System.out.println(ints.compare(5, 3)); // 2 - The ints comparator uses natural sort order. If it returns a positive number 19 | // that means the first number is bigger and we are sorting in ascending order. 20 | 21 | System.out.println(); 22 | 23 | Comparator strings = (s1, s2) -> s2.compareTo(s1); // Does the sorting in descending order because the call is "backwards". 24 | Comparator moreStrings = (s1, s2) -> - s1.compareTo(s2); // This call uses the default order (ascending); however, it applies 25 | // a negative sign to the result, which reverses it to descending. 26 | 27 | System.out.println(strings.compare("bc", "az")); // -1 - descending 28 | System.out.println(moreStrings.compare("a", "az")); // 1 - descending 29 | } 30 | } -------------------------------------------------------------------------------- /src/ocp/chapter/six/ConsumerExample.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.six; 2 | 3 | import java.util.function.*; 4 | 5 | // p.230-231 6 | // Consumer interface - accept() is the most important method on 1Z0-815. 7 | // public interface Consumer { 8 | // void accept(T t); 9 | // } 10 | 11 | // Good to use in cases that you need to do something using lambdas without returning a value (like printing) 12 | public class ConsumerExample { 13 | 14 | private static String color = "Red"; 15 | 16 | public static void main(String args[]) { 17 | 18 | Consumer consumer = x -> System.out.println(x); 19 | 20 | print(consumer, "Hello World"); 21 | // print(x -> System.out.println(x), "Hello World"); // Works too. 22 | 23 | System.out.println("\n"); 24 | 25 | caw("Fulana"); 26 | } 27 | 28 | public static void print(Consumer consumer, String value) { 29 | 30 | consumer.accept(value); // Will execute the consumer passed by params and using the value param in it. 31 | } 32 | 33 | // Only works/compiles because all these local and method parameter variables that are used in the lambda are "effectively final", 34 | // their value will not change after being set (using final on the variables is an option to ensure they are effectively final). 35 | public static void caw(String name) { 36 | 37 | String volume = "loudly"; 38 | 39 | // volume = "HAHA" // This would make line 41 not compile, at the variable, because the lambda sees this assignment as a problem. 40 | // name = "HAHA" // This would not compile for the same reason of volume assignment. 41 | 42 | Consumer consumer = s -> System.out.print(name + " says " + volume + " that she is " + color); 43 | 44 | consumer.accept(""); 45 | } 46 | } -------------------------------------------------------------------------------- /src/ocp/chapter/six/LambdaApiUsage.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.six; 2 | 3 | import java.util.*; 4 | 5 | public class LambdaApiUsage { 6 | 7 | public static void main(String[] args) { 8 | 9 | System.out.println("\n----------------removeIf()----------------\n"); 10 | 11 | List bunnies = new ArrayList<>(); 12 | bunnies.add("long ear"); 13 | bunnies.add("floppy"); 14 | bunnies.add("hoppy"); 15 | 16 | System.out.println(bunnies); // [long ear, floppy, hoppy] 17 | 18 | bunnies.removeIf(s -> s.charAt(0) != 'h'); 19 | 20 | System.out.println(bunnies); // [hoppy] 21 | 22 | System.out.println("\n----------------sort()----------------\n"); 23 | 24 | bunnies.add(0, "long ear"); 25 | bunnies.add(1, "floppy"); 26 | 27 | System.out.println(bunnies); // [long ear, floppy, hoppy] 28 | 29 | bunnies.sort((b1, b2) -> b1.compareTo(b2)); // default ascending order 30 | 31 | System.out.println(bunnies); // [floppy, hoppy, long ear] 32 | 33 | System.out.println("\n----------------forEach()----------------\n"); 34 | 35 | bunnies.forEach(b -> System.out.println(b)); // floppy hoppy long ear 36 | System.out.println(bunnies); // [floppy, hoppy, long ear] 37 | 38 | System.out.println("\n--------------------------------\n"); 39 | 40 | Set dogs = Set.of("fred", "bolt", "luke"); 41 | dogs.forEach(d -> System.out.println(d)); 42 | 43 | System.out.println("\n--------------------------------\n"); 44 | 45 | Map cats = new HashMap<>(); 46 | cats.put("meow", 3); 47 | cats.put("elis", 8); 48 | cats.put("hop", 1); 49 | 50 | // For a map, you have to choose whether you want to go through the keys or values. 51 | cats.keySet().forEach(c -> System.out.println(c)); // prints keys 52 | cats.values().forEach(c -> System.out.println(c)); // prints values 53 | 54 | System.out.println("\n----------------forEach()-BiConsumer-Map----------------\n"); 55 | 56 | // BiConsumer works just like a Consumer, but it can take two parameters. This functional interface 57 | // allows you to use forEach() with key/value pairs from Map. 58 | cats.forEach((k, v) -> System.out.println(k + " " + v)); // prints keys and values 59 | } 60 | } -------------------------------------------------------------------------------- /src/ocp/chapter/six/PredicateSearch.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.six; 2 | 3 | import java.util.*; 4 | import java.util.function.*; 5 | 6 | // p.230 7 | // Predicate interface - Good for conditional statements (returns boolean). 8 | // public interface Predicate { 9 | // boolean test(T t); 10 | // } 11 | 12 | public class PredicateSearch { 13 | 14 | public static void main(String... args) { 15 | 16 | List animals = new ArrayList<>(); 17 | animals.add(new Animal("Fish", true)); 18 | 19 | Predicate predicate = a -> a.canHop(); 20 | 21 | print(animals, predicate); 22 | // print(animals, a -> a.canHop()); // Works too. 23 | } 24 | 25 | private static void print(List animals, Predicate checker) { 26 | 27 | for (Animal animal : animals) { 28 | 29 | if (checker.test(animal)) // a -> a.canHop() 30 | System.out.println(animal + " "); 31 | } 32 | 33 | System.out.println(); 34 | } 35 | } -------------------------------------------------------------------------------- /src/ocp/chapter/six/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 6 - Lambdas and Functional Interfaces 2 | 3 | Programming Abstractly Through Interfaces 4 | 5 | - Declare and use List and ArrayList instances 6 | - Understanding Lambda Expressions 7 | 8 | ## Lambda Syntax (p.226-229) 9 | 10 | print(animals, a -> a.canSwim()); 11 | 12 | This concept is called deferred execution. Deferred execution means that code is specified now but will run later. Later is when the `print()` method call it. 13 | 14 | Lambdas work with interfaces that have only one abstract method. Java relies on context when figuring out what lambda expressions mean. Looking at interfaces that are implemented for ex. Lambda syntax is tricky because many parts are optional. These two lines do the exact same thing: 15 | 16 | a -> a.canHop() // "a" is the parameter name, "->" is the arrow operator that separates param and body, and the a.canHop() 17 | // is the body, which calls one single method and returns the result of that method. 18 | 19 | (Animal a) -> { return a.canHop(); } // This one is similar to the less verbose form of a lambda, but it shows explicitly 20 | // the parameter type and the, which body has a semicolon with a return statement. 21 | 22 | The optional and required parts are explained like this: 23 | 24 | - The parentheses can be omitted only if there is a single parameter and its types is not explicitly stated. 25 | - We can omit braces when we have only a single statement. 26 | - When you omit the braces, Java doesn't require you to type return or use a semicolon (doesn't work when we have 2 or more statements). 27 | 28 | Some valid lambdas: 29 | 30 | s -> {} // If there is no code on the right side of the expression, you don't need the semicolon or return statement. 31 | () -> true // 0 params 32 | a -> a.startsWith("test") // 1 params 33 | (String a) -> a.startsWith("test") // 1 params 34 | (a, b) -> a.startsWith("test") // 2 params - there is no rule that defines you must use all defined params. 35 | (String a, String b) -> a.startsWith("test") // 2 params 36 | 37 | Some invalid lambdas: 38 | 39 | a, b -> a.startsWith("test") // two params missing parentheses. 40 | a -> { a.startsWith("test"); } // braces declared but is missing the return statement. 41 | a -> { return a.startsWith("test") } // braces and return statement declared but is missing the semicolon after the return. 42 | 43 | > **Note:** Remember that the parentheses are optional ONLY when there is one parameter and it doesn't have a type declaration. 44 | 45 | ## Introducing Functional Interfaces (p.229-232) 46 | 47 | Lambdas work with interfaces that have only one abstract method. These are called 'functional interfaces' (simplified definition for the 1Z0-815 exam). This is named Single Abstract Method (SAM) rule. @FunctionalInterface is an annotation that means the authors of the interface promise it will be safe to use in a lambda in the future. However, just because there isn't this annotation in an interface, it doesn't mean it's not a functional interface, having exactly one abstract method is what makes it a functional interface (not the annotation). 48 | 49 | Predicate, Consumer, Supplier and Comparator are functional interfaces. These functional interfaces can be used without specifying the data type (no diamond operator < and >). 50 | 51 | | Functional Interface | # parameters | Return type | 52 | | :------------------- | :----------- | :---------------- | 53 | | Comparator | Two | int | 54 | | Consumer | One | void | 55 | | Predicate | One | boolean | 56 | | Supplier | None | One (type varies) | 57 | 58 | ## Working with Variables in Lambdas (p.233-236) 59 | 60 | Variables can appear in three places with respect to lambdas: 61 | 62 | - The parameter list. 63 | - Local variables declared inside the lambda body. 64 | - Variables referenced from the lambda body. 65 | 66 | ### Parameter List 67 | 68 | Specifying the type of parameters is optional. Additionally, var can be used in place of the specific type. 69 | 70 | These three statements are interchangeable: 71 | 72 | Predicate p = x -> true; 73 | Predicate p = (var x) -> true; 74 | Predicate p = (String x) -> true; 75 | 76 | The type of the lambda parameter is String in all of these, because a lambda infers the type from the surrounding context. 77 | 78 | Predicate p = (String x, y) -> true; // Do not compile, because type declaration for the params is optional, 79 | // but if the params type is declared, it needs to be consistent. 80 | Predicate p = (String x, String y) -> true; // Compiles 81 | 82 | ### Local Variables inside the Lambda Body: 83 | 84 | It is legal to define a block in the lambda's body. That block can have anything that is valid in a normal Java block, including local variable declarations. 85 | 86 | (a, b) -> { int c = 0; return 5; } 87 | 88 | Beware of local variables that are declared with the same name of another that is already declared in the scope. 89 | 90 | (a, b) -> { int a = 0; return 5;} // a is already declared as a parameter of the lambda. 91 | 92 | Note.: When writing your own code, a lambda block with a local variable is a good hint that you should extract that code into a method. 93 | 94 | ### Variables Referenced from the Lambdas Body: 95 | 96 | Lambdas can access a method parameter or local variable under certain conditions. Instance variables and Class variables are always allowed. Method parameters and local variables are allowed to be referenced if they are effectively final. This means that the value of a variable doesn't change after it's set, regardless of whether it is explicitly marked as final. 97 | 98 | Rules for accessing a variable from a lambda body inside a method: 99 | 100 | | Variable type | Rule | 101 | | :---------------------- | :--------------------------- | 102 | | Instance variable | Allowed | 103 | | Static variable (class) | Allowed | 104 | | Local variable | Allowed if effectively final | 105 | | Method parameter | Allowed if effectively final | 106 | | Lambda parameter | Allowed | 107 | 108 | ## Calling APIs with Lambdas (1ZO-815 - p.236-238): 109 | 110 | - `removeIf()` List and Set declare this method, that takes a Predicate. 111 | - `sort()` can be used directly on the list object, instead of calling `Collections.sort(list)`. There is no `sort()` for Set or Map, because neither of those types has indexing. 112 | - `forEach()` takes a Consumer and calls that lambda for each element encountered. 113 | 114 | ## Summary (p.238-239) 115 | 116 | - Lambdas are passed to method expecting an instance of a funtional interfaces. 117 | - Predicate is a common interface that returns a boolean and takes any type. 118 | - Consumer takes any type and doesn't return a value. 119 | - Supplier returns a value and does not take any parameters. 120 | - Comparator takes two parameters and returns an int. 121 | -------------------------------------------------------------------------------- /src/ocp/chapter/six/SupplierExample.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.six; 2 | 3 | import java.util.*; 4 | import java.util.function.*; 5 | 6 | // p.231 7 | // Supplier interface - has only one method. 8 | // public interface Supplier { 9 | // T get(); 10 | // } 11 | 12 | public class SupplierExample { 13 | 14 | public static void main(String args[]) { 15 | 16 | // A good use case for a Supplier is when generating values. 17 | Supplier number = () -> 42; 18 | Supplier random = () -> new Random().nextInt(); 19 | 20 | System.out.println(number.get()); 21 | System.out.println(random.get()); 22 | 23 | System.out.println("\n"); 24 | 25 | System.out.println(returnNumber(number)); 26 | System.out.println(returnNumber(random)); 27 | 28 | System.out.println("\n"); 29 | 30 | System.out.println(returnNumber(() -> 42)); 31 | System.out.println(returnNumber(() -> new Random().nextInt())); 32 | } 33 | 34 | private static int returnNumber(Supplier supplier) { 35 | 36 | return supplier.get(); 37 | } 38 | } -------------------------------------------------------------------------------- /src/ocp/chapter/ten/ExceptionExamples.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.ten; 2 | 3 | class NoMoreCarrotsException extends Exception { 4 | NoMoreCarrotsException() { 5 | super("NO MORE CARROTS!"); 6 | } 7 | } 8 | 9 | interface Animal { 10 | void good() throws NoMoreCarrotsException; 11 | } 12 | 13 | public class ExceptionExamples implements Animal { 14 | 15 | private String string; 16 | 17 | public static void main(String[] args) { 18 | bad(); 19 | } 20 | 21 | private static void bad() throws Error { 22 | try { 23 | nice(); 24 | } catch (NoMoreCarrotsException e) { 25 | System.out.println(e.getMessage()); 26 | System.out.println("HA NoMoreCarrots..."); 27 | } catch (java.io.IOException e) { 28 | System.out.println("IO? Not printed..."); 29 | } 30 | 31 | try { 32 | eatCarrot(); 33 | } catch (NullPointerException | IllegalArgumentException | Error e) { // Handling and declaring Error and its subclasses should not be done, but it works. 34 | System.out.println(e); 35 | System.out.println("HA NullPointer!"); 36 | } 37 | 38 | throw new Error("OH NO"); 39 | } 40 | 41 | public static void nice() throws NoMoreCarrotsException, java.io.IOException { 42 | System.out.println("NICE"); 43 | 44 | throw new NoMoreCarrotsException(); 45 | } 46 | 47 | public void good() { 48 | System.out.println("GOOD"); 49 | } 50 | 51 | private static void eatCarrot() { 52 | ExceptionExamples exceptionExamples = new ExceptionExamples(); 53 | exceptionExamples.good(); 54 | exceptionExamples.string.length(); 55 | } 56 | } -------------------------------------------------------------------------------- /src/ocp/chapter/ten/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 10 - Exceptions 2 | 3 | - Handling Exceptions 4 | - Describe the advantages of Exception handling and differentiate among checked, unchecked execeptions and Errors. 5 | - Create try-catch blocks and determine how exceptions alter program flow. 6 | - Create and invoke a method that throws an exception. 7 | 8 | ## Understanding Exception Types (p.406-407) 9 | 10 | - An exception is an event that alters program flow. 11 | - Java has a Throwable superclass for ALL objects that represent these events. 12 | - They don't need to have the word 'exception' in their class name. 13 | 14 | * Categories of exception: 15 | 16 | (top) java.lang.Object 17 | 18 | extends 19 | 20 | java.lang.Throwable 21 | 22 | extends 23 | 24 | java.lang.Error | java.lang.Exception <- RuntimeException 25 | 26 | - Error means something went so horribly wrong that your program should not attemptto recover from it (like if the program ran out of memory). 27 | - Remember for the exam that Throwable it's the parent class of all exceptions(including the Error class). 28 | - While you can handle Throwable and Error exceptions, it is not recommended you doso in your application code. 29 | 30 | ## Checked Exceptions (p.407-408) 31 | 32 | - A checked exception is an exception that MUST be declared or handled by the application code where it is thrown. 33 | - In Java, checked exceptions all inherit from Exception but not RuntimeException. 34 | - Tend to be more anticipated, for example, trying to read a file that doesn't exist. 35 | - For the exam, you just need to know about checked exceptions extend Exception, but they also include any class that inherits Throwable, 36 | but not Error or RuntimeException. 37 | - You can't throw a checked exception inside a method without declaring it on the method signature. 38 | - You can't declare a checked exception on a catch block without throwing it on the try block (from a method or directly with the throw statement). 39 | 40 | * Checked Exceptions? What are we checking? 41 | 42 | - Java has a rule called the 'handle or declare' rule. Which means that all checked exceptions that could be thrown within a method are either 43 | wrapped in compatible try and catch blocks or declared in the method signature. 44 | - IOException is an unchecked exception for example. Is seen in method signatures (... throws IOException { }) and try and catch blocks. 45 | 46 | > **Note:** The 'throw' keyword tells Java that you want to throw an Exception, while the throws keyword simply declare that the method might throw an Exception. 47 | 48 | ## Unchecked Exceptions (p.408-409) 49 | 50 | - An unchecked exception is any exception that does NOT need to be declared or handled by the application code where it is thrown. 51 | - Often referred to as runtime exceptions, although in Java, unchecked exceptions include any class that inherits RuntimeException or Error. 52 | - A runtime exception is defined as the RuntimeException class and its subclasses. 53 | - Runtime exceptions tend to be unexpected but not necessarily fatal, for example, accessing an invalid array index is unexpected but it doesn't stop the program. 54 | - An unchecked exception can often occur on nearly any line of code, as it is not required to be handled or declared. 55 | - Like a nullpointer exception, that can be thrown anytime if a reference is null and the code tries to reach on a property of that null reference. 56 | - The code will compile when you declare an unchecked exception. However it is redundant. 57 | 58 | * Runtime vs. at the Time the Program Is Run: 59 | - A runtime (unchecked) exception is a specific type of exception. All exceptions occur at the time that the program is run (The alternative is compile time, 60 | which would be a compiler error). People don't refer to them as "run time" exceptions because that would be too easy to confuse with runtime. So when you see 61 | runtime exception, it means unchecked. 62 | 63 | ## Throwing an Exceptio (p.409-411)n 64 | 65 | - throw vs. throws: 66 | - throw keyword is used as a statement inside a code block to throw a new exception or rethrow an existing exception. 67 | - throws keyword is used ONLY at the end of a method declaration to indicate what exceptions it supports and might be thrown. 68 | - An Exception is an Object. This means you can store its value in a variable (`Exception e = new RuntimeException();`). 69 | - Exception has a constructor that takes a message (String). 70 | - Remember that Exceptions are classes, so they need to be have an instance to be thrown (`throw new Exception();`). 71 | - You should not catch Throwable directly in your code (however you can). 72 | - Types of exceptions and errors: 73 | - Runtime exception -> Subclass of RuntimeException -> It's okay for the program to catch -> The program doesn't need to handle or declare. 74 | - Checked exception -> Subclass of Exception but not of RuntimeException -> It's okay for the program to catch -> The program need to handle or declare. 75 | - Error -> Subclass of Error -> Isn't okay for the program to catch -> The program doesn't need to handle or declare. 76 | 77 | ## Recognizing Exception Classes (p.411-416) 78 | 79 | - RuntimeException Classes 80 | - RuntimeException and its subclasses are unchecked exceptions that don't have to be handled or declared. 81 | - They can be thrown by the programmer or by the JVM. 82 | - Common RuntimeException classes include the following: 83 | - ArithmeticException: Thrown when code attempts to divide by zero. 84 | - ArrayIndexOutOfBoundsException: Thrown when code uses an illegal index to access an array. 85 | - ClassCastException: Thrown when an attempt is made to cast an object to a class of which it is not an instance. 86 | - NullPointerException: Thrown when there is a null reference where an object is required. 87 | - IllegalArgumentException: _Thrown by the programmer_ to indicate that a method has been passed an illegal or inappropriate argument. 88 | - NumberFormatException: Subclass of IllegalArgumentException thrown when an attempt is made to convert a string to a numeric type but the string doesn't 89 | have an appropriate format. 90 | - Checked Exceptions Classes 91 | - They have an Exception in their hierarchy but not RuntimeException. They must be handled or declared. 92 | - Common checked exceptions include the following: 93 | - IOException: Thrown programmatically when there's a problem reading or writing a file. 94 | - FileNotFoundException: Subclass of IOException thrown programmatically when code tries to reference a file that does not exist. 95 | - Error Classes 96 | - Errors are unchecked exceptions that extend the Error class. 97 | - They are thrown by the JVM and should not be handled or declared. 98 | - Errors prevents Java from continuing. 99 | - Errors are rare, but you might see these: 100 | - ExceptionInInitializerError: Thrown when a static initializer throws an exception and doesn't handle it (if a RuntimeException is thrown inside an 101 | instance initialiazer, Java can't start using the class, so it will throw this ExceptionInInitializerError and will not start the application). 102 | - StackOverflowError: Thrown when a method calls itself too many times (this is called 'infinite recursion' because the method typically calls itself 103 | without end). 104 | - NoClassDefFoundError: Thrown when a class that the code uses is available at compile time but not runtime. 105 | 106 | ## Using try and catch Statements (p.416-418) 107 | 108 | - `try` statement sintax is simple, it has the 'try' keyword, curly braces (required) and the protected code inside of it (code block), after the curly braces 109 | there is the 'catch' keyword with the type and identifier of the exception object, another set of curly braces (required) and the exception handler code 110 | inside of the curly braces. 111 | 112 | `try { // Protected code } catch (Exception e) { // Exception handler }` 113 | 114 | - If any of the statements running in the try block throws an exception that can be caught by the exception type listed in the catch block, the try block 115 | stops running and execution goes to the catch statement. 116 | - If none of the statements in the try block throws an exception that can be caught, the catch clause is not run. 117 | - Both terms used for refering to a try or catch block/clause are correct. "Block" is correct because there are braces present and "Clause" is correct 118 | because they are part of a try statement. 119 | - Remember that the point of a try statement is for something to happen if an exception is thrown. So the code will not compile if you only declare the try block 120 | without the catch clause. 121 | 122 | `try { // DOES NOT COMPILE // Something }` 123 | 124 | ## Chaining catch Blocks (p.418-420) 125 | 126 | - When chaining catch blocks, it is not possible for all of them to be executed. 127 | - Java looks at them in the order they appear. 128 | - If it is impossible for one of the catch blocks to be executed, a compiler error about unreachable code occurs. For example, this occurs when a superclass catch 129 | block appears before a subclass catch block. 130 | - Chaining with inherited exceptions example: 131 | 132 | try { 133 | // COMPILES seeAnimal(); 134 | } catch (NumberFormatException e) { 135 | // subclass exception System.out.print("NumberFormat"); 136 | } catch (IllegalArgumentException e) { 137 | // superclass exception System.out.print("IllegalArgument"); 138 | } 139 | 140 | - In cases like this, the order of the catch blocks matters, if we reverse the catch blocks shown above, the code would not compile on the line of the subclass 141 | catch declaration, because the exception its unreachable. 142 | 143 | ## Applying a Multi-catch Bloc (p.420-423) 144 | 145 | - A multi-catch block allows multiple exception types to be caught by the same catch block. 146 | 147 | try { 148 | fly(Integer.parseInt(array[1])); 149 | } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) { 150 | System.out.print("Missing or invalid input"); 151 | } 152 | 153 | - You can declare another catch block in case you want to handle other types of exceptions differently. 154 | - Basically it's like a regular catch clause, except two or more EXCEPTION TYPES are specified separated by a pipe, and there is only one variable name in the 155 | catch clause. Remember that the pipe (|) is also used as the "or" logical operator. 156 | - The exceptions can be listed in any order within the catch clause. 157 | - Some exam examples: 158 | 159 | `catch (Exception1 e | Exception2 e | Exception3 e) {} // DOES NOT COMPILE` 160 | 161 | `catch (Exception1 e1 | Exception2 e2 | Exception3 e3) {} // DOES NOT COMPILE` 162 | 163 | `catch (Exception1 | Exception2 | Exception3 e) {} // COMPILES` 164 | 165 | - Java intends multi-catch to be used for exceptions that aren't related, and it prevents you from specifying redundant types in a multi-catch. 166 | 167 | `try { throw new IOException(); } catch (FileNotFoundException | IOException e) { } // DOES NOT COMPILE, redundant since FileNotFoundException is already caught by the alternative IOException.` 168 | 169 | - The same rules listed before are applied to multi-catch blocks, if there are other catch blocks in the try statement for example. 170 | - The main difference between chaining and multi-catch is that the order they appear does not matter on multi-catch blocks within a single catch expression. 171 | 172 | * Reviewing some 'rules': 173 | - There can be only one exception variable per catch block. 174 | - You can't list the same exception type more than once in the same try statement. 175 | - The more general superclasses must be caught after their subclasses. 176 | 177 | ## Adding a finally Block (p.423-426) 178 | 179 | - The try statement also lets you run code at the END with a finally clause, regardless of whether an exception is thrown. 180 | - The block always executes, whether or not an exception occurs. 181 | - The catch block is optional when finally is used. 182 | 183 | try { 184 | // Protected code 185 | } catch (Exception e) { 186 | // OPTIONAL ** // Exception handler 187 | } finally { 188 | // Finally block 189 | } 190 | 191 | - The finally is always executed, and is always the last clause to be executed. 192 | - A finally block with a 'return' statement will replace other returns on the try and catch block, since is always executed last. 193 | - System.exit(int status) is the only exception to 'the finally block is always executed' rule: 194 | - Java defines this method that you call as System.exit(int status), it takes an integer parameter that represents the error code that gets returned. 195 | - When System.exit(int status) is used in the try or catch block, the finally block does not run. 196 | 197 | ## Finally Closing Resources (p.426-428) 198 | 199 | - If you don't close a resource when you are one with it, a lot of bad things could happen. If you are connecting to a database, you could use up all available 200 | connections, meaning no one can talk to the database until you release your connections. Although you commonly hear about memory leaks as causing programs to 201 | fail, a resource leak is just as bad and occurs when a program fails to release its connections to a resource and then the resource becoming inaccessible. 202 | - To treat this without needing lots of try and catch blocks, Java includes the 'try-with-resources' statement to automatically close all resources opened in a 203 | try clause. 204 | - This feature is also known as 'automatic resource management', because Java takes care of the closing. 205 | 206 | // Instead of using this: 207 | FileInputStream is = null; 208 | try { 209 | is = new FileInputStream("myfile.txt"); 210 | // Read file data 211 | } catch (IOException e) { 212 | e.printStackTrace(); 213 | } finally { 214 | if (is != null) { 215 | try { 216 | is.close(); 217 | } catch (IOException e2) { 218 | e2.printStackTrace(); 219 | } 220 | } 221 | } 222 | 223 | // You can use try-with-resources: 224 | public void readFile(String file) { 225 | try (FileInputStream is = new FileInputStream("myfile.txt")) { 226 | // Read file data 227 | } catch (IOException e) { 228 | e.printStackTrace(); 229 | } 230 | } 231 | 232 | - Using a try-with-resources statement, guarantees that as soon as a connection passes out of scope, Java will attempt to close it within the same method. 233 | - try-with-resources has implicit finally blocks. Behind the scenes, the compiler replaces a try-with-resources block with a try and finally block: 234 | - We refer to this "hidden" finally block as an implicit finally block since it is created and used by the compiler automatically. 235 | - You can still create a programmer-defined finally block when using a try-with-resources statement; just be aware that the implicit one will be created and called first. 236 | 237 | ## Try-with-Resources (p.428-432) 238 | 239 | - One or more resources can be opened in the try clause. 240 | - When there are multiple resources opened, they are closed in the REVERSE order from which they were created. 241 | - Notice that parentheses are used to list those resources, and semicolons are used to separate the declarations. It works just like declaring multiple 242 | indexes in a for loop. 243 | - The syntax of a basic try-with-resources: 244 | 245 | try (FileInputStream in = new FileInputStream("data.txt"); // Required semicolon between resource declarations 246 | FileOutputStream out = FileOutputStream("output.txt");) { 247 | // Last semicolon is optional and is usually omitted // Protected code 248 | } // Resources are closed at this point 249 | 250 | - the catch and finally block are optional with ONLY a try-with-resources statement. 251 | - try statement must have one or more catch blocks or a finally block, this is still true with this case, but the finally clause exists implicitly as said before. 252 | - Is still allowed to have catch and/or finally blocks declared anyway. In fact, if the code within the try block throws a checked exception not declared by the 253 | method in which it is defined or handled by another try/catch blocks, then it will need to be handled by the catch block. 254 | - The catch and finally blocks are run in addition to the implicit one that closes the resources. Remember that the implicit finally block always runs before any 255 | programmer-coded ones. 256 | - The syntax of try-with-resources including catch/finally: 257 | 258 | try (FileInputStream in = new FileInputStream("data.txt"); FileOutputStream out = FileOutputStream("output.txt");) { 259 | // Protected code 260 | } // Resources are closed at this point (implicit finally) 261 | catch (IOException e) { 262 | // Exception handler 263 | } finally { // finally block } 264 | 265 | - Legal vs. illegal configurations with a traditional try statement: 266 | 267 | - Legal vs. illegal configurations with a traditional try statement: 268 | 269 | | | 0 finally blocks | 1 finally block | 2 or more finally blocks | 270 | | :--------------------- | :--------------- | :-------------- | :----------------------- | 271 | | 0 catch blocks | Not legal | Legal | Not legal | 272 | | 1 or more catch blocks | Legal | Legal | Not legal | 273 | 274 | - Legal vs. illegal configurations with a try-with-resources statement: 275 | 276 | | | 0 finally blocks | 1 finally block | 2 or more finally blocks | 277 | | :--------------------- | :--------------- | :-------------- | :----------------------- | 278 | | 0 catch blocks | Legal | Legal | Not legal | 279 | | 1 or more catch blocks | Legal | Legal | Not legal | 280 | 281 | - You can see that for both of these try statements, two or more programmer-defined finally blocks are not allowed. The implicit one is not count here. 282 | 283 | * AutoCloseable and Closeable: 284 | 285 | - You can't just put any random class in a try-with-resources statement. 286 | - Java requires classes used in a try-with-resources implement the AutoCloseable or Closeable interfaces, which includes a void close() method. 287 | 288 | * Declaring Resources: 289 | 290 | - try-with-resources statement does not support multiple variable declarations, so each variable must be declared in a separate statement. For example 291 | the following do not compile. 292 | 293 | try (FileInputStream in = new FileInputStream("data.txt"), out = ("output.txt")) { 294 | // DOES NOT COMPILE // Protected code 295 | } 296 | 297 | try (FileInputStream in = new FileInputStream("data.txt"), FileInputStream out = FileInputStream("output.txt")) { 298 | // DOES NOT COMPILE // Protected code 299 | } 300 | 301 | - Each resource must include the data type and be separated by a semicolon (;). 302 | - Declaring resources is a common situation where using var is quite helpful, as it shortens the already long line of code. 303 | 304 | try (var in = new BufferedInputStream(new FileInputStream("data.txt"));) { // COMPILES // Protected code } 305 | 306 | * Scope of Try-with-Resources: 307 | 308 | - The resources created in the try clause are in scope only within the try block. Because the implicit finally runs before any catch/finally blocks that 309 | you code yourself. 310 | 311 | try (Scanner s = new Scanner(System.in)) { 312 | s.nextLine(); 313 | } catch (Exception e) { 314 | s.nextInt(); // DOES NOT COMPILE 315 | } finally { 316 | s.nextInt(); // DOES NOT COMPILE 317 | } 318 | 319 | * Following Order of Operation: 320 | - Remember these two rules: 321 | 1. Resources are closed after the try clause ends and before any catch/finally clauses. 322 | 2. Resources are closed in the reverse order from which they were created. 323 | - The try-with-resources only guarantees that the close() method of the AutoCloseable subclass will be called. 324 | 325 | ## Throwing Additional Exceptions (p.432-434) 326 | 327 | - A catch or finally block can have any valid Java code in it, including another try statement. 328 | - The exception will always be handled in the catch statement if its properlly handled. 329 | - If an exceptions is thrown inside a catch/finally block, and not handled, then the exception thrown in the last executed block will be the one thrown. 330 | 331 | ## Calling Methods That Throw exceptions (p.434-436) 332 | 333 | - When you have a method with a checked exception on the signature (declared), even if the exception is not thrown on the code, you must declare or 334 | handle that exception where you use the method. 335 | - Example where the code do not compile: 336 | 337 | class NoMoreCarrotsException extends Exception { } 338 | public class Bunny { 339 | public static void main(String[] args) { 340 | eatCarrot(); // DOES NOT COMPILE - Because NoMoreCarrotsException is a checked exception 341 | } 342 | 343 | private static void eatCarrot() throws NoMoreCarrotsException { } 344 | } 345 | 346 | - There are some ways to fix this and make this code work: 347 | 348 | public static void main(String[] args) throws NoMoreCarrotsException { // declare exception eatCarrot(); } 349 | 350 | public static void main(String[] args) { try { eatCarrot(); } catch (NoMoreCarrotsException e) { // handle exception ... } } 351 | 352 | - The compiler is always on the lookout for unreachable code, and declaring an unused exception isn't considered unreachable code. 353 | 354 | private static void bad() { 355 | try { 356 | eatCarrot(); 357 | } catch (NoMoreCarrotsException e) { // DOES NOT COMPILE, because Java knows that this checked exception or a subclass of the checked exception will not be thrown on eatCarrot() implementation (unreachable code). 358 | ... 359 | } 360 | } 361 | 362 | public void good() throws NoMoreCarrotsException { // COMPILES, since this exception on good() is unused (not unreachable). 363 | eatCarrot(); 364 | } 365 | 366 | private void eatCarrot() { } // NO EXCEPTION DECLARED 367 | 368 | - You can handle a checked exception with runtime exceptions together in a multi-catch or chaining catch blocks, but you need to handle the checked exception. 369 | - This rule does not extend to unchecked exceptions or exceptions declared in a method signature. So a method such as eatCarrot() can be called inside a 370 | try block, but the exception on the catch block can't be a checked one, because its unreachable. 371 | 372 | > **Note:** Remember that you can't throw a checked exception inside a method without declaring it on the method signature. If eatCarrot() needed to throw NoMoreCarrotsException, then you'll need to declare it on the eatCarrot() signature. 373 | 374 | ## Declaring and Overriding Methods with Exceptions (p.436-437) 375 | 376 | - Remember that an overridden method, it's not allowed to add new CHECKED exceptions to the method signature. For example, this is not allowed: 377 | 378 | class CanNotHopException extends Exception { } 379 | class Hopper { 380 | public void hop() { } 381 | } 382 | 383 | public class Bunny extends Hopper { 384 | public void hop() throws CanNotHopException { } // DOES NOT COMPILE 385 | } 386 | 387 | - An overridden method in a subclass is allowed to declare fewer exceptions than the superclass or interface. This is legal because callers are already 388 | handling them. For example, this is allowed: 389 | 390 | class Hopper { 391 | public void hop() throws CanNotHopException { } 392 | } 393 | 394 | public class Bunny extends Hopper { 395 | public void hop() { } // COMPILES 396 | } 397 | 398 | - Similarly, a class is allowed to declare a subclass of an exception type. The superclass or interface has already taken care of a broader type. Example: 399 | 400 | class Hopper { 401 | public void hop() throws Exception { } 402 | } 403 | 404 | public class Bunny extends Hopper { 405 | public void hop() throws CanNotHopException { } // COMPILES - Bunny could declare that it throws Exception directly, or a more specific type of Exception or even that it throws nothing at all. 406 | } 407 | 408 | > **Note:** Remember that this rule applies only to checked exceptions. So a subclass overridden method can throws unchecked exceptions. Because this is relevant, since a unchecked exception doesn't need to be handled or declared, because methods are free to throw any unchecked exceptions they want. 409 | 410 | ## Printing an Exception (p.437-438) 411 | 412 | - There are three ways to print an exception. You can let Java print it out, print just the message or print where the stack trace comes from. 413 | - Example of the three approaches: 414 | 415 | public static void main(String[] args) { 416 | try { 417 | hop(); 418 | } catch (Exception e) { 419 | System.out.println(e); 420 | System.out.println(e.getMessage()); 421 | e.printStackTrace(); 422 | } 423 | } 424 | 425 | private static void hop() { 426 | throw new RuntimeException("Cannot hop"); 427 | } 428 | 429 | - The code results are: 430 | 1. java.lang.RuntimeException: Cannot hop // Shows that Java prints out by default: the exception type and message 431 | 2. Cannot hop // Shows just the message 432 | 3. java.lang.RuntimeException: Cannot hop // Shows a stack trace 433 | at Handling.hop(Handling.java:15) 434 | at Handling.main(Handling.java:7) 435 | - The stack trace is usually the most helpful one because it is a picture in time the moment the exception is thrown. It shows the hierarchy of method calls 436 | that were made to reach the line that threw the exception. 437 | - The stack trace shows all the methods on the stack. Every time you call a method, Java adds it to the stack until it completes. When an exception is thrown, 438 | it goes through the stack until it finds a method that can handle it or it runs out of stack. 439 | - A method stack: 440 | (top) new RuntimeException -> hop() -> main() 441 | -------------------------------------------------------------------------------- /src/ocp/chapter/twelve/Season.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.twelve; 2 | 3 | public enum Season { 4 | WINTER("Low") { 5 | public void printExpectedVisitors() { System.out.println("CLOSED"); } // Will be used when called by WINTER enum value 6 | }, 7 | SPRING("Medium"), 8 | SUMMER("High"), 9 | FALL("Medium"); 10 | 11 | private final String expectedVisitors; 12 | 13 | private Season(String expectedVisitors) { 14 | this.expectedVisitors = expectedVisitors; 15 | } 16 | 17 | public void printExpectedVisitors() { // Will be used when called by SPRING, SUMMER or FALL enum values 18 | System.out.println(expectedVisitors); 19 | } 20 | } -------------------------------------------------------------------------------- /src/ocp/chapter/twelve/TraditionalSearch.java: -------------------------------------------------------------------------------- 1 | package ocp.chapter.twelve; 2 | 3 | import java.util.*; 4 | import java.util.function.Predicate; 5 | 6 | class Animal { 7 | private String species; 8 | private boolean canHop; 9 | private boolean canSwim; 10 | 11 | public Animal(String speciesName, boolean hooper, boolean swimmer) { 12 | species = speciesName; 13 | canHop = hooper; 14 | canSwim = swimmer; 15 | } 16 | 17 | public boolean canHop() { 18 | return canHop; 19 | } 20 | 21 | public boolean canSwim() { 22 | return canSwim; 23 | } 24 | 25 | public String toString() { 26 | return species; 27 | } 28 | } 29 | 30 | public class TraditionalSearch { 31 | public static void main(String... args) { 32 | 33 | var animals = new ArrayList(); 34 | animals.add(new Animal("fish", false, true)); 35 | animals.add(new Animal("kangaroo", true, true)); 36 | animals.add(new Animal("rabbit", true, false)); 37 | animals.add(new Animal("turtle", false, true)); 38 | 39 | print(animals, a -> a.canHop()); // Will print only the hoppers 40 | } 41 | 42 | private static void print(List animals, Predicate checker) { 43 | for(Animal animal : animals) { 44 | if (checker.test(animal)) System.out.println(animal); 45 | } 46 | } 47 | } --------------------------------------------------------------------------------