├── .gitignore ├── 1.1 Access Modifiers.md ├── 1.2 Overloading - Overriding.md ├── 1.3 - abstract classes.md ├── 1.5 - imports.md ├── 1.6 - instanceof.md ├── 1.7 - equals hashcode toString.md ├── 1.8 - enums.md ├── 1.9 - nested classes.md ├── 10 - jdbc.md ├── 2.1 - Interfaces.md ├── 2.2 - Functional Programming - intro.md ├── 2.3 - Polymorphism.md ├── 2.4 - Design principles.md ├── 3.1 - array-arraylist.md ├── 3.2 - generics.md ├── 4.1 - Functional Programming.md ├── 5.1 Date and time.md ├── 6 - Exception and Assertions.md ├── 7.1 - Threads.md ├── 8 - IO.md ├── 9 - NIO2.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | img 2 | 0-OCP Java 8 SE.md 3 | -------------------------------------------------------------------------------- /1.1 Access Modifiers.md: -------------------------------------------------------------------------------- 1 | theme: Plain Jane, 3 2 | autoscale: true 3 | 4 | # Java visibility: the complete guide 5 | 6 | ## Two classes inside the same file 7 | 8 | - one can be public. Both can't 9 | - they are in the same package 10 | 11 | ```java 12 | package com.freniche; 13 | 14 | public class Main { 15 | public static void main(String[] args) { 16 | ClassInsideMain classInsideMain = new ClassInsideMain(); 17 | classInsideMain.packageField = ""; 18 | classInsideMain.protectedField = ""; 19 | classInsideMain.publicField = ""; 20 | classInsideMain.privateField = ""; // FAILS 21 | } 22 | } 23 | 24 | class ClassInsideMain { 25 | public String publicField; 26 | private String privateField; 27 | String packageField; 28 | protected String protectedField; 29 | } 30 | ``` 31 | 32 | --- 33 | 34 | 35 | ## Two classes inside the same package (general case of former one) 36 | 37 | ```java 38 | PackageClassInComFreniche packageClassInComFreniche = new PackageClassInComFreniche(); 39 | packageClassInComFreniche.packageField = ""; 40 | packageClassInComFreniche.protectedField = ""; 41 | packageClassInComFreniche.publicField = ""; 42 | 43 | // in file PackageClassInComFreniche.java 44 | 45 | package com.freniche; 46 | 47 | class PackageClassInComFreniche { 48 | public String publicField; 49 | private String privateField; 50 | String packageField; 51 | protected String protectedField; 52 | } 53 | ``` 54 | 55 | --- 56 | 57 | ## Access one class in other package 58 | 59 | ```java 60 | 61 | // in file com.freniche.Main 62 | 63 | package com.freniche; 64 | 65 | import com.otherpackage.ClassInOtherPackage; // need to import to use it: must be public 66 | 67 | public class Main { 68 | public static void main(String[] args) { 69 | ClassInOtherPackage classInOtherPackage = new ClassInOtherPackage(); 70 | classInOtherPackage.publicField = ""; // other fields are not visible from outside its package 71 | } 72 | } 73 | 74 | // in file com.otherpackage.ClassInOtherPackage 75 | 76 | package com.otherpackage; 77 | 78 | public class ClassInOtherPackage { 79 | public String publicField; 80 | private String privateField; 81 | String packageField; 82 | protected String protectedField; 83 | } 84 | 85 | 86 | 87 | ``` 88 | 89 | --- 90 | 91 | ## Can't access package level classes from outside 92 | 93 | ```java 94 | // in file com.freniche.Main 95 | 96 | package com.freniche; 97 | 98 | import com.otherpackage.SecondClassInOtherPackage; // FAILS 99 | 100 | // in file SecondClassInOtherPackage 101 | 102 | package com.otherpackage; 103 | 104 | class SecondClassInOtherPackage { 105 | public String publicField; // java allows this, although public here makes no sense 106 | private String privateField; 107 | String packageField; 108 | protected String protectedField; 109 | } 110 | ``` 111 | 112 | --- 113 | 114 | ## Inheritance from a public class in other package 115 | 116 | 117 | 118 | ## Inheritance from a class in the same package 119 | 120 | 121 | -------------------------------------------------------------------------------- /1.2 Overloading - Overriding.md: -------------------------------------------------------------------------------- 1 | theme: Plain Jane 2 | autoscale: true 3 | 4 | 5 | # Overloading / Overridding 6 | 7 | --- 8 | 9 | ## Overridding 10 | 11 | Given Person class: 12 | 13 | ```java 14 | class Person { 15 | public static Person createPerson(String name) { 16 | Person p = new Person(); 17 | p.name = name; 18 | return p; 19 | } 20 | 21 | public Person(String name) { 22 | this.name = name; 23 | } 24 | 25 | public String name; 26 | 27 | public String getName() { 28 | return name; 29 | } 30 | 31 | public String prettyPrint(String someString) { 32 | return someString.concat(name); 33 | } 34 | } 35 | 36 | ``` 37 | 38 | --- 39 | 40 | ## Override? 41 | 42 | - are these valid? 43 | - if not, why? 44 | 45 | ```java 46 | class Worker extends Person { 47 | @Override 48 | public static Person createPerson(String name) { 49 | Person p = new Person(); 50 | p.name = "Worker " + name; 51 | return p; 52 | } 53 | 54 | @Override 55 | public String name; 56 | 57 | @Override 58 | public Worker(String name) { 59 | super(name); 60 | } 61 | } 62 | ``` 63 | 64 | 65 | --- 66 | 67 | - you can't override a static method: you can _hide_ it 68 | - you can't override a field: you can _redeclare_ it 69 | 70 | ```java 71 | class Person { 72 | public String name; 73 | } 74 | 75 | class Worker extends Person { 76 | public StringBuffer name; 77 | } 78 | 79 | Person p = new Person(); 80 | p.name = "Diego"; // String 81 | 82 | Worker w = new Worker(); 83 | w.name = "Worker"; // StringBuffer: error 84 | 85 | Person p2 = new Worker(); 86 | p2.name = "P2"; // String 87 | ``` 88 | 89 | 90 | --- 91 | 92 | - you can't override a constructor: you don't even inherit constructors 93 | 94 | ```java 95 | class Person { 96 | public Person(String name) { 97 | this.name = name; 98 | } 99 | 100 | public String name; 101 | } 102 | 103 | class Worker extends Person { 104 | public String name; 105 | 106 | // if we remove this constructor we get error: "There's no default constructor for class Worker" 107 | // we don't even "inherit" the default constructor 108 | // it's injected by the compiler 109 | // 110 | // public Worker(String name) { 111 | // super(name); 112 | // } 113 | } 114 | 115 | 116 | ``` 117 | 118 | --- 119 | 120 | ## Overridding: virtual method invocation 121 | 122 | ```java 123 | class Person { 124 | public String name = "Person name"; 125 | 126 | void printName() { 127 | System.out.println(name); 128 | } 129 | } 130 | 131 | class Worker extends Person { 132 | public StringBuffer name = new StringBuffer("Worker name"); 133 | 134 | void printName() { 135 | System.out.println(name); 136 | } 137 | } 138 | 139 | // What does this print? 140 | 141 | Person p = new Person(); 142 | p.printName(); 143 | 144 | Worker w = new Worker(); 145 | w.printName(); 146 | 147 | Person p2 = new Worker(); 148 | p2.printName(); 149 | 150 | Worker w2 = new Person(); 151 | w2.printName(); 152 | 153 | ``` 154 | 155 | --- 156 | 157 | ## Overridding: virtual method invocation 158 | 159 | ```java 160 | class Person { 161 | public String name = "Person name"; 162 | 163 | void printName() { 164 | System.out.println(name); 165 | } 166 | } 167 | 168 | class Worker extends Person { 169 | public StringBuffer name = new StringBuffer("Worker name"); 170 | 171 | void printName() { 172 | System.out.println(name); 173 | } 174 | } 175 | 176 | // What does this print? 177 | 178 | Person p = new Person(); 179 | p.printName(); // Person name: the object in memory IS-A Person 180 | 181 | Worker w = new Worker(); 182 | w.printName(); // Worker name: the object in memory IS-A Worker 183 | 184 | Person p2 = new Worker(); 185 | p2.printName(); // Worker name: the object in memory IS-A Worker 186 | 187 | Worker w2 = new Person(); 188 | w2.printName(); // Compiler error! 189 | 190 | ``` 191 | --- 192 | 193 | ## Fields! 194 | 195 | - with methods, Java invokes based on what that object is in memory (not the reference we're using) 196 | - for fields, Java uses the reference 197 | - again: we can't _override_ fields, so no "Field virtual whatever" here 198 | 199 | ```java 200 | 201 | Person p = new Person(); 202 | System.out.println(p.name); // Person name 203 | 204 | Worker w = new Worker(); 205 | System.out.println(w.name); // Worker name 206 | 207 | Person p2 = new Worker(); 208 | System.out.println(p2.name); // Person name 209 | 210 | ``` 211 | 212 | --- 213 | 214 | ## Overridding: Covariant Returns 215 | 216 | ```java 217 | class A { 218 | public Object m1() { 219 | return null; 220 | } 221 | } 222 | 223 | // The return type must be the same or a more restrictive type: covariant returns 224 | class B extends A { 225 | public String m1() { 226 | return null; 227 | // this specialized version of m1() is returning a String, because a String IS-A Object 228 | } 229 | } 230 | ``` 231 | 232 | --- 233 | 234 | We can't do: 235 | 236 | ```java 237 | class A { 238 | public String m1() { 239 | return null; 240 | } 241 | } 242 | 243 | class B extends A { 244 | public Object m1() { // The return type must be the same or a more restrictive type: covariant returns 245 | // THIS won't compile 246 | // An instance of type B could return now a List. This is something quite different from what A::m1() returns 247 | return null; 248 | } 249 | } 250 | ``` 251 | 252 | --- 253 | 254 | ## Overloading Annotations 255 | 256 | - `@Override` used when: 257 | - implements method from interface 258 | - overrides a method from superclass 259 | - overrides an abstract method from superclass (special 1 + 2 case) -------------------------------------------------------------------------------- /1.3 - abstract classes.md: -------------------------------------------------------------------------------- 1 | theme: Plain Jane 2 | autoscale: true 3 | 4 | ## Abstract classes 5 | 6 | - if at least one `abstract` method --> class must be abstract 7 | - class can be abstract without any abstract method 8 | 9 | ```java 10 | abstract class Abstract1 { 11 | 12 | } 13 | 14 | abstract class Abstract2 { 15 | public abstract void abstractM1(); 16 | } 17 | 18 | abstract class Abstract3 { 19 | public abstract void abstractM1(); 20 | void concreteM1() { 21 | 22 | } 23 | } 24 | 25 | abstract class Abstract4 extends Abstract2 { 26 | 27 | } 28 | ``` 29 | 30 | --- 31 | 32 | ## Abstract yay or nay? 33 | 34 | ```java 35 | abstract class Abstract2 { 36 | public abstract void abstractM1(); 37 | } 38 | 39 | abstract class Abstract3 extends Abstract2 { 40 | public abstract void abstractM1(); 41 | void concreteM1() { 42 | 43 | } 44 | } 45 | ``` 46 | 47 | --- 48 | 49 | ## Abstract yay or nay? 50 | 51 | ```java 52 | abstract class Abstract2 { 53 | public abstract void abstractM1(); 54 | } 55 | 56 | abstract class Abstract3 extends Abstract2 { 57 | public abstract void abstractM1(); // this is an override, it's OK 58 | void concreteM1() { 59 | 60 | } 61 | } 62 | ``` 63 | 64 | --- 65 | 66 | ## Abstract yay or nay? 67 | 68 | ```java 69 | abstract class Abstract2 { 70 | public abstract void abstractM1(); 71 | } 72 | 73 | class Abstract4 extends Abstract2 { 74 | // anything else? 75 | } 76 | 77 | ``` 78 | 79 | --- 80 | 81 | ## abstract != final 82 | 83 | - abstract: can't create instances of this class 84 | - final: can't override this class, so MUST be concrete 85 | 86 | ```java 87 | final class A { 88 | 89 | } 90 | 91 | final class B extends A { 92 | // error! 93 | } 94 | ``` 95 | 96 | --- 97 | 98 | ## Abstract & inner classes 99 | 100 | - is this OK? 101 | 102 | ```java 103 | abstract class A { 104 | abstract void m1(); 105 | 106 | class B extends A { 107 | abstract void m1(); 108 | } 109 | } 110 | ``` 111 | 112 | --- 113 | 114 | - is this OK? 115 | 116 | ```java 117 | abstract class A { 118 | abstract void m1(); 119 | 120 | abstract class B extends A { 121 | abstract void m1(); 122 | } 123 | } 124 | ``` -------------------------------------------------------------------------------- /1.5 - imports.md: -------------------------------------------------------------------------------- 1 | theme: Plain Jane 2 | autoscale: true 3 | 4 | # Advanced Class Design 5 | 6 | ## Imports 7 | 8 | - PIC: Package, Imports, Classes 9 | - `import java.lang.*;` by default 10 | - import one class or all classes in that package (wildcard) 11 | - __non recursive__ 12 | - package name: lowercase legal identifiers separated by . 13 | 14 | --- 15 | 16 | ## 😈 Watch out 17 | 18 | Redundant 19 | 20 | ```java 21 | import java.lang.Exception; 22 | import java.lang.*; 23 | ``` 24 | 25 | Error 26 | 27 | import java.lang.*.*; 28 | 29 | --- 30 | 31 | ## Packages as namespaces 32 | 33 | - avoid conflicts with two classes, same name 34 | - FQCN: Fully Qualified Class Name 35 | - default package == no package 36 | 37 | 38 | --- 39 | ## 😈 Watch out 40 | 41 | Error! 42 | 43 | ```java 44 | 45 | import java.sql.Date; // try with * 46 | import java.util.Date; 47 | 48 | public class Main { 49 | public static void main(String m[]) { 50 | Date d; 51 | } 52 | } 53 | ``` 54 | 55 | --- 56 | 57 | 58 | ## Accessing a public class in the default package 59 | 60 | - in file `PublicInDefaultPackage.java` 61 | 62 | ```java 63 | public class PublicInDefaultPackage { 64 | public String publicInstanceVariable = "public"; 65 | private String privateInstanceVariable = "private"; 66 | String packageInstanceVariable = "package"; 67 | protected String protectedInstanceVariable = "protected"; 68 | } 69 | ``` 70 | 71 | - in file `com.freniche.Main.java` 72 | 73 | ```java 74 | package com.freniche; 75 | 76 | import PublicInDefaultPackage; // can't import classes from the default package 77 | // It is a compile time error to import a type from the unnamed package. 78 | // http://docs.oracle.com/javase/specs/#7.5 79 | // https://docs.oracle.com/javase/specs/jls/se6/html/packages.html#26725 80 | 81 | 82 | public class Main { 83 | 84 | public static void main(String[] args) { 85 | PublicInDefaultPackage publicInDefaultPackage = new PublicInDefaultPackage(); // obviously this doesn't compile 86 | } 87 | } 88 | ``` 89 | 90 | --- 91 | 92 | ## What if we still need to access it? 93 | 94 | - use reflection! 95 | 96 | ```java 97 | package com.freniche; 98 | 99 | import java.lang.reflect.Field; 100 | import java.lang.reflect.InvocationTargetException; 101 | import java.lang.reflect.Method; 102 | 103 | public class Main { 104 | 105 | public static void main(String[] args) { 106 | // we want to access class PublicInDefaultPackage. Problem is: we can't import it, as is inside that default package 107 | // Load the class definition: tell the class loader to load this class 108 | 109 | Class fooClass = null; 110 | try { 111 | fooClass = Class.forName("PublicInDefaultPackage"); 112 | } catch (ClassNotFoundException e) { 113 | e.printStackTrace(); 114 | } 115 | 116 | Method noArgumentsMethod = null; 117 | try { 118 | // inspect the class and look for this method 119 | // method name: "myMethod" 120 | // parameter types: null, as we don't have any parameters 121 | // don't use this as it won't work: 122 | // noArgumentsMethod = fooClass.getMethod("myMethod", new Class[] { Void.class }); 123 | noArgumentsMethod = fooClass.getMethod("myMethod", null); 124 | } catch (NoSuchMethodException e) { 125 | e.printStackTrace(); 126 | } 127 | 128 | Method argumentsMethod = null; 129 | try { 130 | argumentsMethod = fooClass.getMethod("myMethodWithArguments", String.class); 131 | } catch (NoSuchMethodException e) { 132 | e.printStackTrace(); 133 | } 134 | 135 | 136 | // let's instantiate an object of class fooClass 137 | Object instance = null; 138 | try { 139 | instance = fooClass.newInstance(); 140 | } catch (InstantiationException e) { 141 | e.printStackTrace(); 142 | } catch (IllegalAccessException e) { 143 | e.printStackTrace(); 144 | } 145 | 146 | 147 | // let's call that method we've constructed on that object 148 | try { 149 | String noargMethodReturned = 150 | (String) noArgumentsMethod.invoke(instance); 151 | System.out.println(noargMethodReturned); 152 | 153 | String argMethodReturned = 154 | (String) argumentsMethod.invoke(instance, "I'm an argument!"); 155 | System.out.println(argMethodReturned); 156 | } catch (IllegalAccessException e) { 157 | e.printStackTrace(); 158 | } catch (InvocationTargetException e) { 159 | e.printStackTrace(); 160 | } 161 | 162 | 163 | try { 164 | Field publicField = fooClass.getField("publicInstanceVariable"); 165 | System.out.println("Field name: " + publicField.getName() + " - value: " + publicField.get(instance).toString()); 166 | } catch (NoSuchFieldException e) { 167 | e.printStackTrace(); 168 | } catch (IllegalAccessException e) { 169 | e.printStackTrace(); 170 | } 171 | } 172 | } 173 | ``` 174 | 175 | --- -------------------------------------------------------------------------------- /1.6 - instanceof.md: -------------------------------------------------------------------------------- 1 | theme: Plain Jane, 3 2 | autoscale: true 3 | 4 | ## instanceof 5 | 6 | ```java 7 | reference instanceof Type 8 | ``` 9 | 10 | - is this reference pointing to an object that in the heap passes the IS-A test? 11 | - Type can be: Class, Interface, Enum 12 | 13 | 14 | 15 | --- 16 | 17 | - instanceof Object is always true 18 | 19 | ```java 20 | if (new Object() instanceof Object) { 21 | System.out.println("Instance of Object!"); 22 | } 23 | ``` 24 | 25 | --- 26 | ## instanceof compares with a type 27 | 28 | ```java 29 | if (new Object() instanceof null) { // Error: null is not a type 30 | System.out.println("Instance of Object!"); 31 | } 32 | 33 | if (new Object() instanceof String) { // String is a type 34 | System.out.println("Instance of String!"); 35 | } 36 | 37 | if (new Integer[0] instanceof Integer[]) { // Integer[] is a type 38 | System.out.println("Instance of array!"); 39 | } 40 | ``` 41 | 42 | --- 43 | 44 | ## instanceof and null 45 | 46 | - what does this print? 47 | 48 | ```java 49 | String s = null; 50 | 51 | if (s instanceof String) { 52 | System.out.println("It's a string"); 53 | } else { 54 | System.out.println("It's NOT a string"); 55 | } 56 | ``` 57 | ^ null is not a String instance 58 | 59 | --- 60 | 61 | ## Correct way of use instanceof 62 | 63 | ```java 64 | String s = ""; 65 | 66 | if (s != null && s instanceof String) { 67 | System.out.println("It's a string"); 68 | } else { 69 | System.out.println("It's NOT a string"); 70 | } 71 | 72 | ``` 73 | 74 | --- 75 | 76 | ## Null is not an instance of anything 77 | 78 | ```java 79 | if (null instanceof Void) { 80 | System.out.println("null is Void"); 81 | } 82 | ``` 83 | 84 | --- 85 | 86 | - instanceof compares with classes in your hierarchy tree 87 | 88 | ```java 89 | public interface Compress { void compress(); } 90 | 91 | public interface Decompress { public abstract void decompress(); } 92 | 93 | public abstract class Compressor implements Compress, Decompress { // code to make this compile omitted } 94 | 95 | public class ZipCompressor extends Compressor { // code to make this compile omitted } 96 | 97 | Compressor cc = new ZipCompressor(); 98 | if (cc instanceof ZipCompressor) { 99 | System.out.println("zc"); // true 100 | } 101 | 102 | if (cc instanceof Compressor) { 103 | System.out.println("Compressor"); // true 104 | } 105 | 106 | if (cc instanceof Compress) { 107 | System.out.println("Compress"); // true 108 | } 109 | 110 | if (cc instanceof Decompress) { 111 | System.out.println("Decompress"); // true 112 | } 113 | ``` 114 | 115 | --- 116 | 117 | - instanceof compares with classes in your hierarchy tree 118 | 119 | ```java 120 | if (cc instanceof String) { // Error: does not compile 121 | System.out.println("Decompress"); 122 | } 123 | ``` -------------------------------------------------------------------------------- /1.7 - equals hashcode toString.md: -------------------------------------------------------------------------------- 1 | theme: Plain Jane 2 | autoscale: true 3 | 4 | 5 | ## default toString 6 | 7 | - default `toString` in Object returns something like: com.freniche.ocp8.Person@511d50c0 8 | - com.freniche.ocp8.Person FQCN 9 | - 511d50c0: hashcode 10 | 11 | --- 12 | 13 | ## toString 14 | 15 | ```java 16 | class Person { 17 | String name; 18 | String address; 19 | int age; 20 | 21 | @Override 22 | public String toString() { 23 | return super.toString() + " " + super.hashCode() + " " + name + " " + address + " " + age; 24 | } 25 | } 26 | ``` 27 | 28 | --- 29 | 30 | ## Prints different numbers? 31 | 32 | The hascode value returned via toString() is different than what is returned via hashCode(). This is because the toString() method returns a hex representaion of the same hashcode . 33 | 34 | `Integer.toHexString(super.hashCode())` will return the same value returned by object.toString(). 35 | 36 | Prints: `com.freniche.ocp8.Person@511d50c0 511d50c0 Diego null 0` 37 | 38 | --- 39 | 40 | ## equals 41 | 42 | - correct override 43 | - receives an Object (can't change argument types on overridden methods) 44 | 45 | ```java 46 | @Override 47 | public boolean equals(Object obj) { 48 | return super.equals(obj); 49 | } 50 | ``` 51 | 52 | --- 53 | 54 | ## equals 55 | 56 | ```java 57 | @Override 58 | public boolean equals(Person obj) { // nope 59 | return super.equals(obj); 60 | } 61 | 62 | public boolean equals(Person obj) { // nope 63 | return super.equals(obj); 64 | } 65 | 66 | @Override 67 | public boolean Equals(Object obj) { // not even the same method 68 | return super.equals(obj); 69 | } 70 | 71 | ``` 72 | 73 | --- 74 | 75 | ## Simple equals 76 | 77 | ```java 78 | @Override 79 | public boolean equals(Object obj) { 80 | if (obj != null && obj instanceof Person) { 81 | Person p = (Person)obj; 82 | 83 | if (p.name == this.name) { 84 | return true; 85 | } 86 | } 87 | 88 | return false; 89 | } 90 | 91 | ``` 92 | 93 | --- 94 | 95 | ## Better equals 96 | 97 | ```java 98 | @Override 99 | public boolean equals(Object obj) { 100 | if (obj instanceof Person) { 101 | Person p = (Person)obj; 102 | 103 | return (p.name == this.name); 104 | } 105 | 106 | return false; 107 | } 108 | 109 | ``` 110 | --- 111 | 112 | ## Hashcode 113 | 114 | ```java 115 | @Override 116 | public int hashCode() { 117 | return name == null ? 0 : name.length(); 118 | } 119 | 120 | ``` 121 | 122 | - in the same program hashCode must not change 123 | - if obj1.equals(obj2) == true ==> obj1.hashCode() == obj2.hashCode() 124 | - if obj1.equals(obj2) == false /=> obj1.hashCode() != obj2.hashCode() -------------------------------------------------------------------------------- /1.8 - enums.md: -------------------------------------------------------------------------------- 1 | theme: Plain Jane, 3 2 | autoscale: true 3 | 4 | ## Enums 5 | 6 | - can be empty 7 | 8 | ```java 9 | package com.freniche.ocp8; 10 | 11 | public class Main { 12 | public static void main(String[] args) { 13 | } 14 | } 15 | 16 | enum Months { 17 | } 18 | 19 | ``` 20 | 21 | --- 22 | 23 | 24 | ## Enums can have a list of "values" 25 | 26 | - `JAN` is an object of class Months 27 | 28 | ```java 29 | enum Months { 30 | JAN, FEB, MAR 31 | } 32 | 33 | System.out.println(JAN instanceof Months); 34 | 35 | for (Months e: Months.values()) { 36 | System.out.println(e.toString()); 37 | } 38 | 39 | // true, JAN, FEB, MAR 40 | ``` 41 | 42 | --- 43 | 44 | ## Enum: a class that contains a certain number of objects 45 | 46 | ```java 47 | enum Months { 48 | JAN(31), FEB(28), MAR(31); // semicolon important here! 49 | 50 | int numDays; 51 | private Months(int numDays) { 52 | this.numDays = numDays; 53 | } 54 | 55 | @Override 56 | public String toString() { 57 | return super.toString().toLowerCase(); 58 | } 59 | } 60 | 61 | // can print number of days 62 | 63 | for (Months e: Months.values()) { 64 | System.out.println(e.toString() + " " + e.numDays); 65 | } 66 | ``` 67 | 68 | --- 69 | 70 | ## Create an enum from a String 71 | 72 | ```java 73 | Months m = Months.valueOf("JAN"); // OK 74 | 75 | Months m = Months.valueOf("JAn"); // java.lang.IllegalArgumentException: No enum constant 76 | ``` 77 | 78 | --- 79 | 80 | ## Can't extend an Enum 81 | 82 | ```java 83 | enum Months extends Object { // fails 84 | JAN(31), FEB(28), MAR(31); 85 | 86 | int numDays; 87 | private Months(int numDays) { 88 | this.numDays = numDays; 89 | } 90 | 91 | @Override 92 | public String toString() { 93 | return super.toString().toLowerCase(); 94 | } 95 | } 96 | ``` 97 | 98 | --- 99 | 100 | ## But... interfaces! 101 | 102 | ```java 103 | @FunctionalInterface 104 | interface Printable { 105 | void print(); 106 | } 107 | 108 | enum Months implements Printable { 109 | JAN(31), FEB(28), MAR(31); 110 | 111 | int numDays; 112 | private Months(int numDays) { 113 | this.numDays = numDays; 114 | } 115 | 116 | @Override 117 | public String toString() { 118 | return super.toString().toLowerCase(); 119 | } 120 | 121 | @Override 122 | public void print() { 123 | 124 | } 125 | } 126 | 127 | ``` 128 | 129 | --- 130 | 131 | ## Methods in enums 132 | 133 | ```java 134 | enum Months { 135 | JAN(31) { // method override for JAN 136 | @Override 137 | public void print() { 138 | super.print(); 139 | } 140 | }, 141 | FEB(28), 142 | MAR(31) ; 143 | 144 | int numDays; 145 | private Months(int numDays) { 146 | this.numDays = numDays; 147 | } 148 | 149 | @Override 150 | public String toString() { 151 | return super.toString().toLowerCase(); 152 | } 153 | 154 | public void print() { // default implementation 155 | 156 | } 157 | } 158 | ``` 159 | 160 | --- 161 | 162 | ## Methods in Enums 2 163 | 164 | ```java 165 | enum Months { 166 | JAN(31) { 167 | @Override 168 | public void print() { 169 | } 170 | }, 171 | FEB(28) { 172 | @Override 173 | public void print() { 174 | } 175 | }, 176 | MAR(31) { 177 | @Override 178 | public void print() { 179 | } 180 | }; 181 | 182 | int numDays; 183 | private Months(int numDays) { 184 | this.numDays = numDays; 185 | } 186 | 187 | @Override 188 | public String toString() { 189 | return super.toString().toLowerCase(); 190 | } 191 | 192 | public abstract void print(); // abstract 193 | } 194 | ``` -------------------------------------------------------------------------------- /1.9 - nested classes.md: -------------------------------------------------------------------------------- 1 | theme: Plain Jane 2 | autoscale: true 3 | 4 | # Nested classes 5 | 6 | --- 7 | 8 | ## Member inner classes 9 | 10 | - declared at the member (field, method) level 11 | - can be: public, private, protected, _package_ 12 | - can be abstract / final 13 | - can't have static fields / methods 14 | - can access _any_ member of enclosing class 15 | 16 | --- 17 | 18 | ## Member inner classes 19 | 20 | ```java 21 | class Ripley { 22 | String name = "Ripley"; 23 | 24 | void useFlamethrower() { 25 | } 26 | 27 | public class Alien { 28 | int acidLitres = 4; 29 | public static String ALIEN = "ALIEN"; // Illegal static declaration in inner class 30 | // 'static' is only allowed in constant variable declarations 31 | 32 | public void killPeople() { 33 | } 34 | } 35 | } 36 | 37 | ``` 38 | 39 | --- 40 | 41 | ## Member inner classes: create them 42 | 43 | - declared at member level, so we need an instance to create them 44 | 45 | ```java 46 | Ripley ripley = new Ripley(); 47 | 48 | Ripley.Alien alien = ripley.new Alien(); 49 | alien.killPeople(); 50 | 51 | ``` 52 | 53 | --- 54 | 55 | ## Is this correct? 56 | 57 | ```java 58 | new Ripley().new Alien().killPeople(); // 1 59 | Ripley.new Alien().killPeople(); // 2 60 | new Ripley.new Alien().killPeople(); // 3 61 | new Ripley().Alien().killPeople(); // 4 62 | new new Ripley().Alien().killPeople(); // 5 63 | ``` 64 | 65 | ^ 66 | 1. ok 67 | 2. static 68 | 3. nope 69 | 4. nope 70 | 5. 😂 71 | 72 | --- 73 | 74 | ## Write code to make this possible 75 | 76 | ```java 77 | new Ripley().new Alien().new AlienParasite().killAlien(); 78 | ``` 79 | 80 | --- 81 | 82 | ## Names of inner .class files 83 | 84 | - look at those $ 85 | 86 | --- 87 | 88 | ## Accessing this from inner class 89 | 90 | - using class name to avoid name clash 91 | 92 | ```java 93 | class Ripley { 94 | String name = "Ripley"; 95 | 96 | void useFlamethrower() { 97 | } 98 | 99 | public class Alien { 100 | int acidLitres = 4; 101 | String name = "Alien"; 102 | 103 | public void killPeople() { 104 | } 105 | 106 | class AlienParasite { 107 | String name = "Parasite"; 108 | public void killAlien() { 109 | System.out.println("I'm " + this.name + " killing " + Alien.this.name + " inside the body of " + Ripley.this.name); 110 | } 111 | } 112 | } 113 | } 114 | 115 | ``` 116 | 117 | --- 118 | 119 | ## can access __any__ member of enclosing class 120 | 121 | - even private (non inherited) members 122 | 123 | ```java 124 | class Ripley { 125 | String name = "Ripley"; 126 | private boolean fear = true; 127 | 128 | void useFlamethrower() { 129 | } 130 | 131 | public class Alien { 132 | int acidLitres = 4; 133 | String name = "Alien"; 134 | 135 | public void killPeople() { 136 | } 137 | 138 | class AlienParasite { 139 | String name = "Parasite"; 140 | public void killAlien() { 141 | System.out.println("I'm " + this.name + " killing " + Alien.this.name + " inside the body of " + Ripley.this.name); 142 | System.out.println(Ripley.this.fear); 143 | } 144 | } 145 | } 146 | } 147 | ``` 148 | 149 | --- 150 | 151 | ## Declaring interfaces 152 | 153 | ```java 154 | class Ripley { 155 | private interface UseWeapons { // inteface 156 | public void useWeapon(); 157 | } 158 | 159 | String name = "Ripley"; 160 | private boolean fear = true; 161 | 162 | void useFlamethrower() { 163 | } 164 | 165 | public class Alien { 166 | int acidLitres = 4; 167 | String name = "Alien"; 168 | 169 | public void killPeople() { 170 | } 171 | 172 | class AlienParasite implements UseWeapons { // used here 173 | String name = "Parasite"; 174 | public void killAlien() { 175 | System.out.println("I'm " + this.name + " killing " + Alien.this.name + " inside the body of " + Ripley.this.name); 176 | System.out.println(Ripley.this.fear); 177 | } 178 | 179 | @Override 180 | public void useWeapon() { 181 | 182 | } 183 | } 184 | } 185 | } 186 | ``` 187 | 188 | --- 189 | 190 | ## Cyclic inheritance 191 | 192 | ```java 193 | class Ripley implements Ripley.UseWeapons { 194 | @Override 195 | public void useWeapon() { 196 | 197 | } 198 | 199 | public interface UseWeapons { 200 | public void useWeapon(); 201 | } 202 | 203 | // ... 204 | } 205 | 206 | ``` 207 | 208 | --- 209 | 210 | ## Local inner classes 211 | 212 | ```java 213 | String crewMember1 = "Cat"; 214 | 215 | class Nostromo { 216 | void explode() { 217 | System.out.println(crewMember1); 218 | } 219 | } 220 | 221 | Nostromo n = new Nostromo(); 222 | n.explode(); 223 | ``` 224 | 225 | --- 226 | 227 | ## Effectively final == constants 228 | 229 | - before Java 8 we need to mark as `final` 230 | - with Java 8 we can use _effectively final_ 231 | 232 | ```java 233 | String crewMember1 = ""; 234 | 235 | class Nostromo { 236 | void explode() { 237 | System.out.println(crewMember1); 238 | crewMember1 = ""; 239 | } 240 | } 241 | 242 | ``` 243 | 244 | --- 245 | 246 | ## Anonymous inner classes 247 | 248 | - write button handler 249 | 250 | --- 251 | 252 | ## Static nested classes 253 | 254 | --- 255 | 256 | ## A private Interface inside a class? 🤔 257 | 258 | ```java 259 | class B { 260 | private interface DoThings { 261 | void doThing(); 262 | } 263 | 264 | class C implements DoThings { 265 | @Override 266 | public void doThing() { 267 | 268 | } 269 | } 270 | } 271 | ``` 272 | 273 | --- 274 | 275 | ## A class inside an Interface! 😱 276 | 277 | ```java 278 | interface Host { 279 | class Guest { 280 | String name = "guest"; 281 | } 282 | } 283 | 284 | Host.Guest guest = new Host.Guest(); 285 | guest.name = "hello"; 286 | ``` -------------------------------------------------------------------------------- /10 - jdbc.md: -------------------------------------------------------------------------------- 1 | theme: Simple 2 | autoscale: true 3 | 4 | 5 | # JDBC: Java Database Connectivity 6 | 7 | --- 8 | 9 | ## Using Apache Derby 10 | 11 | - RazorSQL to inspect Derby DBs: http://razorsql.com/download_mac.html 12 | - add Apache Derby JAR to classpath 13 | - open `module settings` 14 | - copy JDK path 15 | - add to Libraries `$JAVA_HOME/db/lib/derby.jar` 16 | 17 | --- 18 | 19 | ## BASIC SQL 20 | 21 | - DML (Data Manipulation Language) 22 | - SELECT 23 | - INSERT 24 | - DELETE 25 | - UPDATE 26 | - COUNT 27 | - DDL (Data Definition Language) 28 | - DROP 29 | - ALTER 30 | - ETC. 31 | 32 | --- 33 | 34 | ## After running, creates a Derby DB 35 | 36 | - it's just a directory 37 | - don't mess with it 38 | 39 | --- 40 | 41 | ## JDBC: Interfaces inside java.sql (for the exam) 42 | 43 | - Driver 44 | - Connection 45 | - Statement 46 | - ResultSet 47 | 48 | Others have been added in javax.sql 49 | 50 | --- 51 | 52 | ## JDBC URL 53 | 54 | ``` 55 | protocol:vendor:database specific connection details 56 | 57 | jdbc:postgres://localhost:5432/mydb 58 | 59 | jdbc:oracle:thin:@localhost:1521:orcl 60 | 61 | jdbc:oracle:thin:@[HOST][:PORT]:SID 62 | ``` 63 | 64 | - used to connect to the DB 65 | - Several samples: https://www.ibm.com/support/knowledgecenter/en/SSEP7J_10.2.0/com.ibm.swg.ba.cognos.vvm_ag_guide.10.2.0.doc/c_ag_samjdcurlform.html 66 | 67 | --- 68 | 69 | ## Connect to a DB 70 | 71 | - Interfaces: `java.sql.DriverManager` vs `javax.sql.DataSource` 72 | - `DataSource`: factory, pooled, distributed 73 | - not covered in the exam! 74 | - `DriverManager` covered in the exam 75 | - uses Factory pattern 76 | 77 | --- 78 | 79 | ## Creating a connection using DriverManager 80 | 81 | ```java 82 | public static void main(String[] args) throws SQLException { 83 | String url = "jdbc:derby:peopledb;create=true"; 84 | 85 | try (Connection connection = DriverManager.getConnection(url)) { 86 | System.out.println(connection); 87 | } 88 | } 89 | ``` 90 | 91 | - also exists: `getConnection(url, user, password)` 92 | 93 | --- 94 | 95 | ## For reference only: using DataSource 96 | 97 | ```java 98 | EmbeddedDataSource ds = new EmbeddedDataSource(); 99 | ds.setDatabaseName("test/mydb"); 100 | 101 | ds.setCreateDatabase("create"); 102 | 103 | try (Connection connection = ds.getConnection(); 104 | Statement statement = connection.createStatement()) { 105 | 106 | } 107 | 108 | ``` 109 | 110 | --- 111 | 112 | ## Manually loading database Driver 113 | 114 | - DriverManager search JARs that contain a `Driver` class 115 | - looks for `META-INF/services/java.sql.Driver` 116 | - what if our (old) driver does not have `META-INF/services/java.sql.Driver`? 117 | - Since JDBC 4.0 (Java 6) should be there 118 | 119 | ```java 120 | try { 121 | Class.forName("org.apache.derby.jdbc.EmbeddedDriver"); 122 | } catch (ClassNotFoundException e) { 123 | e.printStackTrace(); 124 | } 125 | ``` 126 | 127 | 128 | --- 129 | 130 | ## Creating a test DB from Java 131 | 132 | ```java 133 | String url = "jdbc:derby:peopledb;create=true"; 134 | 135 | try (Connection connection = DriverManager.getConnection(url); // this Throws Exception 136 | Statement statement = connection.createStatement()) { 137 | statement.executeUpdate("Drop table person"); 138 | 139 | statement.executeUpdate("create table PERSON " + 140 | "(" + 141 | "id integer primary key," + 142 | "name varchar(255)" + 143 | ")"); 144 | 145 | statement.executeUpdate("insert into PERSON VALUES (1, 'Diego')"); 146 | } 147 | ``` 148 | 149 | --- 150 | 151 | ## Statement: sending SQL to the DB 152 | 153 | ```java 154 | Statement statement = connection.createStatement() 155 | 156 | ``` 157 | 158 | --- 159 | 160 | 161 | 162 | ## executeUpdate 163 | 164 | - should be called _executedSomethingThatsGonnaChangeTheDB_ 165 | - returns the number of inserted, deleted or updated rows (or 0 if it's a DDL SQL sentence) 166 | 167 | ```java 168 | i = statement.executeUpdate("insert into PERSON VALUES (1, 'Diego')"); // i == 1 169 | 170 | i = statement.executeUpdate("Drop table person"); // i == 0 171 | 172 | System.out.println(statement.getUpdateCount()); // getUpdateCount also returns this 173 | ``` 174 | 175 | --- 176 | 177 | ## Inserting more than one record 178 | 179 | ```sql 180 | INSERT INTO PERSON VALUES (0, 'Person 0'), (1, 'Person 1'), ... 181 | 182 | ``` 183 | 184 | ```java 185 | statement.executeUpdate("insert into PERSON VALUES (0, 'Person 0'), (1, 'Person 1')"); 186 | ``` 187 | 188 | --- 189 | 190 | ## Inserting more than one record 191 | 192 | ```java 193 | StringBuffer insertSQL = new StringBuffer("insert into PERSON VALUES "); 194 | for (int j = 0; j < 10; j++) { 195 | insertSQL.append(String.format("(%d, '%s')", j, "Person " + j)); 196 | if (j < 9) { 197 | insertSQL.append(", "); 198 | } 199 | } 200 | 201 | System.out.println(insertSQL); 202 | 203 | i = statement.executeUpdate(insertSQL.toString()); 204 | System.out.println(i); 205 | ``` 206 | 207 | --- 208 | 209 | ## Deleting 210 | 211 | --- 212 | 213 | ## Updating 214 | 215 | --- 216 | 217 | ## Query 218 | 219 | - a `executeQuery` call returns a `ResultSet` (a cursor) 220 | 221 | ```java 222 | ResultSet rs = statement.executeQuery("SELECT * FROM PERSON"); 223 | while (rs.next()) { 224 | System.out.println(rs.getString(2)); // columns start in 1! 225 | } 226 | ``` 227 | 228 | --- 229 | 230 | ## Query 231 | 232 | - we can also use `execute` and check if it returns a `ResultSet` 233 | 234 | ```java 235 | boolean isResultSet = statement.execute("SELECT * FROM PERSON"); 236 | if (isResultSet) { 237 | ResultSet resultSet = statement.getResultSet(); 238 | System.out.println(resultSet); 239 | } else { 240 | int result = statement.getUpdateCount(); 241 | System.out.println(result); 242 | } 243 | 244 | ``` 245 | 246 | --- 247 | 248 | ## Types of ResultSets 249 | 250 | ```java 251 | Statement statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY) 252 | ``` 253 | 254 | `ResultSet.TYPE_FORWARD_ONLY`: can move --> only, can't see last data (snapshop), supported 255 | `ResultSet.TYPE_SCROLL_INSENSITIVE`: can move <-->, can't see last data (snapshop), supported 256 | `ResultSet.TYPE_SCROLL_SENSITIVE`: can move <-->, can see last data (snapshop), not well supported 257 | 258 | - createStatement does graceful degradation and returns the available ResultSet 259 | 260 | --- 261 | 262 | ## Concurrency modes 263 | 264 | ``` 265 | ResultSet.CONCUR_READ_ONLY: read only cursor 266 | ResultSet.CONCUR_UPDATABLE: read/write cursor. Not required to be supported 267 | ``` 268 | 269 | - to change things in the DB we use Statements, not ResultSets 270 | 271 | --- 272 | 273 | 274 | ```java 275 | ResultSet resultSet = statement.getResultSet(); 276 | System.out.println(resultSet.getConcurrency() == ResultSet.CONCUR_UPDATABLE); 277 | System.out.println(resultSet.getConcurrency() == ResultSet.TYPE_SCROLL_SENSITIVE); 278 | 279 | ``` 280 | 281 | --- 282 | 283 | ## Forward-only means that! 284 | 285 | ```java 286 | Statement statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE)) { 287 | 288 | ResultSet rs = statement.executeQuery("SELECT * FROM PERSON"); 289 | while (rs.next()) { 290 | System.out.println(rs.getString(2)); 291 | } 292 | 293 | rs.first(); // Exception in thread "main" java.sql.SQLException: The 'first()' method is only allowed on scroll cursors. 294 | System.out.println(rs.getString(2)); 295 | 296 | ``` 297 | 298 | --- 299 | 300 | ## Statement vs PreparedStatement 301 | 302 | - Only `Statement` in the exam 303 | - use `PreparedStatement` always 304 | - no SQL injection 305 | - best performance 306 | 307 | --- 308 | 309 | ## Using the wrong method 310 | 311 | - a QUERY inside `executeUpdate` 312 | 313 | ```java 314 | statement.executeUpdate("SELECT * FROM PERSON"); 315 | // Exception in thread "main" java.sql.SQLException: 316 | // Statement.executeUpdate() cannot be called with a statement that returns a ResultSet. 317 | ``` 318 | 319 | - a INSERT, UPDATE, DELETE inside `executeQuery` 320 | 321 | ```java 322 | ResultSet rs = statement.executeQuery("DELETE FROM PERSON"); 323 | // Exception in thread "main" java.sql.SQLException: 324 | // Statement.executeQuery() cannot be called with a statement that returns a row count. 325 | 326 | while (rs.next()) { 327 | System.out.println(rs.getString(2)); 328 | } 329 | ``` 330 | 331 | --- 332 | 333 | |Statement Method|Ret|DELETE|INSERT|UPDATE|SELECT| 334 | |----:|:-:|:-:|:-:|:-:|:-:| 335 | |`execute()`|`boolean`|👍|👍|👍|👍| 336 | |`execute Query()`|`ResultSet`|👎|👎|👎|👍| 337 | |`execute Update()`|`int`|👍|👍|👍|👎| 338 | 339 | --- 340 | 341 | ## Looping through a ResultSet 342 | 343 | - check ResultSet type: remember `ResultSet.TYPE_FORWARD_ONLY`, etc. 344 | - initial position "beforeFirst" 345 | - `rs.beforeFirst()`, `rs.isBeforeFirst()` 346 | - last position "after last" 347 | - `rs.afterLast()`, `rs.isAfterLast()` 348 | - rs.previous(), 349 | - `rs.next()` -> returns true if not at the end 350 | 351 | --- 352 | 353 | ## Absolute 354 | 355 | - moves to the absolute index provided 356 | - returns true if there's a row there 357 | - absolute(0) == before first 358 | - absolute(1) == first row (if exists) 359 | - absolute(-1) == last element 360 | - absolute(-2) == element before last one 361 | 362 | --- 363 | 364 | ## Relative 365 | 366 | - skips n rows from current position 367 | 368 | --- 369 | 370 | ## Accessing fields 371 | 372 | - using name: getInt("id"), getString("name") 373 | - using field position: getInt(1), getString(2) // starts with 1 374 | 375 | --- 376 | 377 | ## Counting 378 | 379 | ```java 380 | ResultSet rsCount = statement.executeQuery("SELECT COUNT(*) FROM PERSON"); 381 | if (rsCount.next()) { 382 | String count = rsCount.getString(1); 383 | System.out.println(count); 384 | } 385 | ``` 386 | 387 | --- 388 | 389 | ## Times & Dates 390 | 391 | |JDBC|Java 8|Contains| 392 | |---|---|--:| 393 | java.sql.Date | java.time.LocalDate | Date 394 | java.sql.Time | java.time.LocalTime | Time 395 | java.sql.TimeStamp | java.time. LocalDateTime | Date & Time 396 | 397 | --- 398 | 399 | ## Inserting TimeStamps 400 | 401 | - convert into `java.sql.TimeStamp` 402 | 403 | ```java 404 | // modify table 405 | 406 | statement.executeUpdate("create table PERSON " + 407 | "(" + 408 | "id integer primary key," + 409 | "name varchar(255)," + 410 | "birthDate timestamp" + // added 411 | ")"); 412 | // ... 413 | 414 | StringBuffer insertSQL = new StringBuffer("insert into PERSON VALUES "); 415 | for (int j = 0; j < 10; j++) { 416 | java.sql.Timestamp timestamp = new Timestamp(LocalDateTime.now().toEpochSecond(ZoneOffset.UTC)); 417 | insertSQL.append(String.format("(%d, '%s', '%s')", j, "Person " + j, timestamp.toString())); 418 | if (j < 9) { 419 | insertSQL.append(", "); 420 | } 421 | } 422 | ``` 423 | 424 | --- 425 | 426 | ## Closing database 427 | 428 | ```java 429 | try (Connection connection = DriverManager.getConnection(url); 430 | Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { 431 | // try-with-resources: closes resources in the opposite order as they were created 432 | } 433 | 434 | ``` 435 | 436 | - closing Connection closes statement (and resultsets) 437 | - closing Statement closes resultsets 438 | 439 | --- 440 | 441 | ## Closing resultsets 442 | 443 | ```java 444 | ResultSet rs = statement.executeQuery("SELECT * FROM PERSON"); 445 | 446 | while (rs.next()) { 447 | System.out.println(rs.getString("name")); 448 | } 449 | 450 | boolean isResultSet = statement.execute("SELECT * FROM PERSON"); // closes here 451 | ``` -------------------------------------------------------------------------------- /2.1 - Interfaces.md: -------------------------------------------------------------------------------- 1 | theme: Plain Jane 2 | autoscale: true 3 | 4 | # Interfaces 5 | 6 | --- 7 | 8 | ## Interfaces 9 | 10 | - Can declare any number of methods 11 | - Can be a _marker_ interface (empty) 12 | - Can _extend_ another interface 13 | 14 | ```java 15 | 16 | interface Marker { 17 | } 18 | 19 | interface A extends Marker { 20 | } 21 | ``` 22 | 23 | --- 24 | 25 | ## Can't 26 | 27 | - a class can't extend from an Interface 28 | - can't create an instance of an interface 29 | - can't contain instance / static blocks of code 30 | 31 | --- 32 | 33 | ## Instance of 34 | 35 | ```java 36 | Marker m = new Marker() { // this is an anonymous class implementing Marker 37 | }; 38 | 39 | System.out.println(m instanceof Marker); 40 | ``` 41 | 42 | ^ 43 | We're instantiating an Object 44 | 45 | --- 46 | 47 | ## What does this print? 48 | 49 | ```java 50 | interface Marker { 51 | } 52 | 53 | interface A extends Marker { 54 | } 55 | 56 | // ... 57 | 58 | A a = new A() { 59 | }; 60 | System.out.println(a instanceof Marker); 61 | System.out.println(a instanceof A); 62 | ``` 63 | ^ 64 | true and true 65 | 66 | --- 67 | 68 | ## Always public abstract 69 | 70 | - we can use any form: the compiler treats them as always `public abstract` 71 | - in the interface _definition_ we can omit `public abstract`. In the class _implementation_: NO 72 | 73 | ```java 74 | public interface Decompress { 75 | public abstract void decompress(); 76 | abstract void decompress(); 77 | public void decompress(); 78 | void decompress(); 79 | } 80 | ``` 81 | 82 | --- 83 | 84 | ## Interface default implementations 85 | 86 | ```java 87 | interface Compress { 88 | void compress(); 89 | } 90 | 91 | interface CompressExtension extends Compress { 92 | @Override 93 | default void compress() { 94 | System.out.println("I'm compressing"); 95 | } 96 | } 97 | 98 | class ZipCompressor implements CompressExtension { 99 | 100 | } 101 | ``` 102 | 103 | --- 104 | 105 | ## Static members in an interface 106 | 107 | ```java 108 | interface I1 { 109 | static void sm() { 110 | System.out.println("Static method"); 111 | } 112 | 113 | default void m1() { 114 | System.out.println("I1::m1"); 115 | } 116 | } 117 | 118 | interface I2 extends I1 { 119 | default void m1() { 120 | I1.sm(); // we need to use the Interface I1 as sm is defined there 121 | System.out.println("I2::m1"); 122 | } 123 | } 124 | 125 | class A implements I2, I1 { 126 | @Override 127 | public void m1() { 128 | I1.sm(); 129 | } 130 | 131 | } 132 | ``` 133 | 134 | 135 | --- 136 | 137 | ## Default implementations useful? 138 | 139 | - to move common code from subclasses to small, focused interfaces instead of a big-ass abstract parent class 140 | - f.i. interface `FilePersistable`: we can persist compressed files, or music, photos, etc. 141 | - the ability to be saved on file is a trait of many different classes 142 | 143 | --- 144 | 145 | ## Problem 1 146 | 147 | - two different (unrelated) interfaces provide the same default 148 | 149 | ```java 150 | class ZipCompressor implements CompressExtension, AnotherCompressExtension { // Error 151 | } 152 | 153 | interface CompressExtension extends Compress { 154 | @Override 155 | default void compress() { 156 | System.out.println("I'm compressing in CompressExtension"); 157 | } 158 | } 159 | 160 | interface AnotherCompressExtension extends Compress { 161 | @Override 162 | default void compress() { 163 | System.out.println("I'm compressing in AnotherCompressExtension"); 164 | } 165 | } 166 | 167 | ``` 168 | 169 | --- 170 | 171 | ## Problem 1, simplified 172 | 173 | ```java 174 | interface I1 { 175 | default void m1() { 176 | System.out.println("I1::m1"); 177 | } 178 | } 179 | 180 | interface I2 { 181 | default void m1() { 182 | System.out.println("I2::m1"); 183 | } 184 | } 185 | 186 | class A implements I1, I2 { // COMPILATION ERROR 187 | 188 | } 189 | ``` 190 | 191 | --- 192 | 193 | ## Problem 1, solved 194 | 195 | ```java 196 | interface I1 { 197 | default void m1() { 198 | System.out.println("I1::m1"); 199 | } 200 | } 201 | 202 | interface I2 extends I1 { 203 | default void m1() { 204 | System.out.println("I2::m1"); // this is used 205 | } 206 | } 207 | 208 | class A implements I1, I2 { 209 | 210 | } 211 | ``` 212 | 213 | 214 | 215 | --- 216 | 217 | ## Problem 2 218 | 219 | - one interface provides a default impl 220 | - another interface extends from it and provides a different default impl 221 | 222 | ```java 223 | class ZipCompressor implements AnotherCompressExtension { 224 | } 225 | 226 | interface CompressExtension extends Compress { 227 | @Override 228 | default void compress() { 229 | System.out.println("I'm compressing in CompressExtension"); 230 | } 231 | } 232 | 233 | interface AnotherCompressExtension extends CompressExtension { 234 | @Override 235 | default void compress() { 236 | System.out.println("I'm compressing in AnotherCompressExtension"); 237 | } 238 | } 239 | 240 | ZipCompressor zc = new ZipCompressor(); 241 | zc.compress(); // I'm compressing in AnotherCompressExtension 242 | ((CompressExtension)zc).compress(); // I'm compressing in AnotherCompressExtension 243 | ``` 244 | 245 | --- 246 | 247 | ## Uses of interfaces & default impl 248 | 249 | - To quickly create mocks 250 | - To let you compile and print warning while running -------------------------------------------------------------------------------- /2.2 - Functional Programming - intro.md: -------------------------------------------------------------------------------- 1 | theme: Plain Jane 2 | autoscale: true 3 | 4 | # Functional Programming 5 | 6 | --- 7 | 8 | # Functional Programming 9 | 10 | - no side effects 11 | - data in, data out 12 | - no mutability (no state) 13 | - state is bad 14 | - shared mutable state is the root of all evil 15 | 16 | --- 17 | 18 | ## Functional Interface 19 | 20 | - an interface with just one method 21 | 22 | ```java 23 | interface Add { 24 | int add(int n1, int n2); 25 | } 26 | ``` 27 | 28 | --- 29 | 30 | ## Functional Interface 31 | 32 | - we can add the annotation `@FunctionalInterface` 33 | 34 | ```java 35 | @FunctionalInterface 36 | interface Add { 37 | int add(int n1, int n2); 38 | } 39 | 40 | @FunctionalInterface 41 | interface Substract { 42 | int substract(int n1, int n2); 43 | } 44 | ``` 45 | 46 | --- 47 | 48 | ## Just one method, please 49 | 50 | ```java 51 | @FunctionalInterface 52 | interface Add { 53 | int add(int n1, int n2); 54 | void m1(); // wrong: two methods 55 | } 56 | 57 | @FunctionalInterface 58 | interface Add { 59 | int add(int n1, int n2); 60 | static void m1(); // right: just one method 61 | } 62 | ``` 63 | 64 | --- 65 | 66 | ## No Sh*t, sherlock, just one method 67 | 68 | ```java 69 | @FunctionalInterface 70 | interface Add { 71 | int add(int n1, int n2); 72 | } 73 | 74 | @FunctionalInterface 75 | interface Substract { 76 | int substract(int n1, int n2); 77 | } 78 | 79 | @FunctionalInterface // ERROR 80 | interface Operation extends Add, Substract { 81 | // add & substract are copied here 82 | } 83 | ``` 84 | 85 | --- 86 | 87 | ## Lambda expressions 88 | 89 | - a way to _consume_ functional interfaces 90 | - a way to _implement_ those interfaces 91 | 92 | ```java 93 | (String instance) -> { return instance.legth(); } 94 | 95 | // Lambda expression for a Functional Interface 96 | // that declares a method taking one input param of type String, and returns an int 97 | 98 | 99 | // shorthand 100 | s -> s.length; 101 | ``` 102 | 103 | --- 104 | 105 | ## Lambda expressions 106 | 107 | - can omit () if no type present and just one argument 108 | - can omit `return` and `;` 109 | 110 | --- 111 | 112 | ## Example: calculator 113 | 114 | - a calculator can +, -, *, /, %, ... 115 | - restricted (for now) to `int` type 116 | - we can use an enum for operations and a Switch: 117 | 118 | ```java 119 | class OldCalculator { 120 | enum OldOperations { 121 | ADD, SUBSTRACT, MULTIPLY, DIVIDE 122 | } 123 | 124 | int calculate(int n1, int n2, OldOperations operation) { 125 | int result = 0; 126 | switch (operation) { 127 | case ADD: 128 | result = n1 + n2; break; 129 | case SUBSTRACT: 130 | result = n1 - n2; break; 131 | case MULTIPLY: 132 | result = n1 * n2; break; 133 | case DIVIDE: 134 | result = n1 / n2; break; 135 | } 136 | return result; 137 | } 138 | } 139 | 140 | OldCalculator oldCalculator = new OldCalculator(); 141 | int r = oldCalculator.calculate(1,2, OldCalculator.OldOperations.ADD); 142 | System.out.println("r: " + r); 143 | ``` 144 | 145 | --- 146 | 147 | ## Example: calculator 148 | 149 | - problem: we want to add another operation 150 | - change the `enum` 151 | - touch the `switch` 152 | - recompile 153 | - if code is copied in other projects... 154 | 155 | 156 | --- 157 | 158 | ## Example: calculator 159 | 160 | - Functional solution: all these are arithmetic operations between two numbers. Let's say that: 161 | 162 | ```java 163 | @FunctionalInterface 164 | interface Operation { 165 | int operate(int n1, int n2); 166 | } 167 | ``` 168 | 169 | - and create a `Calculator` class with a method that takes two numbers and an `Operation` 170 | - as all `Operation` references have `calculate` we can call it 171 | 172 | ```java 173 | class Calculator { 174 | int calculate(int n1, int n2, Operation op) { 175 | return op.operate(n1, n2); 176 | } 177 | } 178 | ``` 179 | 180 | --- 181 | 182 | ## Example: calculator 183 | 184 | - using it: we're passing two numbers and _what we want to do with these two numbers_ (the code block) 185 | 186 | ```java 187 | Calculator c = new Calculator(); 188 | int i = c.calculate(1, 2, (n1, n2) -> n1 * n2); 189 | i = c.calculate(2, 2, (int n1, int n2) -> n1 * n2); 190 | i = c.calculate(2, 2, (int n1, int n2) -> n1 * n2); 191 | i = c.calculate(2, 2, (int n1, int n2) -> { return n1 * n2; }); 192 | 193 | ``` 194 | 195 | --- 196 | 197 | ## Example: calculator 198 | 199 | - Lambda expressions can be passed around, or stored... 200 | 201 | ```java 202 | final Operation multiply = (n1, n2) -> n1 * n2; 203 | ``` 204 | 205 | so we can do: 206 | 207 | ```java 208 | class Calculator { 209 | static final Operation multiply = (n1, n2) -> n1 * n2; 210 | static final Operation add = (n1, n2) -> n1 + n2; 211 | static final Operation substract = (n1, n2) -> n1 - n2; 212 | static final Operation divide = (n1, n2) -> n1 / n2; 213 | 214 | int calculate(int n1, int n2, Operation op) { 215 | return op.operate(n1, n2); 216 | } 217 | } 218 | 219 | // using it 220 | 221 | i = c.calculate(40, 40, Calculator.divide); 222 | ``` 223 | 224 | --- 225 | 226 | 227 | ## Example: calculator 228 | 229 | - we can return a Lambda expression from a method 230 | 231 | ```java 232 | Operation sum() { 233 | return ((n1, n2) -> n1 + n2); 234 | } 235 | ``` 236 | 237 | --- 238 | 239 | ## Example: calculator 240 | 241 | - even return a random operation each time 242 | 243 | ```java 244 | Operation randomOperation() { 245 | Operation[] operations = { 246 | multiply, add, substract, divide 247 | }; 248 | 249 | Random r = new Random(); 250 | return operations[abs(r.nextInt()) % operations.length]; 251 | } 252 | 253 | ``` 254 | 255 | --- 256 | 257 | ## Write correct Functional Interfaces for the following Lambda Expressions 258 | 259 | ```java 260 | () -> 10; 261 | (a) -> a.size(); 262 | ``` 263 | 264 | --- 265 | 266 | ## Answers 267 | 268 | ```java 269 | L1 l1 = () -> 10; 270 | 271 | interface L1 { 272 | int m(); 273 | } 274 | 275 | L3 l3 = a -> a.size(); 276 | 277 | @FunctionalInterface 278 | interface L3 { 279 | int m(Collection c); 280 | } 281 | ``` 282 | 283 | --- 284 | 285 | ## Write correct Functional Interfaces for the following Lambda Expressions 286 | 287 | ```java 288 | (a, b, c) -> a.size() + b.length() + c.length; 289 | ``` 290 | 291 | --- 292 | 293 | ## 294 | 295 | ```java 296 | interface L4 { 297 | int m(Collection a, String b, Object[] c); 298 | } 299 | ``` 300 | --- 301 | 302 | ## Write correct Functional Interfaces for the following Lambda Expressions 303 | 304 | ```java 305 | () -> () -> 10; 306 | ``` 307 | 308 | --- 309 | 310 | 311 | ```java 312 | 313 | L2 = () -> () -> 10; 314 | 315 | interface L2 { 316 | L1 m(); 317 | } 318 | 319 | ``` 320 | 321 | --- 322 | 323 | ## Useful lambdas 324 | 325 | - Without lambdas... 326 | 327 | ```java 328 | Runnable task1 = new Runnable() { 329 | @Override 330 | public void run() { 331 | System.out.println("Something!"); 332 | } 333 | }; 334 | task1.run(); 335 | 336 | ``` 337 | 338 | - With Lambdas... 339 | 340 | ```java 341 | Runnable task2 = () -> { System.out.println("Yeah!"); }; 342 | task2.run(); 343 | ``` 344 | 345 | 346 | --- 347 | 348 | ## Useful lambdas: repeating codeblocks 349 | 350 | ```java 351 | interface CodeBlock { 352 | void execute(); 353 | } 354 | 355 | CodeBlock cb = () -> { 356 | System.out.println("Hello"); 357 | }; 358 | 359 | cb.execute(); 360 | cb.execute(); 361 | 362 | ``` 363 | 364 | --- 365 | 366 | ## Useful lambdas: forEach 367 | 368 | ```java 369 | List streets = Arrays.asList("Torricelli", "Sierpes", "Constitución"); 370 | 371 | for (String street : streets) { 372 | System.out.println(street); 373 | } 374 | 375 | streets.forEach((String x) -> {System.out.println(x);}); 376 | streets.forEach((String x) -> System.out.println(x)); 377 | streets.forEach(x -> System.out.println(x)); 378 | streets.forEach(System.out::println); 379 | 380 | ``` 381 | 382 | --- 383 | 384 | ## Lambdas capture the semantic scope 385 | 386 | ```java 387 | int i = 4; 388 | 389 | CodeBlock cb = () -> { 390 | System.out.println("Hello " + i); 391 | }; 392 | 393 | cb.execute(); 394 | ``` 395 | 396 | --- 397 | 398 | ## Final vs EffectivelyFinal 399 | 400 | - `final`: a constant with a explicit `final` keyword. Can't change after being set 401 | - Effectively final: the compiler knows you have defined a variable, but never changed it (usually, all method parameters). We can use it from a lamda expression without the need to mark it `final` 402 | - but we can't change the value of that constant 403 | - it's a constant, but now we don't have to explicitly mark it as `final` -------------------------------------------------------------------------------- /2.3 - Polymorphism.md: -------------------------------------------------------------------------------- 1 | theme: Plain Jane 2 | autoscale: true 3 | 4 | ## Polymorphism 5 | 6 | - we can "see" only the part of the object we're interested in 7 | - at runtime, if we call a method, the __true__ one is the method from the instance class, not the reference one 8 | 9 | --- 10 | 11 | ## Casting 12 | 13 | - no need to cast if upcasting (from a specialzed version to a general one) 14 | - need to cast if downcasting 15 | - use `instanceof` 16 | - can only cast inheritance-related classes 17 | 18 | ```java 19 | String s = ""; 20 | Object o = s; 21 | 22 | String s1 = (String) o; 23 | 24 | ``` -------------------------------------------------------------------------------- /2.4 - Design principles.md: -------------------------------------------------------------------------------- 1 | theme: Plain Jane 2 | autoscale: true 3 | 4 | # Design Principles 5 | 6 | > a design principle is an established idea or best practice that facilitates software development 7 | 8 | --- 9 | 10 | ## Encapsulation 11 | 12 | - almost always related to information hiding 13 | - invariants about internal data: property or truth that is maintained after data is modified 14 | 15 | --- 16 | 17 | ## Invariants 18 | 19 | - For a Person: 20 | - all people have names 21 | - all living people has age between 0...150 22 | 23 | ```java 24 | class Person { 25 | String name; 26 | int age; 27 | } 28 | ``` 29 | 30 | --- 31 | 32 | ## JavaBeans 33 | 34 | 35 | --- 36 | 37 | ## Inheritance vs Composition 38 | 39 | - Inheritance: IS-A 40 | - instanceof operator 41 | - Composition: HAS-A 42 | - look at properties 43 | 44 | --- 45 | 46 | ## Stupid inheritance 47 | 48 | ```java 49 | class Person { 50 | String name; 51 | int age; 52 | } 53 | 54 | class Car extends Person { 55 | String color; 56 | } 57 | ``` 58 | 59 | --- 60 | 61 | ## Object composition: Delegation 62 | 63 | --- 64 | 65 | ## Design patterns 66 | 67 | - creational patterns 68 | - 4 showed in the book 69 | - only Singleton & Inmutable Object in the exam 70 | 71 | 72 | --- 73 | 74 | ## Singleton 75 | 76 | - allow only one instance of that class in memory 77 | 78 | ```java 79 | class PrintJobsManager { 80 | private int remainingJobs; 81 | 82 | private static PrintJobsManager sharedInstance = new PrintJobsManager(); 83 | 84 | public static synchronized PrintJobsManager sharedPrintJobsManager() { 85 | return sharedInstance; 86 | } 87 | 88 | private PrintJobsManager() {} 89 | 90 | public synchronized void addPrintJob(String s) { 91 | remainingJobs = remainingJobs + 1; 92 | } 93 | 94 | public synchronized int getRemainingJobs() { 95 | return remainingJobs; 96 | } 97 | } 98 | ``` 99 | 100 | --- 101 | 102 | ## Singleton is effectively final 103 | 104 | - we don't have any constructor now! 105 | 106 | ```java 107 | class A extends PrintJobsManager { 108 | A() { 109 | super(); // FAILS 110 | } 111 | } 112 | 113 | ``` 114 | 115 | --- 116 | 117 | ## Double-Checked Locking 118 | 119 | 120 | ```java 121 | class PrintJobsManager { 122 | private int remainingJobs; 123 | 124 | private static volatile PrintJobsManager sharedInstance; 125 | 126 | // Double-Checked Locking 127 | public static PrintJobsManager sharedPrintJobsManager() { 128 | if (sharedInstance == null) { 129 | synchronized (PrintJobsManager.class) { 130 | sharedInstance = new PrintJobsManager(); 131 | } 132 | } 133 | return sharedInstance; 134 | } 135 | 136 | private PrintJobsManager() {} 137 | 138 | public synchronized void addPrintJob(String s) { 139 | remainingJobs = remainingJobs + 1; 140 | } 141 | 142 | public synchronized int getRemainingJobs() { 143 | return remainingJobs; 144 | } 145 | } 146 | ``` 147 | 148 | --- 149 | 150 | ## Volatile? 151 | 152 | - Nice discussion here: http://stackoverflow.com/questions/7855700/why-is-volatile-used-in-this-example-of-double-checked-locking 153 | 154 | 155 | ```java 156 | public final class Singleton { 157 | private Singleton() {} 158 | public static Singleton getInstance() { 159 | return LazyHolder.INSTANCE; 160 | } 161 | private static class LazyHolder { 162 | private static final Singleton INSTANCE = new Singleton(); // gets initialized once, before all threads start 163 | } 164 | } 165 | 166 | ``` 167 | 168 | --- 169 | 170 | ## Inmutable Objects 171 | 172 | 1. use constructor to set all properties 173 | 1. mark all instance variables as `private` and `final` 174 | 1. only use getters, not setters 175 | 1. don't allow referenced mutable objects to be modified or accessed directly 176 | 1. prevent methods from being overridden 177 | 178 | 179 | ```java 180 | class City { 181 | private String name; 182 | 183 | public City(String name) { 184 | this.name = name; 185 | } 186 | 187 | public String getName() { 188 | return name; 189 | } 190 | } 191 | ``` 192 | 193 | --- 194 | 195 | ## Inmutable Objects 196 | 197 | - all instance vars must be private 198 | - if not: we can change it 199 | 200 | ```java 201 | City seville = new City("Seville"); 202 | seville.population = 100; 203 | System.out.println(seville.getName()); 204 | 205 | class City { 206 | private String name; 207 | int population; // should be private to avoid direct access! 208 | 209 | public City(String name) { 210 | this(name, 0); 211 | } 212 | 213 | public City(String name, int population) { 214 | this.name = name; 215 | this.population = population; 216 | } 217 | 218 | public String getName() { 219 | return name; 220 | } 221 | } 222 | ``` 223 | 224 | --- 225 | 226 | ## Inmutable Objects 227 | 228 | - better encapsulated version 229 | 230 | ```java 231 | class City { 232 | private final String name; 233 | private final int population; 234 | 235 | public City(String name) { 236 | this(name, 0); // chained constructors 237 | } 238 | 239 | public City(String name, int population) { 240 | this.name = name; 241 | this.population = population; 242 | } 243 | 244 | public String getName() { 245 | return name; 246 | } 247 | } 248 | ``` 249 | 250 | --- 251 | 252 | ## Inmutable Objects: adding referenced objects 253 | 254 | ```java 255 | List streets = new LinkedList<>(); 256 | 257 | streets.add("Torricelli"); 258 | streets.add("Sierpes"); 259 | streets.add("Constitución"); 260 | 261 | City seville = new City("Seville", 800_000, streets); 262 | seville.getStreets().forEach(System.out::println); 263 | 264 | seville.getStreets().add("Wall Street"); // we can mutate the list! 265 | seville.getStreets().forEach(System.out::println); 266 | 267 | streets.clear(); // even worse, we have stored the reference, so we can change from outside 268 | seville.getStreets().forEach(System.out::println); 269 | 270 | class City { 271 | private final String name; 272 | private final int population; 273 | private final List streets; 274 | 275 | public City(String name) { 276 | this(name, 0); // chained constructors 277 | } 278 | 279 | public City(String name, int population) { 280 | this(name, population, null); 281 | } 282 | 283 | public City(String name, int population, List streets) { 284 | this.name = name; 285 | this.population = population; 286 | this.streets = streets; 287 | } 288 | 289 | public String getName() { 290 | return name; 291 | } 292 | 293 | public int getPopulation() { 294 | return population; 295 | } 296 | 297 | public List getStreets() { 298 | return streets; 299 | } 300 | } 301 | ``` 302 | 303 | --- 304 | 305 | ## Solution 306 | 307 | ```java 308 | class City { 309 | private final String name; 310 | private final int population; 311 | private final List streets; 312 | 313 | public City(String name) { 314 | this(name, 0); // chained constructors 315 | } 316 | 317 | public City(String name, int population) { 318 | this(name, population, null); 319 | } 320 | 321 | public City(String name, int population, List streets) { 322 | this.name = name; 323 | this.population = population; 324 | this.streets = Collections.unmodifiableList(streets); 325 | } 326 | 327 | public String getName() { 328 | return name; 329 | } 330 | 331 | public int getPopulation() { 332 | return population; 333 | } 334 | 335 | public List getStreets() { 336 | return streets; 337 | } 338 | } 339 | 340 | 341 | ``` 342 | 343 | --- 344 | 345 | ## Builder pattern 346 | 347 | ```java 348 | class Person { 349 | private String name; 350 | private String address; 351 | private int age; 352 | 353 | public static class Builder { 354 | private String name; 355 | private String address; 356 | private int age; 357 | 358 | public Person build() { 359 | return new Person(name, address, age); 360 | } 361 | 362 | public Builder setName(String name) { 363 | this.name = name; 364 | return this; 365 | } 366 | 367 | public Builder setAddress(String address) { 368 | this.address = address; 369 | return this; 370 | } 371 | 372 | public Builder setAge(int age) { 373 | this.age = age; 374 | return this; 375 | } 376 | } 377 | 378 | private Person(String name, String address, int age) { 379 | this.name = name; 380 | this.address = address; 381 | this.age = age; 382 | } 383 | 384 | public String getName() { return name; } 385 | 386 | public String getAddress() { return address; } 387 | 388 | public int getAge() { return age; } 389 | } 390 | ``` -------------------------------------------------------------------------------- /3.1 - array-arraylist.md: -------------------------------------------------------------------------------- 1 | theme: Plain Jane 2 | autoscale: true 3 | 4 | # Arrays & ArrayLists 5 | 6 | 7 | --- 8 | 9 | ## ArrayList 10 | 11 | - extends from `AbstractList` and `AbstractCollection` 12 | - ArrayList can contain only objects (not primitives) 13 | - how can I have a list of `boolean`? Using wrapper class `Boolean` 14 | 15 | --- 16 | 17 | ## Arrays 18 | 19 | - bad creation 20 | 21 | ``` 22 | String[] pokemon = new String[0]; 23 | pokemon[0] = "Charmander"; // Error: ArrayIndexOutOfBoundsException: 0 24 | pokemon[1] = "GeoDude"; 25 | ``` 26 | 27 | - good one 28 | 29 | ```java 30 | 31 | String[] pokemon = new String[2]; 32 | pokemon[0] = "Charmander"; 33 | pokemon[1] = "GeoDude"; 34 | 35 | // or this one 36 | 37 | String[] pokemon2 = new String[] { 38 | "Charmander", 39 | "GeoDude" 40 | }; 41 | 42 | // also 43 | 44 | String[] pokemon3 = { 45 | "Charmander", 46 | "GeoDude" 47 | }; 48 | 49 | ``` 50 | 51 | --- 52 | 53 | ## Spot why these are wrong 54 | 55 | ```java 56 | String[] pokemon2 = new String[]() { 57 | "Charmander", 58 | "GeoDude" 59 | }; 60 | 61 | String[] pokemon2 = new String[](2) { 62 | "Charmander", 63 | "GeoDude" 64 | }; 65 | 66 | String[2] pokemon2 = new String[] { 67 | "Charmander", 68 | "GeoDude" 69 | }; 70 | 71 | String pokemon2[2] = new String[] { 72 | "Charmander", 73 | "GeoDude" 74 | }; 75 | 76 | ``` 77 | 78 | --- 79 | 80 | ## Watch out! 81 | 82 | ```java 83 | List names = Arrays.asList("groucho", "harpo", "chicco"); 84 | 85 | for (String s: names) { 86 | System.out.println(s); 87 | } 88 | 89 | names.add("zeppo"); // crash: can't add more elements to this list 90 | // asList: Returns a fixed-size list backed by the specified array 91 | ``` 92 | 93 | --- 94 | 95 | ## Watch out! 96 | 97 | ```java 98 | String[] pokemon = new String[2]; 99 | pokemon[0] = "Charmander"; 100 | pokemon[1] = "GeoDude"; 101 | 102 | 103 | // nice typed List 104 | List names = Arrays.asList(pokemon); 105 | 106 | for (String s: names) { 107 | System.out.println(s); 108 | } 109 | 110 | pokemon[0] = "Pikachu"; 111 | 112 | // after changing element 0 in array, list also changes !! 113 | 114 | for (String s: names) { 115 | System.out.println(s); 116 | } 117 | ``` 118 | 119 | 120 | --- 121 | 122 | ## Searching & Sorting 123 | 124 | ```java 125 | int[] numbers = {9, 1, 4, 6}; 126 | 127 | Arrays.sort(numbers); 128 | 129 | for (int n: numbers) { // arrays get modified 130 | System.out.print(n + "-"); 131 | } 132 | System.out.println(""); 133 | 134 | System.out.println(Arrays.binarySearch(numbers, 4)); 135 | System.out.println(Arrays.binarySearch(numbers, 3)); 136 | System.out.println(Arrays.binarySearch(numbers, 5)); 137 | System.out.println(Arrays.binarySearch(numbers, 7)); // -4: 1-4-6- *7* -9 138 | System.out.println(Arrays.binarySearch(numbers, 8)); // -4: 1-4-6- *8* -9 139 | ``` 140 | 141 | --- 142 | 143 | ## Wrapper Classes 144 | 145 | boolean Boolean 146 | byte Byte 147 | char Character 148 | double Double 149 | float Float 150 | int Integer 151 | long Long 152 | short Short 153 | 154 | --- 155 | 156 | ## Diamond notation 157 | 158 | ```java 159 | List stringList = new ArrayList<>(); 160 | ``` 161 | 162 | --- -------------------------------------------------------------------------------- /3.2 - generics.md: -------------------------------------------------------------------------------- 1 | theme: Plain Jane 2 | autoscale: true 3 | 4 | # Generics 5 | 6 | --- 7 | 8 | ## Problem they solve 9 | 10 | - same operations with different data types 11 | 12 | ```java 13 | interface Stackable { 14 | void push(String element); 15 | String pop(); 16 | String peek(); 17 | int size(); 18 | } 19 | ``` 20 | 21 | --- 22 | 23 | ```java 24 | class Stack implements Stackable { 25 | private List stack = new ArrayList<>(); 26 | 27 | @Override public void push(String element) { 28 | stack.add(element); 29 | } 30 | 31 | @Override public String pop() { 32 | if (stack.size() == 0) { 33 | return null; 34 | } 35 | 36 | String topElement = peek(); 37 | stack.remove(stack.size() - 1); 38 | 39 | return topElement; 40 | } 41 | 42 | @Override public String peek() { 43 | if (stack.size() == 0) { 44 | return null; 45 | } 46 | 47 | String topElement = stack.get(stack.size() - 1); 48 | 49 | return topElement; 50 | } 51 | 52 | @Override public int size() { 53 | return stack.size(); 54 | } 55 | } 56 | ``` 57 | --- 58 | 59 | ## Problem they solve: same operations with different data types 60 | 61 | - now we want a Stack of numbers, of People... 62 | 63 | ```java 64 | interface Stackable { 65 | void push(T element); 66 | T pop(); 67 | T peek(); 68 | int size(); 69 | } 70 | 71 | ``` 72 | 73 | --- 74 | 75 | 76 | ```java 77 | class Stack implements Stackable { 78 | private List stack = new ArrayList<>(); 79 | 80 | @Override public void push(T element) { 81 | stack.add(element); 82 | } 83 | 84 | @Override public T pop() { 85 | if (stack.size() == 0) { 86 | return null; 87 | } 88 | 89 | T topElement = peek(); 90 | stack.remove(stack.size() - 1); 91 | 92 | return topElement; 93 | } 94 | 95 | @Override public T peek() { 96 | if (stack.size() == 0) { return null; } 97 | 98 | T topElement = stack.get(stack.size() - 1); 99 | 100 | return topElement; 101 | } 102 | 103 | @Override public int size() { 104 | return stack.size(); 105 | } 106 | } 107 | ``` 108 | 109 | --- 110 | 111 | ## Naming conventions 112 | 113 | - T generic data type 114 | - S, U, V: more types 115 | - K: key 116 | - V: value 117 | - E: element 118 | - N: number 119 | 120 | --- 121 | 122 | ## Generic types / parametrized types 123 | 124 | - generic type (when defining the generic type) 125 | 126 | ```java 127 | interface Collection { 128 | public void add (E x); 129 | public Iterator iterator(); 130 | } 131 | ``` 132 | - parametrized type (when using the generic type) 133 | 134 | ```java 135 | Collection c = new LinkedList(); 136 | ``` 137 | 138 | --- 139 | 140 | ## Where can I apply generics? 141 | 142 | - All types, except enum types, anonymous inner classes and exception classes, can be generic 143 | 144 | ```java 145 | enum Months { // Compilation error: Enum may not have type parameters 146 | 147 | } 148 | 149 | ``` 150 | 151 | --- 152 | 153 | ## Mixing raw types with Generics 154 | 155 | ```java 156 | Stack numbers = new Stack<>(); 157 | numbers.push(10); // method has Integer in signature 158 | 159 | Stack numbers = new Stack(); 160 | numbers.push(10); // method has Object in signature, also warning 161 | ``` 162 | 163 | --- 164 | 165 | ## Raw type 166 | 167 | 168 | - we can use generics to explicitly state a "list of whatever" 169 | 170 | ```java 171 | List objects = new LinkedList<>(); 172 | 173 | objects.add("Hello"); 174 | objects.add(1); 175 | ``` 176 | 177 | --- 178 | 179 | ## Raw type warning 180 | 181 | - equivalent to `List objects = new LinkedList();` 182 | 183 | ```java 184 | List objects = new LinkedList<>(); 185 | 186 | objects.add("Hello"); 187 | objects.add(1); 188 | ``` 189 | 190 | - we get a warning 191 | 192 | ``` 193 | Information:java: Main.java uses unchecked or unsafe operations. 194 | Information:java: Recompile with -Xlint:unchecked for details. 195 | ``` 196 | 197 | --- 198 | 199 | ## Type erasure 200 | 201 | - Generics only for compile time 202 | - all types changed into `Object`, casts added by compiler 203 | - using Raw types: only using Object 204 | 205 | ```java 206 | // nice typed List 207 | List names = Arrays.asList("groucho", "harpo", "chicco"); 208 | 209 | for (String s: names) { 210 | System.out.println(s); 211 | } 212 | 213 | // after type erasure 214 | // converted into raw list 215 | 216 | List oNames = Arrays.asList("groucho", "harpo", "chicco"); 217 | 218 | for (Object o: oNames) { 219 | System.out.println((String)o); 220 | } 221 | ``` 222 | 223 | --- 224 | 225 | ## Type erasure 226 | 227 | ```java 228 | System.out.println("runtime type of ArrayList: "+new ArrayList().getClass()); 229 | System.out.println("runtime type of ArrayList : "+new ArrayList().getClass()); 230 | ``` 231 | 232 | prints: 233 | 234 | ``` 235 | runtime type of ArrayList: class java.util.ArrayList 236 | runtime type of ArrayList : class java.util.ArrayList 237 | ``` 238 | 239 | --- 240 | 241 | ## Type erasure consecuences 242 | 243 | - problem: we can't assign a `List` to a `List` 244 | - `Object` is a supertype of `String` -> `Object[]` supertype of `String[]` == covariant types 245 | - Parameterized types are not covariant 246 | - `List` NOT supertype of `List` 247 | 248 | ```java 249 | List names = Arrays.asList("groucho", "harpo", "chicco"); 250 | 251 | for (String s: names) { 252 | System.out.println(s); 253 | } 254 | 255 | List objects = names; // COMPILATION ERROR 256 | 257 | ``` 258 | 259 | 260 | --- 261 | 262 | - if we could assign it, once asigned we don't know what's inside 263 | 264 | ```java 265 | List names = Arrays.asList("groucho", "harpo", "chicco"); 266 | 267 | for (String s: names) { 268 | System.out.println(s); 269 | } 270 | 271 | List objects = names; // COMPILATION ERROR: to protect us 272 | 273 | objects.add("Hello"); // although we're treating objects as List it really is List 274 | objects.add(1); // BOOM 275 | 276 | ``` 277 | 278 | --- 279 | 280 | ## Type erasure consecuences 281 | 282 | - we can assign to a List 283 | - problem: we can't add anything to objects (inmutable list) 284 | 285 | ```java 286 | List names = Arrays.asList("groucho", "harpo", "chicco"); 287 | 288 | for (String s: names) { 289 | System.out.println(s); 290 | } 291 | 292 | List objects = names; 293 | 294 | for (Object s: objects) { 295 | System.out.println(s); 296 | } 297 | 298 | ``` 299 | 300 | --- 301 | 302 | ## Generic methods 303 | 304 | - we can use generic types in just one method (not in the whole class) 305 | - to limit the type to that method 306 | - no need to create an object of MyClass using <> 307 | 308 | ```java 309 | 310 | List ls = new ArrayList<>(); 311 | m(ls); // OK 312 | 313 | List ls2 = new ArrayList<>(); 314 | m(ls2); // NO OK: List is not a List 315 | 316 | class MyClass { 317 | static > void m(T a) { 318 | a.clear(); 319 | } 320 | } 321 | ``` 322 | 323 | --- 324 | 325 | ## Generic methods 326 | 327 | - what if we want to clear any list 328 | - and we're not interested in the type of the list's elements 329 | 330 | ```java 331 | static > void m(T a) { 332 | a.clear(); 333 | } 334 | ``` 335 | 336 | 337 | --- 338 | 339 | ## Type parameter bound 340 | 341 | - Type parameters can be declared with bounds 342 | - Bounds give access to methods of the unknown type 343 | - only `T extends Type` --> only upper bound 344 | - can't do `T super Type` 345 | 346 | ```java 347 | class OK { 348 | 349 | } 350 | 351 | class NO_OK { // this doesn't exists 352 | 353 | } 354 | ``` 355 | 356 | --- 357 | 358 | ## Type parameter bound 359 | 360 | 361 | - can't create new objects of the type parameter: I don't know if this constructor is even available 362 | 363 | ```java 364 | T t = new T(); // wrong: is this constructor visible? 365 | ``` 366 | 367 | --- 368 | 369 | ## Type parameter bound: multiple types 370 | 371 | ```java 372 | class A { // extends Class & Interface & Interface 373 | void m(T t) { 374 | t.run(); 375 | } 376 | } 377 | 378 | class B { // extends [Object] & Interface & Interface 379 | void m(T t) { 380 | t.clear(); 381 | } 382 | } 383 | ``` 384 | 385 | --- 386 | 387 | ## Type parameter bound 388 | 389 | - Every type variable declared as a type parameter has a bound. If no bound is declared for a type variable, `Object` is assumed 390 | 391 | ```java 392 | class OK { // T is Object 393 | 394 | } 395 | 396 | ``` 397 | 398 | --- 399 | 400 | ## Wildcards 401 | 402 | - unbounded wildcard: ? 403 | - unknown generic type 404 | - upper bound: ? extends Class 405 | - lower bound: ? super Class 406 | 407 | --- 408 | 409 | ## Wildcard: ? 410 | 411 | - problem: print all elements of a list, don't care about type 412 | 413 | ```java 414 | public static void main(String[] args) { 415 | List stringList = new ArrayList<>(); 416 | stringList.add("Hello"); 417 | 418 | debugPrintAnyList(stringList); 419 | 420 | List integerList = new ArrayList<>(); 421 | integerList.add(10); 422 | integerList.add(20); 423 | 424 | debugPrintAnyList(integerList); 425 | } 426 | 427 | public static void debugPrintAnyList(List list) { 428 | list.forEach(System.out::println); 429 | } 430 | 431 | ``` 432 | 433 | --- 434 | 435 | ## Example classes for wildcards: 436 | 437 | ```java 438 | /* 439 | ------------- 440 | | A | 441 | ------------- 442 | ^ 443 | | 444 | ------------- 445 | | B | 446 | ------------- 447 | ^ 448 | | 449 | ------------- 450 | | C | 451 | ------------- 452 | */ 453 | 454 | class A { 455 | } 456 | 457 | class B extends A { 458 | } 459 | 460 | class C extends B { 461 | } 462 | 463 | ``` 464 | 465 | --- 466 | 467 | ## Upper-bound wildcard: ? extends Class 468 | 469 | ```java 470 | public static void debugPrint(List list) { 471 | list.forEach(System.out::println); 472 | } 473 | 474 | List aList = new ArrayList<>(); // works: A extends A 475 | debugPrint(aList); 476 | 477 | List aList = new ArrayList<>(); // works: B extends A 478 | 479 | ``` 480 | 481 | --- 482 | 483 | ## Lower-bound: ? super Class 484 | 485 | ```java 486 | public static void debugPrint(List list) { 487 | list.forEach(System.out::println); 488 | } 489 | List aList = new ArrayList<>(); // works: A is a superclass of B 490 | debugPrint(aList); 491 | 492 | ``` 493 | 494 | --- 495 | 496 | ## Functional interfaces using generics 497 | 498 | ```java 499 | class Calculator { 500 | // can't create static variables as generic type parameters: the type is linked to the instance of the class 501 | N calculate(N n1, N n2, Operation op) { 502 | return op.operate(n1, n2); 503 | } 504 | } 505 | 506 | @FunctionalInterface 507 | interface Operation { 508 | N operate(N n1, N n2); 509 | } 510 | 511 | 512 | Calculator ci = new Calculator<>(); 513 | ci.calculate(1, 3, (n1, n2) -> n1 + n2); 514 | 515 | Calculator cf = new Calculator<>(); 516 | cf.calculate(1.4f, 4.3f, (n1, n2) -> n1 - n2); 517 | ``` 518 | 519 | 520 | --- 521 | 522 | 523 | ## References 524 | 525 | - Angelika Langer 526 | http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#FAQ203 -------------------------------------------------------------------------------- /4.1 - Functional Programming.md: -------------------------------------------------------------------------------- 1 | theme: Plain Jane 2 | autoscale: true 3 | 4 | # Functional Programming 5 | 6 | --- 7 | 8 | ## Built-in functional interfaces 9 | 10 | |Functional interface | Method | 11 | | --- | --- | 12 | | Supplier | T get(); | 13 | | Consumer | void accept(T t); | 14 | | BiConsumer | void accept(T t, U u); | 15 | | Predicate | boolean test(T t); | 16 | | BiPredicate | boolean test(T t, U u); | 17 | | Function | R apply(T t); | 18 | | BiFunction | R apply(T t, U u); | 19 | | UnaryOperator extends Function | T apply(T t); | 20 | | BinaryOperator extends BiFunction | T apply(T t, T u); | 21 | 22 | 23 | --- 24 | 25 | |Functional interface | Method | 26 | | --- | --- | 27 | | Supplier | T get(); | 28 | 29 | 30 | ```java 31 | interface Stackable { 32 | void push(T element); 33 | T pop(); 34 | T peek(); <-- Supplier! 35 | int size(); 36 | } 37 | 38 | class Stack implements Stackable { 39 | private List stack = new ArrayList<>(); 40 | 41 | // more code 42 | 43 | @Override 44 | public T peek() { 45 | if (stack.size() == 0) { 46 | return null; 47 | } 48 | 49 | T topElement = stack.get(stack.size() - 1); 50 | 51 | return topElement; 52 | } 53 | } 54 | ``` 55 | 56 | --- 57 | 58 | ## Suppliers examples 59 | 60 | - Supplier: a chunk of code that holds and return a T 61 | 62 | ```java 63 | Supplier s1 = () -> "hello"; 64 | Supplier s2 = String::new; 65 | 66 | System.out.println(s1.get()); 67 | System.out.println(s2.get()); 68 | ``` 69 | 70 | ```java 71 | class Stack implements Supplier { 72 | @Override 73 | public T get() { 74 | return null; 75 | } 76 | } 77 | ``` 78 | 79 | --- 80 | 81 | |Functional interface | Method | 82 | | --- | --- | 83 | | Consumer | void accept(T t); | 84 | 85 | ```java 86 | Consumer cs1 = System.out::print; 87 | Consumer ci1 = i -> {}; 88 | 89 | cs1.accept("Hello"); 90 | ci1.accept(10); 91 | ``` 92 | 93 | --- 94 | 95 | |Functional interface | Method | 96 | | --- | --- | 97 | | BiConsumer | void accept(T t, U u); | 98 | 99 | ```java 100 | HashMap map = new HashMap<>(); 101 | map.put(1, "Diego"); 102 | 103 | BiConsumer bc1 = (Integer i, String s) -> {}; 104 | BiConsumer bc2 = map::put; 105 | BiConsumer bc3 = map::replace; 106 | 107 | bc1.accept(2, "Hello"); 108 | bc2.accept(3, "World"); 109 | bc3.accept(3, "Nice!"); 110 | 111 | map.values().forEach(System.out::println); 112 | ``` 113 | 114 | prints: 115 | ``` 116 | Diego 117 | Nice! 118 | ``` 119 | 120 | --- 121 | 122 | |Functional interface | Method | 123 | | --- | --- | 124 | | Predicate | boolean test(T t); | 125 | 126 | - takes one value of type T, then test it -> Boolean 127 | 128 | ```java 129 | Predicate ps1 = String::isEmpty; 130 | Predicate ps2 = s -> s.contains("hello"); 131 | 132 | System.out.println(ps1.test("Diego") && ps2.test("Hello")); 133 | ``` 134 | 135 | --- 136 | 137 | ## Predicates rule 138 | 139 | - default implementations in `Predicate` 140 | 141 | ```java 142 | Person p1 = new Person("Diego", 10_000); 143 | Person p2 = new Person("Exploited Intern", 0); 144 | 145 | Predicate hasSalary = person -> person.getSalary() > 0; 146 | Predicate hasName = person -> !person.getName().isEmpty(); 147 | 148 | Predicate isValidEmployee = hasName.and(hasSalary); 149 | 150 | 151 | if (isValidEmployee.test(p1)) { 152 | 153 | } 154 | ``` 155 | 156 | 157 | --- 158 | 159 | |Functional interface | Method | 160 | | --- | --- | 161 | | BiPredicate | boolean test(T t, U u); | 162 | 163 | - is a test with two parameters 164 | 165 | ```java 166 | BiPredicate bp1 = (String s, Integer i) -> { return s.length() == i; }; 167 | bp1.test("Hello", 10); 168 | 169 | BiPredicate isEqual = (s, t) -> s.equals(t); 170 | System.out.println(isEqual.test("pepe", "Manolo")); 171 | ``` 172 | 173 | --- 174 | 175 | |Functional interface | Method | 176 | | --- | --- | 177 | | Function | R apply(T t); | 178 | 179 | ```java 180 | class Executor { 181 | public U execute(T value, Function function) { 182 | return function.apply(value); 183 | } 184 | } 185 | 186 | Executor lengthCounter = new Executor<>(); 187 | Integer result = lengthCounter.execute("Hello", s -> s.length()); 188 | System.out.println(result); 189 | 190 | ``` 191 | --- 192 | 193 | ```java 194 | result = lengthCounter.execute("Hello", new VowelCounter()::countVowels); 195 | System.out.println(result); 196 | 197 | result = lengthCounter.execute("Hello", VowelCounter::staticCountVowels); 198 | System.out.println(result); 199 | 200 | class VowelCounter { 201 | public Integer countVowels(String s) { 202 | int vowelCount = 0; 203 | for (int i = 0; i < s.length(); ++i) { 204 | switch(s.charAt(i)) { 205 | case 'a': 206 | case 'e': 207 | case 'i': 208 | case 'o': 209 | case 'u': 210 | vowelCount++; 211 | break; 212 | default: 213 | // do nothing 214 | } 215 | } 216 | return vowelCount; 217 | } 218 | 219 | public static Integer staticCountVowels(String s) { 220 | int vowelCount = 0; 221 | for (int i = 0; i < s.length(); ++i) { 222 | switch(s.charAt(i)) { 223 | case 'a': 224 | case 'e': 225 | case 'i': 226 | case 'o': 227 | case 'u': 228 | vowelCount++; 229 | break; 230 | default: 231 | // do nothing 232 | } 233 | } 234 | return vowelCount; 235 | } 236 | } 237 | 238 | ``` 239 | 240 | 241 | --- 242 | 243 | 244 | |Functional interface | Method | 245 | | --- | --- | 246 | | BiFunction | R apply(T t, U u); | 247 | 248 | - is a function, taking two parameters 249 | 250 | ```java 251 | // re-implementing a Predicate 252 | BiFunction isEqualBiFunction= (s, t) -> s.equals(t); 253 | System.out.println(isEqualBiFunction.apply("Hello", "Hello")); 254 | ``` 255 | 256 | --- 257 | 258 | |Functional interface | Method | 259 | | --- | --- | 260 | | UnaryOperator extends Function | T apply(T t); | 261 | 262 | ```java 263 | UnaryOperator inc = s -> s + UUID.randomUUID(); 264 | System.out.println(inc.apply("Hello-")); 265 | ``` 266 | 267 | --- 268 | 269 | |Functional interface | Method | 270 | | --- | --- | 271 | | BinaryOperator extends BiFunction | T apply(T t, T u); | 272 | 273 | ```java 274 | Calculator ci = new Calculator<>(); 275 | ci.calculate(1, 2, (n1, n2) -> n1 + n2); 276 | 277 | class Calculator { 278 | public T calculate(T n1, T n2, BinaryOperator operator) { 279 | return operator.apply(n1, n2); 280 | } 281 | } 282 | ``` 283 | 284 | --- 285 | 286 | ## Our own Functional interfaces: Tuples! 287 | 288 | ```java 289 | class Downloader { 290 | public Tuple download(String url) { 291 | Tuple t = new Tuple<>("Hello", new IllegalArgumentException()); 292 | return t; 293 | } 294 | } 295 | 296 | class Tuple implements Supplier> { 297 | 298 | private T t; 299 | private S s; 300 | 301 | public Tuple(T t, S s) { 302 | this.t = t; 303 | this.s = s; 304 | } 305 | 306 | @Override 307 | public Tuple get() { 308 | return this; 309 | } 310 | 311 | public T getFirstElement() { 312 | return t; 313 | } 314 | 315 | public S getSecondElement() { 316 | return s; 317 | } 318 | } 319 | ``` 320 | 321 | --- 322 | 323 | 324 | 325 | 326 | ## Optionals 327 | 328 | - represent the absence of some data 329 | - latitude: 0 is a valid value. When created we want to know if we have set it or not 330 | - in package `java.util.Optional` 331 | - would have been nice to have non-Optionals... 332 | 333 | --- 334 | 335 | ## Optionals: create 336 | 337 | - create an Optional __containing a value__ 338 | 339 | ```java 340 | Optional name = Optional.of("Diego"); 341 | 342 | System.out.println(name); // prints "Optional[Diego]" 343 | System.out.println(name.get()); // prints "Diego", using Consumer 344 | ``` 345 | 346 | - create an __Empty Optional__ 347 | 348 | ```java 349 | name = Optional.empty(); // represents "nothing" 350 | System.out.println(name); // prints "Optional.empty" 351 | ``` 352 | 353 | --- 354 | 355 | ## Optionals: create from possible null values 356 | 357 | ```java 358 | 359 | Optional nullString = Optional.of(null); 360 | 361 | System.out.println(nullString.isPresent()); // crash 362 | 363 | Optional nullString = Optional.ofNullable(null); 364 | 365 | System.out.println(nullString.isPresent()); // don't crash 366 | ``` 367 | 368 | --- 369 | 370 | ## Optionals: check if Empty 371 | 372 | ```java 373 | if (name.isPresent()) { 374 | System.out.println("Yes"); 375 | } else { 376 | System.out.println("No"); 377 | } 378 | ``` 379 | 380 | --- 381 | 382 | ## Optionals: get value 383 | 384 | - using `get` 385 | 386 | ```java 387 | Optional name = Optional.of("Diego"); 388 | 389 | System.out.println(name.get()); // prints "Diego", using Consumer FI 390 | ``` 391 | 392 | --- 393 | 394 | ## Optionals: get value 395 | 396 | - using `orElse` and `orElseGet` 397 | 398 | ```java 399 | System.out.println(name.orElse("Groucho")); 400 | System.out.println(name.orElseGet(() -> "nothing".toUpperCase())); // Supplier functional Interface 401 | System.out.println(name.orElseGet(() -> UUID.randomUUID().toString())); 402 | 403 | // name still not mutated 404 | System.out.println(name); // prints "Optional.empty" 405 | ``` 406 | 407 | --- 408 | 409 | ## Optionals: get value 410 | 411 | - throw Exception if Empty 412 | 413 | ```java 414 | name.orElseThrow(() -> new IllegalStateException("Empty name!")); 415 | ``` 416 | 417 | 418 | --- 419 | 420 | ## Optionals: example 421 | 422 | ```java 423 | @FunctionalInterface interface DownloadFinished { 424 | void execute(Optional json, Optional errorDescription); 425 | } 426 | 427 | interface DownloadManager { 428 | void downloadJson(DownloadFinished completionLambda); 429 | } 430 | 431 | class DownloadManagerImpl implements DownloadManager { 432 | public void downloadJson(DownloadFinished completionLambda) { 433 | try { 434 | Thread.sleep(3000); // fake download something from Internet 435 | } catch (InterruptedException e) { 436 | e.printStackTrace(); 437 | } 438 | 439 | completionLambda.execute(Optional.of("Json"), Optional.empty()); 440 | } 441 | } 442 | 443 | ``` 444 | 445 | --- 446 | 447 | ## Optionals: example 448 | 449 | ```java 450 | new DownloadManagerImpl().downloadJson((json, errorDescription) -> { 451 | String jsonResult = null; 452 | if (errorDescription.isPresent()) { 453 | 454 | } else { 455 | jsonResult = json.orElseGet(new FakeJson()::get); 456 | } 457 | 458 | System.out.println(jsonResult); 459 | }); 460 | 461 | // ... 462 | 463 | class FakeJson implements Supplier { 464 | @Override 465 | public String get() { 466 | return "{ name: Fake Json}"; 467 | } 468 | } 469 | ``` 470 | 471 | --- 472 | 473 | ## Using Optionals with Streams 474 | 475 | ```java 476 | Optional s = names.stream().reduce((s1, s2) -> { return s1+s2; }); 477 | 478 | if (s.isPresent()) { 479 | System.out.println(s.get()); 480 | } 481 | 482 | ``` 483 | 484 | --- 485 | 486 | ## Streams 487 | 488 | - "sequence" of elements 489 | - lazily created 490 | - can be finite (created from Array or List) or infinite (generated) 491 | 492 | --- 493 | 494 | 495 | ## Creating finite Streams 496 | 497 | ```java 498 | Stream ss = Stream.of("Hello", "World"); 499 | System.out.println(ss.count()); // terminal operation 500 | 501 | ss = Stream.of("Hello", "World"); 502 | System.out.println(ss.findFirst()); 503 | 504 | ss = Stream.of("Hello", "World"); 505 | System.out.println(ss.findFirst().isPresent()); 506 | 507 | ss = Stream.of("Hello", "World"); 508 | System.out.println(ss.findFirst().get()); // which Functional Interface? 509 | 510 | ``` 511 | 512 | --- 513 | 514 | ## Infinite Streams 515 | 516 | - we can't create infinite List 517 | - an infinite Stream never ends (need to interrupt the program) 518 | 519 | ```java 520 | Stream uuids = Stream.generate(() -> UUID.randomUUID().toString()); 521 | 522 | uuids.forEach(System.out::print); 523 | ``` 524 | 525 | --- 526 | 527 | ## Infinite Streams 528 | 529 | ```java 530 | Stream uuids = Stream.generate(() -> { 531 | try { 532 | Thread.sleep(1000); 533 | } catch (InterruptedException e) { 534 | e.printStackTrace(); 535 | } 536 | 537 | return UUID.randomUUID().toString(); 538 | }); 539 | 540 | uuids.forEach(System.out::println); 541 | 542 | 543 | ``` 544 | 545 | - to limit infinite Streams: http://stackoverflow.com/questions/20746429/limit-a-stream-by-a-predicate 546 | 547 | --- 548 | 549 | ## Streams 550 | 551 | ```java 552 | Stream f = people.stream().filter((Person p) -> {return p.isHappy() == true;}); 553 | f.forEach(p -> System.out.println(p.getName())); 554 | ``` 555 | 556 | --- 557 | 558 | ## Operations: Terminal & Intermediate 559 | 560 | - Terminal 561 | - allMatch() / anyMatch() / noneMatch() 562 | - collect() 563 | - count() 564 | - findAny() / findFirst() 565 | - forEach() 566 | - min() / max() 567 | - reduce() 568 | 569 | --- 570 | 571 | ## Count 572 | 573 | ```java 574 | Stream apple = Stream.of(new Person("Diego", 40), new Person("Tim", 55)); 575 | System.out.println(apple.count()); 576 | 577 | // ... 578 | 579 | class Person { 580 | private final String name; 581 | private final int age; 582 | 583 | public Person(String name, int age) { 584 | this.name = name; 585 | this.age = age; 586 | } 587 | } 588 | 589 | ``` 590 | 591 | --- 592 | 593 | ## Min & Max 594 | 595 | - takes a comparator 596 | - Min & Max == reduce (only return one value) 597 | 598 | ```java 599 | Stream apple = Stream.of(new Person("Diego", 40), new Person("Tim", 55), new Person("Becario", 25)); 600 | 601 | apple.min((o1, o2) -> o1.getAge()-o2.getAge()).ifPresent(person -> { 602 | System.out.println(person.getName()); 603 | }); 604 | 605 | ``` 606 | 607 | --- 608 | 609 | ## FindAny / FindFirst 610 | 611 | - terminal operations, but not reductions 612 | - do not produce a value after looking at the whole Stream 613 | 614 | ```java 615 | Stream apple = Stream.of(new Person("Diego", 40), new Person("Tim", 55), new Person("Becario", 25)); 616 | 617 | apple.findAny().ifPresent(person -> System.out.println(person.getName())); 618 | ``` 619 | 620 | 621 | --- 622 | 623 | ## AllMatch / AnyMatch 624 | 625 | ```java 626 | // all people > 18? 627 | System.out.println(apple.allMatch(person -> person.getAge() > 18)); // true 628 | 629 | // any person > 50? 630 | System.out.println(apple.anyMatch(person -> person.getAge() > 50)); // true 631 | 632 | // none person older than 50? 633 | System.out.println(apple.noneMatch(person -> person.getAge() > 50)); 634 | 635 | // cleaner & reusable 636 | 637 | Predicate olderThat50 = p -> p.getAge() > 50; 638 | System.out.println(apple.noneMatch(olderThat50)); 639 | 640 | ``` 641 | 642 | --- 643 | 644 | ## ForEach 645 | 646 | 647 | --- 648 | 649 | ## Reduce 650 | 651 | T reduce(T identity, BinaryOperator accumulator); 652 | 653 | 654 | ```java 655 | Stream tokens = Stream.of("Hello", "World!", "tokens"); 656 | System.out.println(tokens.reduce("", (s, s2) -> s.concat(s2))); 657 | 658 | // can omit initial value & use method reference 659 | System.out.println(tokens.reduce(String::concat)); 660 | ``` 661 | 662 | --- 663 | 664 | ## Collect 665 | 666 | - mutable reduction: same object reused to do the reduction 667 | - 1st parameter: (supplier) the mutable object we're to use (we build it here with a `Supplier`) 668 | - 2nd parameter: (accumulator) how we reduce two elements in the list 669 | - 3rd parameter: (combiner) if we run this in parallel, and have 2 data collections, how we merge them 670 | 671 | ```java 672 | StringBuilder result = tokens.collect(StringBuilder::new, StringBuilder::append, StringBuilder::append); 673 | System.out.println(result); 674 | 675 | // other way 676 | StringBuilder result = tokens.collect(StringBuilder::new, (s, t) -> s.append(t), StringBuilder::append); 677 | System.out.println(result); 678 | 679 | ``` 680 | 681 | --- 682 | 683 | ## Collect explained 684 | 685 | ```java 686 | StringBuilder result = tokens.collect(() -> 687 | { return new StringBuilder(); }, // supplier () -> StringBuilder 688 | (StringBuilder sb, String ss) -> sb.append(ss), // accumulator (StringBuilder, String) -> StringBuilder 689 | (StringBuilder s, StringBuilder t) -> s.append(t.reverse()) // StringBuilder, StringBuilder 690 | ); 691 | System.out.println(result); 692 | ``` 693 | 694 | --- 695 | 696 | ## Intermediate operations 697 | 698 | - filter 699 | - distinct 700 | - limit / skip 701 | - map 702 | 703 | --- 704 | 705 | ## Filter 706 | 707 | - filter elements that return true for the Predicate 708 | 709 | ```java 710 | Stream numbers = Stream.of(10, 20, 30, 40); 711 | numbers.filter(n -> n > 20).forEach(System.out::print); 712 | 713 | Stream apple = Stream.of(new Person("Diego", 40), new Person("Tim", 55), new Person("Becario", 25), new Person("", 80)); 714 | apple.filter(person -> person.getName().isEmpty()).forEach(person -> System.out.println(person.getAge())); // prints 80 715 | 716 | ``` 717 | 718 | --- 719 | 720 | ## Distinct 721 | 722 | - calls `equals` 723 | 724 | ```java 725 | Stream apple = Stream.of(new Person("Diego", 40), new Person("Tim", 55), new Person("Tim", 55), new Person("", 80)); 726 | apple.filter(person -> !person.getName().isEmpty()).distinct().forEach(person -> System.out.println(person.getAge())); 727 | // not working as expected if we don't override equals 728 | 729 | ``` 730 | 731 | --- 732 | 733 | ## limt & skip 734 | 735 | ```java 736 | Stream iterate = Stream.iterate(1, n -> n + 2); 737 | iterate.limit(100).forEach(System.out::println); 738 | 739 | Stream iterate = Stream.iterate(1, n -> n + 2); 740 | iterate.limit(100).skip(10).forEach(System.out::println); 741 | ``` 742 | 743 | 744 | --- 745 | 746 | 747 | ## map 748 | 749 | ```java 750 | List names = Arrays.asList("Grouch", "Chicc", "Harp"); 751 | 752 | // forEach to print 753 | names.stream().forEach(e -> System.out.println(e )); 754 | 755 | names.stream().map((e) -> e + "o").forEach(e -> System.out.printf(e + "\n")); 756 | names.stream().map((e) -> e.toUpperCase()).forEach(e -> System.out.printf(e + "\n")); 757 | 758 | ``` 759 | 760 | 761 | --- 762 | 763 | ## flatmap 764 | 765 | ```java 766 | List lotr = new ArrayList<>(); 767 | lotr.add("Aragorn"); 768 | lotr.add("Bilbo"); 769 | lotr.add("Gollum"); 770 | 771 | List matrix = new ArrayList<>(); 772 | matrix.add("Neo"); 773 | matrix.add("Trinity"); 774 | 775 | Stream> films = Stream.of(lotr, matrix); 776 | //films.forEach(System.out::println); 777 | 778 | films.flatMap(l -> l.stream()).forEach(s -> System.out.print(s.toUpperCase())); 779 | 780 | ``` 781 | 782 | --- 783 | 784 | ## sorted 785 | 786 | ```java 787 | Stream numbers = Stream.of(3, 20, -1, 40); 788 | 789 | numbers.sorted().forEach(System.out::println); 790 | ``` 791 | 792 | --- 793 | 794 | ## peek 795 | 796 | ```java 797 | 798 | Stream iterate = Stream.iterate(1, n -> n + 1); 799 | iterate.limit(100).skip(10).peek(System.out::print).forEach(i -> System.out.print(" " + i + " ")); 800 | ``` 801 | 802 | --- 803 | 804 | ## Primitive Streams 805 | 806 | - IntStream 807 | - LongStream 808 | - DoubleStream 809 | 810 | ```java 811 | IntStream is = IntStream.of(1, 2, 3, 4); 812 | System.out.println(is.average()); 813 | ``` 814 | 815 | --- 816 | 817 | ## Creating primitive Streams 818 | 819 | ```java 820 | LongStream ls = LongStream.empty(); 821 | 822 | DoubleStream randomStream = DoubleStream.generate(Math::random).limit(30); 823 | randomStream.forEach(System.out::println); 824 | ``` 825 | 826 | --- 827 | 828 | ## Ranges 829 | 830 | ```java 831 | LongStream ls = LongStream.range(1, 10); // 1...10, 1..<9 832 | ls.forEach(System.out::println); 833 | 834 | LongStream ls = LongStream.rangeClosed(1, 10); // 1...11, 1..<10 835 | ls.forEach(System.out::println); 836 | ``` 837 | 838 | --- 839 | 840 | ## Summary statistics 841 | 842 | ```java 843 | IntStream is = IntStream.of(1, 2, 3, 4); 844 | is.summaryStatistics().getMax(); 845 | ``` -------------------------------------------------------------------------------- /5.1 Date and time.md: -------------------------------------------------------------------------------- 1 | theme: Plain Jane 2 | autoscale: true 3 | 4 | # Dates and Times in Java 8 5 | 6 | --- 7 | 8 | - `LocalDate.now()`: date 9 | - `LocalTime.now()`: time 10 | - `LocalDateTime.now()`: date +time 11 | - `ZonedDateTime.now()`: date + time + time zone 12 | 13 | --- 14 | 15 | ## Current Date 16 | 17 | 18 | ```java 19 | 20 | LocalDate now = LocalDate.now(); 21 | System.out.println(now); 22 | 23 | // 2015-11-08 24 | 25 | ``` 26 | 27 | - LocalDate: only date (not time) 28 | - can't do `new LocalDate();` 29 | - `import java.time.LocalDate;` 30 | 31 | 32 | --- 33 | 34 | ## Date with year, month, day 35 | 36 | ```java 37 | 38 | LocalDate firstOfJanuary2015 = LocalDate.of(2015, Month.JANUARY, 1); 39 | System.out.println(firstOfJanuary2015); 40 | ``` 41 | 42 | --- 43 | 44 | ## LocalDate inmutable! 45 | 46 | ```java 47 | LocalDate _12Oct1492_ = LocalDate.of(1492, Month.OCTOBER, 12); 48 | _12Oct1492_.plusDays(800); 49 | System.out.println(_12Oct1492_); // 1492-10-12 50 | LocalDate other = _12Oct1492_.plusDays(800); 51 | System.out.println(other); // 1494-12-21 52 | ``` 53 | 54 | --- 55 | 56 | ## LocalTime 57 | 58 | ```java 59 | LocalTime timeNow = LocalTime.now(); 60 | System.out.println(timeNow); // 13:51:53.382 61 | 62 | System.out.println(LocalTime.of(10, 10, 10)); // 10:10:10 63 | ``` 64 | 65 | - LocalTime: sólo tiempo 66 | - `LocalDateTime`: fecha y hora 67 | 68 | --- 69 | 70 | 71 | ## LocalTime inmutable! 72 | 73 | ```java 74 | LocalTime timeNow = LocalTime.now(); 75 | System.out.println(timeNow); 76 | 77 | timeNow.plusHours(1); 78 | System.out.println(timeNow); 79 | 80 | // 19:57:24.995 81 | // 19:57:24.995 82 | 83 | ``` 84 | 85 | - plusMinutes / minusMinutes 86 | - plusSeconds / minus 87 | 88 | --- 89 | 90 | ## Intervals 91 | 92 | ```java 93 | LocalDate start = LocalDate.of(2015, Month.APRIL, 10); 94 | LocalDate end = LocalDate.of(2015, Month.APRIL, 20); 95 | while (start.isBefore(end)) { 96 | System.out.println(start); 97 | start = start.plusDays(1); 98 | } 99 | 100 | 2015-04-10 101 | 2015-04-11 102 | 2015-04-12 103 | 2015-04-13 104 | 2015-04-14 105 | 2015-04-15 106 | 2015-04-16 107 | 2015-04-17 108 | 2015-04-18 109 | 2015-04-19 110 | 111 | ``` 112 | 113 | --- 114 | 115 | ## Periods 116 | 117 | - Create task every week 118 | 119 | ```java 120 | 121 | Period everyWeek = Period.ofWeeks(1); 122 | start = LocalDate.now(); 123 | end = LocalDate.of(2016, Month.APRIL, 10); 124 | while (start.isBefore(end)) { 125 | System.out.println(start); 126 | start = start.plus(everyWeek); 127 | } 128 | 129 | ``` 130 | --- 131 | 132 | ## Periods 133 | 134 | Period.of(year, month, days) 135 | 136 | ```java 137 | System.out.println(Period.of(3, 2, 1)); 138 | // P3Y2M1D 139 | // P 3Y 2M 1D 140 | ``` 141 | 142 | --- 143 | 144 | ## Duration 145 | 146 | - like Periods, but for days, hours, minutes, seconds, milliseconds, nanoseconds 147 | 148 | Duration.ofDays() 149 | 150 | --- 151 | 152 | ## Parse dates 153 | 154 | ```java 155 | 156 | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd"); 157 | LocalDate date = LocalDate.parse("2010/10/40", formatter); 158 | System.out.println(date); 159 | 160 | ``` 161 | - can throw `java.time.format.DateTimeParseException` (Runtime) 162 | 163 | 164 | --- 165 | 166 | ## TimeZones 167 | 168 | ```java 169 | System.out.println(LocalTime.now()); 170 | System.out.println(LocalTime.now(ZoneId.of("US/Pacific"))); 171 | System.out.println(LocalTime.now(ZoneId.of("Zulu"))); 172 | System.out.println(LocalTime.now(ZoneId.of("UTC"))); 173 | // console output 174 | 175 | 20:05:25.170 176 | 11:05:25.172 177 | 19:05:25.173 178 | 19:05:25.173 179 | ``` 180 | 181 | --- 182 | 183 | ## UTC 184 | 185 | The official abbreviation for Coordinated Universal Time is UTC. It came about as a compromise between English and French speakers. 186 | - Coordinated Universal Time in English would normally be abbreviated CUT. 187 | - Temps Universel Coordonné in French would normally be abbreviated TUC. 188 | 189 | --- 190 | 191 | ## GMT & UTC 192 | 193 | Negative <-- GMT 0 == UTC 0 --> Positive 194 | 195 | 196 | ```java 197 | LocalDateTime localDateTime = LocalDateTime.now(); 198 | System.out.println(localDateTime); 199 | 200 | ZonedDateTime zonedDateTimeUSPacific = ZonedDateTime.now(ZoneId.of("US/Pacific")); 201 | System.out.println(zonedDateTimeUSPacific); 202 | 203 | ZonedDateTime zonedDateTimeMadrid = ZonedDateTime.now(ZoneId.of("Europe/Madrid")); 204 | System.out.println(zonedDateTimeMadrid); 205 | ``` 206 | 207 | --- 208 | 209 | ## Print all timezones 210 | 211 | ```java 212 | ZoneId.getAvailableZoneIds().stream().sorted().forEach(System.out::println); 213 | ``` 214 | 215 | --- 216 | 217 | ## Daylight saving time 218 | 219 | - last Sunday of March, we move from 1:59 AM -> 3:00 AM 220 | 221 | ```java 222 | LocalDate change2018 = LocalDate.of(2018, Month.MARCH, 25); 223 | LocalTime changeTime = LocalTime.of(1, 30); 224 | ZoneId zone = ZoneId.of("Europe/Madrid"); 225 | 226 | ZonedDateTime time = ZonedDateTime.of(change2018, changeTime, zone); 227 | 228 | System.out.println(time); // 2018-03-25T01:30+01:00[Europe/Madrid] 229 | System.out.println(time.plusHours(1)); // 2018-03-25T03:30+02:00[Europe/Madrid] 230 | // we add 1 h, but went from 01:30 --> 03:30! 231 | ``` 232 | 233 | --- 234 | 235 | ## Localisation -------------------------------------------------------------------------------- /6 - Exception and Assertions.md: -------------------------------------------------------------------------------- 1 | theme: Simple 2 | autoscale: true 3 | 4 | 5 | # Exceptions 6 | 7 | ``` 8 | Object 9 | | 10 | Throwable 11 | |----------------| 12 | | | 13 | Exception Error 14 | | 15 | RuntimeException 16 | ``` 17 | 18 | --- 19 | 20 | ## Checked vs Unchecked 21 | 22 | - all exceptions occur at runtime 23 | - checked: handle or declare: compiler forces us 24 | - unchecked or _runtime_: we don't need to handle or declare 25 | - because they're too common: NullPointerException, ArrayIndexOutOfBoundsException, etc. 26 | 27 | --- 28 | 29 | ## Should I "catch" Errors? 🤔 30 | 31 | - never, ever 32 | - never 33 | - really 34 | - don't do it 35 | - ever 36 | - I'm serious 37 | - don't 38 | 39 | 40 | --- 41 | 42 | ## Exception on OCP 43 | 44 | - study! (page 288) 45 | 46 | --- 47 | 48 | ## Try-catch-finally 49 | 50 | ```java 51 | 52 | try { 53 | // do something that can throw 54 | } catch (Exception e) { 55 | // do something if this exception is injected 56 | } finally { 57 | // do this always 58 | } 59 | 60 | ``` 61 | 62 | --- 63 | 64 | ## Try-catch gotchas 65 | 66 | * Error! Needs a block 67 | 68 | ```java 69 | try 70 | int i = 0; 71 | catch (Exception e) ; 72 | ``` 73 | 74 | --- 75 | 76 | ## Try-catch gotchas 77 | 78 | * Error! Try need a catch / finally 79 | 80 | ```java 81 | try { 82 | System.out.println("2"); 83 | } // error! 84 | ``` 85 | 86 | * This is fine 87 | 88 | ```java 89 | 90 | try { 91 | int i = 0; 92 | } catch (Exception e) { } 93 | ``` 94 | 95 | --- 96 | ## Try-catch gotchas 97 | 98 | Just __one__ try, please 99 | 100 | ```java 101 | 102 | try { 103 | 104 | } try { 105 | 106 | } catch (Exception e) {} 107 | ``` 108 | 109 | 110 | --- 111 | 112 | ## Try-catch gotchas 113 | 114 | ```java 115 | // we can have a try-catch with Throwable 116 | try { 117 | int i = 0; 118 | } catch (Throwable t) { 119 | // Pokémon catch: Gotta catch'em all! 120 | } 121 | 122 | try { 123 | int i = 0; 124 | } catch (Exception t) { 125 | // i++; Error: i - local to try block 126 | } 127 | 128 | ``` 129 | 130 | --- 131 | 132 | ## Try-catch gotchas 133 | 134 | 135 | ```java 136 | // can have more than one catch 137 | try { 138 | int i = 0; 139 | } catch (Exception e) { 140 | 141 | } catch (Throwable t) { 142 | 143 | } 144 | 145 | try { 146 | int i = 0; 147 | } catch (Throwable t) { 148 | 149 | } catch (Exception e) { // error: Exception has already been caught 150 | 151 | } 152 | ``` 153 | 154 | --- 155 | 156 | ## Finally always gets called 157 | 158 | ```java 159 | static void print(String s) { 160 | try { 161 | System.out.println("2"); 162 | if (s == null) return; 163 | } finally { 164 | System.out.println("3"); 165 | } 166 | System.out.println("1"); 167 | 168 | System.out.println("2"); 169 | } 170 | ``` 171 | 172 | --- 173 | 174 | ## Creating your own exceptions 175 | 176 | 177 | ```java 178 | // Runtime, non-checked Exception 179 | class NonCheckedException extends RuntimeException { 180 | public NonCheckedException() { // typical constructors 181 | } 182 | 183 | public NonCheckedException(String message) { 184 | super(message); 185 | } 186 | 187 | public NonCheckedException(Exception cause) { 188 | super(cause); 189 | } 190 | } 191 | 192 | // Compile-time, checked exception, handle or declare rule 193 | class CheckedException extends Exception { 194 | 195 | } 196 | 197 | ``` 198 | 199 | --- 200 | 201 | ## Catch-Or-Declare rule (Checked exceptions) 202 | 203 | ```java 204 | public class Main { 205 | public static void main(String[] args) { 206 | throwsNonChecked(); // no problem with non-checked 207 | try { 208 | throwsChecked(); 209 | } catch (CheckedException e) { 210 | e.printStackTrace(); 211 | } 212 | } 213 | 214 | static void throwsNonChecked() { 215 | throw new NonCheckedException(); 216 | } 217 | 218 | static void throwsChecked() throws CheckedException { 219 | throw new CheckedException(); 220 | } 221 | } 222 | 223 | ``` 224 | 225 | --- 226 | 227 | ## What does this prints? 😈 228 | 229 | ```java 230 | import java.io.IOException; 231 | 232 | public class Main { 233 | public static void main(String[] args) { 234 | try { 235 | System.out.println("DogeBegin"); 236 | new Main().saveToDisk(); 237 | } catch (IOException e) { 238 | System.out.println(e.getMessage()); 239 | } finally { 240 | System.out.println("DogeFinally"); 241 | } 242 | } 243 | 244 | void saveToDisk() throws IOException{ 245 | throw new IOException("Such litte space. Much files. Wow"); 246 | } 247 | } 248 | ``` 249 | 250 | --- 251 | 252 | ## What does this prints? 253 | 254 | ``` 255 | DogeBegin 256 | Such litte space. Much files. Wow 257 | DogeFinally 258 | ``` 259 | 260 | --- 261 | ## What does this prints? 😈 262 | 263 | ```java 264 | import java.io.IOException; 265 | 266 | public class Main { 267 | public static void main(String[] args) { 268 | try { 269 | System.out.println("DogeBegin"); 270 | new Main().saveToDisk(); 271 | } catch (IOException e) { 272 | System.out.println("IODoge" + e.getMessage()); 273 | } catch (Exception e) { 274 | System.out.println("ExceptionDoge"+ e.getMessage()); 275 | } finally { 276 | System.out.println("DogeFinally"); 277 | } 278 | } 279 | 280 | void saveToDisk() throws IOException{ 281 | throw new IOException("Such litte space. Much files. Wow"); 282 | } 283 | } 284 | ``` 285 | 286 | --- 287 | 288 | ## What does this prints? 289 | 290 | ``` 291 | DogeBegin 292 | IODogeSuch litte space. Much files. Wow 293 | DogeFinally 294 | 295 | ``` 296 | 297 | 298 | --- 299 | 300 | 301 | ## What does this prints? 😈 302 | 303 | ```java 304 | import java.io.IOException; 305 | 306 | public class Main { 307 | public static void main(String[] args) { 308 | new Main().run(); 309 | } 310 | 311 | void run() { 312 | try { 313 | System.out.println("DogeBegin"); 314 | saveToDisk(); 315 | } catch (IOException e) { 316 | System.out.println("IODoge" + e.getMessage()); 317 | return; 318 | } finally { 319 | System.out.println("DogeFinally"); 320 | } 321 | System.out.println("DogeReturn"); 322 | } 323 | 324 | void saveToDisk() throws IOException{ 325 | throw new IOException("Such litte space. Much files. Wow"); 326 | } 327 | } 328 | ``` 329 | --- 330 | 331 | ## What does this prints? 332 | 333 | ``` 334 | 335 | DogeBegin 336 | IODogeSuch litte space. Much files. Wow 337 | DogeFinally 338 | ``` 339 | 340 | --- 341 | ## What does this prints? 😈 342 | 343 | ```java 344 | import java.io.IOException; 345 | 346 | public class Main { 347 | public static void main(String[] args) { 348 | new Main().run(); 349 | } 350 | 351 | void run() { 352 | try { 353 | System.out.println("DogeBegin"); 354 | saveToDisk(); 355 | } catch (IOException e) { 356 | System.out.println("IODoge" + e.getMessage()); 357 | return; 358 | } finally { 359 | System.out.println("DogeFinally"); 360 | } 361 | System.out.println("DogeReturn"); 362 | } 363 | 364 | void saveToDisk() throws IOException{ 365 | throw new RuntimeException("Such litte space. Much files. Wow"); 366 | } 367 | } 368 | 369 | ``` 370 | 371 | --- 372 | 373 | ``` 374 | Exception in thread "main" java.lang.RuntimeException: Such litte space. Much files. Wow 375 | DogeBegin 376 | at Main.saveToDisk(Main.java:22) 377 | DogeFinally 378 | at Main.run(Main.java:11) 379 | at Main.main(Main.java:5) 380 | at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 381 | at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 382 | at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 383 | at java.lang.reflect.Method.invoke(Method.java:497) 384 | at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134) 385 | ``` 386 | 387 | --- 388 | 389 | ## Multicatch 390 | 391 | ```java 392 | try { 393 | 394 | } catch (ArrayIndexOutOfBoundsException | ArithmeticException e) { 395 | // can't use parent & child here 396 | } finally { 397 | 398 | } 399 | 400 | try { 401 | 402 | } catch (Exception | ArithmeticException e) { // won't compile 403 | 404 | } finally { 405 | 406 | } 407 | 408 | ``` 409 | 410 | --- 411 | 412 | ## Multicatch is effectively final 413 | 414 | ```java 415 | try { 416 | 417 | } catch (ArithmeticException | ArrayIndexOutOfBoundsException e) { 418 | e = new ArithmeticException(); // error: e is final 419 | } 420 | ``` 421 | 422 | - but this compiles! 423 | 424 | ```java 425 | try { 426 | 427 | } catch (ArithmeticException e) { 428 | e = new ArithmeticException(); 429 | } finally { 430 | 431 | } 432 | ``` 433 | 434 | --- 435 | 436 | 437 | ## Remember we can catch something that can be thrown 438 | 439 | ```java 440 | static void print(String s) { 441 | try { 442 | thrower(); 443 | } catch (SQLException e) { 444 | 445 | } 446 | } 447 | 448 | static void thrower() throws ArrayIndexOutOfBoundsException { 449 | 450 | } 451 | ``` 452 | 453 | --- 454 | 455 | ## Try-with-resources 456 | 457 | - need that Connection and Statement implement AutoCloseable 458 | - AutoCloseable implemented by more that 150 classes! 459 | 460 | ```java 461 | try (Connection connection = DriverManager.getConnection(url); 462 | Statement statement = connection.createStatement()) { 463 | 464 | } 465 | ``` 466 | 467 | --- 468 | 469 | ## Try-with-resources 470 | 471 | - no need for that try 472 | - here's how this magic works 473 | 474 | ```java 475 | try (Connection connection = DriverManager.getConnection(url); 476 | Statement statement = connection.createStatement()) { 477 | 478 | } finally { 479 | statement.close(); // these are the 1st two lines in the finally block 480 | connection.close(); // like super / this in a constructor 481 | 482 | // can't use the statement here: closed! 483 | } 484 | ``` 485 | 486 | --- 487 | 488 | ## AutoCloseable 489 | 490 | ```java 491 | try(MyFile file = new MyFile()) { 492 | 493 | } 494 | // ... 495 | class MyFile implements AutoCloseable { 496 | public MyFile() { 497 | super(); 498 | 499 | System.out.println("Creating " + this); 500 | } 501 | 502 | @Override 503 | public void close() { 504 | System.out.println("Closing " + this); 505 | } 506 | } 507 | 508 | ``` 509 | 510 | --- 511 | 512 | ## Autocloseable is a functional interface... 513 | 514 | ```java 515 | try (AutoCloseable c = new AutoCloseable() { 516 | @Override 517 | public void close() { 518 | 519 | } 520 | }) { 521 | 522 | } catch (Exception e) { 523 | 524 | } 525 | ``` 526 | 527 | - as lambda 528 | 529 | ```java 530 | try (AutoCloseable c = () -> { 531 | 532 | }) { 533 | 534 | } catch (Exception e) { 535 | 536 | } 537 | 538 | ``` 539 | 540 | --- 541 | 542 | ## Assertions 543 | 544 | - conditions that can never happen while the program is running 545 | - they're absurd, but we want to catch them while developing 546 | - we need to enable assertions (-ea) Edit Configurations > VM Options 547 | 548 | --- 549 | 550 | ## Useful asserts 551 | 552 | - we're on the main thread, or in a background thread 553 | - check exhaustive switch (with assert that fails in default) 554 | - check an else is never met 555 | - check some object that shouldn't be null is never null... 556 | 557 | ```java 558 | // check we're running on Main Thread 559 | 560 | assert (Thread.currentThread().getName().equals("main")); 561 | ``` -------------------------------------------------------------------------------- /7.1 - Threads.md: -------------------------------------------------------------------------------- 1 | theme: Plain Jane 2 | autoscale: true 3 | 4 | # Threads 5 | 6 | 7 | --- 8 | 9 | ## Threads 10 | 11 | - _light processes_ 12 | - each Thread has its own PC & Stack 13 | - they share the heap 14 | - can access shared objects in memory 15 | - process: bunch of Threads 16 | - single-threaded process 17 | - multi-threaded process 18 | 19 | --- 20 | 21 | ## Concurrency vs Parallelism 22 | 23 | - Concurrency: executing multiple Threads & Processes 24 | - can be done with a single CPU & Scheduling (Round-Robin) 25 | - Parallelism: we have multiple CPUs to execute in parallel 26 | 27 | --- 28 | 29 | ## Thread scheduler 30 | 31 | - used by the OS to execute more threads than CPUs at the same time 32 | - Round-robin is not the only one 33 | - This makes Thread behave like they behave 34 | 35 | --- 36 | 37 | ## Types of Threads 38 | 39 | - System 40 | - User 41 | - Both can be marked as Daemon Threads 42 | - a program finishes when there's no non-daemon threads running 43 | 44 | --- 45 | 46 | ## Threads Subclassing Thread 47 | 48 | 49 | ```java 50 | public class HelloThread extends Thread { 51 | public void run() { 52 | System.out.println("Hello from a thread!"); 53 | } 54 | 55 | public static void main(String args[]) { 56 | (new HelloThread()).start(); 57 | } 58 | } 59 | 60 | ``` 61 | 62 | --- 63 | 64 | ## Threads Implementing Runnable 65 | 66 | 67 | ```java 68 | public class HelloRunnable implements Runnable { 69 | public void run() { 70 | System.out.println("Hello from a thread!"); 71 | } 72 | 73 | public static void main(String args[]) { 74 | (new Thread(new HelloRunnable())).start(); 75 | } 76 | } 77 | 78 | ``` 79 | 80 | --- 81 | 82 | ## Pausing a Thread 83 | 84 | ```java 85 | Thread.sleep(4000); 86 | 87 | throws InterruptedException 88 | ``` 89 | --- 90 | 91 | ## Good idiom (pre Java 8) 92 | 93 | 94 | ```java 95 | new Thread(new Runnable() { 96 | public void run() { 97 | yourNetworkStuff(); 98 | } 99 | }).start(); 100 | ``` 101 | 102 | --- 103 | ## Helpers 104 | 105 | ```java 106 | // ... 107 | 108 | public static void dp(String text) { // debug print 109 | System.out.println(text + " - " + Thread.currentThread().getName()); 110 | } 111 | 112 | public static void waitSeconds(long seconds) { 113 | try { 114 | Thread.sleep(seconds*1000); 115 | } catch (InterruptedException e) { 116 | e.printStackTrace(); 117 | } 118 | } 119 | 120 | ``` 121 | 122 | --- 123 | 124 | ## Waiting for results using Threads (polling) 125 | 126 | ```java 127 | static int counter = 0; 128 | static boolean finished; 129 | 130 | // ... 131 | 132 | new Thread(() -> { 133 | for (int i=0; i< 100; i++) { 134 | counter++; 135 | } 136 | }).start(); 137 | 138 | System.out.println(counter); // don't wait for thread to finish! 139 | 140 | ``` 141 | 142 | --- 143 | 144 | ## Waiting for results using Threads (polling) 145 | 146 | ```java 147 | public class Main { 148 | static int counter = 0; 149 | static boolean finished; 150 | 151 | public static void main(String[] args) throws InterruptedException { 152 | new Thread(() -> { 153 | for (int i=0; i< 100; i++) { 154 | counter++; 155 | } 156 | finished = true; 157 | }).start(); 158 | 159 | while (!finished) { 160 | System.out.println("Still not finished"); 161 | Thread.sleep(1000); 162 | } 163 | System.out.println(counter); 164 | } 165 | } 166 | 167 | ``` 168 | 169 | --- 170 | 171 | ## Try / Finally and Threads 172 | 173 | ```java 174 | System.out.println("Starting main"); 175 | 176 | try { 177 | Thread t = new Thread(() -> { 178 | System.out.println("Starting thread"); 179 | System.out.println("Hibernate thread"); 180 | 181 | try { 182 | Thread.sleep(1000); 183 | } catch (InterruptedException e) { 184 | e.printStackTrace(); 185 | } 186 | 187 | System.out.println("Ending Thread"); 188 | }); 189 | t.start(); 190 | // t.join(); 191 | } catch (InterruptedException e) { 192 | e.printStackTrace(); 193 | } finally { 194 | System.out.println("Finally finished"); // will always get executed 195 | // maybe before the thread finishes 196 | } 197 | 198 | System.out.println("Finishing main"); 199 | 200 | ``` 201 | 202 | --- 203 | 204 | ## Exam watch 205 | 206 | - no more focus on Threads 207 | - instead, focus on __Concurrency__ API 208 | 209 | 210 | 211 | 212 | --- 213 | 214 | ## ExecutorService 215 | 216 | - in package `java.util.concurrent` 217 | - interface 218 | 219 | --- 220 | 221 | ## Single Thread Executor 222 | 223 | - it's a serial queue of _tasks_ 224 | - we can add tasks to that queue 225 | - all tasks run in order, but in a background thread 226 | - there's only ONE background thead created 227 | - all tasks are in a queue 228 | 229 | ```java 230 | ExecutorService service = Executors.newSingleThreadExecutor(); 231 | 232 | System.out.println("Main: start " + Thread.currentThread().getName()); 233 | 234 | service.execute(() -> { 235 | dp("Hello"); 236 | }); 237 | 238 | service.execute(()->{ 239 | dp("Bye"); 240 | }); 241 | 242 | dp("Main: stop"); 243 | 244 | service.shutdown(); 245 | ``` 246 | 247 | --- 248 | 249 | ## Shutting down Single Thread Executor 250 | 251 | - need to finish it 252 | - if not, creates a non-daemon thread that executes all Runnables in turn 253 | - this non-daemon thread inhibits us from finishing 254 | - shutdown does not cancel already running threads 255 | 256 | --- 257 | 258 | ## Shutting down Single Thread Executor 259 | 260 | - methods: 261 | - `isShutdown` 262 | - `isTerminated` 263 | 264 | | | Active | Shutting Down | Shutdown | 265 | | --- | --- | --- | --- | 266 | | isShutdown | false | true | true | 267 | | isTerminated | false | false | true | 268 | 269 | --- 270 | 271 | ## We can create more than one ExecutorService 272 | 273 | ```java 274 | ExecutorService service = Executors.newSingleThreadExecutor(); 275 | ExecutorService service2 = Executors.newSingleThreadExecutor(); 276 | 277 | service.execute(() -> { 278 | dp("Hello"); 279 | }); 280 | 281 | service2.execute(() -> { 282 | dp("Hello service 2"); 283 | }); 284 | 285 | service2.execute(() -> { 286 | dp("Bye Service 2"); 287 | }); 288 | 289 | service.execute(()->{ 290 | dp("Bye"); 291 | }); 292 | ``` 293 | 294 | --- 295 | 296 | ## Submit tasks to an Executor 297 | 298 | - execute: async 299 | - submit: async 300 | - invokeAll: sync 301 | - invokeAny: sync 302 | 303 | --- 304 | 305 | ## Submit vs Execute 306 | 307 | - Submit: takes a `Runnable` or `Callable`, returns a `Future` 308 | 309 | ```java 310 | Future submit(Runnable task); 311 | Future submit(Callable task); 312 | ``` 313 | - Execute: takes a `Runnable`, returns nothing, 314 | 315 | ```java 316 | void execute(Runnable command); 317 | ``` 318 | --- 319 | 320 | ## Future example 321 | 322 | ```java 323 | static Optional response = Optional.empty(); 324 | // ... 325 | 326 | Future result = service.submit(() -> { 327 | String sURL = "http://freegeoip.net/json/"; //just a string 328 | 329 | // Connect to the URL using java's native library 330 | 331 | try { 332 | URL url = new URL(sURL); 333 | HttpURLConnection request = (HttpURLConnection) url.openConnection(); 334 | request.connect(); 335 | response = Optional.ofNullable(convertStreamToString((InputStream) request.getContent())); 336 | 337 | } catch (IOException e) { 338 | e.printStackTrace(); 339 | } 340 | }); 341 | 342 | try { 343 | result.get(10, TimeUnit.HOURS); // waits for 10 hours 344 | System.out.println(response.orElse("Noooo")); 345 | } catch (InterruptedException | ExecutionException | TimeoutException e) { 346 | e.printStackTrace(); 347 | } 348 | ``` 349 | 350 | --- 351 | 352 | ## Future Methods 353 | 354 | - isDone() 355 | - isCancelled() 356 | - cancel() 357 | - get(): waits endlessly 358 | - get (long timeout, TimeUnit unit): waits some time 359 | 360 | ``` 361 | 362 | TimeUnit.NANOSECONDS 363 | TimeUnit.MICROSECONDS 364 | ... 365 | TimeUnit.MINUTES 366 | TimeUnit.HOURS 367 | ... 368 | 369 | ``` 370 | 371 | --- 372 | 373 | ## Callable 374 | 375 | - Callable can return a value 376 | - often, `V`is a `Future` 377 | - can throw cheked exceptions 378 | 379 | ```java 380 | @FunctionalInterface public interface Callable { 381 | V call() throws Exception; 382 | } 383 | ``` 384 | 385 | --- 386 | 387 | ## Callable vs Runnable 388 | 389 | 390 | ```java 391 | @FunctionalInterface public interface Callable { 392 | V call() throws Exception; 393 | } 394 | ``` 395 | 396 | - runnable returns nothing 397 | - no exceptions can be thrown 398 | 399 | ```java 400 | @FunctionalInterface public interface Runnable { 401 | public abstract void run(); 402 | } 403 | ``` 404 | 405 | --- 406 | 407 | ## Waiting for all tasks to finish 408 | 409 | ```java 410 | ExecutorService service = null; 411 | try { 412 | service = Executors.newSingleThreadExecutor(); 413 | 414 | service.submit(() -> { 415 | for (int i = 0; i < 10; i++) { 416 | try { 417 | Thread.sleep(1000); 418 | } catch (InterruptedException e) { 419 | e.printStackTrace(); 420 | } 421 | dp("Hello " + i); 422 | } 423 | }); 424 | 425 | service.execute(() -> { 426 | dp("Bye"); 427 | }); 428 | 429 | System.out.println("All tasks added"); 430 | } finally { 431 | dp("Shutting down service"); 432 | if (service != null) { 433 | service.shutdown(); 434 | } 435 | } 436 | 437 | // can't add more here 438 | 439 | ``` 440 | 441 | --- 442 | 443 | ## If we add... 444 | 445 | ```java 446 | 447 | System.out.println("Can't add more tasks"); 448 | 449 | service.execute(() -> { // this crashes the main thread 450 | dp("Nope"); 451 | }); 452 | 453 | System.out.println("Terminated: " + service.isTerminated()); // don't get printed! 454 | 455 | ``` 456 | 457 | --- 458 | 459 | ## Awaiting termination 460 | 461 | ```java 462 | System.out.println("Terminated: " + service.isTerminated()); 463 | 464 | service.awaitTermination(15, TimeUnit.SECONDS); 465 | 466 | System.out.println("Terminated: " + service.isTerminated()); 467 | 468 | ``` 469 | 470 | --- 471 | 472 | ## Scheduling tasks 473 | 474 | - Schedule for start later 475 | 476 | ```java 477 | ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); 478 | 479 | dp("Let's start scheduler"); 480 | 481 | try { 482 | service.schedule(() -> { 483 | dp("Hello scheduled!"); 484 | }, 3, TimeUnit.SECONDS); 485 | } finally { 486 | dp("About to finish it!"); 487 | service.shutdown(); 488 | } 489 | ``` 490 | 491 | --- 492 | 493 | ## Scheduling & repeating tasks 494 | 495 | - scheduleAtFixedRate: after delay, executes, passed some time, executes (although previous could be running) 496 | - scheduleAtFixedDelay: after delay, executes until completion, then waits a fixed delay, then executes, ... 497 | 498 | --- 499 | 500 | ## Scheduling & repeating tasks 501 | 502 | ```java 503 | ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); 504 | 505 | dp("Let's start scheduler"); 506 | 507 | try { 508 | service.scheduleAtFixedRate(() -> { 509 | dp("Hello scheduled & repeating! " + counter++); // counter is static / instance var 510 | 511 | if (counter == 10) { 512 | service.shutdown(); 513 | } 514 | }, 2000, 300, TimeUnit.MILLISECONDS); 515 | dp("Try finished"); 516 | } 517 | 518 | ``` 519 | 520 | --- 521 | 522 | ## Thread-pool executor 523 | 524 | - Thead pool: pre-instantiated reusable threads 525 | - Single Thread executor: if running one task and another comes in, waits for completing first before launching second. Result: ordered execution of tasks in one executor 526 | - Pooled-thread executor: new Task gets in 527 | - if available Threads in the pool, run _immediately_ that task (_immediately_ depending of JVM Thread scheduler) 528 | - if not, waits in a queue until one the pool's thread finishes 529 | 530 | --- 531 | 532 | ## Fixed Thread Pool 533 | 534 | - pass in number of Threads to be created 535 | - threads are reused 536 | - if tasks > threads in pool --> tasks wait to enter in a queue 537 | 538 | ```java 539 | ExecutorService service = null; 540 | 541 | try { 542 | service = Executors.newFixedThreadPool(3); 543 | 544 | service.submit(() -> { waitSeconds(5); dp("Task 1"); }); 545 | 546 | service.submit(() -> { waitSeconds(2); dp("Task 2"); }); 547 | 548 | service.submit(() -> { waitSeconds(1); dp("Task 3"); }); 549 | 550 | for (int i = 0; i < 10 ; i++) { 551 | final int j = i; 552 | service.submit(() -> { 553 | dp("Task for: " + j); 554 | }); 555 | } 556 | } finally { 557 | service.shutdown(); 558 | } 559 | 560 | ``` 561 | 562 | --- 563 | 564 | ## Fixed Thread Pool: result 565 | 566 | ``` 567 | Task 3 - pool-1-thread-3 568 | Task for: 0 - pool-1-thread-3 <-- waiting to reuse 569 | Task for: 1 - pool-1-thread-3 <-- reusing thread 3 570 | Task for: 2 - pool-1-thread-3 571 | Task for: 3 - pool-1-thread-3 572 | Task for: 4 - pool-1-thread-3 573 | Task for: 5 - pool-1-thread-3 574 | Task for: 6 - pool-1-thread-3 575 | Task for: 7 - pool-1-thread-3 576 | Task for: 8 - pool-1-thread-3 577 | Task for: 9 - pool-1-thread-3 578 | Task 2 - pool-1-thread-2 579 | Task 1 - pool-1-thread-1 580 | 581 | ``` 582 | 583 | --- 584 | 585 | ## newCachedThreadPool 586 | 587 | ```java 588 | service = Executors.newCachedThreadPool(); 589 | ``` 590 | 591 | - creates as many threads as needed 592 | - if possible, reuse them 593 | 594 | ``` 595 | Task for: 0 - pool-1-thread-4 596 | Task for: 1 - pool-1-thread-5 597 | Task for: 2 - pool-1-thread-6 598 | Task for: 3 - pool-1-thread-7 599 | Task for: 4 - pool-1-thread-5 <-- reusing 600 | Task for: 5 - pool-1-thread-6 601 | Task for: 7 - pool-1-thread-7 602 | Task for: 8 - pool-1-thread-6 603 | Task for: 6 - pool-1-thread-5 604 | Task for: 9 - pool-1-thread-4 605 | Task 3 - pool-1-thread-3 606 | Task 2 - pool-1-thread-2 607 | Task 1 - pool-1-thread-1 608 | 609 | ``` 610 | 611 | --- 612 | 613 | ## Some Runtime goodies 614 | 615 | 616 | ```java 617 | Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println("Closing!"))); 618 | 619 | System.out.println(Runtime.getRuntime().availableProcessors()); 620 | ``` 621 | 622 | --- 623 | 624 | ## Synchronizing 625 | 626 | > Shared mutable state is the root of all evil 627 | 628 | - problem: race conditions and `++` operator not Thread Safe 629 | 630 | --- 631 | 632 | ```java 633 | public static int n = 0; 634 | 635 | public static void main(String[] args) { 636 | ExecutorService service = null; 637 | 638 | try { 639 | service = Executors.newCachedThreadPool(); 640 | 641 | service.submit(() -> { 642 | waitSeconds(5); dp("Task 1 " + n++); 643 | }); 644 | 645 | service.submit(() -> { waitSeconds(2); dp("Task 2 " + n++); }); 646 | 647 | service.submit(() -> { 648 | waitSeconds(1); 649 | 650 | n++; 651 | dp("Task 3 " + n); 652 | }); 653 | 654 | for (int i = 0; i < 10 ; i++) { 655 | final int j = i; 656 | service.submit(() -> { 657 | dp("Task for: " + j + " " + n++); 658 | }); 659 | } 660 | } finally { 661 | service.shutdown(); 662 | } 663 | } 664 | ``` 665 | 666 | --- 667 | 668 | ## Synchronize blocks 669 | 670 | - `syncronized(object)` creates a mutual-exclusion region 671 | - lock can be any instance object in Java 672 | 673 | --- 674 | 675 | ```java 676 | public static Integer n = new Integer(0); 677 | 678 | public static void main(String[] args) { 679 | ExecutorService service = null; 680 | 681 | try { 682 | service = Executors.newCachedThreadPool(); 683 | 684 | service.submit(() -> { 685 | synchronized (n) { 686 | waitSeconds(5); dp("Task 1 " + n++); 687 | } 688 | }); 689 | 690 | service.submit(() -> { waitSeconds(2); 691 | synchronized (n) { 692 | dp("Task 2 " + n++); 693 | } 694 | }); 695 | 696 | service.submit(() -> { 697 | waitSeconds(1); 698 | 699 | synchronized (n) { 700 | n++; 701 | dp("Task 3 " + n); 702 | } 703 | }); 704 | 705 | for (int i = 0; i < 10 ; i++) { 706 | final int j = i; 707 | service.submit(() -> { 708 | synchronized (n) { 709 | dp("Task for: " + j + " " + n++); 710 | } 711 | }); 712 | } 713 | } finally { 714 | service.shutdown(); 715 | } 716 | } 717 | 718 | ``` 719 | 720 | --- 721 | 722 | ## Synchronized 723 | 724 | - in methods: instance + static 725 | - in vars: only instance 726 | 727 | --- 728 | 729 | ## Atomic types 730 | 731 | - can`t use `synchronize` on static vars 732 | 733 | ```java 734 | public static AtomicInteger n = new AtomicInteger(0); 735 | 736 | public static void main(String[] args) { 737 | ExecutorService service = null; 738 | 739 | try { 740 | service = Executors.newCachedThreadPool(); 741 | 742 | service.submit(() -> { 743 | waitSeconds(5); 744 | dp("Task 1 " + n.incrementAndGet()); 745 | }); 746 | } 747 | } 748 | 749 | ``` 750 | 751 | --- 752 | 753 | ## Concurrent collections 754 | 755 | - modify the List/KeySet while iterating: crash 756 | 757 | ```java 758 | List names = new ArrayList<>(); 759 | names.add("Hello"); 760 | names.add("World"); 761 | names.add("World"); 762 | names.add("World"); 763 | names.add("World"); 764 | 765 | for (String s: names) { 766 | names.remove(s); // crash 767 | } 768 | 769 | Map data = new HashMap<>(); 770 | data.put("hello", 1); 771 | data.put("goodbye", 2); 772 | for (String key: data.keySet()) { 773 | data.remove(key); // crash 774 | } 775 | 776 | ``` 777 | 778 | --- 779 | 780 | ## Parallel Streams 781 | 782 | ```java 783 | Stream names = Stream.of("Gollum", "Frodo", "Bilbo", "Aragorn", "Gandalf"); 784 | names.forEach(System.out::println); 785 | 786 | Stream parallelNames = Stream.of("Gollum", "Frodo", "Bilbo", "Aragorn", "Gandalf"); 787 | parallelNames.parallel().forEach(System.out::println); 788 | ``` -------------------------------------------------------------------------------- /8 - IO.md: -------------------------------------------------------------------------------- 1 | theme: Simple 2 | autoscale: true 3 | 4 | 5 | # IO 6 | 7 | --- 8 | 9 | ## Review 10 | 11 | - __File__ 12 | - some data 13 | - can be empty 14 | - can't contain other files / dirs 15 | - __Directory__ 16 | - _file_ containing a list of files / dirs 17 | - can contain other files / dirs 18 | - can be empty 19 | 20 | --- 21 | 22 | ``` 23 | [dfreniche@Tesla log]$ tree /var/log 24 | . 25 | ├── Bluetooth 26 | ├── CDIS.custom 27 | ├── CoreDuet 28 | ├── DiagnosticMessages 29 | │   ├── 2017.04.19.asl 30 | │   └── StoreData 31 | ├── alf.log 32 | ├── apache2 33 | ├── appfirewall.log 34 | ├── asl 35 | │   ├── 2017.04.12.G80.asl 36 | │   ├── BB.2018.04.30.G80.asl 37 | │   ├── Logs 38 | │   │   ├── aslmanager.20170417T193440+02 39 | │   │   └── aslmanager.20170419T084317+02 40 | │   └── StoreData 41 | ├── com.apple.revisiond [error opening dir] 42 | ├── com.apple.xpc.launchd 43 | ├── corecaptured.log 44 | ├── cups 45 | │   ├── access_log 46 | │   ├── error_log 47 | │   └── page_log 48 | ├── daily.out 49 | ├── wifi.log.0.bz2 50 | └── wifi.log.1.bz2 51 | 52 | ``` 53 | 54 | --- 55 | 56 | ## File System: Paths 57 | 58 | - __relative__ 59 | 60 | `mydir`, `./thisDir`, `bin/bash` 61 | 62 | - __absolute__: start with the root directory 63 | 64 | `c:\\windows`, `/bin` 65 | 66 | --- 67 | 68 | ## File: `java.io.File` 69 | 70 | - reads information about existing files & directories 71 | - needed to create, delete, rename files, check directory contents... 72 | - needs a Path to be created 73 | 74 | ```java 75 | File f = new File("/bin"); 76 | 77 | System.out.println("Getname:" + f.getName()); 78 | System.out.println("Canwrite: " + f.canWrite()); 79 | System.out.println("Exists:" + f.exists()); 80 | ``` 81 | 82 | --- 83 | 84 | ## Absolute vs Relative paths 85 | 86 | - relative Path to our project / app 87 | 88 | ```java 89 | File f = new File("bin"); 90 | ``` 91 | 92 | - absolute Path 93 | 94 | ```java 95 | File f = new File("/bin"); 96 | ``` 97 | 98 | - we can create a file starting with a base path 99 | 100 | ```java 101 | File root = new File("/"); 102 | File f = new File(root, "bin"); 103 | ``` 104 | 105 | --- 106 | 107 | ## System-independent paths 108 | 109 | - `File.separator`: character used to separate parts of a relative / absolute path 110 | - on UNIX systems, __"/"__, on Windows __"\\"__ 111 | - `/bin/ls`, `c:\\windows\\system32` 112 | - `File.pathSeparator`: character used to separate directories in the `PATH` environment variable 😱 113 | - on UNIX systems, __":"__, on Windows __";"__ 114 | 115 | ```java 116 | File root = new File(File.separator); 117 | File f = new File(root, "bin"); 118 | ``` 119 | 120 | --- 121 | 122 | ## Useful methods on File class 123 | 124 | | | | 125 | |---|---| 126 | | exists() | delete() | 127 | | getName() | lastModified() | 128 | | getAbsolutePath() | renameTo(File) | 129 | | isDirectory() | mkdir() | 130 | | isFile() | mkdirs() | 131 | | length | getParent() | 132 | | listFiles() 133 | 134 | --- 135 | 136 | ## Stream magic 137 | 138 | ```java 139 | Arrays.stream(f.listFiles()).sorted().forEach(System.out::println); 140 | ``` 141 | 142 | --- 143 | 144 | ## Reading from the keyboard: old way 145 | 146 | - `System.in` is a `java.io.BufferedInputStream` 147 | - raw stream of bytes 148 | - to read from it, we need an `InputStreamReader` 149 | 150 | ```java 151 | InputStreamReader in = new InputStreamReader(System.in); 152 | int c = 0; 153 | do { 154 | c = in.read(); 155 | System.out.println(c); 156 | } while (c != 32); 157 | ``` 158 | 159 | --- 160 | 161 | ## Reading from the keyboard: old way 162 | 163 | - this reads a _stream_ of bytes, one at a time. We need to read complete lines! 164 | - to read complete lines, we use a `BufferedReader` 165 | 166 | ```java 167 | BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 168 | 169 | String input = reader.readLine(); 170 | ``` 171 | 172 | --- 173 | 174 | ## Reading from the keyboard: "new" way 175 | 176 | - since Java 6. New way... 🤔 177 | - `Console` singleton class 178 | - `Console` can be null! 179 | 180 | ```java 181 | Console console = System.console(); 182 | if (console == null) { 183 | System.out.println("Null console"); 184 | return; 185 | } 186 | 187 | String input = console.readLine(); 188 | ``` 189 | 190 | --- 191 | 192 | ## Reader & Writer 193 | 194 | - reader() ~= System.in 195 | 196 | Retrieves the unique Reader object associated with this console. 197 | 198 | ```java 199 | Console con = System.console(); 200 | if (con != null) { 201 | Scanner sc = new Scanner(con.reader()); 202 | ... 203 | } 204 | ``` 205 | --- 206 | 207 | ## Console: format & printf 208 | 209 | ```java 210 | console.writer().println("Hello"); 211 | console.writer().format("World %s", "!"); 212 | console.printf("This %s", "rules"); 213 | ``` 214 | 215 | --- 216 | 217 | ## flush, readLine, readPassword 218 | 219 | - Flushes the console and forces any buffered output to be written immediately . 220 | 221 | 222 | --- 223 | 224 | ## Streams (file streams) 225 | 226 | - a list of data elements 227 | - if _Stream_ is in the name: all types of binary / byte data 228 | - `FileInputStream` 229 | - if _Reader / Writer_ is in the name: chars / Strings 230 | - `FileReader` 231 | - is a _stream_ of chars / Strings (although Stream does not appear in the name) 232 | 233 | 234 | --- 235 | 236 | 237 | ## InputStream 238 | 239 | - abstract class 240 | - all children include "InputStream" in the name 241 | 242 | ``` 243 | +-------------+ 244 | | InputStream | 245 | | | 246 | +-------------+ 247 | ^ 248 | +-----------------------|---------------------------+ 249 | | | | 250 | +-----------------+ +-------------------+ +-------------------+ 251 | | FileInputStream | | FilterInputStream | | ObjectInputStream | 252 | | | | | | | 253 | +-----------------+ +-------------------+ +-------------------+ 254 | ^ 255 | | 256 | +---------------------+ 257 | | BufferedInputStream | 258 | | | 259 | +---------------------+ 260 | ``` 261 | 262 | --- 263 | 264 | ## OutputStream 265 | 266 | ``` 267 | +--------------+ 268 | | OutputStream | 269 | | | 270 | +--------------+ 271 | ^ 272 | +-----------------------|---------------------------+ 273 | | | | 274 | +------------------+ +--------------------+ +--------------------+ 275 | | FileOutputStream | | FilterOutputStream | | ObjectOutputStream | 276 | | | | | | | 277 | +------------------+ +--------------------+ +--------------------+ 278 | ^ 279 | ----------+------------- 280 | | | 281 | +----------------------+ +-------------+ 282 | | BufferedOutputStream | | PrintStream | 283 | | | +-------------+ 284 | +----------------------+ 285 | ``` 286 | 287 | 288 | 289 | --- 290 | 291 | ## Reader 292 | 293 | --- 294 | 295 | ## Writer 296 | 297 | --- 298 | 299 | ## Serializable 300 | 301 | ```java 302 | class Person implements Serializable { 303 | public static final long serialVersionUID = 1L; 304 | 305 | private String name; 306 | private transient String myId; 307 | 308 | public String getName() { 309 | return name; 310 | } 311 | 312 | public Person setName(String name) { 313 | this.name = name; 314 | return this; 315 | } 316 | 317 | public String getMyId() { 318 | return myId; 319 | } 320 | 321 | public Person setMyId(String myId) { 322 | this.myId = myId; 323 | return this; 324 | } 325 | } 326 | 327 | ``` 328 | 329 | 330 | --- -------------------------------------------------------------------------------- /9 - NIO2.md: -------------------------------------------------------------------------------- 1 | theme: Simple 2 | autoscale: true 3 | 4 | 5 | # NIO2: New I/O api, v2 6 | 7 | --- 8 | 9 | ## NIO2: New I/O api, v2 10 | 11 | - introduced in Java 1.4 as replacement for Streams 12 | - not used by anyone 13 | - Java 1.7 brings up NIO2 14 | - still nobody uses it 15 | 16 | --- 17 | 18 | ## Path 19 | 20 | - interface `java.nio.file.Path` 21 | - understands symbolic links 22 | - to create: 23 | 24 | ```java 25 | Path bin = Paths.get("/bin"); 26 | 27 | // using varargs so no need to change between / & \ 28 | // the correct system-dependent path.separator gets added 29 | 30 | Path bin = Paths.get("/", "bin"); 31 | 32 | ``` 33 | 34 | --- 35 | 36 | ## Path from URIs 37 | 38 | ```java 39 | Path bin = null; 40 | try { 41 | bin = Paths.get(new URI("file:///bin")); 42 | } catch (URISyntaxException e) { 43 | e.printStackTrace(); 44 | } 45 | 46 | System.out.println(bin.getFileName()); 47 | 48 | ``` 49 | 50 | --- 51 | 52 | ## FileSystem 53 | 54 | - get a Path 55 | 56 | ```java 57 | Path bin = FileSystems.getDefault().getPath("/bin"); 58 | 59 | System.out.println(bin.getFileName()); 60 | ``` 61 | 62 | - all mounted volumes 63 | 64 | ```java 65 | FileSystems.getDefault().getFileStores().forEach(System.out::println); 66 | ``` 67 | 68 | --- 69 | 70 | ## Converting Path <--> File 71 | 72 | ```java 73 | Path bin = FileSystems.getDefault().getPath("/bin"); 74 | 75 | System.out.println(bin.getFileName()); 76 | 77 | File f = bin.toFile(); // converts from "new" Path to "old" File 78 | 79 | Path newBin = f.toPath(); 80 | 81 | System.out.println(newBin); 82 | 83 | ``` 84 | --- 85 | 86 | ## Splitting the path into components 87 | 88 | ```java 89 | Path bin = FileSystems.getDefault().getPath("/usr/local/bin"); 90 | 91 | for (int i = 0; i < bin.getNameCount(); i++) { 92 | System.out.println(bin.getName(i)); 93 | } 94 | 95 | usr 96 | local 97 | bin 98 | ``` 99 | 100 | --- 101 | 102 | ## Some utilities 103 | 104 | ```java 105 | Path bin = FileSystems.getDefault().getPath("/usr/local/bin"); 106 | 107 | System.out.println(bin.getFileName()); // bin 108 | System.out.println(bin.getRoot()); // / 109 | System.out.println(bin.getParent()); // /usr/local 110 | 111 | System.out.println(bin.isAbsolute()); // true 112 | ``` 113 | 114 | --- 115 | 116 | ## Getting absolute path from relative 117 | 118 | ```java 119 | Path bin = FileSystems.getDefault().getPath("hello.txt"); 120 | 121 | System.out.println(bin.toAbsolutePath()); 122 | ``` 123 | 124 | --- 125 | 126 | ## Subpath 127 | 128 | ```java 129 | Path bin = FileSystems.getDefault().getPath("/usr/local/bin/this/that"); 130 | 131 | System.out.println(bin.subpath(0, 2)); 132 | System.out.println(bin.subpath(3, 5)); 133 | 134 | usr/local 135 | this/that 136 | ``` 137 | 138 | --- 139 | 140 | ## Testing file exists 141 | 142 | ```java 143 | Path bin = FileSystems.getDefault().getPath("/usr/local/bin/this/that"); 144 | 145 | System.out.println(Files.exists(bin)); 146 | ``` 147 | 148 | --- 149 | 150 | ## `Files`: Creating directories 151 | 152 | ```java 153 | try { 154 | Path hello = Paths.get("hello"); 155 | if (Files.exists(hello)) { 156 | Files.delete(hello); 157 | } else { 158 | Files.createDirectory(hello); 159 | } 160 | } catch (IOException e) { 161 | e.printStackTrace(); 162 | } 163 | 164 | ``` 165 | 166 | --- 167 | 168 | ## `Files`: Deleting directories 169 | 170 | ```java 171 | Path hello = Paths.get("hello"); 172 | 173 | Files.deleteIfExists(hello); 174 | ``` 175 | 176 | --- 177 | 178 | ## Other `Files` methods 179 | 180 | - isSameFile 181 | - copy 182 | - delete 183 | - move 184 | 185 | --- 186 | 187 | ## Printing all lines from a file 188 | 189 | ```java 190 | try { 191 | Files.readAllLines(Paths.get("/Users/dfreniche/.bash_history")). 192 | stream(). 193 | forEach(System.out::println); 194 | } catch (IOException e) { 195 | e.printStackTrace(); 196 | } 197 | 198 | ``` 199 | 200 | --- 201 | 202 | ## Walking a directory 203 | 204 | - print all files in `/usr/local` 205 | 206 | ```java 207 | try { 208 | Files.walk(Paths.get("/usr/local")).forEach(System.out::println); 209 | } catch (IOException e) { 210 | e.printStackTrace(); 211 | } 212 | 213 | ``` 214 | 215 | --- 216 | 217 | - now just the MarkDown files, please 218 | 219 | ```java 220 | try { 221 | Files.walk(Paths.get("/usr/local")).filter(f -> f.getFileName().toString().endsWith(".md")).forEach(System.out::println); 222 | } catch (IOException e) { 223 | e.printStackTrace(); 224 | } 225 | 226 | ``` 227 | 228 | --- 229 | 230 | - only directories 231 | 232 | ```java 233 | try { 234 | Files.walk(Paths.get("/usr/local")). 235 | filter(f -> Files.isDirectory(f)). 236 | forEach(System.out::println); 237 | } catch (IOException e) { 238 | e.printStackTrace(); 239 | } 240 | ``` 241 | 242 | ```java 243 | try { 244 | Files.walk(Paths.get("/usr/local")). 245 | filter(f -> Files.isDirectory(f) && f.getParent().toString().equals("/usr/local") ). 246 | forEach(System.out::println); 247 | } catch (IOException e) { 248 | e.printStackTrace(); 249 | } 250 | ``` 251 | 252 | --- 253 | 254 | ## Find files 255 | 256 | - Predicate takes: Path & File Attributes 257 | 258 | ```java 259 | Path home = Paths.get("/Users/dfreniche"); 260 | 261 | Stream foundJavas = null; 262 | try { 263 | foundJavas = Files.find(home, 4, (p, a) -> p.toString().endsWith(".java")); 264 | } catch (IOException e) { 265 | e.printStackTrace(); 266 | } 267 | foundJavas.forEach(System.out::println); 268 | 269 | ``` -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OCP Java 8 study notes 2 | 3 | --- 4 | 5 | These are some notes I've used for some training I've done preparing people to get this certification, also these notes are for myself (learning & getting that certification) 6 | 7 | 8 | ## How to read 9 | 10 | These docs are in Markdown format, prepared to be used with the superb presentation software [Deckset](http://www.decksetapp.com/) 11 | 12 | If you need a PDF version you can use gitprint.com. Just change any link to my MD documents from github to gitprint. 13 | 14 | --- 15 | 16 | ### Java SE 8 Programmer II: 1Z0-809 17 | 18 | Duration: 150 19 | Number of Questions:85 20 | Passing Score: 65% 21 | 22 | https://education.oracle.com/pls/web_prod-plq-dad/db_pages.getpage?page_id=652&get_params=p_exam_id:1Z0-809 23 | 24 | - update path (for those with previous certs): 25 | 26 | http://education.oracle.com/pls/web_prod-plq-dad/db_pages.getpage?page_id=654&get_params=p_id:333 27 | 28 | --- 29 | 30 | ## Exam simulator 31 | 32 | Disclaimer: I love this simulator and used it to prepare every Java cert exam I've passed. I'm not affiliated to them. 33 | 34 | ### Enthuware for OCP ($9.95) 35 | 36 | http://enthuware.com/index.php/mock-exams/oracle-certified-professional/ocpjp-8-questions 37 | 38 | - upgrades for SCJP 6 --> OCP 8 & SCJP 7 --> OCP 8 exist also 39 | 40 | 41 | ### JavaRanch 42 | 43 | http://www.javaranch.com/ 44 | 45 | --- 46 | 47 | ## Book 48 | 49 | OCP: Oracle Certified Professional Java SE 8 Programmer II Study Guide: Exam 1Z0-809 50 | 51 | https://www.amazon.es/OCP-Certified-Professional-Programmer-1Z0-809/dp/1119067901/ref=sr_1_1?ie=UTF8&qid=1490033852&sr=8-1&keywords=ocp 52 | 53 | --- 54 | 55 | ## License 56 | 57 | ``` 58 | MIT - Licence 59 | 60 | Copyright (c) 2017 Diego Freniche 61 | 62 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 63 | 64 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 65 | 66 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 67 | ``` --------------------------------------------------------------------------------