📄 Page
1
(This page has no text content)
📄 Page
2
Java Challengers Master the Java Fundamentals with fun Java Code Challenges! Become a Java Challenger! Rafael Chinelato del Nero This book is for sale at http://leanpub.com/javachallengers This version was published on 2023-10-29 This is a Leanpub book. Leanpub empowers authors and publishers with the Lean Publishing process. Lean Publishing is the act of publishing an in-progress ebook using lightweight tools and many iterations to get reader feedback, pivot until you have the right book and build traction once you do. © 2021 - 2023 Rafael Chinelato del Nero
📄 Page
3
Tweet This Book! Please help Rafael Chinelato del Nero by spreading the word about this book on Twitter! The suggested tweet for this book is: I just bought the Java Challengers book! It’s time to have fun challenging myself with the Java Code Challenges and refine my Java skills! The suggested hashtag for this book is #JavaChallengers. Find out what other people are saying about the book by clicking on this link to search for this hashtag on Twitter: #JavaChallengers
📄 Page
4
Contents Foreword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Jeanne Boyarsky . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.2 Why Java? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.3 What kinds of concepts are in this book? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.4 Who is this book for? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.5 What are the Java Challenges? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.6 Disclaimer about the Java Challenges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.7 Java versioning and tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 1.8 Will this book prepare you for the software development market? . . . . . . . . . . . . . 7 2 Variable types and flow control (Review) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.1 A Brief Review about Algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.2 Arithmetic Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 2.3 Flow Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.4 Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 2.5 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 2.6 Local variable restrictions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 2.7 Candy Price Code Challenge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 2.8 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 3 Basic object-oriented programming (Review) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 3.1 Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 3.2 Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 3.3 The Keyword this . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 3.4 Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 3.5 Object references . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 3.6 Arrays are objects in Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 3.7 Bank Deposit/Withdraw Challenge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 3.8 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 4 Encapsulation access modifiers, and package structure . . . . . . . . . . . . . . . . . . . . . 76 4.1 Programming to interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 4.2 What are and how to use getters and setters? . . . . . . . . . . . . . . . . . . . . . . . . . . 77
📄 Page
5
CONTENTS 4.3 The Builder Design Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 4.4 Organizing Packages in a Real Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 4.5 Encapsulation Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 4.6 Access Modifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 4.7 Inner Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 4.8 The static keyword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 4.9 Instance and static block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 4.10 Small Real-World Project Challenge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 4.11 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 5 Overloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 5.1 Overloading basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 5.2 Wrappers and autoboxing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 5.3 Varargs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 5.4 Overloading Real-World Usage Challenge . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 5.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 6 Inheritance and Polymorphism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 6.1 When to use inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 6.2 Every Class is an Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 6.3 Checking the type of an object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 6.4 The toString method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 6.5 Access modifiers and inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 6.6 Object composition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 6.7 Multiple inheritance in Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 6.8 Using super to access a parent class’s methods . . . . . . . . . . . . . . . . . . . . . . . . . 147 6.9 Constructors and inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 6.10 Class casting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 6.11 Preventing inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 6.12 Abstract classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 6.13 Factory Method Strategy Discount Real-world Challenge . . . . . . . . . . . . . . . . . 160 6.14 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 7 Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 7.1 Interfaces and Polymorphism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 7.2 Covariant return types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 7.3 Default methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 7.4 Abstract classes vs. interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 7.5 Static methods in interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 7.6 Simulating multiple inheritance with default methods . . . . . . . . . . . . . . . . . . . . 173 7.7 Private methods in interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 7.8 Command Design Pattern Challenge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 7.9 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
📄 Page
6
CONTENTS 8 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 8.1 Checked and unchecked exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 8.2 Stack Trace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 8.3 Handling or Declaring Checked Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 8.4 try, catch, finally . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191 8.6 try with resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195 8.7 Multi catch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 8.8 Creating a customized exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 8.9 Throw early, catch late . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210 8.10 Real World Exception Creation Challenge . . . . . . . . . . . . . . . . . . . . . . . . . . . 212 8.11 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212 9 Lambdas and Functional Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214 9.1 What is Lambda? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214 9.2 Functional Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217 9.3 Method Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228 9.4 Lambda Method Reference Matcher Challenge: . . . . . . . . . . . . . . . . . . . . . . . . 235 9.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239 10 Optional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 10.1 Wrapping a value into Optional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 10.2 isPresent and isEmpty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 10.3 Optional Antipatterns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244 10.4 ifPresent and ifPresentOrElse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248 10.6 Handling Exceptions with orElseThrow . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253 10.7 Transforming Optional Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257 10.8 Final Yoshi Food Optional Challenge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 10.9 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 11 Generics and Object Comparison . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 11.1 Comparing objects with equals and hashcode . . . . . . . . . . . . . . . . . . . . . . . . . 266 11.2 Generics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273 11.4 Upper and Lower Bound Generics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282 11.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289 12 Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290 12.1 Collections API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290 12.2 List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291 12.3 ArrayList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296 12.4 Vector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 300 12.5 Deque & Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301 12.6 ConcurrentModificationException . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307 12.7 Using Comparable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310 12.8 Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317
📄 Page
7
CONTENTS 12.9 HashSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318 12.10 LinkedHashSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321 12.11 TreeSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323 12.12 Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326 12.16 TreeMap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339 12.17 Elements Searching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345 12.18 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347 13 Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349 13.1 Streams Basic Principles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349 13.2 Creating a Stream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351 13.3 Intermediate VS Terminal Operation Methods . . . . . . . . . . . . . . . . . . . . . . . . 355 13.4 Intermediate Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356 13.5 Terminal Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375 13.6 Parallelizing Data Processing with parallel() . . . . . . . . . . . . . . . . . . . . . . . . . 383 13.7 Collecting Data with collect() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389 13.8 Collectors.groupingBy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396 13.9 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401 14 Newest Features of Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402 14.1 Java Release Strategy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402 14.2 Introduction to Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403 14.3 Java JDK Base Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404 14.4 Named application module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406 14.5 Unnamed module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412 14.6 Exporting Packages from Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413 14.7 Requiring a Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415 14.8 Exporting a service with provides with . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419 14.9 Module Reflection Access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422 14.10 Star Trek Planets Module Special Challenge . . . . . . . . . . . . . . . . . . . . . . . . . 425 14.11 Reserved word var . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 428 14.12 New switch case statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 434 14.13 Using Pattern Matching Type Checks Java 15 . . . . . . . . . . . . . . . . . . . . . . . . 438 14.14 Using record . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443 14.15 Using Sealed classes Java 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 448 14.16 Text Blocks Java 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 453 14.17 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459 15 Concurrency Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 461 15.1 Fundamentals of Concurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 461 15.2 Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464 15.3 Using Thread sleep . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 470 15.4 Using join . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 471 15.5 non-daemon and daemon Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 472
📄 Page
8
CONTENTS 15.6 Using interrupt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 476 15.7 Race Condition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 478 15.8 Mutual Exclusion (Mutex) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 480 15.9 Using wait and notify . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 486 15.10 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494 16 Advanced Concurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495 16.1 ReentrantLock Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495 16.2 Atomic Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498 16.3 The volatile keyword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 500 16.4 The happens-before Rule . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 505 16.5 CompletableFuture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 506 16.6 Threadpool with Executors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 513 16.7 ConcurrentHashMap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 529 16.8 ConcurrentSkipListMap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 531 16.9 Producer Consumer with BlockingQueue . . . . . . . . . . . . . . . . . . . . . . . . . . . 532 16.10 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 534 17 Next Steps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535 17.1 Other important Java features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535 17.2 Practicing Clean Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 536 17.3 Tendencies of the market . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537 17.4 Getting prepared for interviews . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 538 17.5 Strategies to Stay Sharp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539 17.6 Learn more about negotiation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539 17.7 Do you want more? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 540
📄 Page
9
Foreword James Gosling // Will be added soon! Jeanne Boyarsky Back in 2017, I attended Rafael’s JavaOne session: “Learn the Concepts between these 10 Java Challenges and Eliminate Stressful Bugs.” My reaction at the time: This was fun! Being a cert book author gave me an advantage but some were still tricky and tough! And using The Simpsons as examples was fun. He did show of hands for each option; most people didn’t raise their hand for any of the choices. It’s now five years later. I’m still a certification book author, but the session has grown into a full book! There are more challenges with the same fun and style. I’m pleased that the Simpsons remain! Whether you are learning Java or an experienced developer, there is something in this book for you. Don’t let bugs hit you. Learn here so you can avoid surprises in your code! And have fun. I’m sure you will find it, um, challenging.
📄 Page
10
1 Introduction Java is one of the most used programming languages in the world, and it’s also very powerful. Developers who know Java in depth are highly valued by the market and ablfe to create high-quality, maintainable code. Java is not a simple language to master, but this book will provide valuable guidance for developers who want to harness its full power and be a reference as a software engineer. Even senior developers may not be familiar with some key concepts of the Java language, and that will impact the quality of the code they write. But reading a book is not enough to really acquire a skill. Developers have to put their knowledge into practice by applying what they’ve learned in some way. This book provides more than 70 Java Code Challenges in total to test your understanding of the and trully absorb the concepts it introduces. You’ll get up-to-date with the most recent Java versions and will learn Java from real project situations so that when you come across similar situations you will know how to respond effectively. As the name suggests, Java Challengers is not an easy book, but it will guide you through the concepts and won’t leave gaps that will make learning difficult. Although the subjects the book presents are complex, the concepts are explained in a practical way, aiming to facilitate the learning process of the reader. After you read, consider, and try to solve each challenge, you can test the code provided and run your own tests by changing it and analyzing the output. This will help you connect the dots with the content you consume in the book. You’ll then be able to use the concepts you’ve learned in your day-to-day work, which is the whole point of going deep into the concepts of a programming language. To produce highly maintainable Java code you have to use the most suitable features of the language. Then bugs have a really hard time hiding. This increases the satisfaction of developers, managers, and customers with the delivered product, bringing more profit to the company. Everyone wins. It’s definitely worth it to invest time in a deep dive into the Java language, and that’s exactly what this book will provide. So, what are you waiting for? Are you ready for all the challenges? How many of them can you get right? Are you prepared to take your Java skills to a whole new level? 1.2 Why Java? Java is the world’s most popular programming language, and a developer who knows Java will rarely be unemployed. Many companies opt to use this language to make hiring new developers an easier task—its popularity means it’s easier to find professionals who know Java.
📄 Page
11
1 Introduction 3 Reliability, maturity, and robustness are the essence of the language, and companies of all sizes choose Java because of those qualities. Java also has a large ecosystem of open source projects that help programmers with their day-to-day development, many of which are free. With Java it’s possible to create organized, structured code with reliable unit tests that help developers build robust software that’s resistant against bugs. 1.3 What kinds of concepts are in this book? You will learn about core concepts from the Java language that will be useful in your day-to- day work. The book covers crucial concepts such as polymorphism, encapsulation, overloading, inheritance, composition, exceptions, Optionals, generics, concurrency, equals and hashCode, collections, streams, functional programming with lambdas and method references, and the main concepts from the newest Java versions (since this book will be updated from time to time). It makes a big difference if a Java developer really understands these concepts, and that’s why they are explored in this book. 1.4 Who is this book for? Java Challengers is aimed at developers who want to create high-quality code in their day-to-day work. With a consolidated knowledge of the core concepts you will be able to use the full power of Java, applying the most suitable features to the situations you are facing. Developers who like solving challenging puzzles will also enjoy the book—the challenges aren’t easy, but they are fun. You don’t have to be an experienced developer to get value out of this book. Developers who have at least some knowledge of the basics of programming logic and algorithms should be able to understand the book, although familiarity with object-oriented programming is also recommended. 1.4.1 Who is this book not for? Java Challengers covers most of the core certification content, but this book is not focused on certification. You can use it as supporting material, and if your goal is Java certification you can get extra material such as mock exams, check tutorials, articles, or other books. It’s actually a good idea to mix your learning sources, we learn much better a subject when reading, listening, watching and doing something useful with the learned concepts. This also may not be the right book for developers who are looking for a general introduction but aren’t focused on creating high-quality code and becoming experts. The point of going deep into
📄 Page
12
1 Introduction 4 Java concepts is to give developers the power to use the full capabilities of Java by applying the most suitable features of the language to the problem at hand. Finally, developers who just want to write "code that works" without going any deeper shouldn’t read this book. 1.4.2 What is covered in the book? Many features that are infrequently used in real projects have not been included in this book. For example, the Java JDBC (Database library) are not discussed because it’s likely that in a real project you will be using some kind of persistence framework (a set of libraries that facilitates day-to-day work with a predefined and simpler structure) such as Hibernate, Spring Data, or others. Instead, core features of Java are explored in a way that they can be totally absorbed and used as best as possible. Reinventing the wheel is one of the worst things that can happen in software development. If you know the core features of Java well, you won’t take the risk of using the wrong feature to solve a problem. You will be using Java masterfully. 1.5 What are the Java Challenges? The Java Challenges are challenging code puzzles that require you to know the relevant Java concepts verywell. Most of the challenges include the mainmethod, and your goal is to guess what will happen when running the code. The Java code challenges are carefully designed to explore themost important Java concepts that will make a difference in your day-to-day work as a Java developer. Many of them feature well-known shows and characters, and expect to see funny class/method/variable names. If you get the challenges right, that’s great! But if not, don’t get frustrated; try to understand why, and eventually you will absorb the concepts. The point of the book is to deepen your understanding of Java by having fun with the challenges. Youwill also find a real-world challenge at the end of each chapter whichwill get you better prepared for applying suitable solutions to problems you might face in real projects. These will help you with interview problem-solving questions too. The real-world challenge will usually be a situation where you must apply the concepts learned in the chapter to solve a common problem. Many of them involve established design patterns and unit tests, and solutions are available so you can check if your code is correct. 1.6 Disclaimer about the Java Challenges The intention of the Java challenges is to test your understanding of the concepts explained throughout the book, so don’t expect clean code in every challenge. Instead, see the challenges as a way to fix the concepts in your mind and practice your code analyzing skills.
📄 Page
13
1 Introduction 5 The better you are able to analyze code, the faster and sharper programmer you will become. These exercises will enable and empower you to produce flexible and meaningful code using the most appropriate Java concepts. The more features and concepts from Java you master, the better able you will be to track down bugs and fix them efficiently. In addition, you will be able to produce highly optimized solutions for many different situations. 1.6.1 Running a Java application without a class and main method As of Java 9, you don’t need to create a class or a main method for simple code tests. You can use the command line with jshell. It’s a powerful tool when you want to run something quickly to test syntax or code logic. You can implement the code examples in this book using jshell if you wish. Make sure you have Java 9 or later installed on your machine by running the following command on your command terminal: java --version Then configure the environment variable JAVA_HOME and add JAVA_HOME\bin to your operating system environment variable PATH. Just a brief review about the PATH environment variable, this path will enable you to run commands globally on your command terminal. We have two options when running the java command lines, either we point our current directory in the command terminal to JAVA_HOME\bin or we inform our OS that we want to use the commands located in JAVA_HOME\bin globally without having to change your current directory to the JAVA_- HOME\bin every time we want to use java commands. Once you’ve done that, you can start JShell using the following command: jshell Then you can write Java code without the obligation of declaring a class and a main method, and execute it immediately from the command line. It’s a great option to practice the examples in the book, but any way you choose to write your code is fine. What really matters is you doing your own tests with as many examples as you can from this book. 1.6.1 Where to run the Java applications You canwrite Java code in a Notepad file, at the command line, and so on, but of course that wouldn’t be productive for big, complex projects. It would be very hard to organize and produce all the Java files required by the system! Fortunately, there are tools that can help us in our day-to-day work, known as integrated develop- ment environments (IDEs). Of the top Java IDEs, the one I like the most is IntelliJ. It’s practical and easy to use, has great integration with most common Java technologies, and is very performant.
📄 Page
14
1 Introduction 6 Another option is Eclipse, which has the best set of programming keyboard shortcuts but in my opinion is not so good at integrating and building complex systems. A third popular IDE is NetBeans; I haven’t used it much but it’s generally regarded as a good IDE for Java and it will do the job. IDE choice is very personal, so pick the IDE you like the most—after all, what matters most is the Java code, not where the code was written! 1.6.2 Golden tips to solve the Java Challenges The challenges are tricky, and they will demand that you analyze the code carefully so that you can guess the output. Before deciding on a solution to a challenge, you should consider every alternative to see if there is another one that makes sense. If so, analyze the code again and make your best guess. It can be tempting to go straight to the obvious answer. Before all the challenges there will be a detailed explanation covering everything you need to answer the problem correctly. If you feel confident that you already know the concept you can try the challenge before reading through the description; if you get the answer wrong, you can always go back to the concept’s explanation to try to find out what happened. Another crucial action for taking full benefit of this book is to run the code in a challenge and change it so that you can test the outputs by yourself. This is a good way to be sure that you’ve absorbed the main concepts. Some persistence will be required, but if you run the code enough times, the concepts will be clear and consolidated. 1.7 Java versioning and tools As you read the book, it’s highly recommended that you test the code to see what happens with each example. All the code is stored in GitHub. You can download the project if you don’t have knowledge of Git, or you can simply use the Git commands if you know them. Git is a widely used tool for storing and versioning code, and familiarity with it is a must for every software engineer. If you don’t know Git yet, it’s time to practice it. You can learn the basic commands and run the Java Challenges code. You will find all the code for this book, from examples to the challenges, at https://github.com/rafadelnero/javachallengersbook. You’ll see that the project includes a build manager tool called Maven. Maven provides an automated way to build, test, deploy, and manage code dependencies that makes our lives as software engineers easier.
📄 Page
15
1 Introduction 7 You will have to import the project as a Maven project, and then you will be able to run the code from the book. There are also some unit tests included so you can learn a bit about how tests should be applied. In working through the challenges, you will be able to use and learn about a variety of popular tools. 1.8 Will this book prepare you for the software development market? A deep knowledge of Java is the most important knowledge every Java developer should have in their toolbelt, because it’s from code that all the business logic will be built. If developers write high- quality code it will require less maintenance, which translates to more profit for the company and less stress for everyone. The Java knowledge on its own is great but you need to expand more your knowledge-base to be highly effective. You don’t need to know every other single technology very well, instead, you need to know enough to solve a a problem in a real-project. Also, be careful to not try to embrace the world. If you start learning several technologies at the same time, it might be overwhelming and you will be very likely to be frustrated and eventually give up. One culture that is expanding in the market is DevOps. That’s because many projects are being moved to a cloud platform, and many automation/container technologies come along with it (Jenkins, GitHubActions, Docker, Kubernetes). Instead of manually making deployments, testing, and checking code quality, we can simply use DevOps tools to automate the whole process of software delivery. When we talk about DevOps, a crucial skill to have is the Linux OS, I highly encourage you to use Linux on your machine or if you have a Mac OS it will be better for you to get familiarized with command lines. If you are a Windows user though, you can still use a Linux subsystem, a dual-boot or a virtual machine with Linux too. Also, if you are a beginner on Linux, I recommend you to start with Ubuntu because it’s a more user-friendly platform and at the same time a robust one. The cloud era is in full swing, so we need to know at least a bit about technologies such as top cloud providers such as AWS, Google Cloud Platform, Azure, Oracle Cloud, a little bit about Infrastructure as Code technologies Terraform, Cloud Formation, or any other scripts to provision cloud services. A working knowledge of databases is also essential for every developer, because we often have to build complex SQL scripts to bring in the necessary data for the business. NoSQL is a big thing too. It’s also important to know the main concepts of the Microservices architecture. You will be asked about these concepts in an interview, so at least have an idea of the advantages and disavantages of using Microservices. Many projects in the market rely on full stack developers, which means that developers have to know at least the basics of a front-end technology.
📄 Page
16
1 Introduction 8 Therefore frameworks such as Angular, React, and Vue are some of the big ones; this might change with time. All these technologies are based on Javascript, so it’s a good idea to have a basic knowledge of the language as well. The good thing is that by mastering Java concepts, you will be able to learn any other language far more easily because in the end you will simply use the same language concepts and paradigms you have from Java to learn another language and this process will be incredibly faster. It’s a lot to learn, isn’t it? But don’t worry, you don’t need to be a specialist in all those technologies. You need a basic understanding of how to use them, and then you can choose one specific technology that you would like to explore in depth. If you’re reading this book it means you’ve selected Java, which I think is a powerful choice. Let’s start going deep into Java!
📄 Page
17
2 Variable types and flow control (Review) This chapter covers: • Creating basic Java algorithms based on a problem • Using suitable types of primitive variables • Using flow control instructions • Using loops • Using unidimensional and bidimensional arrays • Declaring and using local variables • Total of 6 Java code challenges The core purpose of every programming language is to control the flow of logic, making computa- tions with different values and organizing information in a way that solves a problem for the final user of the software. This chapter introduces several concepts that you can use to accomplish this objective, including variables (primitives and special types), conditions, loops, and arrays. Using the information in this chapter, you will be able to develop your own algorithms to solve specific problems. For example, you could build a mathematical formula to make a calculation, construct logic to check if a password is correct with a condition, or create a program that will receive two numbers, multiply them, and print the result. Your imagination is the limit. Your code might not have the robustness required by a real project, but you will be able to design the logic to solve specific problems. We’ll start with an in-depth exploration of variables. 2.1 A Brief Review about Algorithms Code algorithm is an organized and logical way to solve a particular problem through instructions where we get the output or result expected. We are dealing with algorithms every day in our lives. When we go to a shop to buy what we need, we have to give our brain logical instructions to get the job done. We can go beyond that, when we are going to sleep, we also have to take some logical actions to sleep properly, any other common action we take every day can be seen as an algorithm. Mathematical functions are another example of algorithms, in the computer, the difference is the way we pass the instructions. The instructions have to be in the language the computer understand that would be binary numbers but binary numbers are too hard to manipulate in a pure way, that’s
📄 Page
18
2 Variable types and flow control (Review) 10 why we have programming languages that have powerful features to solve real-world problems about financial businesses, entertainment, modern machines, mobile devices and the list goes on and on. Let’s then review the universal code concepts so that we can apply a logic algorithm effectively with Java or any other language. 2.1.1 Code Syntax Code syntax is the way the compiler will understand the code, it’s a predefined way that we must write our code. If we don’t follow the pattern the JVM is expecting, the code won’t compile. We can try to use a variable without declaring the type for example, which Java won’t accept: intVariable = 7; Wehave to always follow the code syntax toworkwith any programming language. Java for example has a very similar syntax from the C language. 2.1.2 Code Semantic Everything is the real-world has to be done with a defined logic, whenwewant to brush our teeth we open the bathroom cabinet, then get the toothbrush, then put on the toothpaste, move the toothbrush into our mouth, brush it until our teeths get clean, wash the toothbrush, wash the mouth, then put the toothbrush back in the cabinet. Notice that it wouldn’t be possible to brush our teeths without following that logic, if we try to brush our teeths without the toothpaste for example, that wouldn’t work. Another example is when we are going to cook something, we have to follow a logic with the receipt, if we cook the ingredients in the wrong order or with the wrong ingredients, the receipt won’t work as well. Simply put, code semantic is the logic we have to implement to perform tasks. 2.1.3 Variables in Java: Primitive types and values A variable in programming is a way to store a value into a named allocated space in the computer’s memory. We can store text, binary, and numerical values in a variable and then make calculations, perform comparisons, and so on. Java has two main types of variables: primitives and objects. Many of the primitive variable types are also used in other programming languages. If you’ve worked with C, for example, you will find that many of the variable types in Java are the same. We’ll focus on the primitive types for now; Java objects will be introduced in the next chapter.
📄 Page
19
2 Variable types and flow control (Review) 11 2.1.4 Primitive types As mentioned previously, it’s possible to store and manipulate characters, numbers, and binary values such as true and false with the variety of primitive variable types defined in Java. The eight Java primitives are listed in table 2.1. The table contains the following information: • Type: The variable type, defined by the size of the allocated space in memory and the data structure (for example, if it’s text or numbers). • Range: The range of values that can be used for the variable type. Default instance value—The default value of the variable when no value is assigned to it upon creation of a new instance. We will explore instances in the next chapter. • Size: The size that will be allocated in memory for the variable type. Example literals—Examples of values that can be used in this type of variable. Type Range Default value Size Example literals boolean true or false false 1 bit true, false byte -128 .. 127 0 8 bits 1, -90, 128 char Unicode character or 0 to 65,536 \u0000 16 bits bits ‘a’, ‘\u0031’, ‘\201’, ‘\n’, 4 short -32,768 .. 32,767 0 16 bits 1, 3, 720, 22000 int -2,147,483,648 .. 2,147,483,647 0 32 bits -2, -1, 0, 1, 9 long - 9,223,372,036,854,775,808 .. 9,223,372,036,854,775,807 0 64 bits -4000L, -900l, 10L, 700L float 3.40282347 x 1038 .. 1.40239846 x 10-45 0.0 32 bits 1.67e200f, -1.57e-207f, .9f, 10.4F double 1.7976931348623157 * 10308 .. 4.9406564584124654 * 10-324 0.0 64 bits 1.e700d, -123457e, 37e1d Table 2.1.4 The primitive variable types defined in Java Note that the primitive types in Java can never have the value null; if you don’t assign them a value when you create them the JVM will assign them the default value listed in this table. This will only happen with an instance variable, a concept we will explore more deeply in future chapters. As you’ll see later in this chapter, local variables are not assigned default values if one is not provided; you must assign them values when you create them, or your code will not compile.
📄 Page
20
2 Variable types and flow control (Review) 12 2.1.5 Manipulating a variable in Java Java is a strongly typed language and it’s necessary to define the variable type before using it. After declaring the variable we must assign some value, otherwise the variable existence doesn’t make much sense. The most basic way to assign a value to a variable is by using the simple assignment operator, =. When we are assigning a value to a variable for the first time we say we are initializing it. If we are using the primitive types for example, we need to use the following syntax to declare and assign the values to those variables. 1 int luckNumber = 7; 2 double weight = 70.0; 3 boolean isJavaRocker = true; In Java 10 we also have the possibility to define a non-typed variable that can have any value type within it. For example: var luckNumber = 7; The luckNumber variable will be inferred as an int type with the value of 7. We can’t try to declare a variable without giving a type like Javascript, the following code, for example, won’t be compiled: luckNumber = 7; 2.1.6 Variable Names Rules There are some rules in order to give variable names. In Java, ideally we should simply follow the JavaBeans convention using the camelCase pattern. But it’s also good to at least know what name we can use for variables. Let’s see at first valid examples of variable names in Java: Case scenario Valid variable names (but not recommended) A variable name can start with A to Z int HomerAge = 35; A variable name can start with _ int _homerAge = 35; A variable name can start with $ int $homerAge = 35; After the first character, we can use numbers. int homerAge007 = 35; Let’s see now invalid variable names in Java: