Introduction |
|
xxi | |
Assessment Test |
|
xliv | |
|
Chapter 1 Java Fundamentals |
|
|
1 | (58) |
|
Applying the final Modifier |
|
|
2 | (4) |
|
Declaring final Local Variables |
|
|
3 | (1) |
|
Adding final to Instance and static Variables |
|
|
4 | (1) |
|
|
5 | (1) |
|
|
5 | (1) |
|
|
6 | (6) |
|
|
6 | (2) |
|
Using Enums in Switch Statements |
|
|
8 | (1) |
|
Adding Constructors, Fields, and Methods |
|
|
9 | (3) |
|
|
12 | (10) |
|
|
12 | (3) |
|
Creating a static Nested Class |
|
|
15 | (2) |
|
|
17 | (1) |
|
Defining an Anonymous Class |
|
|
18 | (3) |
|
|
21 | (1) |
|
Understanding Interface Members |
|
|
22 | (10) |
|
Relying on a default Interface Method |
|
|
23 | (4) |
|
Using static Interface Methods |
|
|
27 | (1) |
|
Introducing private Interface Methods |
|
|
28 | (1) |
|
Introducing private static Interface Methods |
|
|
29 | (2) |
|
Reviewing Interface Members |
|
|
31 | (1) |
|
Introducing Functional Programming |
|
|
32 | (11) |
|
Defining a Functional Interface |
|
|
32 | (2) |
|
Declaring a Functional Interface with Object Methods |
|
|
34 | (2) |
|
Implementing Functional Interfaces with Lambdas |
|
|
36 | (2) |
|
Writing Lambda Expressions |
|
|
38 | (2) |
|
Working with Lambda Variables |
|
|
40 | (3) |
|
|
43 | (1) |
|
|
44 | (2) |
|
|
46 | (13) |
|
|
59 | (46) |
|
|
60 | (4) |
|
|
60 | (1) |
|
|
61 | (3) |
|
Creating Custom Annotations |
|
|
64 | (5) |
|
|
64 | (1) |
|
Specifying a Required Element |
|
|
65 | (1) |
|
Providing an Optional Element |
|
|
66 | (1) |
|
Selecting an Element Type |
|
|
67 | (1) |
|
Applying Element Modifiers |
|
|
67 | (1) |
|
Adding a Constant Variable |
|
|
68 | (1) |
|
Reviewing Annotation Rules |
|
|
68 | (1) |
|
|
69 | (5) |
|
Using Annotations in Declarations |
|
|
69 | (2) |
|
Mixing Required and Optional Elements |
|
|
71 | (1) |
|
Creating a value() Element |
|
|
71 | (2) |
|
Passing an Array of Values |
|
|
73 | (1) |
|
Declaring Annotation-Specific Annotations |
|
|
74 | (9) |
|
Limiting Usage with @Target |
|
|
74 | (3) |
|
Storing Annotations with @Retention |
|
|
77 | (1) |
|
Generating Javadoc with @Documented |
|
|
77 | (2) |
|
Inheriting Annotations with @Inherited |
|
|
79 | (1) |
|
Supporting Duplicates with @Repeatable |
|
|
79 | (2) |
|
Reviewing Annotation-Specific Annotations |
|
|
81 | (2) |
|
|
83 | (8) |
|
Marking Methods with @Override |
|
|
83 | (1) |
|
Declaring Interfaces with @Functionallnterface |
|
|
84 | (1) |
|
Retiring Code with @Deprecated |
|
|
85 | (1) |
|
Ignoring Warnings with @SuppressWarnings |
|
|
86 | (2) |
|
Protecting Arguments with @SafeVarargs |
|
|
88 | (1) |
|
Reviewing Common Annotations |
|
|
89 | (2) |
|
|
91 | (1) |
|
|
92 | (2) |
|
|
94 | (11) |
|
Chapter 3 Generics and Collections |
|
|
105 | (70) |
|
|
107 | (4) |
|
|
108 | (1) |
|
Calling Instance Methods on a Particular Object |
|
|
109 | (1) |
|
Calling Instance Methods on a Parameter |
|
|
109 | (1) |
|
|
110 | (1) |
|
Reviewing Method References |
|
|
110 | (1) |
|
|
111 | (2) |
|
Using the Diamond Operator |
|
|
113 | (1) |
|
Using Lists, Sets, Maps, and Queues |
|
|
114 | (23) |
|
Common Collections Methods |
|
|
115 | (4) |
|
|
119 | (5) |
|
|
124 | (2) |
|
Using the Queue Interface |
|
|
126 | (2) |
|
|
128 | (7) |
|
Comparing Collection Types |
|
|
135 | (2) |
|
|
137 | (10) |
|
Creating a Comparable Class |
|
|
137 | (4) |
|
Comparing Data with a Comparator |
|
|
141 | (1) |
|
Comparing Comparable and Comparator |
|
|
142 | (1) |
|
Comparing Multiple Fields |
|
|
143 | (2) |
|
|
145 | (2) |
|
|
147 | (14) |
|
|
148 | (3) |
|
|
151 | (1) |
|
|
152 | (1) |
|
|
153 | (1) |
|
|
154 | (5) |
|
|
159 | (2) |
|
|
161 | (2) |
|
|
163 | (1) |
|
|
164 | (11) |
|
Chapter 4 Functional Programming |
|
|
175 | (72) |
|
Working with Built-in Functional Interfaces |
|
|
176 | (11) |
|
|
178 | (1) |
|
Implementing Consumer and BiConsumer |
|
|
179 | (1) |
|
Implementing Predicate and BiPredicate |
|
|
180 | (1) |
|
Implementing Function and BiFunction |
|
|
181 | (2) |
|
Implementing UnaryOperator and BinaryOperator |
|
|
183 | (1) |
|
Checking Functional Interfaces |
|
|
184 | (1) |
|
Convenience Methods on Functional Interfaces |
|
|
185 | (2) |
|
|
187 | (4) |
|
|
188 | (1) |
|
Dealing with an Empty Optional |
|
|
189 | (2) |
|
|
191 | (22) |
|
Understanding the Pipeline Flow |
|
|
191 | (3) |
|
|
194 | (3) |
|
Using Common Terminal Operations |
|
|
197 | (7) |
|
Using Common Intermediate Operations |
|
|
204 | (5) |
|
Putting Together the Pipeline |
|
|
209 | (4) |
|
Working with Primitive Streams |
|
|
213 | (11) |
|
Creating Primitive Streams |
|
|
214 | (3) |
|
|
217 | (2) |
|
Using Optional with Primitive Streams |
|
|
219 | (1) |
|
|
220 | (1) |
|
Learning the Functional Interfaces for Primitives |
|
|
221 | (3) |
|
Working with Advanced Stream Pipeline Concepts |
|
|
224 | (10) |
|
Linking Streams to the Underlying Data |
|
|
224 | (1) |
|
|
224 | (3) |
|
|
227 | (7) |
|
|
234 | (2) |
|
|
236 | (2) |
|
|
238 | (9) |
|
Chapter 5 Exceptions, Assertions, and Localization |
|
|
247 | (62) |
|
|
248 | (5) |
|
|
248 | (2) |
|
Distinguishing between throw and throws |
|
|
250 | (1) |
|
Examining Exception Categories |
|
|
250 | (2) |
|
Inheriting Exception Classes |
|
|
252 | (1) |
|
Creating Custom Exceptions |
|
|
253 | (3) |
|
Declaring Exception Classes |
|
|
253 | (1) |
|
Adding Custom Constructors |
|
|
253 | (2) |
|
|
255 | (1) |
|
Automating Resource Management |
|
|
256 | (8) |
|
Constructing Try-With-Resources Statements |
|
|
256 | (3) |
|
Learning the New Effectively Final Feature |
|
|
259 | (2) |
|
Understanding Suppressed Exceptions |
|
|
261 | (3) |
|
|
264 | (4) |
|
Validating Data with the assert Statement |
|
|
264 | (2) |
|
|
266 | (1) |
|
|
267 | (1) |
|
|
267 | (1) |
|
Writing Assertions Correctly |
|
|
268 | (1) |
|
Working with Dates and Times |
|
|
268 | (8) |
|
|
269 | (2) |
|
Formatting Dates and Times |
|
|
271 | (5) |
|
Supporting Internationalization and Localization |
|
|
276 | (9) |
|
|
276 | (3) |
|
|
279 | (4) |
|
|
283 | (1) |
|
Specifying a Locale Category |
|
|
284 | (1) |
|
Loading Properties with Resource Bundles |
|
|
285 | (8) |
|
Creating a Resource Bundle |
|
|
286 | (2) |
|
Picking a Resource Bundle |
|
|
288 | (1) |
|
Selecting Resource Bundle Values |
|
|
289 | (2) |
|
|
291 | (1) |
|
Using the Properties Class |
|
|
292 | (1) |
|
|
293 | (1) |
|
|
294 | (1) |
|
|
295 | (14) |
|
Chapter 6 Modular Applications |
|
|
309 | (36) |
|
Reviewing Module Directives |
|
|
310 | (1) |
|
Comparing Types of Modules |
|
|
311 | (5) |
|
|
311 | (1) |
|
|
312 | (3) |
|
|
315 | (1) |
|
|
315 | (1) |
|
Analyzing JDK Dependencies |
|
|
316 | (5) |
|
Identifying Built-in Modules |
|
|
316 | (2) |
|
|
318 | (3) |
|
|
321 | (7) |
|
|
321 | (1) |
|
Exploring a Bottom-Up Migration Strategy |
|
|
322 | (2) |
|
Exploring a Top-Down Migration Strategy |
|
|
324 | (1) |
|
Splitting a Big Project into Modules |
|
|
325 | (1) |
|
Failing to Compile with a Cyclic Dependency |
|
|
326 | (2) |
|
|
328 | (9) |
|
Declaring the Service Provider Interface |
|
|
329 | (1) |
|
Creating a Service Locator |
|
|
330 | (2) |
|
|
332 | (1) |
|
Adding a Service Provider |
|
|
333 | (1) |
|
Merging Service Locator and Consumer |
|
|
334 | (3) |
|
|
337 | (1) |
|
|
337 | (1) |
|
|
338 | (1) |
|
|
339 | (6) |
|
|
345 | (74) |
|
|
347 | (8) |
|
Distinguishing Thread Types |
|
|
348 | (1) |
|
Understanding Thread Concurrency |
|
|
348 | (1) |
|
Defining a Task with Runnable |
|
|
349 | (2) |
|
|
351 | (2) |
|
|
353 | (2) |
|
Creating Threads with the Concurrency API |
|
|
355 | (12) |
|
Introducing the Single-Thread Executor |
|
|
355 | (1) |
|
Shutting Down a Thread Executor |
|
|
356 | (1) |
|
|
357 | (1) |
|
|
358 | (4) |
|
Submitting Task Collections |
|
|
362 | (1) |
|
|
363 | (3) |
|
Increasing Concurrency with Pools |
|
|
366 | (1) |
|
|
367 | (15) |
|
Understanding Thread-Safety |
|
|
367 | (2) |
|
Protecting Data with Atomic Classes |
|
|
369 | (2) |
|
Improving Access with Synchronized Blocks |
|
|
371 | (2) |
|
|
373 | (2) |
|
Understanding the Lock Framework |
|
|
375 | (4) |
|
Orchestrating Tasks with a CyclicBarrier |
|
|
379 | (3) |
|
Using Concurrent Collections |
|
|
382 | (7) |
|
Understanding Memory Consistency Errors |
|
|
383 | (1) |
|
Working with Concurrent Classes |
|
|
383 | (5) |
|
Obtaining Synchronized Collections |
|
|
388 | (1) |
|
Identifying Threading Problems |
|
|
389 | (5) |
|
|
390 | (3) |
|
|
393 | (1) |
|
Working with Parallel Streams |
|
|
394 | (10) |
|
Creating Parallel Streams |
|
|
395 | (1) |
|
Performing a Parallel Decomposition |
|
|
396 | (2) |
|
Processing Parallel Reductions |
|
|
398 | (5) |
|
Avoiding Stateful Operations |
|
|
403 | (1) |
|
|
404 | (1) |
|
|
405 | (1) |
|
|
406 | (13) |
|
|
419 | (56) |
|
Understanding Files and Directories |
|
|
420 | (6) |
|
Conceptualizing the File System |
|
|
420 | (2) |
|
|
422 | (1) |
|
Introducing the File Class |
|
|
422 | (4) |
|
|
426 | (7) |
|
Understanding I/O Stream Fundamentals |
|
|
426 | (1) |
|
Learning I/O Stream Nomenclature |
|
|
427 | (6) |
|
Common I/O Stream Operations |
|
|
433 | (7) |
|
|
433 | (2) |
|
|
435 | (1) |
|
Manipulating Input Streams |
|
|
436 | (2) |
|
|
438 | (1) |
|
Reviewing Common I/O Stream Methods |
|
|
439 | (1) |
|
Working with I/O Stream Classes |
|
|
440 | (18) |
|
Reading and Writing Binary Data |
|
|
440 | (1) |
|
|
441 | (2) |
|
Reading and Writing Character Data |
|
|
443 | (1) |
|
|
444 | (1) |
|
|
445 | (7) |
|
|
452 | (5) |
|
|
457 | (1) |
|
|
458 | (6) |
|
Printing Data to the User |
|
|
459 | (1) |
|
Reading Input as a Stream |
|
|
460 | (1) |
|
|
460 | (1) |
|
Acquiring Input with Console |
|
|
461 | (3) |
|
|
464 | (1) |
|
|
464 | (2) |
|
|
466 | (9) |
|
|
475 | (54) |
|
|
476 | (10) |
|
|
477 | (1) |
|
|
478 | (5) |
|
Understanding Common NIO.2 Features |
|
|
483 | (3) |
|
|
486 | (9) |
|
Viewing the Path with toString(), getNameCount(), and getName() |
|
|
486 | (1) |
|
Creating a New Path with suhpath() |
|
|
487 | (1) |
|
Accessing Path Elements with getFileName(), getParent(), and getRoot() |
|
|
488 | (2) |
|
Checking Path Type with isAbsolute() and to AbsolutePath() |
|
|
490 | (1) |
|
Joining Paths with resolve() |
|
|
491 | (1) |
|
Deriving a Path with relativize() |
|
|
491 | (2) |
|
Cleaning Up a Path with normalize() |
|
|
493 | (1) |
|
Retrieving the File System Path with toRealPath() |
|
|
493 | (1) |
|
|
494 | (1) |
|
Operating on Files and Directories |
|
|
495 | (8) |
|
Checking for Existence with exists() |
|
|
495 | (1) |
|
Testing Uniqueness with isSameFile() |
|
|
496 | (1) |
|
Making Directories with createDirectory() and createDirectoriesQ |
|
|
497 | (1) |
|
Copying Files with copy() |
|
|
498 | (2) |
|
Moving or Renaming Paths with move() |
|
|
500 | (1) |
|
Deleting a File with delete() and deletelfExists() |
|
|
500 | (1) |
|
Reading and Writing Data with newBufferedReader() and newBufferedWriter() |
|
|
501 | (1) |
|
Reading a File with read All Lines() |
|
|
502 | (1) |
|
|
502 | (1) |
|
|
503 | (5) |
|
Discovering File Attributes |
|
|
503 | (3) |
|
Improving Attribute Access |
|
|
506 | (2) |
|
Applying Functional Programming |
|
|
508 | (9) |
|
Listing Directory Contents |
|
|
508 | (2) |
|
Traversing a Directory Tree |
|
|
510 | (4) |
|
Searching a Directory with find() |
|
|
514 | (1) |
|
Reading a File with lines() |
|
|
515 | (2) |
|
Comparing Legacy java.io.File and NIO.2 Methods |
|
|
517 | (1) |
|
|
518 | (1) |
|
|
518 | (2) |
|
|
520 | (9) |
|
|
529 | (46) |
|
Introducing Relational Databases and SQL |
|
|
530 | (5) |
|
Identifying the Structure of a Relational Database |
|
|
532 | (1) |
|
Writing Basic SQL Statements |
|
|
533 | (2) |
|
Introducing the Interfaces of JDBC |
|
|
535 | (2) |
|
|
537 | (5) |
|
|
537 | (2) |
|
Getting a Database Connection |
|
|
539 | (3) |
|
Working with a PreparedStatement |
|
|
542 | (9) |
|
Obtaining a PreparedStatement |
|
|
543 | (1) |
|
Executing a PreparedStatement |
|
|
543 | (3) |
|
|
546 | (3) |
|
|
549 | (2) |
|
Getting Data from a ResultSet |
|
|
551 | (6) |
|
|
551 | (4) |
|
Getting Data for a Column |
|
|
555 | (1) |
|
|
556 | (1) |
|
Calling a CallableStatement |
|
|
557 | (4) |
|
Calling a Procedure without Parameters |
|
|
558 | (1) |
|
|
559 | (1) |
|
Returning an OUT Parameter |
|
|
559 | (1) |
|
Working with an INOUT Parameter |
|
|
560 | (1) |
|
Comparing Callable Statement Parameters |
|
|
560 | (1) |
|
Closing Database Resources |
|
|
561 | (3) |
|
|
564 | (1) |
|
|
564 | (2) |
|
|
566 | (9) |
|
|
575 | (36) |
|
Designing a Secure Object |
|
|
576 | (7) |
|
|
576 | (1) |
|
Restricting Extensibility |
|
|
577 | (1) |
|
Creating Immutable Objects |
|
|
578 | (3) |
|
|
581 | (2) |
|
Introducing Injection and Input Validation |
|
|
583 | (5) |
|
Preventing Injection with a PreparedStatement |
|
|
583 | (3) |
|
Invalidating Invalid Input with Validation |
|
|
586 | (2) |
|
Working with Confidential Information |
|
|
588 | (3) |
|
Guarding Sensitive Data from Output |
|
|
589 | (1) |
|
Protecting Data in Memory |
|
|
589 | (1) |
|
|
590 | (1) |
|
Serializing and Deserializing Objects |
|
|
591 | (6) |
|
Specifying Which Fields to Serialize |
|
|
591 | (1) |
|
Customizing the Serialization Process |
|
|
592 | (1) |
|
Pre/Post-Serialization Processing |
|
|
593 | (3) |
|
Reviewing Serialization Methods |
|
|
596 | (1) |
|
Constructing Sensitive Objects |
|
|
597 | (3) |
|
|
598 | (1) |
|
|
598 | (1) |
|
Making the Constructor private |
|
|
599 | (1) |
|
Preventing Denial of Service Attacks |
|
|
600 | (3) |
|
|
600 | (1) |
|
Reading Very Large Resources |
|
|
600 | (1) |
|
Including Potentially Large Resources |
|
|
601 | (1) |
|
|
601 | (1) |
|
|
602 | (1) |
|
|
603 | (1) |
|
|
604 | (1) |
|
|
605 | (6) |
|
|
611 | (1) |
|
Appendix A The Upgrade Exam |
|
|
611 | (46) |
|
Working with Local Variable Type Inference |
|
|
612 | (5) |
|
|
613 | (1) |
|
|
614 | (3) |
|
|
617 | (1) |
|
|
617 | (4) |
|
|
618 | (1) |
|
|
619 | (2) |
|
Creating and Running a Modular Program |
|
|
621 | (7) |
|
|
622 | (1) |
|
Compiling Our First Module |
|
|
623 | (2) |
|
|
625 | (2) |
|
Packaging Our First Module |
|
|
627 | (1) |
|
Updating Our Example for Multiple Modules |
|
|
628 | (7) |
|
Updating the Feeding Module |
|
|
628 | (1) |
|
|
629 | (2) |
|
Creating the Talks Module |
|
|
631 | (3) |
|
Creating the Staff Module |
|
|
634 | (1) |
|
Diving into the module-info File |
|
|
635 | (4) |
|
|
635 | (1) |
|
|
636 | (3) |
|
provides, uses, and opens |
|
|
639 | (1) |
|
|
639 | (6) |
|
|
639 | (4) |
|
|
643 | (1) |
|
|
643 | (2) |
|
|
645 | (1) |
|
Reviewing Command-Line Options |
|
|
645 | (3) |
|
|
648 | (1) |
|
|
649 | (1) |
|
|
650 | (7) |
|
Appendix B Answers to Review Questions |
|
|
657 | (40) |
|
Chapter 1 Java Fundamentals |
|
|
658 | (4) |
|
|
662 | (3) |
|
Chapter 3 Generics and Collections |
|
|
665 | (4) |
|
Chapter 4 Functional Programming |
|
|
669 | (3) |
|
Chapter 5 Exceptions, Assertions, and Localization |
|
|
672 | (4) |
|
Chapter 6 Modular Applications |
|
|
676 | (2) |
|
|
678 | (4) |
|
|
682 | (3) |
|
|
685 | (4) |
|
|
689 | (2) |
|
|
691 | (2) |
|
Appendix A: The Upgrade Exam |
|
|
693 | (4) |
Index |
|
697 | |