Today we will walk through some syntax & features in core Java. Note that the version we use here is Java 8.
Intro
Notes
OpenJDK: open source version of Java
JVM:
OS process that provides the Java runtime environment
Interpreter for the bytecode form (with JIT compilation to give a huge performance boost)
Other languages can also run in JVM, as long as they have valid class files
Makes use of runtime information self-manageable
Research: Programs’ runtime behavior has a large amount of interesting & useful patterns that cannot be deduced at compile time.
JVM was the 1st platform to utilize this research, collects info to make better decisions about how to execute the code.
JIT:
- HotSpot VM improved by detecting hot methods (methods used most often), then JVM compiles the hot methods directly to machine code.
- Old days, Javac produces heavily optimized machine code. But then it’s better to just optimize JIT itself
Class file is the smallest unit of functionality the platform will deal with.
Javac:
Produces bytecode, while compilers produce machine code
Javac creates the intermediate representation (bytecode)
Compilation: JIT (it actually produces machine code)
Bytecode:
- The instruction code (opcode) is just a single byte, only 256 possibilities
- Byte ordering: big-endian
Comparison
Java & C
- Java is object-oriented; C is not
- Java is portable as class files; C need to be recompiled
- Java has no pointers & pointer arithmetic,
- Java provides automatic memory management via garbage collection
- Java has no ability to lay out memory at low level (no structs)
- Java has no pre-processor
Java & C++
- Java is always pass by value (object references are values)
- Java does not support full multiple inheritance
- Java has no operator overloading
Java & JS
- Java uses class-based objects; JS is prototype-based
- Java has namespaces; JS does not
- Java is multi-threaded; JS is not
Syntax
Note: strictfp
& assert
keywords are almost never used.
Overview
Classes are collections of methods & fields.
Reference types:
- Fields
- Methods
- Constructors
Structure:
Primitives
Operators
Expressions
Statements
Methods
Classes
Packages
Programs / Applications
Lexical Structure
Java programs are written using Unicode.
const
& goto
are reserved keywords, but aren’t actually used in the language.
Literals
- Definition: Literals are values that appear directly in Java source code.
- Include: ints, floats, chars with single & double quotes, reserved words (true / false / null)
- Each primitive type has a literal syntax for including type values literally in the code
Primitives
Eight types:
- 1 boolean type
- 1 character type
- 2 floating-point type
- 4 integer type
Type | Size | Comments |
---|---|---|
boolean | 1 bit | true / false |
char | 16 bits | Unicode |
byte | 8 bits | signed int |
short | 16 bits | signed int |
int | 32 bits | signed int |
long | 64 bits | signed int |
float | 32 bits | |
double | 64 bits |
boolean
: A boolean
is neither an integral nor an object type. It cannot be widened / narrowed.
char
:
- Java 8 uses Unicode 6.2
- Recent release of Unicode includes chars whose encoding / codepoints do not fit in 16 bits (use 21 bits instead)
- Use
int
to hold codepoint of a supplementary char, or encode in surrogate pair of 2 char values
- Use
- String literals:
String
type is class (a reference type)
Ints (4):
- All int types represent signed numbers
- Ints can be expressed in hex, binary, or octal notation (use underscore for binary literal)
- Integer arithmetic in Java never produces overflow / underflow (numbers just wrap around)
Floats (2):
- Floating-point literals are
double
by default - Cannot be expressed in hex, binary, octal
-
float
&double
values are only approximation of the represented numbers - 4 special values: Positive & negative infinity, zero, NaN (not a number)
- Differentiate between positive & negative zero
- Arithmetic Never throws exceptions, even when performing illegal operations (NaN)
Type Conversion
Only
boolean
cannot be convertedWidening: Value converted to a wider type
Narrowing: Value converted to a narrower type
- Not always safe, may lose data
cast: Force type conversion (often used to convert floats to ints)
1
2
3int i = 13;
byte b = (byte) i; // (byte) is a cast
i = (int) 13.1; // (int) another cast
Expressions & Operators
Operators
- Precedence:
- Operators with higher precedence are performed first
- Default precedence is compatible with rules in C
- Associativity:
- Most are left-to-right associative
- A reference is an object / array
Comparison, equality, Boolean operators always return boolean
values.
Post-increment: a++
1 | a[i++]++; |
Pre-increment: ++a
first increments a
, then returns the incremented value.
1 | int a = 2; |
Java has built-in string conversion for all primitive types ( use toString()
)
==
:
- For reference types, it only compares the content (if refers to the same object)
- If
==
is used to compare different types of numeric / character values, the narrower type will be first converted to the wider type
Boolean operator
-
A && B
: To increase efficiency, only evaluate B, if A istrue
-
A || B
: If A istrue
, then skip B. (since it will always be true) A & B
,A | B
:- Always evaluate both A & B
- Used as a bitwise operator with integer operands
-
A ^ B
: Must always evaluate both
Bitwise & Shift Operators
-
<<
: left shift -
>>
: signed right shift -
>>>
: unsigned right shift
Other operators
-
instanceof
-
.
: object member access -
[]
: array element access -
()
: method invocation / type conversion / casting -
->
: lambda expression new
: object creation- Objects are created with
new
- A constructor is a special block of code that initializes a newly created object
- Objects are created with
Statements
Many statements defined by Java are flow-control statements.
Compound statement: Statements grouped together with { }
Labeled statement: pre-pend an identifier, used by break
& continue
1 | loop1: for (int i = 0; i < n; ++i) |
Local var declaration statement:
- Since Java is a statically typed language, only values of that type can be stored in the variable
- Local vars can be used only within the method / block in which they’re defined (lexical scope)
Boolean
: wrapper type (the wrapper object is auto unboxed)
boolean
: primitive type
else
Without { }
, else
is associated with the nearest if
.
switch
Use break
after each case. Each case must be a constant or a constant expression that the compiler can evaluate.
1 | switch(n) { |
do-while
- loop expression is tested at the boom of the loop
- Execute at least once
for
Three things at the top : initialize, test, and update steps
1
2
3
4
5
6
7
8for (init; test; update)
// Equal to the while below:
init;
while (test) {
statement;
update;
}Use comma to separate multiple init. / update:
1
for (int i = 0, j = 0; i < 10; ++i, -j)
Can be used for iterating through a linked list:
1
2for ( node n = head; n != null; n = n.next() )
process(n);Infinite loop:
1
for(;;) // All three expressions are optional
foreach loop: Iterate collections
- Hides loop counter (iterator)
- Cannot get the array index
1
for (element: collection)
break
- Exit innermost loop
- Use label to choose exit
continue
-
continue
quits the current iteration, and starts the next one - Only used within
while
/for
loops
synchronized
Prevent multiple threads from modifying an object simultaneously (might corrupt the object’s state)
1
2
3synchronized (expression) {
// code block
}Before executing the code block, the Java interpreter first obtain an exclusive lock on the object specified by
expression
. The lock is held until finish running the code block. While a thread holds the lock, other threads cannot obtain the lock.synchronized
as a method modifier: The entire method is locked
throw
An exception: A signal that indicates exceptional condition / error has occurred
throw
signals the exceptional condition,catch
handles that exception. When there’s athrow
, the interpreter stops normal program execution, and starts looking for an exception handler that can catch / handle the exception顺序:
- 先看 method 里有没有 exception handler
- 再看 code 里有没有处理 exception
- 如果都没有就 print error message & stack trace
An exception is represented by an object
try / catch / finally
- Every
try
must be followed by acatch
/finally
(to do the exception handling and cleanup) -
finally
: close files / shut down network connections - Exit try before
finally
:System.exit()
assert
Rarely used, inflexible for testing applications
Never attempt to catch
AssertionError
from your own code (might have unexpected results in future versions)
Methods
A method invocation is an expression that’s evaluated by the Java interpreter.
Method Signature
A method signature contains:
- Method name
- Parameters (number, order, type, name)
- Returned value type
- Checked exceptions to
throw
- Method modifiers
Method signature can also include type variable declarations (generic methods).
Abstract methods only have specification, but no implementation (no method body).
A method signature is the method specification, and defines the API for the method.
1 | modifiers type name (paramlist) [throws exception] |
The signature is followed by the method body ( = method implementation = bunch of Java statements).
modifiers
: public / protected / private, final, native, static, synchronized / volatile, abstract, strictfptype
: specifies the return typeConstructor: initialize newly created objects (constructor’s signature does not include the
type
specification)name
: follows the specification of its modifier & type (method names & variable names are Java identifiers)- Method overloading: Define more than one method with the same name (each method has a different param list)
Param list: empty is
( )
. Java does not regardvoid
as a typethrow
:Checked exceptions:
- Category of exception classes that must be listed in the
throw
clause of methods that can throw them - Must use
throw
clause to declare the exception in the method signature - Java compiler checks to make sure they’re declared in the method signature, hence the name “checked”
- Category of exception classes that must be listed in the
Unchecked exceptions:
Failures that cannot be predicted, due to runtime conditions. (e.g.
OutOfMemoryError
,NullPointerException
)-
Murphy’s law: Anything that can go wrong, will go wrong.
Exceptions are throwable objects. 2 categories:
- Error (Any exception object that is an
Error
is unchecked) - Exception (checked)
- 特例:
RuntimeException
is unchecked
- Error (Any exception object that is an
Method Modifiers
abstract
An abstract method is a specification without an implementation
A class that includes an abstract method must also be
abstract
. Such class cannot be instantiatedNeed implementation of specification, to instantiate the class.
final
- A
final
method may not be overridden or hidden by a subclass - All
private
methods are implicitlyfinal
native
- Indicates method implementation is written in “native” languages such as C
- Provided externally to the Java program, platform-dependent
- All native & abstract methods have no body
- Used to interface Java code to existing C / C++ libraries
static
A method with static
is a class method associated with the class itself, but not associated with the instance of the class
strictfp
-
fp
: floating point - Only perform fp arithmetic using 32 / 64 bit floating-point formats, even this is less accurate
synchronized
Makes a method thread safe, prevents 2 thread from executing the method at the same time
Before a thread invokes a
synchronized
method, it must obtain a lock on the method’s class, or on relevant instance of the class.synchronized
modifier is an implementation detail (because methods can make themselves thread safe in other ways)
Annotations: intermediary between method modifier & supplementary type information.
Class & Objects
A class is a named collection of fields that hold data values & methods
One of the 5 reference types
流程: define a class, instantiate it, and use the resulting object
Classes define new data types.
Important to distinguish between data type & the value data type represents.
A class is data type, and class value is called the object. Each class defines a type of objects.
Define a class
1 | public class Point { |
Create an object
1 | // New object p, of the class Point |
- Dynamic loading mechanism: Java allows programs to load classes & create instances of classes dynamically
- Objects can also be created by deserializing them
Object literals
String literal: strings are objects; the data type to represent text is the
String
classType literal: a
Class
class. Instances ofClass
class represent a Java data type1
2// Include a Class object literally in the code
Class<?> typeIntArray = int[].class;Null reference: reference to nothing / absence of a reference .
Null
is a member of every reference type.
Lambda Expressions
A lambda expression is a function that does not have a name.
Can be treated as a value
Java does not allow code to run on its own outside of class: Lambda is an anonymous method that is defined on some class
Syntax:
(paramlist) -> (statements)
1
Runnable r = () -> System.out.println("hello");
When lambda is used as a value, it is automatically converted to a new object of the correct type .
Auto conversion & Type inference is essential to Java’s lambda expressions.
Arrays
Array type are reference types, and instances of arrays are objects.
- Arrays inherit the methods of
java.lang.Object
- Arrays implement the
Cloneable
interface, and override theclone()
method to ensure arrays can be cloned - Arrays also implement
Serializable
, so it can be serialized, if its elements are serialized - All arrays have a
public final int
field calledlength
Type conversion
- Since arrays extend
Object
and implementClonable
&Serializable
interfaces, an array type can be widened to any of these 3 types. - Ability to widen array type (array covariance): Array’s compile-time type is not same as runtime type
- Compilers need runtime checks, to ensure runtime value type match runtime array element type
Init. Arrays
Array types don’t have constructors
Init. value: 0 /
false
/null
Use anonymous array literals (apply to multi-dimensional array as well):
1
String response = Question( "Exit?", new String[] {"Yes", "No"} );
As part of variable declaration: (Array literals are created & initialized at runtime)
1
String[] response = {"Yes", "No"};
Java does all array initialization at runtime:
Expressions in an array initializer may be computed at runtime, and need not be compile-time constants.
Copy Arrays
Since all array types implement
Cloneable
, hence any array can be copied by theclone()
methodA cast is required to convert return value to the appropriate array type
1
2int[] a = {1, 2, 3};
int[] b = (int[]) a.clone();Two ways to copy arrays
clone()
: shallow copyIf array element type is a reference type, then only the references are copied. Any array can be cloned even if element type is not
Clonable
.System.arraycopy()
1
2
3// arraycopy(source, s[i], destination, d[j], #-of-elements)
System.arraycopy(a, 1, a, 0, n);
// Shift elements in [1, n] one index down Works even for overlapping copies within the same array.
Array Utilities
-
java.util.Arrays
contains a number of static utility methods - Most of the methods are heavily overloaded, with versions for arrays of primitive types & arrays of objects
-
sort()
&binarySearch()
for sort, search arrays -
Arrays.toString()
, convert array content to string output
Multi-dimensional Arrays
1 | int[][] a = new int[10][10]; |
Line 1 does three things:
- Declare the variable
a
- Creates a 10-element array, to hold 10 arrays of
int
- Creates 10 more arrays with a loop
When using the new
keyword, only need to specify the leftmost dimension of the array.
1 | // 1-D array |
Reference Types
- Annotation: Associate metadata with program elements
- Array
- Enumeration: Reference for a set of objects that represents a related set of choices
- Class: Provide inheritance, polymorphism, and encapsulation
- Interface: Provide public API and is implemented by Java classes
Object: value / instance of any reference type.
Reference & Primitive Types
User cannot define new primitive types, but reference types are user-defined
Primitive types represent single values; Reference types are aggregate types that hold zero / more primitive values or objects
Primitive types only require 1 - 8 bytes of memory. For reference types, only the reference to that memory is stored
Imagine a reference as a pointer or a memory address (Java cannot manipulate references)
Memory for storing a object is dynamically allocated on the heap, and it’s auto garbage-collected when the object is no longer needed .
Pass arguments to methods
- Primitive: The method is given a copy of the argument used to invoke the method
- Reference: Method pass a private copy of a reference to the object
Compare Objects
Reference types, 2 kinds of equality:
- Equality of reference
-
.equals()
: 判断内容是否一致
-
- Equality of object
-
==
: Whether 2 references refer to the same object
-
Arrays always inherit the default equals()
method the compares references, rather than array content.
Boxing & Unboxing
Treat primitive values as objects: wrapper class for each of the 8 primitive types (Immutable, final classes)
Boolean
,Byte
,Short
,Character
,Integer
,Long
,Float
,Double
Use wrapper class when you want to store primitive values in collections
Boxing convert primitives to wrapper objects, and Unboxing converts wrapper class back to primitives
Autoboxing: Java performs boxing & unboxing automatically
- Autoboxing makes dealing with collections much easier.
1
List<Integer> n = new ArrayList<>(); // Box into integer
Packages & Namespaces
A package is a named collection of classes , interfaces & other reference types.
javax
: Extension to the Java Platform.
Each class has a simple name & fully qualified name.
E.g. class String
& java.lang.String
Use globally unique package name to partition the Java namespace, and prevent name collisions between classes
Static Imports
On-demand import does not apply to subpackages.
1 | // On-demand import |
Import static members
1 | import static java.lang.Math.*; |
Important use: Import the name of constants into your code.
1 | // Enumerated type |
Using static member import
declarations for constants is generally better than implementing an interface that defines the constants.
It is legal to import static methods with the same name from more than 2 different types, as long as the method signatures are different.
1 | // Legal Import |
File Structure
All Java statements must appear within methods;
All methods must appear within type definition.
A Java file consists of:
-
package
directive (optional) -
import
/import static
directives - Type definitions
Restriction for Java files:
- Each file contain at most one top-level
public
class - A public class is designed for use by other classes in other packages
- File name & class name must be the same
Tell the interpreter to look in locations other than the current directory:
Specify java -classpath
in Terminal
Run Programs
The main()
method is the main entry point for your program. This method is passed an array of strings, and returns no value.
When main()
returns, the Java interpreter exits.