1 Understanding Java Technology and environment
1.1 Describe Java Technology and the Java development
1.2 Identify key features of the Java language
2 Working With Java Primitive Data Types and String APIs
2.1 Declare and initialize variables (including casting and promoting primitive data types)
-
Identifier
- May only contain letters, numbers,
$
, or_
- Mustn't start with a number
- Mustn't be a single
_
(Java 9+), but_
can still be used as part of an identifier. - Mustn't be a reserved word
- May only contain letters, numbers,
-
Integer literals
-
integer literal falling into the scope of a certain type can be assigned without a cast
byte
: -128 -> 127short
: -32768 -> 32767char
: 0 -> 65535int
: -2147483648 -> 2147483647long
: any other integer literal, requiringL/l
suffix
byte b = 100; // 100 < 127 OK byte b1 = 128; // 128 > 127 Compiler error short s = 'A'; // 'A' < 32767 OK short s1 = '艺'; // 33402 ('艺') > 32767 Compiler error
-
integer literal prefix
- Hex:
0x
- Oct:
0
- Bin:
0b
- Underscore in numerical literals (opens in a new tab)
- An underscore
_
can be placed in any numeric literal, between any two digits, so long as it is not at the beginning, the end, or next to a decimal point.
. - Underscores can even be placed next to each other.
- An underscore
- Hex:
-
-
Primitive Conversion
- Narrowing conversion
- Explicit
- Widening conversion
- Implicit
- Most preserve precision
- Some lose precision
int
->float
long
->float
long
->double
- Narrowing conversion
-
Unboxing will throw NPE if the boxed value is null.
2.2 Identify the scope of variables
- local variable
- Must be initialized before being accessed
- If declared and initialized on different lines, there can't be statement in between trying to read the variable, which would cause compiler error.
- Must be initialized before being accessed
2.3 Use local variable type inference
var
is not a keyword but a reserved type name. This means that code that usesvar
as a variable, method, or package name will not be affected. Therefore,var
can continue to be used as a variable name, method name, package name, but not a type declaration.var
is not allowed in a compound declaration- Compiler error:
var fall2 = 2, autumn2 = 2;
- Compiler error:
var
cannot be assigned tonull
upon declaration.
2.4 Create and manipulate Strings
java.lang.String.intern
returns aString
from the string pool.java.lang.String.concat
/+
returns a newString
object.java.lang.String.lastIndexOf
search backwards, by default from the endint lastIndexOf(String str, int fromIndex)
from the specified index
java.lang.String.repeat
(opens in a new tab)java.lang.String.indexOf
search forwards, by default from the start, namely zero index.- if
fromIndex
is specified, it would start search from that position.
- if
String.strip
(Java 11+)- strip is Unicode whitespace aware, whereas the existing method trim removes any space which is less than or equal to (\u0020)
2.5 Manipulate data using the StringBuilder
class and its methods
StringBuilder
class uses a dynamic array to hold the string similar to anArrayList
.toString
creates a newString
object.StringBuilder.substring
andString.substring
throw runtime exception when:- beginIndex is negative
- endIndex is negative
- beginIndex is larger than endIndex
- endIndex is larger than string length
StringBuilder.substring
andString.substring
return empty string when beginIndex equals to endIndex.StringBuilder
implementsjava.lang.Comparable.compareTo
(11+)append
can specify start and enbd index for the target sequence to be appended.StringBuilder
doesn't overrideequals
method, therefore itsequals
is equivalent to==
.
3 Working with Java Arrays
- API
array.length
is the capacity of the array, not the actual number of elements in the array- For comparison,
Collection.size()
returns the actual number of elements in the collection, alladd
,remove
methods andclear
will change size. Passingnull
withadd
andremove
will change size too.
- For comparison,
Arrays.compare
(Java 9+)null
comes first.
Arrays.mismatch
(Java 9+)- Return the index of the first mismatch between the two arrays, otherwise -1.
- Array does not override equal method, so
Arrays.equals
should be used to compare equality of two arrays, while usingequals
method on array instances has the same effect as identity equality. ArrayStoreException
: Array keeps type information in runtime, for reference type, it works when a subclass object is assigned to a cell of a superclass type, but anArrayStoreException
would be thrown if the types are not compatible.Arrays.binarySearch
works the same way as with Java Collections.Arrays.asList
- Only allowed modifications are
set
andsort
, others causing compiler errors - Modifications to the list will reflect in the array and vice versa, as the array is used to back the list.
- Only allowed modifications are
List.of
- No modification allowed, all generating compiler errors
<T> T[] list.toArray(T[] a)
- If the array's length is smaller than the list's size, the list's size will be used for copying and a new array will be created instead to store the contents.
- If the array's length is greater than or equal to the list's size, the array will be used for copying, with spaces if any padded with
null
.
Arrays.equals
Object[] a, int aFromIndex, int aToIndex, Object[] b, int bFromIndex, int bToIndex
Arrays.sort
- Can specify a range to sort by providing start and end index.
3.1 Declare, instantiate, initialize and use a one-dimensional array
-
Array initializer such as
int[] a = {1}
can only be used upon variable declaration.int[] c = {1, 2, 3}; // Correct // or int[] c = new int[]{1, 2, 3}; // Correct // or int[] c; c = new int[]{1, 2, 3}; // Correct int[] c; c = {1, 2, 3}; // Compiler error
-
int ids[], types;
gives us an int array called ids and an int called types. -
Array reference can be assigned to another array of its parent type.
String[] strs = {"abc", "def"}; Object[] objs = strs; Integer[] ints = {1, 2, 3}; Number[] nums = ints;
3.2 Declare, instantiate, initialize and use a two-dimensional array
-
Multi-dimensional array is essentially an array of array pointers.
-
For multi-dimensional array, the length of first dimension is required. Lengths of other dimensions could be omitted or zero.
-
int[][] a = new int[3][];
creates an array of three null pointers. -
int[][] a = new int[3][2];
creates an array of three array pointers, each of which points to a newly created array with specified elements of initial value ([0, 0]
in this case). Memory space will not be allocated without the length of the corresponding dimension. -
If the lengths of higher dimensions are specified, corresponding memory space will be allocated. If not, the pointers to higher dimensions will remain
null
. In either case, they can be modified and assigned a new pointer to an array. Their lengths will be decided during runtime by the real contents of the arrays.Object[][][] objs = new Object[3][0][0]; objs[0] = new Object[5][]; objs[0][0] = new Object[7]; objs[0][1] = new Object[8]; objs[0][2] = new Object[6]; objs[0][3] = new Object[9]; objs[0][4] = new Object[10]; objs[1] = new Object[2][]; objs[1][0] = new Object[21]; objs[1][1] = new Object[22]; objs[2] = new Object[3][]; objs[2][0] = new Object[31]; objs[2][1] = new Object[32]; objs[2][2] = new Object[33];
-
If first dimension has a length, second and third can leave it out, or second could have the length, while third leaves it out. But it cannot be that second leaves it out and third has a length.
4 Creating and Using Methods
4.1 Create methods and constructors with arguments and return values
-
Method signature
- method name
- parameter list
-
Varargs
-
Must be the last parameter
-
Only one is allowed if any
-
Considered the same type as array in parameter list
class Parent { void t1(int[] a1, int... a2) { } } class Child extends Parent { @Override void t1(int[] a1, int[] a2) { // Compiles } }
-
-
Constructors
-
When there is no constructor defined in a class, Java compiler will generate a default no-argument constructor with a
super()
in it, and the access modifier of the constructor is the same as the class. This would require parent having a no-argument constructor defined. -
The Java compiler automatically inserts a call of
super()
to all constructors whose first statement is notsuper()
orthis()
. -
If the parent class doesn't define a no-argument constructor, an explicit call to a parent constructor in the child constructor is required.
-
this()
orsuper()
must be the first statement of a constructor body, therefore only one of them is allowed in one constructor. -
A constructor cannot call itself recursively.
-
If a parent class only has
private
constructors, only an inner class is able to extend it, because the child class definition must be part of the parent class to be able to callprivate
parent constructors.class Parent { } class Child extends Parent { Child() { // if not present, generated implicitly, Line 1 super(); // Line 2 } // Line 3 } // or class Child extends Parent { Child() { super(); // if first line of constructor is not a call // to a parent constructor, generated implicitly } }
-
4.2 Create and invoke overloaded methods
-
Multiple overloaded method
-
Argument doesn't down cast.
-
As few conversion as possible
@Test public void t() { Q26 test = new Q26(); test.printMessage(1); // print "Argument is long" } void printMessage(short argument) { System.out.println("Argument is short"); } void printMessage(Integer argument) { System.out.println("Argument is Integer"); } void printMessage(long argument) { System.out.println("Argument is long"); }
-
Argument's reference type, not its runtime type, is used to match method parameter type
@Test public void t() { Plant p = new Plant(); Plant f1 = new Flower(); Flower f2 = new Flower(); Collection c = new ArrayList<>(); p.print(c); // Plant C f1.print(c); // Flower C f2.print(c); // Flower C List d = new ArrayList<>(); p.print(d); // Plant C f1.print(d); // Flower C f2.print(d); // Flower L } class Plant { void print(Collection c) { System.out.println("Plant C"); } } class Flower extends Plant { void print(Collection c) { System.out.println("Flower C"); } void print(List m) { System.out.println("Flower L"); } }
-
4.3 Apply the static keyword to methods and fields
-
static
variable-
A
static
variable can be accessed via an instance of the class, even if the instance isnull
.Koala k = new Koala(); System.out.println(k.count); // k is a Koala k = null; System.out.println(k.count); // k is still a Koala
-
If parent and child class have
static
variables with the same name, it would cause hiding, regardless of access modifier, type of the variables.
-
-
static
method- Mustn't reference any non-static field or method such as
this
orsuper
.
- Mustn't reference any non-static field or method such as
-
Inheritance
- All
static
methods or fields that are accessible are not inherited by subclasses, and they are simply accessible- with a child referencing type or instance
- without a referencing type inside a child type
- Even if the referencing type is child class or object, they would still refer to the parent's version. Subclasses do not have a copy of their own.
static
methods can be hidden in the child class, but still determined by the referencing type.
- All
5 Reusing Implementations Through Inheritance
5.1 Create and use subclasses and superclasses
-
instance methods & fields
- All instance methods that are accessible are inherited by subclasses.
- If overriden, child's version would be used, otherwise parent's version would be used.
- All instance fields that are accessible are inherited by subclasses.
- When having the same type and name, fields in parent class are hidden. The version to be used is determined by the referencing type.
- If not hidden, subclasses would have their own copy of the fields. They would be used no matter the referencing type is parent class or child class.
- All instance methods that are accessible are inherited by subclasses.
5.2 Create and extend abstract classes
abstract
classes may have zero or moreabstract
methods and concrete methods.- Non
abstract
classes mustn't haveabstract
methods. - It is a compile-time error if a class is declared both
final
andabstract
. abstract
classes can have constructors, and they can only be called when theabstract
class is being initialized through a subclass.- If an
abstract
class does not provide a constructor, the compiler will still automatically insert a default no-argument constructor. - A
abstract
method cannot be marked asprivate
orfinal
. static
method cannot be marked asabstract
.
5.3 Enable polymorphism by overriding methods
-
final
methodsfinal
instance methods cannot be overridden.static
methods andprivate
instance methods can befinal
, but it's redundant and has no effect.
-
private
methods- parent
private
method with the same name in child class is not considered overridden, therefore when invoked on parent type reference, parent's version would be invoked.
- parent
5.4 Utilize polymorphism to cast and call methods, differentiating object type versus reference type
-
Compiler check for type cast and
instanceof
is based on deduction.- Fail if
- Target is an unrelated class
- Target is an unrelated interface while the class itself is also final
- Pass if
- Target is an unrelated interface while the class itself is not final
- Fail if
-
Type cast
-
A class can only be directly cast from a type from its ancestry.
-
This can be worked around by assigning to a common ancestor for transition. This will pass compiler check, but causing
ClassCastException
in runtime.// cast to an unrelated class Long x = (Long) new RuntimeException(); // Compiler error Object a = new RuntimeException(); Long d = (Long) a; // Compiler OK, ClassCastException in runtime // a non-final class cast to an unrelated interface Runnable r = (Runnable) new RuntimeException(); // Compiler OK, ClassCastException in runtime // a final class cast to an unrelated interface Runnable r = (Runnable) new String(); // Compiler error
-
-
instanceof
BigDecimal tickets = BigDecimal.ZERO; if (tickets instanceof Collections) { // Compiler error when target is an unrelated class } BigDecimal t = BigDecimal.ZERO; if (t instanceof List) { // Compiler OK when target is an unrelated interface, and the class is not final } String s = ""; if (s instanceof List) { // Compiler error when target is an unrelated interface, and the class is final }
5.5 Distinguish overloading, overriding, and hiding
-
Overloading
-
Same name, different parameters
-
When child and parent types are both present, choosing the closest one without promoting.
-
When neither of two types can be determined to be closer to the argument, compiler error will occur saying ambiguous method
-
Primitives and their wrapper classes are considered different types, and invocation will choose the closest type without boxing or unboxing
void autobox(int p) { System.out.println("autobox int"); } void autobox(Integer p) { System.out.println("autobox Integer"); }
-
Due to type erasure, parameters of the different generic types are considered the same.
-
Only one conversion is allowed
public class TooManyConversions { public static void play(Long l) {} public static void play(Long... l) {} public static void main(String[] args) { play(4); // DOES NOT COMPILE play(4L); // calls the Long version } }
-
-
Overriding
-
Suppose both methods have the same signature
- instance -> static: compilation error (methods with same signature)
- static -> instance: compilation error (methods with same signature)
- instance -> instance: overriding
- static -> static: hiding
-
The method in the child class must have the same signature as the method in the parent class.
-
The method in the child class cannot be more restrictive than the method in the parent class.
- eg:
protected
->public
is allowed, notpublic
toprotected
.
- eg:
-
The method in the child class may not throw a checked exception that is new or broader than the class of any exception thrown in the parent class method.
- In other words, checked exceptions thrown by the child must be able to be covered by those thrown by the parent.
- eg: parent:
IOException
,SQLException
; child:FileNotFoundException
-
If the method returns a value, its type must be the same or a subclass of the type return by the method in the parent class, known as covariant return types.
-
Autoboxing types and primitive types are not considered covariant return types to each other.
-
Methods with generic type parameters must be overridden with the exact same generic type.
class Parent { void test(List<String> args) { System.out.println("Parent test"); } } class Child extends Parent { @Override void test(List<String> args) { // If it's not String, there'd be a compiler error System.out.println("Child test"); } }
-
Methods whose return value is generic can be overridden with a return value of subtype with the exact same generic parameter type, considered covariant.
class Parent { List<String> test(List<String> args) { System.out.println("Parent test"); return Collections.emptyList(); } } class Child extends Parent { @Override ArrayList<String> test(List<String> args) { System.out.println("Child test"); return new ArrayList<>(); } }
-
Implementing a method is essentially overriding a method when the parent version is abstract. Therefore all the rules about overriding are applicable.
-
abstract
class extending a concrete class can override a concrete method with anabstract
method.
-
-
Hiding
-
Must meet the same criteria of overriding
-
Only happens to
static
methods. -
If the
static
method is invoked inside of the same class without a reference variable, thestatic
method in the same class would be used. -
If the
static
method is invoked with a variable, its invocation would depend on the type of the variable. -
If both parent and child have a
static
method with the same signature, calling this method with an instance, the invoked method will be determined by the type of the variable.@Test public void m() { Child c = new Child(); c.t1(); // print "Child" Parent p = new Child(); p.t1(); // print "Parent" } class Parent { static void t1() { System.out.println("Parent"); } } class Child extends Parent { static void t1() { System.out.println("Child"); } }
-
The version of the overridden method that gets invoked is the one in the subclass. The version of the hidden method that gets invoked depends on whether it is invoked from the superclass or the subclass.
-
6 Handling Exceptions
6.1 Describe the advantages of Exception handling and differentiate among checked, unchecked exceptions, and Errors
-
Any checked exceptions cannot be caught without invoked methods declaring one.
Exception
can still be caught without declared, as it's a super class ofRuntimeException
as well.
-
Error
s are essentially unchecked exceptions that extend theError
class, thrown by the JVM, and can but shouldn't be handled or declared.
6.2 Create try-catch blocks and determine how exceptions alter program flow
-
try
must be followed by either acatch
or afinally
block. -
For multiple
catch
blocks, at most onecatch
block will run, and it will be the firstcatch
block that can handle it. -
Exception types in multi-catch must be disjoint.
-
Exception variable of multi-catch is
final
, so cannot be reassigned. -
Exception variable of
catch
is notfinal
, but its type is fixed, therefore casting is required for narrowing conversion.try { System.exit(0); } finally { System.out.print("Never going to get here"); // Not printed }
-
finally
decides execution flowfinaly
gets run almost always, but doesn't get executed when JVM exits.- Throwing exceptions in
finally
will cause it unfinished. - If
try
throws an exception that is not compatible with any catch clause, andfinally
block also throws an exception, the one thrown bytry
block will be discarded. - If
catch
block andfinally
block throw an exception respectively, the one thrown bycatch
block will be discarded. - If
try
,catch
andfinally
all return a value,finally
's return value will override those oftry
andcatch
. In other words, thereturn
statements intry
andcatch
are redundant whenfinally
returns a value. - JLS - Execution of try-finally and try-catch-finally (opens in a new tab)
-
try-with-resources
-
try-with-resources can only have
AutoCloseable
variable declarations, separated by semi-colon if multiple. -
All variables used as try-with-resources resource must be
final
or effectively final, no matter where they are declared. -
Declared resource variables are local to the
try
block, sovar
can be used. -
catch
andfinally
block are both optional for try-with-resources. -
A user defined
finally
block gets executed after the implictfinally
block. -
Resources are closed after the
try
clause ends and before anycatch
/finally
clauses. -
Resources are closed in the reverse order from which they were created.
-
An already defined final or effectively final
AutoCloseable
variable can be used in try-with-resources statement. (9+)// New and improved try-with-resources statement in JDK 9 try (resource1; resource2) { // Use of resource1 and resource 2. }
-
6.3 Create and invoke a method that throws an exception
- A method that declares an exception (checked or not) isn't required to throw one.
- But
catch
requires the exceptions declared on the invoked method get handled. - Thrown checked exceptions must be either caught or declared on method signature.
- Classes listed in the throws part of a method declaration must extend
java.lang.Throwable
. - The checked exceptions handled by
catch
block(s) must match the checked exceptions declared on the method, making sure all checked exceptions possibly thrown by the method would be handled should they ever happen. Also handling checked exception not declared on the method is not allowed. catch
onjava.lang.Exception
is permitted without invocations declaring any checked exceptions.
7 Creating a Simple Java Program
7.1 Create an executable Java program with a main class
7.2 Compile and run a Java program from the command line
7.3 Create and import packages
-
Multiple wildcard imports containing same class name would cause conflict, and therefore fully qualified class name reference is required.
-
Explicit import of class trumps wildcard import of classes with the same name.
import foo.*; import bar.*; import bar.Greeting; // Comment this line would cause compiler error at call site import org.junit.Test; public class Q23 { @Test public void t() { Greeting greeting = new Greeting(); System.out.println(greeting.say()); } }
8 Using Operators and Decision Constructs
8.1 Use Java operators including the use of parentheses to override operator precedence
-
Operator order
- Compare Precedence
- Check Associativity
-
a++
generates bytecode:ILOAD 1
IINC 1 1
The old value is pushed to the operand stack, and if it is stored back to the variable array, the incremented value will get overridden, because theIINC
instruction increment the variable without pushing it to the operand stack.
-
Unary plus/minus sign means positive/negative number, and it can be used before a variable
-
The result of an assignment is an expression in and of itself, equal to the value of the assignment.
-
null == null
:true
-
Calling
instanceof
on thenull
literal or anull
reference always returnsfalse
, andnull instanceof null
does not compile. -
Compound assignment operators
- Auto casting JLS 15.26.2 (opens in a new tab)
-
Conditional operator
-
The conditional operator is syntactically right-associative (it groups right-to-left). (JLS 15.25 (opens in a new tab))
-
Second and third expressions can have different types, as long as the assignment type is compatible with both expressions.
Number r = a > b ? 8L : 3.2F;
-
-
References
8.2 Use Java control statements including if, if/else, switch
-
if/else
- A single pair of
if/else
can be considered as a single statement.
- A single pair of
-
switch
- The type of the expression can be Enum or any integer type (also their object wrapper) except
long
, andString
. - The expression cannot be resolved to
null
, which would cause NPE. var
can be used for the expression, if it can be resolved to a supported type, but it cannot be used for acase
expression.- Only the matched
case
gets executed, the order of cases does not matter when matching expression value. case
expression must be a compile-time constant, therefore known before runtime. Such as:- number / string literals
- enum values
final
variables of supported types
- The type of the expression can be Enum or any integer type (also their object wrapper) except
8.3 Create and use do/while, while, for and for each loops, including nested loops, use break and continue statements
-
For
for
,while
ordo/while
orif
, variables with duplicate name of local variable cannot be declared in those constructs. -
Variables declared in those constructs cannot be accessed outside in the enclosing method.
-
for
- variable can be any type.
- If declared in
for
construct, all variables must be of the same type. - To have multiple variables of different types, they can be declared outside the
for
construct.
9 Describing and Using Objects and Classes
9.1 Declare and instantiate Java objects, and explain objects' lifecycles (including creation, dereferencing by reassignment, and garbage collection)
-
Initialization block
-
Order of execution upon creation of an object
static
initialization blocks- Run in the order of definition in the class
- Only run once for the first time an instance is created, not necessarily an instance of the same class. It could be a subclass.
- Parent first, child next, following the inheritance tree
- instance initialization blocks
- Run in the order of definition in the class
- Run every time an instance is created
- Constructor
- Run the chain of constructors, starting from the
java.lang.Object
constructor
- Run the chain of constructors, starting from the
-
When parent and child both have all three initialization constructs
- parent
static
initialization block(s) - child
static
initialization block(s) - parent instance initialization block(s)
- parent constructor(s)
- child instance initialization block(s)
- child constructor(s)
- parent
-
When a field is initialized with an expression, this expression can be considered an initialization block.
-
During compilation, the body of each instance initialization block is copied to all the constructors in the order the block is declared. This copied code is placed right before the existing code in those constructors.
-
9.2 Define the structure of a Java class
- A top-level
class
orinterface
can only be declared withpublic
or package-private access.
9.3 Read or write to object fields
-
Fields
-
All
static
and instance fields declaration are processed before respective initialization blocks. -
final static
variables can be defined upon declaration or in anystatic
initialization block and cannot be changed thereafter. -
final
instance variables can be defined upon declaration or in any initialization block or in any constructor. They are equivalent and cannot be changed thereafter. -
A field's forward reference reading must have a prefix
-
static
field- Can modify it if it's not
final
, or define it if it'sfinal
- Cannot read it before
static
initialization is finished - Must read it via Class reference
class Child { static { count = 3; // OK System.out.println(count); // Compiler error System.out.println(Child.count); // OK } static int count; }
- Can modify it if it's not
-
instance field
- Can modify it if it's not
final
, or define it if it'sfinal
- Cannot read it before instance initialization is finished
- Must read it via
this
reference
class Child extends Parent { { count = 10; System.out.println(count); // Compiler error System.out.println(this.count); // OK } int a = 2 + count; // Compiler error int b = 2 + this.count; // OK int count = 10; }
- Can modify it if it's not
-
-
Field hiding
-
Only the type of the Primary expression, not the class of the actual object referred to at run time, is used in determining which field to use.
class Parent { protected int number = 10; static int count = 12; } class Child extends Parent { protected int number = 25; static int count = 27; } public class Test { @Test public void t() { Child c = new Child(); System.out.println(c.number); // 25 System.out.println(c.count); // 27 Parent p = c; System.out.println(p.number); // 10 System.out.println(p.count); // 12 } }
-
In the child class, the parent's hidden instance variable can be accessed using
super
-
-
10 Applying Encapsulation
10.1 Apply access modifiers
10.2 Apply encapsulation principles to a class
11 Programming Abstractly Through Interfaces
11.1 Create and implement interfaces
-
interface
is implicitlyabstract
. -
interface
can extend multipleinterface
s. -
interface
doesn't inherit fromjava.lang.Object
, when it has no direct superinterfaces, everypublic
instance method injava.lang.Object
will be implicitly declared in thisinterface
. -
abstract
methods ininterface
andabstract
class can be duplicate, abiding by the same rules of overriding, but they are considered compatible. -
When implementing multiple
interface
s with duplicateabstract
methods, to resolve incompatibility- For declared checked exception, intersection of the exceptions declared on all compatible abstract methods can be declared on the concrete version of the method. If the intersection is none, then no checked exception can be declared.
- For return type, intersection of the return types of all compatible abstract methods can be used as the return type of the concrete version of the method. If the intersection is none, the method would cause compiler error, therefore the intersection cannot be none.
-
Fields allowed in interface
- all variables are
public static final
with the three keywords optional.
- all variables are
-
Methods allowed in interface
public abstract
instance methods (public
andabstract
are both optional)public
static methods (public
is optional)private
static methodsprivate
instance methodspublic default
instance methods (public
is optional, methods can be overridden in subclasses)
-
Implementing multiple interfaces
- Abstract and default methods or multiple default methods with the same name conflict with each other, causing compilation error.
- Only multiple abstract methods with the same name are allowed.
- If the conflicting default methods are overriden as an abstract or concrete method, there wouldn't be any compilation error.
11.2 Distinguish class inheritance from interface inheritance including abstract classes
11.3 Declare and use List and ArrayList instances
Arrays.binarySearch
andCollections.binarySearch
return(-(insertion point) - 1)
when the target element cannot be found.AbstractList
overridesequals
method, which returns true when two lists have the same elements in the same order.- Only
java.util.List
provides thesort
method as a shortcut toCollections.sort
. Neitherjava.util.Set
norjava.util.Map
has that. java.util.List.of
, as well asList.copyOf
, forbids any modifications, all of which throwingUnsupportedOperationException
11.4 Understanding Lambda Expressions
-
If there are braces, statements must be complete.
-
Autoboxing doesn't work for Predicates, primitives must use primitive type specializations of
java.util.function.Predicate
such asjava.util.function.IntPredicate
. -
Parentheses around parameters are optional only when there is one parameter and its type is omitted.
-
Lambdas can only reference effectively final enclosing local variable and method parameter. They must be effectively final throughout the whole method. Even modification after the invocation of lambda is not allowed.
-
java.lang.FunctionalInterface
annotation enforces the interface only has one abstract method. -
Lambda parameters cannot have the same name as enclosing local variable and method parameter.
-
// Correct @FunctionalInterface public interface PreparedStatementSetup<T> { void run(PreparedStatement ps, T movie); } // Would cause compiler error upon lambda usage, saying "Target method is generic." @FunctionalInterface public interface PreparedStatementSetup { <T> void run(PreparedStatement ps, T movie); }
12 Understanding Modules
- JPMS enables fine-grained package access, as defined in
module-info.java
, that some packages are exposed publicly, while others are for internal use only.
12.1 Describe the Modular JDK
java.base
module is available to all modules.
12.2 Declare modules and enable access between modules
-
The module-info file must be in the root directory of your module, along with all other root packages.
- With Apache Maven's directory structure, this file would be placed under
src/main/java
.
- With Apache Maven's directory structure, this file would be placed under
-
The module name follows the naming rules for package names. It often includes periods ( . ) in its name.
-
module has no modifier.
-
A package is only allowed to be supplied by one module.
-
requires
directive specifies that this module depends on another module. -
The packages in a module are accessible to other modules only if the module explicitly
exports
them inmodule-info.java
.- Exporting is necessary for other code to use the packages; it is not necessary to call the main() method at the command line, therefore main class still can be run.
-
module-info.java
module <module a name> { exports <package name> [to <module name>, <module name>]; requires <module b name>; requires transitive <module c name>; // when module a is required by a module, module c will also be required }
exports
can only export one package per statement, but the package can be exported to multiple modules.exports
moduleto
a specific module will deny other modules' access to it, essentially a white list.requires transitive
essentially means requires the module along with its dependencies.- The same module cannot be repeated in two
requires
clause.
12.3 Describe how a modular project is compiled and run
-
Compiling
-
javac [options] <source files>
-
All paths are relative to the working directory.
-
[options]
- Specify where to find application modules:
-p <path>
/--module-path <path>
- Specify where to find user class files:
-cp <path>
/--class-path <path>
/-classpath <path>
- Specify where to place generated class files:
-d <directory>
- Specify where to find application modules:
-
<source files>
<directories relative to the working directory>/*.java
-
-
Order matters for the list of
<source files>
-
Packaging as a jar file
jar cvf <jar file> [-C <directory>] <class files>
-c
create new archive-v
generate verbose output on standard output-f
specify archive file name-C
change to specified directory.
could be use to denote all files
-
-
Running
-
java -p (or --module-path) <path> -m <module name>/<main class>
- Specify where to find application modules:
-p (or --module-path) <path>
- Specify which main class of which module to run:
-m <module name>/<fully qualified main class>
- slash is required, and both
module name
andfully qualified main class
must be the same identifiers as used in Java code.
- slash is required, and both
- Specify where to find application modules:
-
-
java <main class> <arguments>
- Quotes around arguments are not included.
java Test "1" "2" 3
: arguments are{"1", "2", "3"}
-
-
Describing a module
java -p (or --module-path) <module directory path> -d (or --describe-module) <module name>
jar -f (or --file) <module jar file> -d (or --describe-module)
-
List available modules
java --list-modules
lists the JDK’s set of modules.java -p (or --module-path) <module directory path> --list-modules
lists all modules under the module path, in addtion to the JDK modules.
-
View dependencies
jdeps -s (or -summary) --module-path <module directory path> <jar file>
-
Show module resolution
java --show-module-resolution -p (or --module-path) <module path> -d (or --describe-module) <module name>