- Object-oriented
- Encapsulation
- Platform independent
- Robust
- Simple
- Secure
- Multithreaded
- Backward Compatibility
- JRE (no longer separately available):
- JVM
- core classes
- supporting classes
- Interpreter (java)
- Compiler (javac)
- Archiver (jar)
- Documentation generator (javadoc)
- ...
Multiple files:
javac FileName.java
java Filename
One file (in memory):
java FileName.java
Multiple files in multiple packages
javac -d classes packagea/ClassA.java packageb/ClassB.java
javac -d classes packagea/.java packageb/.java
java -cp classes packageb.ClassB
- -cp
- -classpath
- --class-path
- -d
- -cp
- -classpath
- --class-path
- -c
- --create
- -v
- --verbose
- -f
- --file
- -C
Primitives:
- boolean
- byte (8-bit)
- short (16-bit)
- int (32-bit)
- long (64-bit)
- float (32-bit)
- double (64-bit)
- char (16-bit)
Literals can have '_' to make reading big numbers more easy, but not:
- At the beginning
- At the end
- Near a comma
Identifiers:
- Start with a letter, $ or _
- Can hold numbers but not start with them
- Can't be a single '_'
- Can't be a reserved word
Var can only be used with single local variables:
- Not with instance~ or class variables
- Not in constructor or method parameters
- Not in multiple variable declarations
Scopes:
- Local variables: in scope from declaration to end of block, also in nested blocks
- Instance variables: in scope from declaration until the object is eligible for garbage collection
- Class variable: in scope from declaration until the program ends
An object is eligible for garbage collection:
- when it no longer has any references
- when all references have gone out of scope
Garbage collection:
- Can delete objects from the heap to release memory
- Can only be suggested (System.gc())
- Might never run
Finalize():
- Can run zero or one time(s)
- Was deprecated as of Java 9
Operator precedence:
- Post-unary
- Pre-unary
- Unary
- Multiplication, division & modulus
- Addition & subtraction
- Shift
- Relational
- Equal~ & not equal to
- Logical
- Short-circuit logical
- Ternary
- Assignment
Primitive numeric promotion in arithmetic operations:
- Will always promote primitives smaller than integers to an int
- Will promote the smallest of 2 operands to the larger one
- Will promote an integral data type to its floating-point equivalent when one of the operands is a floating-point
When assigning values:
- Casting to a larger datatype is automatic
- Casting to a smaller data type requires a cast, with possible loss of data
If-statements:
- Can have only one else statement each
- Can be chained
Switch-statements:
- Can be of these data types:
- Integer & int
- Byte & byte
- Short & short
- Character & char
- String
- Enum
- Var
- Case values should be:
- Compile-time constant values (literal, enum or final constant)
- Of the same data type as the switch value
While-statements:
- Might never run if condition is not met
Do/while-statements:
- Always run at least once, even if condition is not met
For-loop:
- Optional
- Initialization statements
- Boolean expressions
- Update statements
- Code block
Enhanced For-loop:
- Iterable collection or array
- Single member data type and handle
Flow statements:
break, continue & return
Labels:
Optional in front of statements that allow flow to jump to or break from that statement
- String, StringBuilder & The String Pool
- Array
- List
- Wrapper class, Autoboxing & Unboxing
- Set & Map
- Math API
Functional Interfaces:
Simplified definition: Functional interfaces have only one abstract method.
-
Predicate:
A function used to return a boolean value.public interface Predicate { boolean test(T t); }
-
Consumer:
A function which takes in one argument and produces a result. However, it doesn't return any value.public interface Consumer { void accept(T t); }
-
Supplier:
A function which does not take in any argument, but produces a value of type T.public interface Supplier { T get(); }
-
Comparator:
A function used to compare 2 objectspublic interface Comparator(T o1, T o2) { int compare(T o1, T o2) }
Has many other static and default methods for writing complex comparators.
Lambda:
- Are only allowed to reference effectively final values
Short notation:
a -> a.System.out.println(a)
Full notation:
(String a, String b) -> { return a.compareTo(b); }
Some API that take lambda's:
- removeIf(): Takes a Predicate
- sort(): Takes a Comparator
- forEach(): Takes a Consumer
Method Signature:
- Access modifier
- Optional specifier
- Return type
- Method name
- Parameter list
- Optional exception list
- Method body
Access Modifiers:
- Private
- None (Package-private)
- Protected
- Public
Optional Specifiers:
- Static
- Abstract
- Final
- Synchronized
- Native
- Scriptfp
With Method overloading:
- Multiple methods can have the same name with different parameters.
- Type erasure will enforce type constraints only at compile time and discards the element type information at runtime.
Java handles method parameters as pass-by-value, which means we can't reassign parameter values inside a method. However, we can call methods on them.
Java only allows single inheritance. However, we can use multiple interface implementations, or inner classes that inherit from a parent to get around this 'limitation'.
The this keyword helps us to reference an instance variable of the current instance. This is useful when a method or constructor param share the instance variable name.
The super keyword helps us to refer to variables in the scope of a parent class.
Constructors:
- Do not have a return type
- Match name with the name of the class
- Can't have 'var' as params
- Can be overloaded, like methods
- Are called when creating a new object
- Will be provided by the compiler, when we do not (default constructor)
- Final instance fields must be initialized before the end of the constructor
- In the same line
- In an instance initializer block
- In the constructor itself
We can use this() to prevent code duplication when overloading constructors.
- The call to this() has to be first in the constructor
- There can only be one
- Calling on other constructors has to end in a constructor not calling this() at some point (no infinite loops)
We can use super() to call parent constructors when inheriting.
- The call to super() has to be first in the constructor
- There can only be one
When overriding a method:
- It should have the same signature (if it doesn't, we are overloading or creating a new method)
- It has to be at least as accessible as the method in the parent class
- It should return the same type, or a subtype of the method in the parent class
- It can not declare exceptions that are broader than or new those of the parents
When overriding generic methods:
- The collection type has to match (or else you are overloading, instead of overriding)
- The generic type params have to match
When hiding static methods:
- It should have the same signature (if it doesn't, we are overloading or creating a new method)
- It has to be at least as accessible as the method in the parent class
- It should return the same type, or a subtype of the method in the parent class
- It can not declare exceptions that are broader than or new those of the parents
- Both methods should be static
Final methods can't be overridden nor hidden!
Because of polymorphism an object can be accessed using a reference of:
- The same type as the object
- A superclass of the object
- An interface that the object implements
Abstract Classes:
- Do not have to contain abstract methods
- Can not be instantiated
- Can hold all members a regular class can (variables, constructor, ...)
- Can not be final
- Can not be private or protected
Abstract Methods:
- Can only exist in abstract classes or interfaces
- Can not have a method body
- Can not be more accessible than their concrete implementations (*Overriding rules apply!)
- Because it prevents the ability to be overridden:
- They can not be final
- They can not be private
- They can not be static
*Implementing an abstract method = overriding.
Concrete Classes
The first concrete class to inherit from an abstract class:
- Must implement all inherited abstract methods from abstract classes
- Must implement all abstract methods from inherited interfaces
Interfaces:
- Are implicitly abstract and can't be instantiated
- Can only be public or package-private (like classes)
- Members are implicitly assumed to be public
- Variables are implicitly static final (or constant), and thus must be initialized
- Methods without a body are implicitly abstract
- Can hold:
- Constant variables
- Abstract methods
- Static methods (Java 8+)
- Default methods (Java 8+)
- Private methods (Java 9+)
- Private static methods (Java 9+)
- Can extend multiple interfaces! (unlike classes)
- Can not implement other interfaces
- Can not extend, nor implement any classes
- Files can hold only one public interface (like classes)
Interface methods without a body are implicitly abstract.
Default methods can have a body and do not HAVE TO be overridden.
Other methods that contain a body have to be either private, static or private static.
An interface reference can be cast to any reference that inherits the interface,
although this may produce an exception at runtime when they are unrelated.
The instanceof operator can only detect unrelated types if the reference on the left side is marked final.
Inner Classes:
- Member inner classes
- Local classes
- Anonymous classes
- Static nested classes
Member Inner Classes:
- Access modifier is not limited to public or default, like in top-level classes
- Can't have static members
- The wrapper class manages the lifecycle of the inner class
- Object
- Throwable
- Error
- Exception
- RuntimeException
- Throwable
Exceptions:
- Checked: Anticipated* (Inherit Exception)
- Unchecked: Unexpected, but not fatal (Inherit RuntimeException or Error)
*We can catch both, but are only required to handle checked exceptions.
Java throws exceptions:
- When code is wrong
- When stated by the code
Example:
public String trySomething() throws Exception {
throw new Exception();
}
throws: Keyword used at the end of a method to indicate what exceptions it supports
throw: Used as a statement inside a code block to throw an exception
RuntimeExceptions:
- ArithmeticException
- ArrayIndexOutOfBoundsException
- ClassCastException
- NullPointerException
- IllegalArgumentException
- NumberFormatException
Checked exceptions:
- IOException
- FileNotFoundException
Error Classes:
- ExceptionInInitializerError
- StackOverflowError
- NoClassDefFoundExceptions
Exception Handling:
- Try/Catch block (optional *finally{})
- Chaining catch blocks: Handle each exception differently
- Multi-catch block: Handle each exception in the same way
Example:
try {
// Code
} catch (Exception e){
// Exception handling
} finally {
// Final code
}
*Finally blocks are typically used to close resources like files or databases.
We can't catch a subtype of an exception that was caught already by a supertype. The code will not compile because it is unreachable.
- Try-with-Resources (implicit finally{})
- Automates closing used resources
Example:
try (Resource r1 = new Resource; Resource r2 = new Resource){
// Code
} catch (Exception e){
// Exception handling
}
These resources have to implement AutoClosable. A close() method has to be implemented, which Try-with-Resources guarantees to run. It does NOT guarantee the resource will be closed.
The implicit finally-block runs before a finally-block written by the programmer. In fact, it runs right after the try-block, before any catch~ or finally-blocks. They are closed in the reverse order from which they were created.
Because a finally-block is implicit, the Try-with-Resources can exist of just a try-block.
For a catch-block to expect an Exception, a method in the try block has to actually be able to throw it. If the exception or a subclass is not marked with throws for a method in the try-block, the code would be unreachable.
Overriding:
- A subclass is not allowed to add new checked exceptions to the method signature
- A subclass can have less checked exceptions in the method signature
- A subclass can have subclasses of existing exceptions in the method signature
A module is a group of one or more packages plus a special file called module.info.java.
Benefits:
- They provide a 'fifth level' of access control.
- They help with dependency management.
- Creation of smaller runtime images with jlink.
- Improved startup time, because Java knows what modules it will need.
- Enforcing of unique packages to prevent name collisions.
- -d
- -p
- --module-path
- -m
- --module
- -p
- --module-path
Directives:
- module
- exports
- requires
- provides
- uses
- opens
These are special 'keywords' only in module-info.java files.
Exports:
All public classes, enums and interfaces are 'exported'. Public or protected fields and methods in those files are visible, private or package private fields and methods are not.
Example:
module zoo.animal.talks {
exports zoo.animal.talks.content to zoo.animal.staff;
exports zoo.animal.talks.media;
exports zoo.animal.talks.schedule;
requires zoo.animal.feeding;
requires zoo.animal.care;
}
Requires transitive:
Any module that requires this module, also requires ...
Example:
module zoo.animal.care {
exports zoo.animal.care.medical;
requires transitive zoo.animal.feeding;
}
Java doesn't allow duplicate statements.
Provides:
Provides an implementation of a service.
Example:
provides zoo.staff.ZooApi with zoo.staff.ZooImpl
Uses:
Specifies reliance on a service.
Example:
uses zoo.staff.ZooApi
Opens:
Allows reflection.
Example:
opens zoo.animal.talks.schedule;
opens zoo.animal.talks.media to zoo.staff;
java -p out -d zoo.animal.feeding
java -p out --describe-module zoo.animal.feeding
requires java.base mandated is automatically added as a dependency to all modules.
java --list-modules
Including ours:
java -p out --list-modules
java --show-module-resolution -p feeding -m zoo.animal.feeding/zoo.animal.feeding.Task
jar -f out/zoo.animal.feeding.jar -d jar --file out/zoo.animal.feeding.jar --describe-module
jdeps -s out/zoo.animal.feeding.jar
jdeps -summary out/zoo.animal.feeding.jar
jdeps -s --module-path out out/zoo.animal.care.jar
jdeps -summary --module-path out out/zoo.animal.care.jar
They are only used when working with .jmod files, used only with native files or something that doesn't go in a .jar (aka hardly ever).