# Java Basics
# Docs
docs — JDK 11 Documentation - Home (opens new window)
- oracle JDK 1.8 (opens new window)
- CLI tools
- Java Platform, Standard Edition HotSpot Virtual Machine Garbage Collection Tuning Guide, Release 11 (opens new window)
- JSR-000221 JDBC API 4.3 Maintenance Release 3 (opens new window)
- specification (opens new window)
- The Java® Language Specification
- The Java® Virtual Machine Specification
source
# CLI
javac
— compile,javac
docs (opens new window)- timestamps aware — auto compile dependencies and recompile when source file updated according to timestamps
- extra options —
--help-extra
,-X
- warnings —
-Xlint:<key>(,<key>)*
-Xlint
or-Xlint:all
— all checks-Xlint:deprecation
— same as-deprecation
, checks for deprecated methods-Xlint:fallthrough
— checks for missingbreak
statements inswitch
statements-Xlint:finally
— warns about finally clauses that cannot complete normally-Xlint:none
— carries out none of the checks-Xlint:path
— checks that all directories on the class path and source path exist-Xlint:serial
— warns about serializable classes withoutserialVersionUID
-Xlint:unchecked
— warns of unsafe conversions between generic and raw types
java
— execute,java
docs (opens new window)- synopsis
java [options] <mainclass> [args...] (to execute a class) java [options] -m <module>[/<mainclass>] [args...] java [options] --module <module>[/<mainclass>] [args...] (to execute the main class in a module)
- args in
public static void main(String[] args)
— class name is not includedjava Message -g cruel world # args: ["-g", "cruel", "world"]
- jar —
java -jar MyProgram.jar
, see Jarjava [options] -jar <jarfile> [args...]
- single source file program — compile and run, no
.class
file generatedjava [options] <sourcefile> [args]
- args in
-cp
or-classpath
— specify the class pathjava -classpath /home/user/classdir:.:/home/user/archives/archive.jar MyProg
-verbose
— watch class loadingjava -X
— a listing of all nonstandard options-Xprof
— profiling, support was removed in JDK 10-XshowSettings:properties
,-XshowSettings:locale
-Xverify:none
, or-noverify
— turn off verification when loading classes- memory related — see JVM
-XX
—-XX
docs (opens new window), GC Tuning Guide, Release 11 (opens new window)-XX:+PrintFlagsFinal
— print options,java -XX:+PrintFlagsFinal --version
-XX:+PrintCommandLineFlags
— print flags, can check used GC configurations
-ea
, enable and disable assertion — see Assertion-D
, system properties —System::getProperty
,System::getProperties
- log related — see Logging
- log configuration file location —
-Djava.util.logging.config.file=configFile
- log configuration file location —
- see
Properties
for list of system properties
- log related — see Logging
- remote debug
java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n \ -jar target/myapplication-0.0.1-SNAPSHOT.jar # remote debug
javaw
—java
without a shell window
- synopsis
javadoc
— generates HTML documentation from your source files,javadoc
docs (opens new window)- information source
- packages
- public classes and interfaces
- public and protected fields
- public and protected constructors and methods
- assets directory —
/doc-files
directory for assets - syntax
/** ... */
- tags
@
@param variable description
@return description
@throws class description
- more
- HTML tags
- use
{@code ... }
instead of<code>...</code>
to cope with escaping of^
- use
- example
/** * Raises the salary of an employee. * @param byPercent the percentage by which to raise the salary (e.g. 10 means 10%) * @return the amount of the raise */ public double raiseSalary(double byPercent) {}
- more
- information source
javap
— print java class information,javap
docs (opens new window)javap -v -p ClassName
-v
— verbose, some options combined-c
— disassemble the code, can be used to inspect if atomic
-p
-private
— show all classes and members
jshell
— REPL from Java 9,jshell
docs (opens new window)monitoring and troubleshooting tools — see Debugging
serialver
— get serial version ID,serialver
docs (opens new window)sign — Security Tools and Commands (opens new window)
keytool
— signatures, certificates- password for cacerts —
changeit
- password for cacerts —
jarsigner
— add a signature to a (jar) file
javah
— produces a C header file from class files fornative
methods, superseded by superior functionality injavac
, removed since JDK 10
# JAR
jar
— creates an archive for classes and resources, and can manipulate or restore individual classes or resources from an archivejar [OPTION...] [ [--release VERSION] [-C dir] files] ...
- docs (opens new window)
- compression — ZIP
- similar to
tar
jar cvf JARFileName File1 File2 ...
.exe
wrapper — Launch4J, IzPack, etc.- resources
- resources finding — delegates to class loader, which remembers how to locate the class, so it can then search for the associated resource in the same location
URL Class::getResource(String name)
,InputStream Class::getResourceAsStream(String name)
- resource name
- absolute — starts with
/
- relative —
data/text/about.txt
- absolute — starts with
manifest
Manifest-Version: 1.0 lines describing this archive Name: Woozle.class lines describing this file Name: com/mycompany/mypkg/ lines describing this package
- each jar file contains a
META-INF/MANIFEST.MF
manifest file - syntax — key-value entries
- main section — starts with
Manifest-Version
, applies to the whole JAR file - subsequent entries — starts with
Name
, can specify properties of named entities such as individual files, packages, or URLs - section delimiter — blank lines
- file end — the file must end with a newline
- main section — starts with
- edit manifest
jar cfm JARFileName ManifestFileName ... # create jar ufm MyArchive.jar manifest-additions.mf # update
- specify entry point for execution
jar -e
optionMain-Class
in manifest- execution —
java -jar MyProgram.jar
- sealing — a package can have no more classes,
Sealed: boolean
,false
by defaultName: com/mycompany/util/ Sealed: true
- global default defined in main section
- each jar file contains a
# Philosophy
class based
- everything inside class
camelCase naming
Character.isJavaIdentifierStart()
andCharacter.isJavaIdentifierPart()
$
is intended for names that are generated by the Java compiler and other tools
curly braces and semicolons
no operator overloading
no block variable shadowing — may not declare identically named variables in two nested blocks
- in JS and C++ inner one shadows outer one
# Control Flow
switch
- A case label can be
- primitive type expressions — a constant expression of type
char
,byte
,short
, orint
Enum
— likewith
in JSSize sz = . . .; switch (sz) { case SMALL: // no need to use Size.SMALL // . . . break; // . . . }
- strings — Starting with Java SE 7, a string literal, uses
hashCode()
behind scenes
- primitive type expressions — a constant expression of type
- A case label can be
labeled
break
andcontinue
— for labeled blocks, can only jump out of a block, never into a blockiterator —
for (variable : collection) statement
collection
— an array or an object of a class that implements theIterable
interface- see Collections
method
- vararg parameter —
...
- if only an array passed, then that array is used, without nesting
- arity limit — JVM imposes on all methods and constructors of any kind an absolute limit of 255 stacked arguments
long
ordouble
argument — counts (for purposes of arity limits) as two argument slots- non-static methods, constructors,
MethodHandle::invoke
— argument slot overhead
- vararg parameter —
# Package
package
- package name — reversely ordered domain
- package availability — A class can use all classes from its own package and all public classes from other packages.
- package at runtime
- locating classes is done by compiler — the only benefit of the
import
statement is convenience - canonical name after compilation — the byte codes in class files always canonical names to refer to other classes
- locating classes is done by compiler — the only benefit of the
class importation
- built-in —
java.lang
- without
import
— use canonical name import
statementimport java.time.*; import java.time.LocalDate;
- import a class — canonical name
- import a package —
*
- import a inner class —
java.util.AbstractMap.SimpleEntry
- solve name conflict — import the specific class, or use canonical name
import java.util.*; import java.sql.*; // compile-time error when use `Date` class
- static imports — the importing of static methods and fields
import static java.lang.System.*; import static java.lang.System.out;
- built-in —
add to package — put the name of the package at the top of a source file
package com.example;
- directory — match the canonical name
javac com/mycompany/PayrollApp.java java com.mycompany.PayrollApp
- default package — classes belong to the default package if no
package
statement - no custom
java.
prefixed packages — disallow loading of user-defined classes whose package name starts with "java.
"
- directory — match the canonical name
class path
/home/user/classdir:.:/home/user/archives/archive.jar c:\classdir;.;c:\archives\archive.jar
- system property —
java.class.path
- possible components
/home/user/classdir:.:/home/user/archives/'*' # - In UNIX, the `*` must be escaped to prevent shell expansion. # c:\classdir;.;c:\archives\*
- base directory for the package tree
- jar files
- jar file directory
- do not add runtime libary files —
rt.jar
and the other JAR files in thejre/lib
andjre/lib/ext
directories are always searched for classes (modules from JDK 9, and no moreext
)
- used by
java
but notjavac
- the
javac
compiler — always looks for files in the current directory - the
java
virtual machine — launcher only looks into the class path, default class path is.
- the
- class search order
- for
javac
— fromjava.lang
to imports to current package - for
java
— from runtime libary to the class path
- for
- set class path
-cp
or-classpath
optionjava -classpath /home/user/classdir:.:/home/user/archives/archive.jar MyProg # java -classpath c:\classdir;.;c:\archives\archive.jar MyProg
- the
CLASSPATH
environment variable
- system property —
# Fundamentals
# Data Types
# primitive types
integer types
- types
byte
short
— 2 bytesint
long
- number literals
long
—l
orL
suffix forlong
type- hexadecimal, octal and binary —
0x
,0
,0b
or0B
- friendly underscores —
1_000_000
,0b1111_0100_0010_0100_0000
- no
unsigned
- shift overflow bits — mod
1l << 65 // 1l << (65 % 64)
- types
float point types
- types
float
— 4 bytesdouble
- number literals
float
—f
orF
suffixdouble
—d
,D
suffix or no suffix- exponent —
e
- binary exponent —
p
, e.g.0x1.0p-3
(2^-3)
- overflows and errors
Double.POSITIVE_INFINITY
,Double.NEGATIVE_INFINITY
, andDouble.NaN
, also inFloat
Double::isNaN
, also inFloat
- types
char
— describes a code unit in the UTF-16 BE encoding- syntax — single quote
- Unicode escaping, e.g.
\u0fff
— inside and outside quotespublic static void main(String\u005B\u005D args) {} "\u0022+\u0022" // yielding ""+"" // \u000A is a newline // syntax error // since \u000A is replaced with a newline when the program is read // Look inside c:\users // syntax error
- processing — Unicode escape sequences are processed before the code is parsed
- other escapes —
\b
,\t
,\n
,\r
native2ascii
— CLI for converting the native character encoding to plain ASCII, removed in JDK 9 due to the ability to support UTF-8 based properties resource bundles
- code unit — a 16-bit value
- supplementary characters — whose code points are greater than
U+FFFF
, encoded as consecutive pairs of code units, a range of 2048 unused values of the basic multilingual plane - surrogates area — high-surrogates range
U+D800
toU+DBFF
for the first code unit, low-surrogates rangeU+DC00
toU+DFFF
for the second code unit
- supplementary characters — whose code points are greater than
boolean
- cannot convert between integers and boolean values —
if (x = 0)
does not compile - stored as
int
- cannot convert between integers and boolean values —
# primitive type conversion
conversion
- legal conversion — types with less information to types with more information, but not vice versa
- type priority —
double
>float
>long
>int
>char
- implicit conversion using operators — converted to a common type before the operation is carried out
- example — for
int x
,x += 3.5
isx = (int)(x + 3.5)
- example — for
casts
double x = 9.997; int nx = (int) x; int nx2 = (int) Math.round(x); // Math.round() return long for double, int for float
- truncate when out of range —
(byte) 300
is 44 - not between
boolean
and number — cannot cast betweenboolean
values and any numeric type
- truncate when out of range —
# other types
enum
enum Size { SMALL, MEDIUM, LARGE, EXTRA_LARGE }; Size s = Size.MEDIUM; // s can be null
public enum Size { SMALL("S"), MEDIUM("M"), LARGE("L"), EXTRA_LARGE("XL"); private String abbreviation; private Size(String abbreviation) { this.abbreviation = abbreviation; } public String getAbbreviation() { return abbreviation; } }
enum
extendsEnum
—Size
is actually a subclass ofEnum
, having exactly four instances (static field)- singleton — not possible to construct new objects,
==
can be used
- singleton — not possible to construct new objects,
- implicitly defined methods (i.e. added by the compiler)
static E[] values()
static E valueOf(String name)
Enum
public abstract class Enum<E extends Enum<E>> extends Object implements Comparable<E>, Serializable
String toString()
static <T extends Enum<T>> T valueOf(Class<T> enumType, String name)
int ordinal()
int compareTo(E other)
— by ordinal number
arrays
int[] a = new int[100]; int[] smallPrimes = { 2, 3, 5, 7, 11, 13 }; int[] smallPrimes2 = new int[] { 17, 19, 23, 29, 31, 37 }; new int[] { 17, 19, 23, 29, 31, 37 }; // anonymous array
- arrays are objects — extends
Object
and implementsCloneable
,Serializable
final int length
T[] clone()
Object
methods
- initialization — zero,
false
, ornull
- two dimensional
double[][] balances; balances = new double[NYEARS][NRATES]; int[][] magicSquare = { {16, 3, 2, 13}, {5, 10, 11, 8}, {9, 6, 7, 12}, {4, 15, 14, 1} };
- ragged
int[][] odds = new int[NMAX + 1][]; for (int n = 0; n <= NMAX; n++) odds[n] = new int[n + 1];
- arrays are objects — extends
# Classes and Modifiers
public class
- filename and class name — the name of the file must match the name of the
public
class - unique in a file — can only have one
public
class in a source file - when run
java ClassName
in CLI, themain
method inClassName
is run
- filename and class name — the name of the file must match the name of the
class
this
- field variable shadowing —
this.
is optional, local variables can shadow instance fields - implicit parameter — implicit parameter
this
does not appear in the method declaration- can be explicitly declared as the first parameter, usually for annotations
- as constructor — constructor call in the form
this(...)
must be the first statement in a constructor
- field variable shadowing —
- initialization
- implicit field initialization — fields automatically set to a default zero
- explicit field initialization — initialize with constant value or an expression
- initialization block
- can be
static
— static initialization block, executed when loading the class - can set fields but cannot read later fields — legal to set fields defined later in the class. However, to avoid circular definitions, not legal to read from fields initialized later
- can be
- execution order — runs after
super()
call or other constructor call, but before the rest of the constructor, see below
- constructors
- method name — same as the class
new
— must be called withnew
- default no-arg constructor — when no constructor present, a no-argument constructor is provided
- call another constructor — see
this
above
- execution order when a constructor is called
- other constructor call — if the first line of the constructor calls a second constructor, then the second constructor runs before the body of this constructor.
- implicit field initialization — all data fields are initialized to their default values (0 ,
false
, ornull
) - explicit field initialization and initialization blocks — all field initializers and initialization blocks are executed, in the order they appear in the class declaration
- the rest — The body of the constructor is executed.
- encapsulation
- getter, setter —
private
data field withpublic
accessor and mutator - return clone for mutable objects — If you need to return a reference to a mutable object, return a clone
- getter, setter —
- destructor
- garbage collection — Java does automatic garbage collection, does not support destructors
Object::finalize
deprecated since JDK 9 andjava.lang.ref.PhantomReference
— see JVM, and javadoc ofObject::finalize
tbdRuntime::addShutdownHook
— when JVM shutdown
access modifiers
public
— no access limitprivate
— accessible only when the class is the sameprotected
— can be accessed by subclasses and within the same package- limitation to subclasses — when not within the same package,
SuperType.protectedField
are not accessible to subclass
- limitation to subclasses — when not within the same package,
- default package access — when no access modifiers specified, can be accessed within the same package
- access privileges when overriding — no more restrictive access privileges when overriding
other modifiers
final
final
fields — must be initialized when the object is constructed (can be initialized in constructor) and cannot be modifiedfinal
methods — cannot be overloadedfinal class
— cannot be inherited, and methods are automaticallyfinal
final
parameters — cannot be modified
static
- call by instance — static methods can be invoked by object call, but not recommended
- execution order — static initialization occurs when the class is first loaded
- get class from static method (
this.getClass()
will not work in static methods) besides.class
propertynew Object(){}.getClass().getEnclosingClass();
strictfp
— methods tagged with thestrictfp
keyword must use strict rules for floating-point computations that yield reproducible results
# Math
Math
— elementary exponential, logarithm, square root, and trigonometric functionsMath.E
,Math.PI
static double random()
— usesjava.util.Random
behind scenesmin
,max
- double
static double ulp(double d)
— an ulp, unit in the last place, of a double value is the positive distance between this floating-point value and the double value next larger in magnitude
- rounding
static double ceil(double a)
static long round(double a)
static int round(float a)
static double floor(double a)
Math.floorDiv()
Math.floorMod(x, y)
—x - Math.floorDiv(x, y) * y
- compared to
x % y
—x - x / y * y
- compared to
-Exact
suffixed methods —ArithmeticException
if overflowaddExact
,subtractExact
,multiplyExact
,decrementExact
,incrementExact
,negateExact
static int toIntExact(long value)
- more
java.util.Random
— generate a stream of pseudorandom numbers, of whichMath.random()
uses an static inner class singleton instancepublic class Random extends Object implements Serializable
- creation
Random()
Random(long seed)
- thread-safe — use
ThreadLocalRandom
to avoidAtomicLong::compareAndSet
- set —
void setSeed(long seed)
- next — for
boolean
,byte
,double
,float
,int
,long
int nextInt()
int nextInt(int bound)
- more
double nextGaussian()
- stream
java.security.SecureRandom
- creation
StrictMath
— guaranteeing identical results on all platformsjava.math.BigInteger
public class BigInteger extends Number implements Comparable<BigInteger>
- creation
static BigInteger valueOf(long val)
static BigInteger ONE
static BigInteger TEN
static BigInteger ZERO
- arithmetic
BigInteger add(BigInteger other)
BigInteger subtract(BigInteger other)
BigInteger multiply(BigInteger other)
BigInteger divide(BigInteger other)
BigInteger mod(BigInteger other)
BigInteger modInverse(BigInteger m)
BigInteger modPow(BigInteger exponent, BigInteger m)
- more
- creation
java.math.BigDecimal
— Immutable, arbitrary-precision signed decimal numbers, decimal version ofBigInteger
- equality — use
BigDecimal::compare
instead ofBigDecimal::equals
, seeComparable
- equality — use
# Built-In Classes
- inside
java.lang
package
# System
System
public final class System extends Object
- std
static InputStream in
— instance ofBufferedInputStream
static PrintStream err
static PrintStream out
static Console console()
static void setErr(PrintStream err)
static void setIn(InputStream in)
static void setOut(PrintStream out)
- util
static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
static long currentTimeMillis()
static long nanoTime()
static native int identityHashCode(Object x)
—Object::hashCode
regardless of overriden or not, 0 fornull
- system property — see Legacy Collections for the list of system properties
static Properties getProperties()
static String getProperty(String key)
static String getProperty(String key, String def)
Integer::getInteger
,Long::getLong
static void setProperties(Properties props)
static String setProperty(String key, String value)
static String clearProperty(String key)
static String lineSeparator()
— equivalent toSystem.getProperty("line.separator")
- see
File
for other separators
- see
- environment
static Map<String,String> getenv()
static String getenv(String name)
- JVM
static void exit(int status)
static void gc()
— run garbage collectorstatic SecurityManager getSecurityManager()
static Channel inheritedChannel()
— the channel inherited from the entity that created this Java virtual machinestatic void load(String filename)
static void loadLibrary(String libname)
static String mapLibraryName(String libname)
static void runFinalization()
static void setSecurityManager(SecurityManager s)
- std
SecurityManager
— check permissions, like read / write on certain files
# String
CharSequence
— provides uniform, read-only access to many different kinds of char sequencespublic interface CharSequence
char charAt(int index)
default IntStream chars()
default IntStream codePoints()
int length()
CharSequence subSequence(int start, int end)
String toString()
String
public final class String extends Object implements Serializable, Comparable<String>, CharSequence, Constable, ConstantDesc
- length
int length()
boolean isEmpty()
int codePointCount(int startIndex, int endIndex)
— the number of code pointsint cpCount = greeting.codePointCount(0, greeting.length());
- substring or transform
char charAt(int index)
,int codePointAt(int index)
,codePointBefore
- conversion methods to and from
bytes[]
,char[]
String substring(int beginIndex)
String substring(int beginIndex, int endIndex)
String replace(char oldChar, char newChar)
String replace(CharSequence target, CharSequence replacement)
String replaceAll(String regex, String replacement)
String replaceFirst(String regex, String replacement)
String toLowerCase()
String toUpperCase()
String trim()
String[] split(String regex)
String[] split(String regex, int limit)
- creation
static String format(String format, Object... args)
static String format(Locale l, String format, Object... args)
static String join(CharSequence delimiter, CharSequence... elements)
static String join(CharSequence delimiter, Iterable<? extends CharSequence> elements)
Collectors::joining
StringJoiner
valueOf
static String valueOf(type c)
— from various typesstatic String copyValueOf(char[] data)
—valueOf
equivalent
static String copyValueOf(char[] data, int offset, int count)
String concat(String str)
— do nothing if empty string; in contrast,+
will be compiled to temporaryStringBuilder
String(byte[] bytes)
String(byte[] bytes, Charset charset)
String(byte[] bytes, int offset, int length)
String(byte[] bytes, int offset, int length, Charset charset)
String(int[] codePoints, int offset, int count)
String(char[] value)
String(char[] value, int offset, int count)
String(String original)
String(StringBuffer buffer)
String(StringBuilder builder)
- comparaison
int hashCode()
int hash = 0; for (int i = 0; i < length(); i++) hash = 31 * hash + charAt(i);
boolean equals(Object other)
,boolean equalsIgnoreCase(String other)
- reference type — do not use the
==
operator to test whether two strings are equal - string pool — only string literals are shared, not strings that are the result of operations like
+
orsubstring
- reference type — do not use the
int compareToIgnoreCase(String str)
boolean startsWith(String prefix)
,boolean endsWith(String suffix)
boolean contentEquals(CharSequence cs)
,boolean contentEquals(StringBuffer sb)
String intern()
— determined byequals
, return the string from string pool, add to the pool if not contained already
- transverse
- with index
i
// incremental int cp = sentence.codePointAt(i); if (Character.isSupplementaryCodePoint(cp)) i += 2; else i++; // decreasing i--; if (Character.isSurrogate(sentence.charAt(i))) i--; int cp = sentence.codePointAt(i);
int offsetByCodePoints()
— get at the i^th^ code pointint offsetByCodePoints(int index, int codePointOffset)
— the resulted index by moving given number of code points from given indexstr.codePoints().toArray()
- with index
- find
boolean contains(CharSequence s)
boolean matches(String regex)
boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)
— Tests if two string regions are equal
boolean regionMatches(int toffset, String other, int ooffset, int len)
int indexOf(String str)
int indexOf(String str, int fromIndex)
int indexOf(int cp)
int indexOf(int cp, int fromIndex)
int lastIndexOf(String str)
int lastIndexOf(String str, int fromIndex)
int lastIndexOf(int cp)
int lastIndexOf(int cp, int fromIndex)
- length
StringBuilder
— mutable, not synchronizedStringBuffer
, build a string from many small piecespublic final class StringBuilder extends Object implements Serializable, CharSequence
- constructors
StringBuilder()
StringBuilder(CharSequence seq)
StringBuilder(int capacity)
StringBuilder(String str)
- modify
append
StringBuilder appendCodePoint(int cp)
void setCharAt(int i, char c)
insert
StringBuilder delete(int startIndex, int endIndex)
StringBuilder deleteCharAt(int index)
- more
- reuse
void setLength(int newLength)
- output —
String toString()
- constructors
StringBuffer
public final class StringBuffer extends Object implements Serializable, CharSequence
java.util.StringJoiner
— store components inString[]
with doubling strategy when expanding capability, used byCollectors::joining
andString::join
public final class StringJoiner extends Object
- constructors
StringJoiner(CharSequence delimiter)
StringJoiner(CharSequence delimiter, CharSequence prefix, CharSequence suffix)
- use
StringJoiner add(CharSequence newElement)
int length()
StringJoiner merge(StringJoiner other)
StringJoiner setEmptyValue(CharSequence emptyValue)
String toString()
- constructors
# Wrappers
wrappers
Integer
,Long
,Float
,Double
,Short
,Byte
,Character
, andBoolean
- all extends
Number
exceptBoolean
— no arithmetic operations and number conversions for boolean - immutable and
final
- autowrapping (autoboxing) — done by compiler, nothing related to VM
valueOf
— example:list.add(3);
is automatically translated tolist.add(Integer.valueOf(3));
typeValue()
— example: the compiler translatesint n = list.get(i);
intoint n = list.get(i).intValue();
- arithmetic operations — example:
Integer n = 3; n++;
compiler automatically inserts instructions to unbox the object, increment the resulting value, and box it back.
- fixed wrapping — wrapped into fixed objects
boolean , byte , char <= 127
short
, andint
between -128 and 127
- wrapper class references can be
null
— possibleNullPointerException
- conditional promotion —
Integer
toDouble
Integer n = 1; Double x = 2.0; System.out.println(true ? n : x); // Prints 1.0
Number
public abstract class Number implements Serializable
byte byteValue()
abstract double doubleValue()
abstract float floatValue()
abstract int intValue()
abstract long longValue()
short shortValue()
Integer
public final class Integer extends Number implements Comparable<Integer>, Constable, ConstantDesc
- fields
static int BYTES
— usually 4static int MAX_VALUE
static int MIN_VALUE
static int SIZE
— usually 32static Class<Integer> TYPE
—int.class
- creation
Integer(int value)
— deprecated since JDK 9Integer(String s)
— usesparseInt
internally, deprecated since JDK 9static Integer decode(String nm)
— accepts decimal, hexadecimal (0x
,0X
,#
prefixed), octal (0
prefixed), can be negativestatic Integer valueOf(int i)
static Integer valueOf(String s)
— usesparseInt
internally
static Integer valueOf(String s, int radix)
- conversion to primitive types
- methods in
Number
int intValue()
static int parseInt(String s)
static int parseInt(String s, int radix)
- methods in
- arithmetic operations
static int signum(int i)
static int sum(int a, int b)
- unsigned
static int parseUnsignedInt(String s)
static int parseUnsignedInt(String s, int radix)
static int divideUnsigned(int dividend, int divisor)
static int compareUnsigned(int x, int y)
static int remainderUnsigned(int dividend, int divisor)
static String toBinaryString(int i)
— two's complement representationstatic String toHexString(int i)
static String toOctalString(int i)
static String toUnsignedString(int i)
static String toUnsignedString(int i, int radix)
static long toUnsignedLong(int x)
- bits in the two's complement
static int bitCount(int i)
— the number of one-bitsstatic int highestOneBit(int i)
static int lowestOneBit(int i)
static int numberOfLeadingZeros(int i)
static int numberOfTrailingZeros(int i)
static int reverse(int i)
static int reverseBytes(int i)
static int rotateLeft(int i, int distance)
static int rotateRight(int i, int distance)
- for
int
static int compare(int x, int y)
static int hashCode(int value)
static String toString(int i)
static String toString(int i, int radix)
- fields
Double
- counterparts of fields and methods in
Integer
- IEEE 754
static int MAX_EXPONENT
static int MIN_EXPONENT
static double MIN_NORMAL
Math::ulp
- infinite and not a number
static double NaN
static double NEGATIVE_INFINITY
static double POSITIVE_INFINITY
static boolean isFinite(double d)
boolean isInfinite()
static boolean isInfinite(double v)
boolean isNaN()
static boolean isNaN(double v)
- counterparts of fields and methods in
Character
— see afterBoolean
public final class Boolean extends Object implements Serializable, Comparable<Boolean>
# Inheritance and Object
inheritance
extends
super
super()
- first statement — the call using
super
must be the first statement in the constructor for the subclass - default no-arg constructor — if the subclass constructor does not call a superclass constructor explicitly, the no-argument
super()
is invoked - order — invoked before initializers
- first statement — the call using
- polymorphism
- object variables are polymorphic — a variable can be assigned subclasses of its type
- no polymorphism exploit in arrays — all arrays remember the element type with which they were created (
new
ed)Manager[] managers = new Manager[10]; Employee[] staff = managers; // OK staff[0] = new Employee("Harry Hacker", ...); // ArrayStoreException
method call
- overriding resolution — according to function signatures, done by compiler
- function signature
- return type — return type is not a part of the signature (but is in JVM so bridge methods work)
- bridge method — when return another type, a bridge method is synthesized
- function signature
- static binding — for
private
,static
,final
methods or constructors, done by compiler - dynamic binding — JVM resolving the implicit parameter with method table lookup
- method table — method table lists all method signatures and the actual methods to be called, computed by VM for each class in advance
- order of method table lookup — from actual type to superclasses to
Object
- overhead of dynamic binding — no need to use static binding to avoid the overhead, JIT does the inlining optimization
- overriding resolution — according to function signatures, done by compiler
casting
- direct assign to more general — cast to more general, a subclass reference to a superclass variable, direct assign
- cast needed for more specific — cast to more specific, a superclass reference to a subclass variable, use the same syntax as primitive type cast, check at runtime
- exception —
ClassCastException
when cannot cast - check — use
instanceof
to check before casting - cast range — can cast only within an inheritance hierarchy
- minimal usage — best to minimize the use of casts and the
instanceof
operator
- exception —
abstract class
- no instance — cannot be instantiated, but can be super type
- abstract methods — any class can be tagged
abstract
, but not vice versa- can be none — abstract classes can have no abstract methods, abstract classes can have fields and concrete methods
- none in concrete class — a class with one or more
abstract
methods must itself be declaredabstract
Object
— the cosmic superclass- for all reference type — only the values of primitive types (numbers, characters, and boolean values) are not objects
boolean equals(Object otherObject)
— determines whether two object references are identical- override — template as below, need to override
hashCode
also ifequals
overriden@Override public boolean equals(Object otherObject) { // super.equals(other) // a quick test to see if the objects are identical, may be unnecessary if covered in `super.equals(other)` if (this == otherObject) return true; // must return false if the explicit parameter is null if (otherObject == null) return false; // if the classes don't match, they can't be equal // alternative — use instanceof and tagging final to allow objects of different subclasses to be equal to one another if (getClass() != otherObject.getClass()) return false; // now we know otherObject is a non-null Employee Employee other = (Employee) otherObject; // test whether the fields have identical values return name.equals(other.name) && salary == other.salary && hireDay.equals(other.hireDay); }
- override — template as below, need to override
native int hashCode()
— derived from the memory address, recommended to be compatible withequals()
String toString()
—getClass().getName() + "@" + Integer.toHexString(hashCode());
- for arrays — arrays will come up with something like
"[I@1a46e30"
, where[I
denotes an array of integers
- for arrays — arrays will come up with something like
Class<?> getClass()
protected Object clone()
protected void finalize()
— deprecated in JDK 9, see before- concurrency related — see Concurrency
- methods in utility class
Objects
# Interfaces, Lambdas and Inner Classes
# Interfaces
interface
- methods in interfaces
- non-static methods — all methods are implicitly
abstract public
, redundancy is discouraged- when implementing —
public
still required when implementing
- when implementing —
- static methods — supported as of Java SE 8, need explicit access modifier
- prohibited modifiers — an interface method may not be declared with
protected
or package access, or with the modifiersfinal
,synchronized
, ornative
- non-static methods — all methods are implicitly
- inner classes in interfaces — automatically
static public
- constant fields — implicitly
public static final
, automatically inherited when implementing - no instance fields
implements
,SuperInterface.super
— examples below- can be generic —
class Employee implements Comparable<Employee>
- use as super type — supports
instanceof
,extend
, multiple inheritance- diamond problem — see below
- methods in interfaces
default methods
default
implementationpublic interface Comparable<T> { default int compareTo(T other) { return 0; } // By default, all elements are the same }
default
method conflict resolving — interface vs superclass vs another interface- superclasses take precedence — default methods are ignored if implemented in superclasses
- no default
Object
methods — not possible to make a default method that redefines one of the methods in theObject
class - no abstract
Object
methods — redeclaring methods from theObject
class do not make the methods abstract, no effect to function interfaces - attach javadoc by
Object
methods — some interfaces redeclareObject
methods in order to attach javadoc comments, likeComparator
- no default
- interface clash — if clashes, even only one of the methods is
default
, the method must be overridenSuperInterface.super
— choose one when interface clashinterface Named { default String getName() { return getClass().getName() + "_" + hashCode(); } } interface Person { default String getName() { return ""; }; } class Student implements Person, Named { public String getName() { return Person.super.getName(); } }
- superclasses take precedence — default methods are ignored if implemented in superclasses
companion class
- used to place static methods — it has been common to place static methods in companion classes, like
Collection
/Collections
orPath
/Paths
- used to implement some or all of methods of an interface — such as
Collection
/AbstractCollection
orMouseListener
/MouseAdapter
default
andstatic
methods in interfaces — with Java SE 8, this technique of companion class is obsolete, as the support of default methods and static methods
- used to place static methods — it has been common to place static methods in companion classes, like
some use of interface
- callback — pass an object of a class implementing a callback interface, methods in the interface will be called when the event fires
- tagging interface —
Cloneable
# Common Interfaces
interface Comparable<T>
—int compareTo(T o)
- overflow when implementing with subtraction — make sure absolute values of operands are at most
(Integer.MAX_VALUE - 1) / 2
- otherwise use
Integer.compare()
- otherwise use
equals()
compliance — strongly recommended (though not required) to comply withequals()
BigDecimal
violates —new BigDecimal("1.0").equals(new BigDecimal("1.00"))
isfalse
because the numbers differ in precision
- associative — to make
x.compareTo(y)
compatible withy.compareTo(x)
, start with below when implementingif (getClass() != other.getClass()) throw new ClassCastException();
- overflow when implementing with subtraction — make sure absolute values of operands are at most
interface java.util.Comparator<T>
—int compare(T o1, T o2)
- nature and reversed order
static <T extends Comparable<? super T>> Comparator<T> naturalOrder()
static <T extends Comparable<? super T>> Comparator<T> reverseOrder()
— usesCollections::reverseOrder
under the hood
- key extract
// sort people by name Arrays.sort(people, Comparator.comparing(Person::getName));
static <T,U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T,? extends U> keyExtractor)
static <T,U> Comparator<T> comparing(Function<? super T,? extends U> keyExtractor, Comparator<? super U> keyComparator)
static <T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor)
static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor)
static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor)
- comparator chaining
Arrays.sort(people, Comparator .comparing(Person::getLastName) .thenComparing(Person::getFirstName) );
default Comparator<T> thenComparing(Comparator<? super T> other)
default <U extends Comparable<? super U>> Comparator<T> thenComparing(Function<? super T,? extends U> keyExtractor)
default <U> Comparator<T> thenComparing(Function<? super T,? extends U> keyExtractor, Comparator<? super U> keyComparator)
default Comparator<T> thenComparingType(ToTypeFunction<? super T> keyExtractor)
—type
forint
,double
andlong
default Comparator<T> reversed()
— usesCollections::reverseOrder
under the hood
- comparing
null
static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator)
static <T> Comparator<T> nullsLast(Comparator<? super T> comparator)
- nature and reversed order
interface Cloneable
- mark interface — serves as a tag, a checked
CloneNotSupportedException
if an object requests cloning but does not implement that interface - make a class cloneable — implement this interface, redefine
clone
to bepublic
Object::clone
— protected, and does a shallow copy- use
Object::clone
—(T) super.clone()
- return
Object
by convention — Up to Java SE 1.4, the clone method always had return typeObject
, but now the correct return type can be specified- inconsistency —
HashMap::clone
andArrayList::clone
etc. returnObject
, whereasint[]::clone
andArrayDeque::clone
etc. return specific type
- inconsistency —
- mark interface — serves as a tag, a checked
# Lambdas
closure
- effectively final — any captured variable in a lambda expression must be effectively final: no difference if declared
final
for (int i = 1; i <= count; i++) { ActionListener listener = event -> { System.out.println(i + ": " + text); // Error: Cannot refer to changing i }; new Timer(1000, listener).start(); }
- no mutation outside — illegal to refer to a variable in a lambda expression that is mutated outside
- no mutation inside — cannot mutate captured value
- access mutable data — use an array of length 1
- no block variable shadowing — illegal to declare a parameter or a local variable in the lambda that has the same name as a local variable
- block scope — the same scope as a nested block
- same
this
—this
is the same as what outside the lambda
- effectively final — any captured variable in a lambda expression must be effectively final: no difference if declared
lambda expression syntax
- inline
(String first, String second) -> first.length() - second.length();
- block with explicit
return
(String first, String second) -> { if (first.length() < second.length()) return -1; else if (first.length() > second.length()) return 1; else return 0; }
- type inference
Comparator<String> comp = (first, second) -> first.length() - second.length();
- type inference without parentheses
ActionListener listener = event -> System.out.println("The time is " + new Date()");
- inferred return type — return type is always inferred, cannot be specified
- inline
functional interface — an interface with a single abstract method, like
Comparator<T>
- for conversion from lambdas — conversion to a functional interface is the only function for lambdas
- object instance used behind the scenes — methods like
Arrays::sort
receives an object of some class that implements the interface, lambda is executed when invoking the method of that interface @FunctionalInterface
— optional annotation- lambda expression holders (also function interface) — see Common Functional Interfaces for
java.util.function
method reference — use as lambdas
object::instanceMethod this::instanceMethod super::instanceMethod // uses `this` as the target and invokes the superclass version of the given method Class::staticMethod Class::instanceMethod // the implicit parameter becomes explicit Class::new // constructor reference int[]::new
- object instance used behind the scenes — turned into instances of functional interfaces like lambdas
int[]::new
—new T[n]
is illegal, so libary designers use this syntax to mitigateObject[] people = stream.toArray(); Person[] people = stream.toArray(Person[]::new);
lambda at runtime — see Lambda at Runtime
# Common Functional Interfaces
java.util.function
package, all@FunctionalInterface
java.util.function.Function<T, R>
—R apply(T t)
static <T> Function<T,T> identity()
- chaining
default <V> Function<T,V> andThen(Function<? super R,? extends V> after)
default <V> Function<V,R> compose(Function<? super V,? extends T> before)
- variants
java.util.function.DoubleFunction<R>
—R apply(double value)
java.util.function.DoubleToIntFunction
java.util.function.DoubleToLongFunction
java.util.function.IntFunction<R>
java.util.function.IntToDoubleFunction
java.util.function.IntToLongFunction
java.util.function.LongFunction<R>
java.util.function.LongToDoubleFunction
java.util.function.LongToIntFunction
java.util.function.ToDoubleFunction<T>
java.util.function.ToIntFunction<T>
java.util.function.ToLongFunction<T>
- variants with two parameters
java.util.function.BiFunction<T,U,R>
—R apply(T t, U u)
java.util.function.ToDoubleBiFunction<T,U>
java.util.function.ToIntBiFunction<T,U>
java.util.function.ToLongBiFunction<T,U>
operator —
Function
with type parameters of the same primitive type@FunctionalInterface public interface UnaryOperator<T> extends Function<T,T>
- unary
java.util.function.UnaryOperator<T>
static <T> UnaryOperator<T> identity()
java.util.function.DoubleUnaryOperator
java.util.function.IntUnaryOperator
java.util.function.LongUnaryOperator
- binary
java.util.function.BinaryOperator<T>
static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator)
static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator)
java.util.function.DoubleBinaryOperator
—double applyAsDouble(double left, double right)
java.util.function.IntBinaryOperator
java.util.function.LongBinaryOperator
- unary
java.util.function.Supplier<T>
—T get()
- variants
java.util.function.BooleanSupplier
—boolean getAsBoolean()
java.util.function.DoubleSupplier
java.util.function.IntSupplier
java.util.function.LongSupplier
- variants
java.util.function.Consumer<T>
—void accept(T t)
default Consumer<T> andThen(Consumer<? super T> after)
— chaining// default implementation return (T t) -> { accept(t); after.accept(t); };
- variants
java.util.function.DoubleConsumer
—void accept(double value)
java.util.function.IntConsumer
java.util.function.LongConsumer
- variants with two parameters
java.util.function.BiConsumer<T, U>
—void accept(T t, U u)
java.util.function.ObjDoubleConsumer<T>
java.util.function.ObjIntConsumer<T>
java.util.function.ObjLongConsumer<T>
java.util.function.Predicate<T>
—boolean test(T t)
static <T> Predicate<T> isEqual(Object targetRef)
- chaining
default Predicate<T> and(Predicate<? super T> other)
default Predicate<T> negate()
default Predicate<T> or(Predicate<? super T> other)
- variants
java.util.function.DoublePredicate
java.util.function.IntPredicate
java.util.function.LongPredicate
java.util.function.BiPredicate<T,U>
# Inner Class
inner class
OuterClass.this
— explicit reference to the outer class- passed as implicit parameter to inner class constructors
- implicit reference — can access the data from the scope in which they are defined
- synthesized constructor parameter for implicit reference — the compiler modifies all inner class constructors, adding a parameter for the outer class reference
- constructing inner classes —
new
keyword changes for implicit reference- inside outer class —
this.new
or alternativelynew
- outside outer class —
outerObj.new
- inside outer class —
- access control — can be hidden from other classes in the same package
- only inner classes can be private — regular classes always have either package or public visibility
private
accessible for each other — between the outer class and inner classes
- refer to inner class outside the outer class —
OuterClass.InnerClass
inner class limits
- static fields — must be
final
- static methods — cannot have static methods
- static fields — must be
inner class after compilation or at runtime — synthesized regular classes
Outer$Inner
class — inner classes are translated into regular class files with$
(dollar signs) delimiting outer and inner class names- compared to regular classes — more access privileges to the outer class, like private fields
- synthesized outer class reference — inner class has a
final
this$0
field for reference to outer class generated by compiler - private inner classes — JVM does not support private classes, so the compiler produces a package-visible class with a private constructor, and a second package-visible constructor that calls the private one
private TalkingClock$TimePrinter(TalkingClock); TalkingClock$TimePrinter(TalkingClock, TalkingClock$1); // the last parameter type is synthesized solely to distinguish this constructor from others new TalkingClock$TimePrinter(this, null); // actual call in outer class
- mechanism for more privileged access to outer class — synthesized outer class backdoor method
- backdoor method — outer class generates a package accessible static
access$0(OuterClass outer)
method (method name can vary slightly), for inner class, outer class private field access is translated to backdoor method call - vulnerability — the generated backdoor method name is not legal in source code, but can be exploited by build or modify a class file
- backdoor method — outer class generates a package accessible static
- transparent to JVM — the virtual machine does not have any special knowledge about inner classes
- verify by inspecting class files — use
javap -p
to verify
local inner class — class locally in a single method
- no access modifier — never declared with an access specifier
- restricted scope — scope is always restricted to the block being declared
- effectively final closure — can access effectively final local variables
- as final fields — behind the scenes stored as a final field of inner class, and spawned to constructor for initialization
- anonymous inner subclass
new SuperType(construction parameters) { // inner class methods and data }
- implementing or extending —
SuperType
can be an interface or a class, the inner class implements that interface or extends the class- a different subclass — take care that
equals()
checkinggetClass() == otherObject.getClass()
may fail
- a different subclass — take care that
- no constructor redefining — anonymity cannot have constructors — the name of a constructor must be the same as the name of a class
- use case
- double brace initialization for
ArrayList
invite(new ArrayList<String>() {{ add("Harry"); add("Tony"); }});
- get the class from static methods, alternative to
T.class
new Object(){}.getClass().getEnclosingClass();
- double brace initialization for
- implementing or extending —
static inner class
- static — do not have a outer class reference, can have static fields and methods
- use case
- enums are static inner classes
- use in outer static methods — must be declared static if needed in a outer class static method
- return type — can be used for holder for a method to return multiple values
- the only static classes — only inner classes can be declared static
- implicitly static
- inner interfaces are implicitly
static
- inner classes inside interfaces are automatically
static public
- inner interfaces are implicitly
# Error Handling
# Debugging
print or log
- debug by print concatenated or formatted string
- logging proxy — anonymous inner class overriding methods of interest with logger
- stack trace —
Throwable::printStackTrace
and rethrow, orThread.dumpStack()
- capture string instead of printing to
System.err
StringWriter out = new StringWriter(); new Throwable().printStackTrace(new PrintWriter(out)); String description = out.toString();
- change handler for uncaught exceptions
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { /* logging... */ }; });
- capture string instead of printing to
CLI options related to debugging — tbd
ctrl
+\
— get thread dump when the program hangs??java
- use
-verbose
when launching JVM for diagnosing class path problems -XX:+HeapDumpOnOutOfMemoryError
,-XX:HeapDumpPath=<file-or-dir-path>
- use
javac
with-Xlint:all
- monitoring — Monitoring Tools and Commands (opens new window)
jconsole
— start a graphical console to monitor and manage Java applications, to track memory consumption, thread usage, class loading- experimental — unsupported and might not be available in future JDK releases
jps
— list the instrumented JVMs on the target systemjstat
— monitor JVM statisticsjstatd
— monitor the creation and termination of instrumented Java HotSpot VMs
- troubleshooting — Troubleshooting Tools and Commands (opens new window)
jcmd
: send diagnostic command requests to a running Java Virtual Machine (JVM)- example: NMT — see #Memory
jdb
: find and fix bugs in Java platform programsjhsdb
: attach to a Java process or to a core dump from a crashed Java Virtual Machine (JVM)- experimental — unsupported and might not be available in future JDK releases
jinfo
: generate Java configuration information for a specified Java process. For core files usejhsdb jinfo
.jmap
: print details of a specified process. For core files usejhsdb jmap
.jstack
: print Java stack traces of Java threads for a specified Java process. For core files usejhsdb jstack
.
- deprecated
jhat
— examining dump byjmap
, removed since JDK 9java -Xprof
for profiling, removed since JDK 10-agentlib:hprof
— heap and CPU profiling, removed since JDK 9
syslog
jvisualvm
(opens new window) — VisualVM is a visual tool integrating commandline JDK tools and lightweight profiling capabilities.mat
(opens new window) — The Eclipse Memory Analyzer is a fast and feature-rich Java heap analyzer that helps you find memory leaks and reduce memory consumption- Java Profiler - JProfiler (opens new window)
# Exceptions
unchecked exceptions and checked exceptions
- unchecked — any exception that derives from the class
Error
or the classRuntimeException
an unchecked exception - checked — All other exceptions are called checked exceptions, including
Exception
- why called checked — The compiler checks that you provide exception handlers for all checked exceptions
- unchecked — any exception that derives from the class
Throwable
— the superclass of all errors and exceptions, other objects cannot be thrownpublic class Throwable implements Serializable
- constructors
Throwable()
Throwable(String message)
Throwable(String message, Throwable cause)
protected Throwable(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace)
Throwable(Throwable cause)
- stack trace
void printStackTrace()
void printStackTrace(PrintStream s)
void printStackTrace(PrintWriter s)
void setStackTrace(StackTraceElement[] stackTrace)
StackTraceElement[] getStackTrace()
Throwable fillInStackTrace()
- error message
String getMessage()
String getLocalizedMessage()
— for overriding, defaults togetMessage()
String toString()
— class name, and message if applicable
- wrapping
Throwable initCause(Throwable cause)
Throwable getCause()
- suppress
void addSuppressed(Throwable exception)
Throwable[] getSuppressed()
- subclasses
Error
Exception
- constructors
Error
— internal errors and resource exhaustion situations, not expected to throw by userpublic class Error extends Throwable
Exception
and its hierarchypublic class Exception extends Throwable
CloneNotSupportedException
InterruptedException
ReflectiveOperationException
ClassNotFoundException
IllegalAccessException
InstantiationException
NoSuchFieldException
NoSuchMethodException
RuntimeException
ArithmeticException
ArrayStoreException
ClassCastException
EnumConstantNotPresentException
IllegalArgumentException
IllegalThreadStateException
NumberFormatException
IllegalMonitorStateException
IllegalStateException
IndexOutOfBoundsException
ArrayIndexOutOfBoundsException
StringIndexOutOfBoundsException
NegativeArraySizeException
NullPointerException
SecurityException
TypeNotPresentException
UnsupportedOperationException
StackTraceElement
public final class StackTraceElement extends Object implements Serializable
- creation
StackTraceElement(String declaringClass, String methodName, String fileName, int lineNumber)
Throwable::getStackTrace
Thread::getStackTrace
Thread.getAllStackTraces()
- stack info
String getClassName()
String getFileName()
int getLineNumber()
String getMethodName()
- creation
# Exception Handling
exception specification — declare checked exceptions
// modifiers return_type method_name(parameters) throws Exception1, Exception2 // java.io.FileInputStream public FileInputStream(String name) throws FileNotFoundException
- when to declare
- nested method call — when calling a method that threatens to throw a checked exception
throw
checked exceptions spontaneously — check exceptions can be thrown only when declared by the method
- if not declared — compiling error if a method fails to faithfully declare all checked exceptions or handle them
- if caught — no need for
throws
- when overriding a method
- more specific exceptions or not at all — exception specification cannot be more general; OK to throw more specific exceptions, or not to throw any exceptions in the subclass method
- none if none in superclass — if the superclass method throws no checked exception at all, neither can the subclass
- when to declare
try catch
try { // statements that might throw exceptions } catch (FileNotFoundException e) { // optionally final in parameter // emergency action for missing files } catch (UnknownHostException e) { // emergency action for unknown hosts } catch (IOException e) { // emergency action for all other I/O problems } finally { // close resources }
- multiple exception types — only needed when catching exception types that are not subclasses of one another
catch (FileNotFoundException | UnknownHostException e) { // emergency action for missing files and unknown hosts }
- implicit
final
— the exception variable is implicitlyfinal
when multiple exception types
- implicit
- rethrow —
throw
incatch
block- exception wrapping — use
Throwable::initCause
to throw as another wrapped type andThrowable::getCause
for original failure - bypass exception specification limit — rethrow a wrapped
RuntimeException
if a method cannot throw checked exception- for
IOException
—java.io.UncheckedIOException
is designed to wrapIOException
- for
- use generics to make checked exceptions unchecked, see Generics
- exception wrapping — use
- smart narrowing — when rethrow any exception
public void updateRecord() throws SQLException { try { // access the database } catch (Exception e) { logger.log(level, message, e); throw e; } }
- example above — compiler now tracks the fact that
e
originates from thetry
block, it is valid to declare the enclosing method as throwsSQLException
- smart narrowing conditions
- only checked exceptions — provided that the only checked exceptions in that block are
SQLException
instances final
e
— and provided thate
is not changed in the catch block
- only checked exceptions — provided that the only checked exceptions in that block are
- example above — compiler now tracks the fact that
- multiple exception types — only needed when catching exception types that are not subclasses of one another
finally
— always executed, can be used withoutcatch
- order — executes before the method return, if
return
used beforefinally
- mask
return
and exceptionsreturn
infinally
will mask previousreturn
- exceptions in
finally
will mask exceptions previously thrown
- handle exceptions in
finally
- wrap a
try catch
block to handle possible exception thrown byfinally
InputStream in = . . .; try { try { // code that might throw exceptions } finally { // in.close(); } } catch (IOException e) { // show error message }
- rethrow the original, suppress exception thrown by
finally
InputStream in = . . .; Exception ex = null; try { try { // code that might throw exceptions } catch (Exception e) { ex = e; throw e; } } finally { try { in.close(); } catch (Exception e) { if (ex == null) throw e; else ex.addSuppressed(e); } }
- wrap a
- order — executes before the method return, if
try (resources)
— auto close when exiting the blocktry (Resource res = . . .) { // work with res }
- the resource needs to implement
AutoCloseable
which has a single methodpublic interface AutoCloseable { void close() throws Exception; }
- multiple resources — use
;
as delimiter - when both
try
block andAutoCloseable::close
throw exception — any exceptions thrown byclose
methods are suppressed - can have
catch
andfinally
blocks, but not recommended
- the resource needs to implement
# Assertion
assert
assert condition; assert condition : expression;
condition
— throw anAssertionError
if the assertion failsexpression
— passed toAssertionError::new
to produce a message string, usingString::valueOf
when converting- enabling and disabling
- disabled — disabled by default,
-da
or-disableassertions
to explicitly disable certain classes - enable — by
-ea
or-enableassertions
java -enableassertions MyApp java -ea:MyClass -ea:com.mycompany.mylib... MyApp # for specific classes
- enabling mechanism — when enabled, no recompiling, but the class loader stops stripping out the assertion code
- also for JVM loaded classes — some classes are not loaded by a class loader but directly by the virtual machine, but above switches still work
- enable for system classes —
-enablesystemassertions
/-esa
for system classes
- disabled — disabled by default,
assert use
- fatal errors — assertion failures are intended to be fatal, unrecoverable errors
- for development and testing — assertion checks are turned on only during development and testing
- use for precondition — parameter checking
- use for documenting assumptions
// use comments to document underlying assumptions if (i % 3 == 0) . . . else if (i % 3 == 1) . . . else // (i % 3 == 2) . . .
// use assertion instead if (i % 3 == 0) . . . else if (i % 3 == 1) . . . else { assert i % 3 == 2; . . . }
// even better assertion assert i >= 0; if (i % 3 == 0) . . . else if (i % 3 == 1) . . . else { . . . }
AssertionError
public class AssertionError extends Error
# Logging
see Logging.
# Generics
Generics
- further reading (opens new window)
- diamond syntax
- raw and typed
- typed are subtypes — typed ones are subtypes of the raw one
- warning when using raw types
- raw at runtime — types only checked when compiling, all are raw without type at runtime
- differently parameterized, different type — no relationship between
Generic<Type_2>
andGeneric<Type_2>
, regardless of the relationship between the type variables - at runtime in JVM
- erased to bound — type variables are erased and replaced by first bound, or
Object
- cast when needed — compiler inserts casts to other bounds when necessary
- place the predominant interface at the first one for performance
- bridge methods are synthesized when necessary (when overriding)
- override method can have a different signature — due to type erasure of generics or different return type
- bridge method — the same signature of super type method, calls actual method
- erased to bound — type variables are erased and replaced by first bound, or
generic syntax
- name conventions
E
— for the element type of a collectionK
andV
— for key and value types of a tableT
(and the neighboringU
andS
) — for “any type at all”
- generic class syntax
public class Pair<T, U> { . . . }
- generic methods inside ordinary classes
@SafeVarargs // to suppress Warning: Possible heap pollution from parameterized vararg type public static <T> T getMiddle(T... a) { return a[a.length / 2]; }
- call — type parameter before method name,
className.<type>method(params)
- avoid parsing ambiguities in C++ —
g(f<a,b>(c))
- avoid parsing ambiguities in C++ —
- type inference — type can be inferred from parameters, but can be problematic when multiple super types
- call — type parameter before method name,
- generic bounds —
extends
, includingpublic static <T extends Comparable & Serializable> T min(T[] a)
- class bound — must be the first one in the bounds list
- interface bound and class bound — arbitrary number of interfaces, but at most one class
&
- wildcards —
?
- wildcard type
?
— for a variable of type?
, can only assign when left value isObject
, or right value isnull
- example —
Collection<?>
can be used as a super type for anyCollection
whileCollection<Object>
cannot; can readObject
from but can only addnull
to - problem when nested: signature
Iterable<Map<String, ?>>
not applicable for argumentIterable<Map<String, Object>>
or anything similar — useIterable<? extends Map<String, ?>>
- example —
? extends SomeType
— including; a variable of this type can only be right valuePair<Manager> managerBuddies = new Pair<>(ceo, cfo); Pair<? extends Employee> wildcardBuddies = managerBuddies; // OK Employee e = wildcardBuddies.getFirst(); // function signature is `? extends Employee getFirst()`, OK wildcardBuddies.setFirst(lowlyEmployee); // function signature is `void setFirst(? extends Employee)`, compile-time error
? super SomeType
— including; the contrary of? extends SomeType
(left value can only beObject
)- example —
<T extends Comparable<? super T>>
, a rescue whenT
does not implementComparable
but its super class does
- example —
- wildcard capture — when the wildcard represents a single, definite type, it can be captured by type parameter
public static <T> void swapHelper(Pair<T> p) { T t = p.getFirst(); p.setFirst(p.getSecond()); p.setSecond(t); } public static void swap(Pair<?> p) { swapHelper(p); }
- wildcard type
- name conventions
use generics to make checked exceptions unchecked
@SuppressWarnings("unchecked") public static <T extends Throwable> void throwAs(Throwable e) throws T { throw (T) e; }
try { // do work } catch (Throwable t) { // the compiler will believe that t becomes an unchecked exception Block.<RuntimeException>throwAs(t); // alternatively, see https://stackoverflow.com/questions/31316581/a-peculiar-feature-of-exception-type-inference-in-java-8 // Block.throwAs(t); }
limits of generics
- type parameters cannot be primitive types — not compatible with
Object
when type erased at runtime - not in static context — type variables not valid in static context (parameterized types are available)
public class Singleton<T> { private static T singleInstance; // Error public static T getSingleInstance() { // Error if (singleInstance == null) // ... construct new instance of T return singleInstance; } }
- not when
throw
orcatch
— cannot throw or catch instances of a generic class - not when cast and
instanceof
— compile warning when cast ((Pair<String>) a
), compile error wheninstanceof
(a instanceof Pair<T>
) - name clash
- name clash with methods in
Object
— error by clash withObject::equals
when definingequals(T other)
- error when generic interfaces implemented more than once with different arguments — will be a conflict with the synthesized bridge methods
class Employee implements Comparable<Employee> { } class Manager extends Employee implements Comparable<Manager> { } // Error // bridge method for Comparable<X> public int compareTo(Object other) { return compareTo((X) other); }
- name clash with methods in
- heap pollution, cannot initialize arrays of parameterized types, but can be declared — error when
new Pair<String>[10]
// legal but not safe workaround, possible heap pollution Pair<String>[] table = (Pair<String>[]) new Pair<?>[10];
// heap pollution Object[] objArray = table; // defined above objArray[0] = new Pair<Employee>();
- cannot instantiate type variable — error when
new T()
- workaround — provide the constructor using lambda
Pair<String> p = Pair.makePair(String::new); public static <T> Pair<T> makePair(Supplier<T> constr) { return new Pair<>(constr.get(), constr.get()); }
- workaround — use reflection
Pair<String> p = Pair.makePair(String.class); public static <T> Pair<T> makePair(Class<T> cl) { try { return new Pair<>(cl.newInstance(), cl.newInstance()); } catch (Exception ex) { return null; } }
- workaround — provide the constructor using lambda
- cannot construct generic array — error when
new T[n]
- parameterized vararg type (
T...
) — against the rule, but can use@SafeVarargs
to suppress warning - workaround — use
Object[]
public class ArrayList<E> { private Object[] elements; @SuppressWarnings("unchecked") public E get(int n) { return (E) elements[n]; } public void set(int n, E e) { elements[n] = e; } // no cast needed }
- workaround — use cast from
Object[]
, type erasure makes the cast undetectable at runtimepublic class ArrayList<E> { private E[] elements; public ArrayList() { elements = (E[]) new Object[10]; } }
- not work when assigning to actual type —
ArrayList::toArray
either returnObject[]
or take aT[]
parameter to returnT[]
- not work when assigning to actual type —
- workaround — provide constructor or use reflection, see above
- parameterized vararg type (
- type parameters cannot be primitive types — not compatible with
# Annotations
annotations
- syntax — each annotation is preceded by an
@
symbol, used like a modifier and is placed before the annotated item without a semicolon- an item can have multiple annotations
- one annotation can be used multiple times on one item if
@Repeatable
- annotation interfaces — define annotations, creates actual Java interfaces, implicitly extend
Annotation
modifiers @interface AnnotationName { type elementName(); type elementName() default value; }
- cannot be extended or implemented explicitly
- when being processed — tools that process annotations receive objects implementing annotation interfaces, and call methods to retrieve elements
java.lang.annotation.Annotation
— the common interface extended by all annotation types. Note that an interface that manually extends this one does not define an annotation type.public interface Annotation
Class<? extends Annotation> annotationType()
- annotation places
- declarations
- type uses
- syntax — each annotation is preceded by an
annotation elements
- elements of annotations — parameters when annotating, all element values must be compile-time constants, correspond to methods of annotation interfaces
@AnnotationName(elementName1=value1, elementName2=value2, ...) @AnnotationName @AnnotationName(valueForSingleElement)
- marker annotation — annotations no elements need to be specified when annotating
- single value annotation — only one element called
value
- annotation element types — non-null, usually
""
orVoid.class
as substitution ofnull
- primitive types
String
Class
Enum
- annotation types, error to introduce circular dependencies
Reference ref() default @Reference(); // an annotation type @BugReport(ref=@Reference(id="3352627"), ...) // when annotating
- arrays of the preceding types (flat), enclosed in braces when annotating
@BugReport(..., reportedBy={"Harry", "Carl"}) @BugReport(..., reportedBy="Joe") // OK, same as {"Joe"}
- elements of annotations — parameters when annotating, all element values must be compile-time constants, correspond to methods of annotation interfaces
declaration annotations
- annotation target — implementing classes of
AnnotatedElement
:Class
(also interfaces),Constructor
,Executable
,Field
,Method
,Package
,Parameter
; sub-interfaceTypeVariable
and local variables- package annotations — in
package-info.java
, can only be processed at the source level/** * Package-level javadoc */ @GPL(version="3") package com.a.b; import org.gnu.GPL;
- parameter annotations — explicitly declare
this
if necessary
- package annotations — in
- local variable annotations — can only be processed at the source level
- an annotation can annotate itself
- annotation target — implementing classes of
type use (
ElementType.TYPE_USE
) annotations — annotate types, as sub-interfaces ofAnnotatedElement
- type arguments —
List<@NonNull String>
,List<@Localized ? extends Message>
,List<? extends @Localized Message>
- arrays —
@NonNull String[][] words
(words[i][j]
is notnull
),String @NonNull [][] words
(words
is notnull
),String[] @NonNull [] words
(words[i]
is notnull
) - when inheriting —
class Warning extends @Localized Message
- when
new
—new @Localized String(...)
- casts and
instanceof
—(@Localized String) text
,if (text instanceof @Localized String)
- exception specifications —
public String read() throws @Localized IOException
- method references —
@Localized Message::getText
- cannot
@NonNull String.class // ERROR: Cannot annotate class literal import java.lang.@NonNull String; // ERROR: Cannot annotate import
- type arguments —
# Standard Annotations
for compilation
@Deprecated
@Documented @Retention(value=RUNTIME) @Target(value={CONSTRUCTOR,FIELD,LOCAL_VARIABLE,METHOD,PACKAGE,PARAMETER,TYPE}) public @interface Deprecated
@SuppressWarnings
@Target(value={TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE}) @Retention(value=SOURCE) public @interface SuppressWarnings
@SuppressWarnings("fallthrough")
@Override
— error when not overriding but define a new method@Target(value=METHOD) @Retention(value=SOURCE) public @interface Override
@javax.annotation.Generated
— mark source code that has been generated. It can also be used to differentiate user written code from generated code in a single file (injavax.annotation.processing
for post JDK 8)@Documented @Retention(value=SOURCE) @Target(value={PACKAGE,TYPE,ANNOTATION_TYPE,METHOD,CONSTRUCTOR,FIELD,LOCAL_VARIABLE,PARAMETER}) public @interface Generated
@FunctionalInterface
— error if conditions of functional interfaces not meet@Documented @Retention(value=RUNTIME) @Target(value=TYPE) public @interface FunctionalInterface
@SafeVarargs
— assertion that the body of the annotated method or constructor does not perform potentially unsafe operations on its varargs parameter@Documented @Retention(value=RUNTIME) @Target(value={CONSTRUCTOR,METHOD}) public @interface SafeVarargs
meta
@Documented @Retention(value=RUNTIME) @Target(value=ANNOTATION_TYPE)
@java.lang.annotation.Target
— the contexts in which an annotation type is applicable, any declaration except a type parameter declaration if absentElementType[] value
enum java.lang.annotation.ElementType
—ANNOTATION_TYPE
,CONSTRUCTOR
,FIELD
,LOCAL_VARIABLE
,METHOD
,PACKAGE
,PARAMETER
,TYPE
,TYPE_PARAMETER
,TYPE_USE
TYPE
— class, interface (including annotation type), or enum declaration
@java.lang.annotation.Retention
— how long annotations with the annotated type are to be retained, defaults toRetentionPolicy.CLASS
if absentRetentionPolicy value
enum java.lang.annotation.RetentionPolicy
CLASS
— in class files but not the VMRUNTIME
SOURCE
@java.lang.annotation.Documented
— indicates that annotations with a type are to be documented by javadoc and similar tools by default@java.lang.annotation.Inherited
— indicates that an annotation type is automatically inherited, has no effect if the annotated type is used to annotate anything other than a class@java.lang.annotation.Repeatable
— indicates the annotation type is repeatable, with the containing annotation type to hold repeated annotations@Repeatable(TestCases.class) @interface TestCase { String params(); String expected(); } @interface TestCases { TestCase[] value(); }
Class<? extends Annotation> value
— a container annotation that holds the repeated annotations in an array
for java EE resource managing (deprecated from JDK 9 and removed from JDK 11, available in Maven)
@javax.annotation.PostConstruct
— used on a method that needs to be executed after dependency injection is done@Documented @Retention(value=RUNTIME) @Target(value=METHOD) public @interface PostConstruct
- Only one method can be annotated with this annotation
- annotated method signature — see javadoc
@javax.annotation.PreDestroy
— used on methods as a callback notification to signal that the instance is in the process of being removed by the container@Documented @Retention(value=RUNTIME) @Target(value=METHOD) public @interface PreDestroy
- annotated method requirements — see javadoc
@javax.annotation.Resource
— marks a resource that is needed by the application@Target(value={TYPE,FIELD,METHOD}) @Retention(value=RUNTIME) public @interface Resource
- example
@Resource(name="jdbc/mydb") private DataSource source;
- example
@javax.annotation.Resources
— multiple resources
# Source-Level Annotation Processing
CLI
javac -processor <class1>[,<class2>,<class3>...] sourceFiles
- also other alternatives
- produce new source files until no more — Each annotation processor is executed in turn and given the annotations in which it expressed an interest. If an annotation processor creates a new source file, the process is repeated. Once a processing round yields no further source files, all source files are compiled.
-XprintRounds
— show rounds- cannot modify source files — use with agents or bytecode engineering tools
javax.annotation.processing
@SupportedAnnotationTypes("com.example.annotations.ToString") @SupportedSourceVersion(SourceVersion.RELEASE_8) public class ToStringAnnotationProcessor extends AbstractProcessor { public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment currentRound) { } }
javax.annotation.processing.AbstractProcessor
— for processors to extendpublic abstract class AbstractProcessor extends Object implements Processor
interface
javax.annotation.processing.RoundEnvironment
@javax.annotation.processing.SupportedAnnotationTypes
@javax.annotation.processing.SupportedOptions
@javax.annotation.processing.SupportedSourceVersion
language model (AST) —
javax.lang.model
javax.lang.model.element.Element
— AST nodes
# Metaprogramming
# Reflection
runtime type identification — used by VM for method resolution
Object::getClass
Class::forName
T.class
ifT
is any Java type (orvoid.class
,int.class
etc.)- type capturing — use
Class<T>
as a parameter for type match, when called with a class object, the type parameterT
will be matched
java.lang.reflect
package (see Proxy for proxies)- outside
java.lang.reflect
—java.lang.Class
,java.lang.Package
(implementsAnnotatedElement
) - interface hierarchy
Member
— a field or a method or a constructorAnnotatedElement
— represents an annotated element with methods getting annotationsAnnotatedType
AnnotatedArrayType
AnnotatedParameterizedType
AnnotatedTypeVariable
AnnotatedWildcardType
GenericDeclaration
TypeVariable<D>
(also extendsjava.lang.reflect.Type)
Type
GenericArrayType
ParameterizedType
TypeVariable<D>
(also extendsjava.lang.reflect.AnnotatedElement
)WildcardType
- class hierarchy
AnnotatedElement
interfaceParameter
AccessibleObject
— allows suppression of access checks if the necessaryjava.lang.reflect.ReflectPermission
is available, access is checked every time a reflective method is invokedMember
interfaceExecutable
(implementsGenericDeclaration
)Constructor<T>
—T newInstance(Object... initargs)
Method
—Object invoke(Object obj, Object... args)
Field
— get and set methods
Array
— get, set methods andnewInstance
Modifier
— as a bit vector
- outside
Class
public final class Class<T> extends Object implements Serializable, GenericDeclaration, Type, AnnotatedElement, TypeDescriptor.OfField<Class<?>>, Constable
- reflection
String getName()
String getTypeName()
String toString()
Class<?> getComponentType()
— type of elements in an array,null
ifthis
is not an arrayClassLoader getClassLoader()
T[] getEnumConstants()
Class<? super T> getSuperclass()
- instance creation
T newInstance()
T cast(Object obj) throws ClassCastException
- method reflection — from this class and superclasses,
declared-
only for this classField[] getFields()
Field getField(String name)
Field[] getDeclaredFields()
Field getDeclaredField(String name)
Method[] getMethods()
Method getMethod(String name, Class<?>... parameterTypes)
Method[] getDeclaredMethods()
Method getDeclaredMethod(String name, Class<?>... parameterTypes)
Constructor[] getConstructors()
Constructor<T> getConstructor(Class<?>... parameterTypes)
Constructor[] getDeclaredConstructors()
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
- inner class and outer class
Class<?>[] getClasses()
Class<?> getEnclosingClass()
- generics
Type[] getGenericInterfaces()
Type getGenericSuperclass()
TypeVariable<Class<T>>[] getTypeParameters()
- get resources, delegating to class loader
URL getResource(String name)
InputStream getResourceAsStream(String name)
- reflection
# Proxy
proxies
- usage — at runtime, create new classes that implement given interfaces, with a method invocation handler
- proxy class definition
- runtime defined class — proxy objects are of classes defined at runtime with names such as
$Proxy0
- modifiers and inheritance — all proxies are
public final
and extendsProxy
- cached — only one proxy class for a particular class loader and ordered set of interfaces
- package — default package if given interfaces all public, else belongs to the package of given non-public interfaces
- runtime defined class — proxy objects are of classes defined at runtime with names such as
- proxying — all proxy classes override the
toString()
,equals()
, andhashCode()
, and given interface methods withInvocationHandler::invoke
- other methods in
Object
are untouched
- other methods in
interface java.lang.reflect.InvocationHandler
— invocation handlerspublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable
- additional data is stored in the invocation handler
java.lang.reflect.Proxy
public class Proxy extends Object implements Serializable
- creation
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces)
static InvocationHandler getInvocationHandler(Object proxy)
static boolean isProxyClass(Class<?> cl)
- creation
use example
public class ProxyTest { public static void main(String... args) { Object[] elems = new Object[1000]; final Class[] clz = { Comparable.class }; Arrays.setAll(elems, i -> Proxy.newProxyInstance(null, clz, new TraceHandler(Integer.valueOf(i)))); Arrays.binarySearch(elems, Integer.valueOf(ThreadLocalRandom.current().nextInt(elements.length) + 1)); } } class TraceHandler implements InvocationHandler { private Object target; public TraceHandler(Object t) { target = t; } public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { // print implicit argument System.out.print(target); // print method name System.out.print("." + m.getName() + "("); // print explicit arguments if (args != null) { for (int i = 0; i < args.length; i++) { System.out.print(args[i]); if (i < args.length - 1) System.out.print(", "); } } System.out.println(")"); // invoke actual method return m.invoke(target, args); } }
# Handles
java.lang.invoke
package special treatment by JVM- signature polymorphism — for some methods in
MethodHandle
,VarHandle
, see below Constable
— forMethodHandle
,VarHandle
andMethodType
, see belowinvokedynamic
instruction — makes use of bootstrapMethodHandle
constants to dynamically resolveCallSite
objects for custom method invocation behaviorldc
instruction — makes use of bootstrapMethodHandle
constants to dynamically resolve custom constant values
- signature polymorphism — for some methods in
signature polymorphism — for example, methods of other signatures can be invoked from
MethodHandle.invoke(Object... args)
- signature polymorphism method calls at compile and runtime
- compile — the Java compiler emits an
invokevirtual
instruction with the given symbolic type descriptor against the named method as usual, but the symbolic type descriptor is derived from the actual argument and return types, not from the method declaration(int) mh.invoke(7); // compiles to // 23: invokevirtual #8 // Method java/lang/invoke/MethodHandle.invoke:(I)I
mh.invoke(7); // compiles to // 24: invokevirtual #10 // Method java/lang/invoke/MethodHandle.invoke:(D)Ljava/lang/Object;
- at runtime
- link if the first time — as usual
invokevirtual
, but the JVM will successfully link any such call, regardless of its symbolic type descriptor - invocation check — see below
- invoke — optionally adjust types, then invoke the method handle's underlying method (or other behavior, as the case may be)
- link if the first time — as usual
- compile — the Java compiler emits an
- invocation check —
NoSuchMethodException
,IllegalAccessException
- symbolic type descriptor check — the caller's one is matched against the one assigned when the method handle is created after
invokevirtual
is linked;NoSuchMethodException
upon failure - access check — performed when the method handle is created; if
ldc
, access checking is performed as part of linking;IllegalAccessException
upon failure
- symbolic type descriptor check — the caller's one is matched against the one assigned when the method handle is created after
- signature polymorphism method calls at compile and runtime
interface java.lang.constant.Constable
— immediate constant support by JVM bytecode format forMethodHandle
,VarHandle
andMethodType
CONSTANT_MethodHandle
— refers directly to an associatedCONSTANT_Methodref
,CONSTANT_InterfaceMethodref
, orCONSTANT_Fieldref
constant pool entry#29 = MethodHandle 6:#44 // REF_invokeStatic Solution.lambda$foo$0:(IILjava/lang/Integer;)Z #44 = Methodref #7.#54 // Solution.lambda$foo$0:(IILjava/lang/Integer;)Z
CONSTANT_MethodType
— type is(Integer) -> boolean
in the below example#30 = MethodType #45 // (Ljava/lang/Integer;)Z #45 = Utf8 (Ljava/lang/Integer;)Z
VarHandle
— tbd
# Dynamically-Computed CallSite and Constant
dynamically-computed call sites —
invokedynamic
instruction22: invokedynamic #4, 0 // InvokeDynamic #0:test:(II)Ljava/util/function/Predicate; #4 = InvokeDynamic #0:#31 // #0:test:(II)Ljava/util/function/Predicate; #31 = NameAndType #46:#47 // test:(II)Ljava/util/function/Predicate;
#4 = InvokeDynamic
#0
: bootstrap method — eachinvokedynamic
instruction statically specifies its own bootstrap method as a constant pool reference#31 = NameAndType
— likeinvokestatic
and other invoke instructions, specifies the invocation's name and method type descriptor- linkage
- initial unlinked state — no target method for the instruction to invoke; it is linked just before first execution
- link
invokedynamic
to aCallSite
— by calling a bootstrap method which is given the static information content of the call, and which must produce aCallSite
dynamically-computed constants —
CONSTANT_Dynamic
tagged constants in constant poolCONSTANT_Dynamic
contents — like theInvokeDynamic
above- bootstrap method
NameAndType
— likegetstatic
instruction and the other field reference instructions, specifies the constant's name and field type descriptor
- linkage — similar to
invokedynamic
, resolve to a value of declared type InvokeDynamic
andCONSTANT_Dynamic
— aCONSTANT_Dynamic
is to aInvokeDynamic
like aCONSTANT_Fieldref
is to aCONSTANT_Methodref
bootstrap methods
- bootstrap method execution — link
invokedynamic
or resolveCONSTANT_Dynamic
- resolve the bootstrap method related constants in constant pool
- the bootstrap method, a
CONSTANT_MethodHandle
- the
Class
orMethodType
derived from type component of theCONSTANT_NameAndType
descriptor - static arguments, if any (note that static arguments can themselves be dynamically-computed constants)
- the bootstrap method, a
- invoke the bootstrap method with following args, as if by
MethodHandle::invoke
- resolve the bootstrap method related constants in constant pool
- bootstrap method args — see Lambda at Runtime for example
MethodHandles.Lookup
- a lookup object on the caller class in which dynamically-computed constant or call site occursCONSTANT_NameAndType
— aString
the name, and aMethodType
orClass
, the resolved type descriptorClass
, if it is a dynamic constant — the resolved type descriptor of the constant- the additional resolved static arguments, if any
- no type limitation — dynamically-computed constants can be provided as static arguments to bootstrap methods
- return —
CallSite
or theClass
mentioned above
- thread safety — must take the usual precautions against race conditions; if several threads simultaneously execute a bootstrap method for a single dynamically-computed call site or constant, the JVM must choose one bootstrap method result and install it visibly to all threads
- bootstrap method execution — link
# Method Handle
java.lang.invoke.MethodHandle
— a typed, immutable, directly executable reference to an underlying method, constructor, field, or similar low-level operation, with optional transformations of arguments or return valuespublic abstract class MethodHandle implements Constable
- functional equivalent of a particular bytecode behavior — see lookup methods in
MethodHandles.Lookup
- type
MethodType type()
— method handles are dynamically and strongly typed according to their parameter and return types- type conversion
MethodHandle asType(MethodType newType)
— produces an adapter method handleMethodHandle bindTo(Object x)
— curry- other
as-
methods and more
- invoke
Object invoke(Object... args) throws Throwable
—invokeExact
iftype
match, otherwise mayasType
or may perform adaptations directly on the caller's argumentsObject invokeExact(Object... args) throws Throwable
— requiring an exacttype
match- more
- reflection of above methods —
UnsupportedOperationException
if invoked viaMethod::invoke
, via JNI, or indirectly viaLookup.unreflect
- signature polymorphic — see before
- functional equivalent of a particular bytecode behavior — see lookup methods in
java.lang.invoke.MethodHandles
— utility class- lookup methods
MethodHandles.Lookup lookup()
MethodHandles.Lookup publicLookup()
- method handle combine and transform methods
- other method handle factory methods
MethodHandle identity(Class<?> type)
java.lang.invoke.MethodHandles.Lookup
— access restrictions enforced against look up class, which is the class where thisLookup
is createdClass<?> lookupClass()
- lookup factory methods — see javadoc, correspond to all major use cases for methods, constructors, and fields
unreflect
— reflection to method handle- lookup factory methods to bytecode behavior — see javadoc
- cross module — tbd
- lookup methods
java.lang.invoke.CallSite
— hold a variabletarget
of typeMethodHandle
invokedynamic
- call delegation — an invokedynamic instruction linked to a
CallSite
delegates all calls to the site's current target - one to none or many — a
CallSite
may be associated with severalinvokedynamic
instructions or none
- call delegation — an invokedynamic instruction linked to a
MethodHandle dynamicInvoker()
— produces a method handle equivalent to aninvokedynamic
instruction which has been linked to this call site (equivalent togetTarget
and theninvokeExact
)void setTarget(MethodHandle newTarget)
— the type of the new target must be equal to the type of the old targetjava.lang.invoke.ConstantCallSite
—UnsupportedOperationException
forsetTarget
java.lang.invoke.MutableCallSite
java.lang.invoke.VolatileCallSite
—MutableCallSite
but thetarget
isvolatile
# VarHandle
java.lang.invoke.VarHandle
— a dynamically strongly typed reference to a variable, or to a parametrically-defined family of variables, including static fields, non-static fields, array elements, or components of an off-heap data structure- properties
- immutable and stateless
- similar to
MethodHandle
— dynamic argument check and signature polymorphic, access check at creation
Class<?> varType()
— the type of every variable referencedfloat
anddouble
— compared bitwise, which differs from==
andequals
List<Class<?>> coordinateTypes()
— the types of coordinate expressions that jointly locate a variable referenced by thisVarHandle
- static memory fence methods —
fullFence()
,acquireFence()
,releaseFence()
,loadLoadFence()
andstoreStoreFence()
- properties
VarHandle
access methods- access mode method properties
enum VarHandle.AccessMode
— each member corresponds to an access method inVarHandle
- signature polymorphic — see before
- actual arguments — the coordinate types of a
VarHandle
instance, and the types for values of importance to the access mode, see example - dynamic argument check —
MethodType accessModeType(VarHandle.AccessMode accessMode)
- invocation behaves as if
MethodHandle::invoke
, see javadoc for examples
- access mode methods
- atomicity and consistency properties, override declarations
- plain — bitwise atomic only for references and for primitive values of at most 32 bits
- opaque — bitwise atomic and coherently ordered with respect to accesses to the same variable
- acquire, release — opaque, and acquire mode reads and their subsequent accesses are ordered after matching release mode writes and their previous accesses
- volatile — acquire, release, and ordered with respect to each other
- taxonomy
- read —
get
,getVolatile
,getAcquire
,getOpaque
- write —
set
,setVolatile
,setRelease
,setOpaque
- atomic update —
compareAndSet
,weakCompareAndSetPlain
,weakCompareAndSet
,weakCompareAndSetAcquire
,weakCompareAndSetRelease
,compareAndExchangeAcquire
,compareAndExchange
,compareAndExchangeRelease
,getAndSet
,getAndSetAcquire
,getAndSetRelease
- numeric atomic update —
getAndAdd
,getAndAddAcquire
,getAndAddRelease
- bitwise atomic update —
getAndBitwiseOr
,getAndBitwiseOrAcquire
,getAndBitwiseOrRelease
,getAndBitwiseAnd
,getAndBitwiseAndAcquire
,getAndBitwiseAndRelease
,getAndBitwiseXor
,getAndBitwiseXorAcquire
,getAndBitwiseXorRelease
- read —
- atomicity and consistency properties, override declarations
- access mode method properties
VarHandle
creation and conversion- creation — access modes supported according to javadoc
- in
MethodHandles.Lookup
findVarHandle(Class<?> recv, String name, Class<?> type)
— returns aVarHandle
of a non-staticrecv.name
oftype
; one coordinate type,recv
findStaticVarHandle(Class<?> decl, String name, Class<?> type)
— returns aVarHandle
of a staticrecv.name
oftype
; no coordinate typesunreflectVarHandle(Field f)
- in
MethodHandles
arrayElementVarHandle(Class<?> arrayClass)
— the list of coordinate types is(arrayClass, int)
byteArrayViewVarHandle
,byteBufferViewVarHandle
- in
- to
MethodHandle
MethodHandle toMethodHandle(VarHandle.AccessMode accessMode)
MethodHandles::varHandleInvoker
MethodHandles::varHandleExactInvoker
MethodHandles.lookup().findVirtual(VarHandle.class, ...)
- creation — access modes supported according to javadoc
VarHandle
exampleString[] sa = ... VarHandle avh = MethodHandles.arrayElementVarHandle(String[].class); boolean r = avh.compareAndSet(sa, 10, "expected", "new");
# Lambda at Runtime
lambda at runtime reference — from Translation of Lambda Expressions (opens new window)
desugar
- desugar to method — when the compiler encounters a lambda expression, it first lowers (desugars) the lambda body into a method whose argument list and return type match that of the lambda expression, possibly with some additional arguments (for values captured from the lexical scope, if any)
- desugar strategy — private, static over instance, in the innermost class in which the lambda expression appears, signatures should match the body signature of the lambda, extra arguments should be prepended on the front of the argument list for captured values, and would not desugar method references at all
- instance-capturing lambda — instance-capturing lambdas are desugared to private instance method; when capturing an instance-capturing lambda, the receiver (
this
) is specified as the first dynamic argument, meshes well with available implementation techniques (bound method handles) - example: desugar of a method — see below
- example: deadlock caused by desugar — during class loading, other fork join threads will call desugared static method, which requires the class loaded
public class Main { public static void main(String[] args) { System.out.println(Main.name); } public static String name; static { name = getName(); } private static String getName() { List<String> names = new ArrayList<>(); for (int i = 0; i < 10; i++) { names.add("a" + i); } names = names.parallelStream().filter(s -> s.equalsIgnoreCase("a9")).collect(Collectors.toList()); return names.get(0); } }
CallSite
frominvokedynamic
invokedynamic
call site, built by lambda factory — at the point at which the lambda expression would be captured, it generates aninvokedynamic
call site, which implements lambda capture as the dynamic argument list and, when invoked, returns an instance of the functional interface to which the lambda is being converted- see Handles for
invokedynamic
java.lang.invoke.LambdaMetafactory::metafactory
,LambdaMetafactory::altMetafactory
static CallSite metafactory( // automatically stacked by the VM at CallSite linkage MethodHandles.Lookup caller, String invokedName, MethodType invokedType, MethodType samMethodType, // single abstract (functional interface) method MethodHandle implMethod, // the implementation method, may have extra arguments and may subtype or box // enforced dynamically at invocation time; samMethodType, or may be a specialization of it MethodType instantiatedMethodType)
invokedType
— expected signature of theCallSite
, the parameter types represent the types of capture variables; the return type is the functional interface; see number of instantiations below for example
- method references — treated the same way as lambda expressions, except that most method references do not need to be desugared into a new method; we can simply load a constant method handle for the referenced method and pass that to the metafactory
- see Handles for
- example:
invokedynamic
in bytecode — see below - number of instantiations — only one instantiation (
MethodHandles::constant
) if no capture// called by bootstrap methods in LambdaMetafactory to build CallSite CallSite buildCallSite() throws LambdaConversionException { final Class<?> innerClass = spinInnerClass(); if (invokedType.parameterCount() == 0 && !disableEagerInitialization) { // In the case of a non-capturing lambda, we optimize linkage by pre-computing a single instance, // unless we've suppressed eager initialization // ... try { Object inst = ctrs[0].newInstance(); return new ConstantCallSite(MethodHandles.constant(samBase, inst)); } // ... } else { try { if (!disableEagerInitialization) { UNSAFE.ensureClassInitialized(innerClass); } /* this CallSite calls innerClass::get$Lambda with method type invokedType every time to get an instance */ return new ConstantCallSite( MethodHandles.Lookup.IMPL_LOOKUP .findStatic(innerClass, NAME_FACTORY, invokedType)); } // ... } }
// number of instantiations test example static IntUnaryOperator oper = null; static int opCounter = 0; static int lambdaTest(IntUnaryOperator op) { if (op != oper) ++opCounter; oper = op; return op.applyAsInt(3); } static void test() { opCounter = 0; for (int i = 0; i < 100; ++i) { lambdaTest(j -> j * j); } System.out.println(opCounter); // 1 } static void test2(int num) { opCounter = 0; for (int i = 0; i < 100; ++i) { lambdaTest(j -> j * j * num); } System.out.println(opCounter); // 100 }
example: desugar of a lambda with capturing and its
invokedynamic
call siteclass B { public void foo() { List<Integer> list = List.of(20, 30); int bottom = 0, top = 103; // final int bottom = 0, top = 103; // no capture if final list.removeIf( p -> (p >= bottom && p <= top) ); } }
class B { public void foo() { List<Integer> list = List.of(20, 30); int bottom = 0, top = 103; list.removeIf(/* invokedynamic #4, 0 */); } private static boolean lambda$foo$0(int bottom, int top, Integer p) { return p >= bottom && p <= top; } }
- constant pool contents and correspondences to the bootstrap method
#4 = InvokeDynamic #0:#31 // #0:test:(II)Ljava/util/function/Predicate; #31 = NameAndType #46:#47 // test:(II)Ljava/util/function/Predicate; #46 = Utf8 test /* invokedName */ #47 = Utf8 (II)Ljava/util/function/Predicate; /* invokedType */ 0: #27 /* method handle of bootstrap method */ #27 REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:... Method arguments: #28 (Ljava/lang/Object;)Z /* samMethodType */ #29 REF_invokeStatic B.lambda$foo$0:(IILjava/lang/Integer;)Z #30 (Ljava/lang/Integer;)Z /* instantiatedMethodType */
#47
(II)Ljava/util/function/Predicate;
—MethodType
of(int, int) -> Predicate
#29
— argumentimplMethod
inLambdaMetafactory::metafactory
; aMethodHandle
invokingB::lambda$foo$0
and ofMethodType
of(int, int, Integer) -> boolean
- constant pool contents and correspondences to the bootstrap method
serialization — tbd