Introduction to Java Programming (10th ed.)

  • Author: Y. Daniel Liang
  • Released: January, 2014

Very thorough CS1 + CS2 course with emphasize on Java. It covers everything one need to know to fully embrace the power of Java language.

It is pretty complete and fast paced, intermediate-to-expert level.

Java 8 used throughout the book.

Content


Chapter 1: Introduction to Computers, Programs and Java

A computer is an electronic device that stores and processes data.

Computers includes both hardware and software. CPU consists of a control unit and arithmetic/logic unit.

Every computer has an internal clock which emits electronic pulses at a constant rate.

These pulses are used to control and synchronize the pace of operations.

Operating system performance techniques:

  • Multiprogramming: allows multiple programs to run simultaneously by sharing the same CPU.
  • Multiprocessing: allows to use two or more CPU units to run programs concurrently.
  • Multithreading: allows a single program to execute multiple tasks at the same time.

Multitasking: same as multiprogramming but in a more general sense.

In multiprogramming (older OSs) one program as a whole keeps running until it blocks, in multitasking (modern OSs) time sharing is best manifested because each running process takes only a fair quantum of the CPU time. More on this.

  • JAVA documentation: https://docs.oracle.com/en/java/
  • Java JDK documentation: https://docs.oracle.com/javase/10/
  • Java language specification: https://docs.oracle.com/javase/specs/
  • Java API documentation: https://docs.oracle.com/javase/10/docs/api/overview-summary.html

Java editions:

  • Java SE: Standard Edition for client-side applications
  • Java EE: Enterprise Edition for server-side applications (Java servlets, JavaServer Pages, JavaServer Faces)
  • Java ME: Micro Edition for mobile devices

Every Java program must have at least one class.

Class name starts with an uppercase letter.

The main method is the program entry point.

To compile a Java source file into a bytecode:

javac Welcome.java # creates Welcome.class with JVM bytecode
java Welcome # run bytecode from Welcome.class

If a class file does not exist, NoClassDefFoundError will occur

If a class file does not have a main method, NoSuchMethodError will occur

Types of programming errors:

  • Syntax Errors / Compile-Time errors
  • Runtime Errors
  • Logic Errors

Chapter 2: Elementary Programming

Java uses System.out to refer to the standard output device and System.in to the standard input device.

import java.util.Scanner;

public class ComputeAreaWithConsoleInput {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Enter a number for radius: ");

        double radius = input.nextDouble();
    }
}

No performance difference between types of import:

  • Specific import -> import java.util.Scanner;
  • Wildcard import -> import java.uitl.*;

Identifiers are the names that identify the elements such as classes, methods, and variables in a program.

Every variable has a scope. The scope of a variable is the part of the program where the variable can be referenced.

To declare a constant:

final double PI = 3.14159

Java have 8 primitive data types:

byte: 8b: -2^7 to 2^7 - 1 (-128 to 127)
short: 16b: (-32768 to 32767)
int: 32 bits: (-2147483648 to 2147483647)
long: 64 bits: (-9_223_372_036_854_775_808 to 9_223_372_036_854_775_807)

float: 32 bits
double: 64 bits

char: 16 bits
boolean: 8 bits

Division has the same priority as multiplication

System.out.println("3.0 * 2 / 4 is " + 3.0 * 2 / 4) // 1.5

A literal is a constant value that appears directly in a program.

For example, 42 and 0.555L.

To denote an integer literal of the long type, append the letter L or l to it.

System.out.println(0B1111); // Displays 15
System.out.println(07777); // Displays 4095
System.out.println(0XFFFF); // Displays 65535
System.out.println(5.0534E+1) // Displays 50.534
System.currentTimeMillis() returns the current time in UNIX epoch format.

Casting a type with a small range to a type with a larger range is known as widening a type. Casting a type with a large range to a type with a smaller range is known as narrowing a type. Java will automatically widen a type, but you must narrow a type explicitly.

Chapter 3: Selections

Math.random() generates a random double value in a range [0.0, 1.0).

Generate a random single-digit number:

int number = (int)(Math.random() * 10);

Chapter 4: Math, Characters and Strings

ceil(x), x is rounded up to its nearest integer. This integer is returned as a double value.

floor(x), x is rounded down to its nearest integer. This integer is returned as a double value.

rint(x), x is rounded up to its nearest integer. If x is equally close to two integers, the even one is returned as a double value.

round(x), Returns (int)Math.floor(x + 0.5) if x is a float and returns (long)Math.floor(x + 0.5) if x is a double.

Mapping a character to its binary representation is called encoding.

A 16-bit Unicode takes two bytes, preceded by u, expressed in four hexadecimal digits that run from u0000 to uFFFF.

Unicode includes ASCII code, with u0000 to u007F corresponding to the 128 ASCII characters.

'0' to '9'  48 to 57    \u0030 to \u0039
'A' to 'Z'  65 to 90    \u0041 to \u005A
'a' to 'z'  97 to 122   \u0061 to \u007A

When an integer is cast into a char, only its lower 16 bits of data are used;

char ch = (char)0XAB0041; // The lower 16 bits hex code is 0041 (A)
String message = "Welcome to Java";
message.charAt(1); // ‘e’
message[1]; // error

To read a string from the console, invoke the next() method on a Scanner object:

Scanner input = new Scanner(System.in);
System.out.print("Enter three words separated by spaces: ");
String s1 = input.next();
String s2 = input.next();
String s3 = input.next();

string1.equals(string2) vs (string1 == string2)

s1.compareTo(s2) - compare lexicographically

int intValue = Integer.parseInt(intString);

double doubleValue = Double.parseDouble(doubleString);

The Integer and Double classes are both included in the java.lang package, and thus they are automatically imported.

String s1 = "Welcome to Java";
String s2 = "Programming is fun";
String s3 = "Welcome to Java";

s1 == s3 // true

System.out.println('1' + 1); // 50

Chapter 5: Loops

Loops are basically the same as in C++/JavaScript.

Chapter 6: Methods

Some programming languages refer to methods as procedures and functions. In those languages, a value-returning method is called a function and a void method is called a procedure.

Each time a method is invoked, the system creates an activation record (also called an activation frame) that stores parameters and variables for the method and places the activation record in an area of memory known as a call stack

Overloaded methods must have different parameter lists. You cannot overload methods based on different modifiers or return types.

Sometimes there are two or more possible matches for the invocation of a method, but the compiler cannot determine the best match. This is referred to as ambiguous invocation. Ambiguous invocation causes a compile error.

The scope of a variable is the part of the program where the variable can be referenced.

Task: Design modular simple calendar program through stepwise refinement.

Chapter 7: Single-Dimensional Arrays

Create an array syntax:

elType[] arrayRefVar = new elType[arraySize];
// alternatively
elType arrayRefVar[] = new elType[arraySize];

Array initializer shorthand example:

double[] myList = {0.9, 1.9, 2.5};

Foreach loops:

for (double e: myList) {
    System.out.println(e);
}

One of the options to shallow copy an array:

arraycopy(sourceArray, srcPos, targetArray, tarPos, length);

Anonymous array:

new elementType[]{value0, value1, ..., valuek};

Variable length parameters treated as an array.

In the method declaration, you specify the type followed by an ellipsis (…):

public static void printMax(double... numbers) {}

The java.util.Arrays class contains useful methods for common array operations such as sorting and searching.

java.util.Arrays.sort(chars, 1, 3); // Sort part of the array
java.util.Arrays.parallelSort(chars, 1, 3); // Sort part of the array
java.util.Arrays.binarySearch(list, 12)
java.util.Arrays.equals(list1, list2)
java.util.Arrays.toString(list)
java.util.Arrays.fill(list, 7)

`mean =(x_1 + x_2 + … + x_n) / n`

`std deviation = sqrt( sum( (x_i - mean)^2 ) / (n - 1))`

Chapter 8: Multidimensional arrays

Create two-dimentional array

int[][] matrix = new int[3][3];
int[][] array = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

Chapter 9: Objects and Classes

An object represents an entity in the real world that can be distinctly identified.

Two classes can reside in one file, but only one can be a public class. The public class must have the same name as the file name. Each class in the source code is compiled into a .class file.

Constructors do not have a return type — not even void.

java.util.Date

+Date()
+Date(elapseTime: long)

+toString(): String
+getTime(): long

The private modifier makes methods and data fields accessible only from within its own class

private modifier restricts access to its defining class

default modifier restricts access to a package

public modifier enables unrestricted access

To prevent direct modifications of data fields, you should declare the data fields private, using the private modifier. This is known as data field encapsulation.

Anonymous object:

System.out.println("Area is " + new Circle(5).getArea()); 

Chapter 10: Object-Oriented Thinking

The object-oriented paradigm couples data and methods together into objects

The collection of methods and fields that are accessible from outside the class, together with the description of how these members are expected to behave, serves as the class’s contract.

The user of the class does not need to know how the class is implemented. The details of implementation are encapsulated and hidden. This principe is called class encapsulation.

Class is also known as an abstract data type (ADT).

In procedural programming, data and operations on the data are separate, and this methodology requires passing data to methods. Object-oriented programming places data and the operations that pertain to them in an object.

The object-oriented approach combines the power of the procedural paradigm with an added dimension that integrates data with operations into objects.

A Java program can be viewed as a collection of cooperating objects.

The common relationships among classes are association, aggregation, composition, and inheritance. More on that on stackoverflow.

Owing to performance considerations, primitive data type values are not objects in Java.

Java provides Boolean, Character, Double, Float, Byte, Short, Integer, and Long wrapper classes in the java.lang package for primitive data types.

Converting a primitive value to a wrapper object is called boxing. The reverse conversion is called unboxing.

The BigInteger and BigDecimal classes can be used to represent integers or decimal numbers of any size and precision.

Regex example:

"440-02-4534".matches("\\d{``3}-\\d{2}-\\d{4}")

Convert string to array and back:

char[] chars = "Java".toCharArray();
String str = String.valueOf(new char[]{'J', 'a', 'v', 'a'});

The StringBuilder and StringBuffer classes are similar to the String class except that the String class is immutable.

Chapter 11: Inheritance and Polymorphism

Java does not allow multiple inheritance.

Nevertheless, multiple inheritance can be achieved through interfaces.

A constructor may invoke an overloaded constructor or its superclass constructor. If neither is invoked explicitly, the compiler automatically puts super() as the first statement in the constructor.

Constructing an instance of a class invokes the constructors of all the superclasses along the inheritance chain.

The keyword super can also be used to reference a method other than the constructor in the superclass:

super.method(parameters); 

Overriding means to provide a new implementation for a method in the subclass.

Every class in Java is descended from the java.lang.Object class.

Polymorphism means that a variable of a supertype can refer to a subtype object -> An object of a subclass can be used wherever its superclass object is used.

A class defines a type. A type defined by a subclass is called a subtype, and a type defined by its superclass is called a supertype.

A method can be implemented in several classes along the inheritance chain. The JVM decides which method is invoked at runtime.

Object o = new GeometricObject();
System.out.println(o.toString());

Declared type of a variable: Object

Actual type of a variable: GeometricObject

Which toString() method is invoked by o is determined by o’s actual type. This is known as dynamic binding.

Matching a method signature and binding a method implementation are two separate issues: The declared type of the reference variable decides which method to match at compile time.

The compiler finds a matching method according to the parameter type, number of parameters, and order of the parameters at compile time.

The JVM dynamically binds the implementation of the method at runtime, decided by the actual type of the variable.

One object reference can be typecast into another object reference. This is called casting object.

Test for object equality, to be overridden in custom classes:

object1.equals(object2);

Java provides ArrayList class which can be used to store an unlimited number of objects.

ArrayList<AConcreteType> list = new ArrayList<AConcreteType>(); 

Simplified with type inference:

ArrayList<AConcreteType> list = new ArrayList<>(); 

Array to ArrayList:

String[] array = {"red", "green", "blue"};
ArrayList<String> list = new ArrayList<>(Arrays.asList(array));

ArrayList to Array:

String[] array1 = new String[list.size()];
list.toArray(array1);

You can use an ArrayList to implement Stack

A protected member of a class can be accessed from a subclass.

Use the final modifier to indicate that a class is final and cannot be a parent class. A final method cannot be overridden by its subclasses.

Chapter 12: Exception Handling and Text I/O

An exception is an object that represents an error or a condition that prevents execution from proceeding normally.

A handler for an exception is found by propagating the exception backward through a chain of method calls, starting from the current method.

Floating-point number divided by 0 does not raise an exception.

try {
    Code to run;
    A statement or a method that may throw an exception;
    More code to run;
} catch (type ex) {
    Code to process the exception;
}

The Throwable class is the root of exception classes.

Every method must state the types of checked exceptions it might throw. This is known as declaring exceptions. Java does not require that you declare Error and RuntimeException (unchecked exceptions) explicitly in the method.

The finally clause is always executed regardless whether an exception occurred or not.

To define a custom exception class, extend Exception or a subclass of Exception.

The File class can be used to obtain file and directory properties, to delete and rename files and directories, and to create directories.

RuntimeException and Error are unchecked exceptions; all other exceptions are checked.

Chapter 13: Abstract Classes and Interfaces

A superclass defines common behavior for related subclasses. An interface can be used to define common behavior for classes (including unrelated classes).

An abstract class cannot be used to create objects. An abstract class can contain abstract methods, which are implemented in concrete subclasses.

An abstract method is defined without implementation. Its implementation is provided by the subclasses. A class that contains abstract methods must be defined as abstract.

The constructor in the abstract class is defined as protected, because it is used only by subclasses.

Number is an abstract superclass for numeric wrapper classes, BigInteger, and BigDecimal.

An interface is a class-like construct that contains only constants and abstract methods.

public interface Edible {
    /* Describe how to eat */
    public abstract String howToEat();
}

The relationship between the class and the interface is known as interface inheritance. Interface inheritance and class inheritance are essentially the same.

The Comparable interface defines the compareTo method for comparing objects.

The Cloneable interface specifies that an object can be cloned.

Java allows only single inheritance for class extension but allows multiple extensions for interfaces.

In general, interfaces are preferred over abstract classes because an interface can define a common supertype for unrelated classes. Interfaces are more flexible than classes.

Chapter 14: JavaFX Basics

JavaFX is a new framework for developing Java GUI programs.

The AWT user-interface components were replaced by a more robust, versatile, and flexible library known as Swing components. Swing is essentially dead, because it will not receive any further enhancement.

A JavaFX application can run seamlessly on a desktop and from a Web browser - so it’s the future.

Chapter 15: Event-Driven Programming and Animation

You can write code to process events such as a button click, mouse movement, and keystrokes.

Chapter 16: JavaFX UI Control and Multimedia

JavaFX provides many UI controls for developing a comprehensive user interface.

Chapter 17: Binary I/O

Files can be classified as either text or binary.

Text data are read using the Scanner class and written using the PrintWriter class.

Binary I/O does not involve encoding or decoding and thus is more efficient than text I/O. Text I/O is built upon binary I/O to provide a level of abstraction for character encoding and decoding

The abstract InputStream is the root class for reading binary data, and the abstract OutputStream is the root class for writing binary data.

Chapter 18: Recursion

Recursion is an alternative form of program control. It is essentially repetition without a loop.

A couple of case studies about recursion.

Chapter 19: Generics

Generics enable you to detect errors at compile time rather than at runtime.

<T> represents a formal generic type, which can be replaced later with an actual concrete type. Replacing a generic type is called a generic instantiation. By convention, a single capital letter such as E or T is used to denote a formal generic type.

Chapter 20: Lists, Stacks, Queues and Priority Queues

Chapter 21: Sets and Maps

Chapter 22: Developing Efficient Algorithms

Chapter 23: Sorting

Chapter 24: Implementing Lists, Stacks, Queues and Priority Queues

Chapter 25: Binary Search Trees

Chapter 26: AVL Trees

Chapter 27: Hashing

Chapter 28: Graphs and Applications

Chapter 29: Weighted Graphs and Applications

Chapter 30: Multithreading and Parallel Programming

Chapter 31: Networking

Chapter 32: Java Database Programming

Relational model in short:

A relation is a table that consists of non-duplicate rows.

A row is called a tuple

A column is called an attribute.

A row of a table represents a record

A column of a table represents the value of a single attribute of the record.

An integrity constraint imposes a condition that all the legal values in a table must satisfy.

In general, there are three types of constraints:

  • domain constraints
  • primary key constraints
  • foreign key constraints.

Domain constraints and primary key constraints are known as intrarelational constraints meaning that a constraint involves only one relation.

The foreign key constraint is intrarelational meaning that a constraint involves more than one relation.

Keys:

A superkey is an attribute or a set of attributes that uniquely identifies the relation. That is, no two tuples have the same values on the superkey.

By definition, a relation consists of a set of distinct tuples. The set of all attributes in the relation forms a superkey.

A relation can have several keys. In this case, each of the keys is called a candidate key

The primary key is one of the candidate keys designated by the database designer. The primary key is often used to identify tuples in a relation.

The foreign key constraints define the relationships among relations. Informally speaking, the common attributes are foreign keys.

Formally, a set of attributes FK is a foreign key in a relation R that references relation T if it satisfies the following two rules:

  • The attributes in FK have the same domain as the primary key in T.
  • A non-null value on FK in R must match a primary key value in T.

JDBC is the Java API for accessing relational database.

Chapter 33: JavaServer Faces

JavaServer Faces (JSF) is a new technology for developing server-side Web applications using Java.

Appendix A: Java Keywords

The literal values true, false, and null are not keywords, just like literal value 100.

The keywords goto and const are C++ keywords reserved, but not currently used in Java.

strictfp keyword is a modifier for a method or class that enables it to use strict floating-point calculations.

transient modifier marks a member variable not to be serialized when it is persisted to streams of bytes.

native method indicates that it is implemented using a language other than Java.