Sunteți pe pagina 1din 100

▐▄▄▄ ▄▄▄· ▌ ▐· ▄▄▄·

·██▐█ ▀█ ▪█·█▌▐█ ▀█
▪▄ ██▄█▀▀█ ▐█▐█•▄█▀▀█
▐▌▐█▌▐█ ▪▐▌ ███ ▐█ ▪▐▌
▀▀▀• ▀ ▀ . ▀ ▀ ▀

System.out is an object of PrintStream.


Few things observed :
The package serves as a container and also as a folder structure. So any class
under a specific container (cum folder structure) can be accessed as
path.to.container.class , mostly the name of classes starts with a capital letter.
To import a specific class (or may be container) we can give the complete path name
import java.util.Random

Java is having eight data types, four of them are integer type, two of them float,
one is char and last one is boolean.
Integers : int, long, short, byte (byte is shortest ranging from -127 to 127)
Integer, Long, Short and Byte represents their corresponding wrapper
classes. All of these classes have two constants named MIN_VALUE and MAX_VALUE,
which gives min and max value of the range.
For things bigger then long one can use BigInteger.
** Hexadecimal are prefixed with 0x (eg 0xCAFE), binaries are prefixed
with 0b (eg 0b101), octals are prefixed with 0 (eg 011 is 9)
Float : float and double are floating point, something like 1.2 is by default
double, double can also be specified using D suffix (eg 1.2D). float can be
represented using F, like 1.2F

Infinities : Double.POSITIVE_INFINITY and Double.NEGETIVE_INFINITY. Double.NaN is


used to represent not a number. To check we can use Double.isNaN, Double.isFinite,
Double.isInfinite, to represent unicode characters we prefix with \u.

Constants are defined with final keyword.


final int SOMETHING = 7

public class Calendar {


public static final int DAYS_PER_WEEK = 7;
...
}
We can refer like Calender.DAYS_PER_WEEK
"out" is a constant declared like above in System class
public static final PrintStream out;

Enumerated type and constant


Instead of declaring
public static final int MONDAY = 0;
public static final int TUESDAY = 0;
...
The alternative way is to use
enum WeekDay { MON, TUE, WED, THU, FRI, SAT, SUN };
WeekDay aDay = WeekDay.MON; // Here the allowed values are only from the set
specified above

Math
** A floating point division with 0 will yield infinite value or NaN, an
integer division will raise an exception
Math.floorMod ?

Java allows machine based (as per the present hardware) optimizing, like
optimizing floating point operation to use floating point register to add more
precision and reduce the risk of over flowing, this can reduce portability as it
depends on presence of that register. To make sure all the methods are strictly
portable we need to add strictfp modifier to all methods.

Power operation
Math.pow(x,y) === x^y
Square root of x = Math.sqrt(x)

When overflow occurs Math class will quietly return incorrect result. To remove
this we can use
Math.multiplyExact(x,y)
Math.addExact(x,y)
Math.subtractExact(x,y)
Math.incrementExact(x)
Math.decrementExact(x)
Math.negateExact(x)
All of these will raise an exception in occasion of overflow

Type coversion precedence


1. If either of the operands is of type double, the other one is converted to
double.
2. If either of the operands is of type float, the other one is converted to
float.
3. If either of the operands is of type long, the other one is converted to
long.
4. Otherwise, both operands are converted to int
3.14 + 42 will promote 42 -> 42.0
'J' + 1 will convert 'J' -> 74

Conversion that will not have any data losses and are legal,
From byte to short, int, long, or double
From short and char to int, long, or double
From int to long or double

With losses
From int to float
From long to float or double

To convert not permitted ones we need to use cast


double x = 3.75;
int n = ( int ) 3.75;
int n = (int) Math.round(x); //This is an useful way
char next = (char)('J' + 1); // Converts 75 to 'K'

Math.toIntExact //When it cannot convert a long to an int, an exception occurs.

Bitwise Operators
0xF has binary digits 0...01111, n & 0xF yields the lowest four bits in n,
n = n | 0xF sets the lowest four bits to 1
n = n ^ 0xF flips them

<< is used for left shift


>> is used for right shift
>>> is used for right shifting but fill with sign bit, above two fills with 0

BigInterger and BigDecimal


BigInteger n = BigInteger.valueOf(876543210123456789L);
or
BigInteger k = new BigInteger("9876543210123456789");
We can not use operators with BigInteger
BigInteger r = BigInteger.valueOf(5).multiply(n.add(k)); // r = 5*(n+k)

BigDecimal.valueOf(n, e) => n x 10^-e


BigDecimal calculates accurate 2.0 - 1.1 unlike float (which calculates .899999)
BigDecimal.valueOf(2,0).subtract(BigDecimal.valueOf(11, 1)); => 0.9

String
Concatenation
String greeting = "Hello " + "World!";
Any datatype, if concatenated will be converted to String

Join
String names = String.join(" : ", "A", "B"); // "A : B"

StringBuilder
StringBuilder builder = new StringBuilder();
builder.append("A ");
builder.append("B "); // or append through a loop
String result = builder.toString();
// It is not efficient to concatenate huge number of string, instead use
StringBuilder

SubString
String greeting = "Hello, World!";
String location = greeting.substring(7, 12); // "World"

The second argument is the first position which should not be included, in this
case
it is the index of "!"

Split
String names = "Peter, Paul, Mary";
String[] result = names.split(", ");
We can split using regular expression as well
names.split("\\s+")

Comparison
Strings should not be compared using == as it will only return true if they are
same object in memory
Instead use
location.equals("World")

Strings can be null as well and null checking can be done using ==
String a = null;
if ( a == null ) // Valid
Empty string is not null

Any operation invoked on null can raise null pointer exception, to compare
against literal string
using "World".equals(location) is better

To compare and ignore case


location.equalsIgnoreCase("world")

first.compareTo(second)
negative integer if first comes before second
positive integer if first comes after second
0 if they are equal

Converting Integer to String


String str = Integer.toString(n); // ...toString(n,2) Second parameter is the
radix, in this case it is 2 (can be from 2- 36)
String to Integer
Integer.parseInt(str); // ...parseInt(str, 2)

Same for Double.toString and Double.parseDouble

Other methods
.indexOf(str)
.lastIndexOf(str)
.toUpperCase()
.toLowerCase()
.trim()

Previously Unicode 1.0 was built by assigning a 16 bit unique number (identifier)
to each character in all of the writing system ever devised.
Later due to Chinese ideograph 16 bit was not sufficient, now Unicode is using 21
bits

Java instead of saving complete code points stores code units, one code point can
contain multiple code units (max 2, ?)
So if we are using Chinese or using some special character which uses more then
one code unit can behave unexpectedly when using
char ch = str.charAt(i);
or length calculation using
int length = str.length();

int codePoint = str.codePointAt(str.offsetByCodePoints(0, i));


int length = str.codePointCount(0, str.length());
int[] codePoints = str.codePoints().toArray(); // Convert all characters to code
points

Input and Output


Writing to standard output stream is simple in Java because one can write using
System.out.println
But reading from Standard Input stream is not simple as System.in only has
methods to read individual bytes.
We need to establish a Scanner on top of System.in (available in
java.util.Scanner)

Scanner in = new Scanner(System.in);


String name = in.nextLine(); // gives a prompt and read that line when return is
pressed
String name = in.next(); // reads the next word delimited by space
Others
in.nextInt();
in.nextDouble();
For checking
in.hasNextLine/hasNext/hasNextInt/hasNextDouble
if(in.hasNextInt()) {
int age = in.nextInt();
}
To read credentials we use Console class
Console terminal = System.console();
String username = terminal.readLine("User name : ");
char[] passwd = terminal.readPassword("Password : "); // because you can
overwrite an array when you are done but String are immutable

java mypackage.MainClass < input.txt > output.txt


** Now System.in reads from input.txt and System.out writes to output.txt

Printf
System.out.printf("%8.2f", 1000.0 / 3.0);

Before decimal show 8 digit and after decimal 2 digits of precision


System.out.printf("Hello, %s. Next year, you'll be %d.\n", name, age);

String.format will create the string with out printing (kind of like sprintf?)
String message = String.format("Hello, %s. Next year, you'll be %d.\n", name,
age);

Control flow
switch (count) {
case 0:
// some stuff
break;
case 1:
case 2:
//some stuff again
break;
default:
// ...
break;
}

To warn again accidental fallthrough mistake (when break is not used in a case
statement)
javac -Xlint:fallthrough mypackage/MainClass.java
To ignore
@SuppressWarnings("fallthrough")

Labeled break
outer:
while(..) {
..
while(..) {
..
if (..) break outer;
}
}
// break will jump to here
Naturally break, breaks out only from immediate loop, labeled break can be used
to break from multiple loops

Array
Array can be initialized in both way
String[] names = new String[100];
String name[] = new String[100]; // Old C style
int[] primes = {2, 3, 5, 7};
to assign it to an existing array variable:
primes = new int[] { 17, 19, 23, 29, 31 };

ArrayList
ArrayList is a dynamic length array and it is generic type class
ArrayList<String> friends = new ArrayList<>(); // or new ArrayList<String>()

The constructor here does not accept any arguments.


To add elements
friends.add("Peter");
friends.add("Cercei");

To add element in any position


friends.add(0, "Peter");
friends.remove(1); // removes from index 1

get and set


String name = friends.get(0);
friends.set(0, "Mary"); // update the 0th index

** There is no initializer list for this


for(int i = 0; i < friends.size(); i++) {
System.out.println(friends.get(i));
}

*** ArrayList does not recieve the native data types, we always need to use the
wrapper classes
Integer, Float, Double, Long, Char, Byte, Short, Boolean
So ArrayList<int> is not valid but ArrayList<Integer> is valid

ArrayList<Integer> numbers = new ArrayList<>();


numbers.add(42); // 42 is automatically converted to Integer, "Autoboxing"
int first = numbers.get(0); // Integer automatically converted to int "unboxing"

equals method for comparison is also preferred and required here

Foreach equivalent
for(int n : numbers) {
// Do something
}

Copying array
If we directly try to copy array we will end up copying its reference.
To copy an array to a different memory location
int[] copiedPrimes = Arrays.copyOf(primes, primes.length);

To copy ArrayList, use copy constructor


ArrayList<String> copiedFriends = new ArrayList<>(friends);

To copy an array to an ArrayList


String[] names = ...;
ArrayList<String> friends = new ArrayList<>(Arrays.asList(names));

We can use array initializer list with asList


ArrayList<String> friends = new ArrayList<>(Arrays.asList("Peter", "Paul",
"Mary"));

Copying ArrayList to Array


String[] names = friends.toArray(new String[0]);

** There is no easy way to convert between primitive type arrays and the
corresponding array lists of wrapper classes. For example, to convert between an
int[] and an ArrayList<Integer>, you need an explicit loop or an IntStream
Arrays.fill(numbers, 0); // int[] array
Collections.fill(friends, ""); // ArrayList<String>
Arrays.sort(names);
Collections.sort(friends);

Collection class need to be used regarding ArrayList


parallelSort method can be used to distribute the work over multiple processors
if the array is large (nothing for ArrayList here)

Arrays.toString(primes)
friends.toString(); // friends is an ArrayList
System.out.println(friends); // Calls friends.toString() and prints the result

Following have no counter part for Array


Collections.reverse(names); // Reverses the elements
Collections.shuffle(names); // Randomly shuffles the elements

Using command line arguments


public class Greeting {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if (arg.equals(“-h”)) arg = “Hello”;
else if (arg.equals(“-g”)) arg = “Goodbye”;
System.out.println(arg);
}
}
}
java Greeting -g cruel world
Multidimensional Array
int[][] square = {
{ 16, 3, 2, 13 },
{ 3, 10, 11, 8 },
{ 9, 6, 7, 12 },
{ 4, 15, 14, 1}
};

swap rows:
int[] temp = square[0];
square[0] = square[1];
square[1] = temp;

With out initializer list


int[][] square = new int[4][4]; // First rows, then columns

Non uniform second dimension array length


int[][] triangle = new int[n][];

// filling up the array with Pascals triangle


for (int i = 0; i < n; i++) {
triangle[i] = new int[i + 1]; // initializing second dimension
triangle[i][0] = 1;
triangle[i][i] = 1;
for (int j = 1; j < i; j++) {
triangle[i][j] = triangle[i - 1][j - 1] + triangle[i - 1][j];
}
}

// Show triangle
for (int r = 0; r < triangle.length; r++) {
for (int c = 0; c < triangle[r].length; c++) {
System.out.printf(“%4d”, triangle[r][c]);
}
System.out.println();
}
Using foreach / enhanced for loop
for (int[] row : triangle) {
for (int element : row) {
System.out.printf(“%4d”, element);
}
System.out.println();
}

System.out.println(Arrays.deepToString(triangle));
// This is used to print multidimensional array

There are no two-dimensional array lists, but you can declare a variable of type
ArrayList<ArrayList<Integer>> and build up the rows yourself.

Declaring static methods and calling them from main is very normal
public static void x(){
//...
}
public static void main(String[] args) {
x();
}

Accepting array and returning array


public static int[] firstLast(int[] values) {
if (values.length == 0) return new int[0];
else return new int[] { values[0], values[values.length - 1] };
}

Variable length argument


// "double..."
public static double average(double... values) {
double sum = 0;
for (double v : values) sum += v;
return values.length == 0 ? 0 : sum / values.length;
}

double avg = average(3, 4.5, 10, 0);

or array
double[] scores = { 3, 4.5, 10, 0 };
double avg = average(scores);

The variable parameter must be the last parameter of the method, but you can
have other parameters before it.

** End of Chapter 1, need to do exercise **

Accessor and Mutator


The method call date.plusDays(1), there are two ways in which the designers of
the LocalDate class could have implemented the plusDays method. They could make it
change the state of the date object and return no result. Or they could leave date
unchanged and return a newly constructed LocalDate object. As you can see, they
chose to do the latter.
We say that a method is a mutator if it changes the object on which it was
invoked. It is an accessor if it leaves the object unchanged. The plusDays method
of the LocalDate class is an accessor.

In Java every object variable is the reference to the actual object somewhere in
the memory. If we assign one object to another we are actually assigning and
creating another reference to that object.

String and LocalDate do not have any mutator methods. So there is no risk of
loosing track regarding which reference updated the state of object.

Constructors are commonly public but it can also be useful to have private
constructors. For example, the LocalDate class has no public constructors. Instead,
users of the class obtain objects from “factory methods” such as now and of. These
methods call a private constructor. Constructor has no return type
public Employee(double salary) {
this.name = ””;
this.salary = salary;
}

Calling One Constructor from Another


public Employee(double salary) {
this(””, salary); // Calls Employee(String, double)
// Other statements can follow
}
Here, this is not a reference to the object that is being constructed. Instead,
it is a special syntax that is only used for invoking another constructor of the
same class.

Number instance variables (not local variables) are initialized to default 0 but
String will be initialized to null instead of "".

Initialization Block
public class Employee() {
private String name = ””;
private int id;
private double salary;
{ // An initialization block
Random generator = new Random();
id = 1 + generator.nextInt(1_000_000);
}
public Employee(String name, double salary) {

}
}

Instance variable initializations and initialization blocks are executed in the


order in which they appear in the class declaration, and before the body of the
constructor.

(This is not a commonly used feature. Most programmers place lengthy


initialization code into a helper method and invoke that method from the
constructors)

You can declare an instance variable as final. Such a variable must be


initialized by the end of every constructor. Afterwards, the variable may not be
modified again. When used with a reference to a mutable object, the final modifier
merely states that the reference will never change. It is perfectly legal to mutate
the object.
public class Person {
private final ArrayList<Person> friends = new ArrayList<>();
// OK to add elements to this array list

}
Methods may mutate the array list to which friends refers, but they can never
replace it with another. In particular, it can never become null.

Static
If you declare a variable in a class as static, then there is only one such
variable per class (you can declare many but it will exist once in the memory). In
contrast, each object has its own copy of an instance variable.

To declare a static constant we use static final


public class Math {
...
public static final double PI = 3.14159265358979323846;
...
}
You can access this constant in your programs as Math.PI,
Random number generator can be static, (example scenario)
private static final Random generator = new Random();

out is a constant in System class


public class System {
public static final PrintStream out;
...
}
Unusual situation with out
Even though out is declared as final in the System class, there is a method
setOut that sets System.out to a different stream. This method is a “native”
method, not implemented in Java, which can bypass the access control mechanisms of
the Java language.

Static initialization occurs when the class is first loaded. Like instance
variables, static variables are 0, false, or null unless you explicitly set them to
another value. Static initialization block can be used to initialize them after
declaration,
public class CreditCardForm {
private static final ArrayList<Integer> expirationYear = new ArrayList<>();
static {
// Add the next twenty years to the array list
int year = LocalDate.now().getYear();
for (int i = year; i <= year + 20; i++) {
expirationYear.add(i);
}
}
...
}

It is legal to invoke a static method on an object. For example, instead of


calling LocalDate.now() to get today’s date, you can call date.now() on an object
date of the LocalDate class. But that does not make a lot of sense. The now method
doesn’t look at the date object to compute the result.
Since static methods don’t operate on objects, you cannot access instance
variables from a static method. However, static methods can access the static
variables in their class

Factory Methods
A common use for static methods is a factory method, a static method that
returns new instances of the class.

NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance();


NumberFormat percentFormatter = NumberFormat.getPercentInstance();
double x = 0.1;
System.out.println(currencyFormatter.format(x)); // Prints $0.10
System.out.println(percentFormatter.format(x)); // Prints 10%

Why not use a constructor instead? The only way to distinguish two
constructors is by their parameter types. You cannot have two constructors with no
arguments. Moreover, a constructor new NumberFormat(...) yields a NumberFormat. A
factory method can return an object of a subclass. In fact, these factory methods
return instances of the DecimalFormat class.
** A factory method can also return a shared object, instead of unnecessarily
constructing new ones. For example, the call Collections.emptyList() returns a
shared immutable empty list.

Packages
A package name is a dot-separated list of identifiers such as java.util.regex.
The main reason for using packages is to guarantee the uniqueness of class names.
Suppose two programmers come up with the bright idea of supplying an Element class.
As long as all of them place their classes into different packages, there is no
conflict.

** It is a good idea to use an Internet domain name(which is known to be unique)


written in reverse. For example, I own the domain name horstmann.com. For my
projects, I use package names such as com.horstmann.corejava. A major exception to
this rule is the standard Java library whose package names start with java or
javax.

In Java, packages do not nest. For example, the packages java.util and
java.util.regex have nothing to do with each other.

package com.horstmann.corejava;
public class Employee {
...
}
The file Employee.class must be in a subdirectory com/horstmann/corejava
javac com/horstmann/corejava/EmployeeDemo.java
To run - java com.horstmann.corejava.EmployeeDemo

It is a good idea to run javac with the -d option. Then the class files are
generated in a separate directory, without cluttering up the source tree, and they
have the correct subdirectory structure.

Instead of storing class files in the file system, you can place them into one or
more archive files called JAR files. You can make such an archive with the jar
utility that is a part of the JDK. (similar to TAR)

jar cvf library.jar com/mycompany/*.class

(commonly done with package libraries)


JAR files use the ZIP format. There is also an option for another compression
scheme, called “pack200,” that is designed to compress class files more
efficiently.

You can use JAR files to package a program, not just a library. Generate the JAR
file with
jar cvfe program.jar com.mycompany.MainClass com/mycompany/*.class

Then run the program as


java -jar program.jar

Class path is used to specify library location (JAR etc) and can contain,
- Directories containing class files (in subdirectories that match their
package names)
- JAR files
- Directories containing JAR files

java -classpath .:../libs/lib1.jar:../libs/lib2.jar com.mycompany.MainClass


(In Windows, use semicolons instead of colons to separate the path elements)

If you have many JAR files, put them all in a directory and use a wildcard to
include them all:
java -classpath .:../libs/\* com.mycompany.MainClass
(* is escaped to prevent shell expansion)

javac will always look in the current directory but not java if -classpath is
supplied with out . in it. By default the path contains . (current dir).

An alternate approach is the CLASSPATH environment variable.

***
Some people recommend to bypass the class path altogether, by dropping all JAR
files into the jre/lib/ext directory, a special directory that the virtual machine
consults for “installed extensions.” That is truly bad advice, for two reasons.
Code that manually loads classes does not work correctly when placed in the
extension directory. Moreover, programmers are even less likely to remember the
obscure jre/lib/ext directory than a CLASSPATH environment variable

Package Scope
If you don’t specify either public or private, the feature (that is, the class,
method, or variable) can be accessed by all methods in the same package.

****
A source file can contain multiple classes, but at most one of them can be
declared public. If a source file has a public class, its name must match the class
name.

Default package scope can be a security issue because packages are open ended.
Any class can add itself to a package by providing the appropriate package
statement. The Java implementors protect themselves from such an attack by rigging
the ClassLoader class so it will not load any class whose fully qualified name
starts with java.

Sealed JAR (Protecting packages)


If you want to have a similar protection for your own packages, you need place
them into a sealed JAR file. Provide a manifest, a plain text file containing
entries
Name: com/mycompany/util/
Sealed: true
Name: com/mycompany/misc/
Sealed: true
Then run the jar command like this:
jar cvfm library.jar manifest.txt com/mycompany/*/*.class
Import
Import all classes from a package with a wildcard:
import java.util.*;

The wildcard can only import classes, not packages. You cannot use import java.*;
to obtain all packages whose name starts with java.

java.util and java.sql both contain a Date class. Suppose you import both
packages:

import java.util.*;
import java.sql.*;

If your program doesn’t use the Date class, this is not a problem. But if you
refer to Date, without the package name, the compiler complains. In that case, you
can import the specific class that you want:
import java.util.*;
import java.sql.*;
import java.sql.Date;
If you really need both classes, you must use the fully qualified name for at
least one of them.

Static Import:
You can import static memebers of a class
import static java.lang.Math.*;

Then you will be able to use,


sqrt(pow(x, 2) + pow(y, 2)) // i.e., Math.sqrt, Math.pow

or, individually
import static java.lang.Math.sqrt;
import static java.lang.Math.PI;

**** You cannot import static methods or fields from a class in the default
package.

Nested Class
public class Invoice {
private static class Item { // Item is nested inside Invoice
String description;
int quantity;
double unitPrice;
double price() { return quantity * unitPrice; }
}
private ArrayList<Item> items = new ArrayList<>();

}
The nested class must be static.

The class is private in Invoice, so only Invoice methods can access it.

If public, one can use,


Invoice.Item newItem = new Invoice.Item(“Blackwell Toaster”, 2, 19.95);
myInvoice.add(newItem);

Inner Class
If we drop the static from nested class it will become inner class.
*** A method of an inner class can access instance variables of its outer class
unlike nested class they are not static

A static nested class does not have such a reference (just like a static method
does not have the this reference). Use a static nested class when the instances of
the nested class don’t need to know to which instance of the enclosing class they
belong. Use an inner class only if this information is important.
An inner class can also invoke methods of the outer class through its outer class
instance (which is implicit).
public class Network {
public class Member {
...
public void leave() {
unenroll(this); // unenroll defined on outer class
}
}

private ArrayList<Member> members;


public Member enroll(String name) {
Member newMember = new Member(name);
members.add(newMember); // adding to the ArrayList
return newMember;
}
public void unenroll(Member m) { … }

}
Outer class can be explicitly referred using OuterClassName.this.member,

public void leave() {


// can be written as
Network.this.unenroll(this);
}
This explicit reference is unnecessary though some of the cases it can be used
public class Network {
public class Member {
...
// The following function will check if a member belongs to a certain
// network
public boolean belongsTo(Network n) {
return Network.this == n;
}
}
}
When an inner class object is created, it remembers the outer class object it is
enclosed with in
Network myFace = new Network();
Network.Member fred = myFace.enroll("fred");

Here the enroll method is defined on Network class and it is responsible for
creating object of inner class Member and push it to an internal array list in
myFace object then return the Member object. The member object remembers the outer
class object "myFace" using Network.this
So if we call fred.belongTo(myFace) <- this will return true

The line Member newMember = new Member(name); can also be written as,

Member newMember = this.new Member(name);


So we can create the objects from outside using this technique
Network.Member wilma = myFace.new Member("Wilma");

Inner class can not have static members because that will result in an ambiguity
regarding if we should keep the static member only once or only once for every
outer class object.
When an inner class is created then its compiled form will be stored in a file
like Network$Member.class file
if we inspect the class with javap command
javap -private ClassName
javap -private Network$Member

Warning: Binary file Network$Member contains


com.javalearning.ex2.Network$Member
Compiled from "Network.java"
public class com.javalearning.ex2.Network$Member {
private java.lang.String name;
private java.util.ArrayList<com.javalearning.ex2.Network$Member> friends;
final com.javalearning.ex2.Network this$0;
public com.javalearning.ex2.Network$Member(com.javalearning.ex2.Network,
java.lang.String);
public void leave();
}

Here we can see that `final com.javalearning.ex2.Network this$0;` contains the


reference to the parent class

Java Docs comments


javadoc comments starts with /** and the complete JAVA API documentation are done
using running javadoc utility on java source code. It is easy to update code and
comment at the same time.

Provide comment for following items


Packages
Public classes and interfaces
Public and protected variables
Public and protected constructors and methods
javadoc will look for comments regarding these

The documentation comment starts with a summary line where html tags like
<em> <code> <strong> <img> can be used although header tags and <hr> tags
should not be used as they interfere with default documentation format
To use images or other links to resources the assets should be placed in side a
sub directory of the current directory named doc-files, so the images should be
referred like
<img src="doc-files/uml.png" alt="UML diagram" />

The documentation can also contain tags like @author, @param

Class comment
/**
* An <code>Invoice</code> object represents an invoice with
* line items for each part of the order.
* @author Sutirtho Sen
* @author SomeOne Else
* @version 1.0
*/
public class Invoice {

Method comment
@param to specify the parameter objective
@return to specify the return data objective
if there is none then void:@return
@throws exceptionClass description

/**
* 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) {

Variable comment
Only need to document public variables and static constants
/**
* The number of days per year on Earth (excepting leap years)
*/
public static final int DAYS_PER_YEAR = 365;

With all comments @since can be used to describe from which version the
specific feature got added
@since version 1.7.1

@deprecated can be used to specify alternative method for soon to be removed


features

@deprecated Use <code>SomeClass</code> instead

@see <reference> : can be used to specify related sections of java docs or


external resources
the reference could be specified as
- package.class#feature label
- <a href="...">label</a>
- "text"

Example :
@see com.horstmann.corejava.Employee#raiseSalary(double)

If package name is omitted then it will look into current package

To introduce a link inside the documentation text we can use


{@link package.class#feature label}

Package Comment
Package comments are placed by creating a file named package-info.java which
should contain the complete comment /** */ in a single block and no other code or
comment section

overview comment is supplied by placing the information in overview.html


located at parent directory that contains all source file

So if we have an directory structure like


package/
overview.html
com/
horstmann/
corejava
then we can run at parent level directory (package/) in this example
javadoc -d docDir package1 package2 ...

**** If we write an method to swap two native data type it won't work because
JAVA is strictly call by value. So to pass reference the trick is to create a class
around that variable and pass object of that class which will be passed by
reference. This thing was implemented as IntHolder class for java, this holds an
int value which can be passed around as reference.

Source code for IntHolder : https://alvinalexander.com/java/jwarehouse/netbeans-


src/mdr/src/org/netbeans/mdr/persistence/btreeimpl/btreestorage/IntHolder.java.shtm
l

TODO : Do Chapter 2 Exercise 5 and on


** End of Chapter 2 **

Interface
Interface naturally contains a contract of a service which need to be
implemented by the class that is using the interface. It works as a super type of
the class that is 'implementing' this interface.
- An interface specifies a set of methods that an implementing class must
provide.
- An interface is a supertype of any class that implements it. Therefore, one
can assign instances of the class to variables of the interface type.
- An interface can contain static methods. All variables of an interface are
automatically static and final.
- An interface can contain default methods that an implementing class can
inherit or override.

Example
A function to calculate average of n numbers from a sequence of integers
public static double average(IntSequence seq, int n) {
int count = 0;
double sum = 0;
while(seq.hasNext() && count < n) {
count++;
sum = sum + seq.next();
}
return count == 0 ? 0 : (sum/count);
}
Now this function uses a type IntSequence and expects the object of
IntSequence to have two methods hasNext() to check if the next element exists in
the sequence and next() to get the next element. This is defined as an interface

public interface IntSequence {


boolean hasNext();
int next();
}

This states a contract and the class which will implement this interface need
to abide by the contact and override these two methods (rather implement them)

public class SquareSequence implements IntSequence {


private int i;

public boolean hasNext() {


// Always return true because it is an infinite sequence
return true;
}
public int next() {
i++;
return i*i;
}
}

The above class actually generates infinite number of squares and can be used
with the average method defined above.

IntSequence squares = new SquareSequence();


double avg = average(squares, 100);
The methods should be declared public by implementing class otherwise they
would default to package access

If a class only implements some of the methods declared by interface then the
class need to be marked as abstract

If we want to put the SquareSequence object back to a SquareSequence reference


then we need to cast
if(squares instanceof SquareSequence){
SquareSequence sq = (SquareSequence) squares;
}
So if we have some extra methods at SquareSequence class those are not
accessible from its super type reference, we need to cast back at that point.
instanceof operator can be used to check if the object is of proper type

One interface can "extend" (inherit) other interface.


public interface Channel extends Closeable {
boolean isOpen();
}

Extending multiple interfaces,


public class FileSequence implements IntSequence, Closeable {
...
}

All variables defined with in interface is by default "public static final"


and can be referred by InterfaceName.constantName (all of them are thus
constants)

Static methods in interface


Interface can implement static methods which is useful for implementing factory
methods. In our IntSequence interface we can implement a method called digitsOf
which will take an integer and can return the sequence of integers till that amount
(a special type of IntSequence).

Lets say we have a DigitSequence class which will count downwards


public class DigitSequence implements IntSequence {
private limit = 0;

public DigitSequence(int n) {
this.limit = n;
}

public boolean hasNext() {


return (limit != 0);
}

public int next() {


return limit--;
}
}

Now the digitsOf can be implemented at interface level specifically for this
class

public interface IntSquence {


...
public static IntSequence digitsOf(int n) {
return new DigitSequence(n);
}
}

Default methods in interface


One can supply a default implementation of method
public interface IntSequence {
default boolean hasNext() { return true; }
int next();
}

This helps if a method is added later to an interface, in that case all the
classes implementing that interface will not compile as their existing
implementation do not implement the newly added method. Putting a default method is
good in such cases.

** If one interface implements a default method and another interface also


defines another method of same name (default or not) and both interface is
implemented by a class then a name conflict will happen
public interface Person {
String getName();
default int getId() { return 0; }
}

public interface Identified {


default int getId() { return Math.abs(hashCode()); }
}

public class Employee implements Person, Identified {


...
}

Compiler will raise an error in this case and developer need to resolve it
either by implementing it or by delegating to one of the parent method

public int getId() {


return Identified.super.getId();
}
If any one of the interface provides a default implementation this conflict
will arise even if the other one does not provide an implementation.

** If a super class and an interface both supplies a method definition of same


name then only super class definition is taken and interface's default definition
is ignored

Examples of commonly known library interfaces


Comparable Interface
Sorting algorithm need to compare two elements and these two elements can be
of any type (any type of Object). It is the responsibility of corresponding class
to implement the comparison algorithm so the sorting can happen smoothly. The
sorting method and the class should agree on some method which will be implemented
by class and used by sorting algo to compare the elements. Here the "Comparable"
interface comes into picture. As it can accept any type of element it is having a
generic type
public interface Comparable<T> {
int compareTo(T other);
}
So the String class an implement Comparable<String> which will make sure
compareTo(String other) will work with strings.
and one can call x.compareTo(y) where x and y are of same type
Return 1 if x > y
return 0 if x == y
return -1 if y > x

The values can be any integer and not need to be only 1, so difference of
two integers can be returned from compareTo function (if positive, definitely the
first one will be greater than second)
Integer.compare method works correctly for all integers
While comparing floating point values we can not just return difference of
them, instead we should use Double.compare method.

public class Employee implements Comparable<Employee> {


public int compareTo(Employee other) {
return Double.compare(this.salary, other.salary);
}
}

String[] friends = {"Peter", "Paul", "Mary"};


Arrays.sort(friends);

Comparator Interface
If we want to use Array sort but need to sort using length (representing any
arbitrary logic), we need to use the version of Arrays.sort which accepts two
arguments the array and a comparator instance.
public interface Comparator<T> {
int compare(T first, T second);
}

class LengthComparator implement Comparator<String> {


public int compare(String first, String second) {
return first.length() - second.length();
}
}

Comparator<String> comp = new LengthComparator();


if(comp.compare(words[i], words[j]) > 0) {
...
}
Now instead of comparing like "some string".compareTo("string") we are using
the object of an external class
Arrays.sort(friends, new LengthComparator());

Runnable Interface
To make sure one can run a task in a separate thread for better parallel
processing

class HelloTask implements Runnable {


public void run() {
...
}
}

Runnable task = new HelloTask();


Thread th = new Thread(task);
th.start();

EventHandler Interface to manage callbacks (event driven programming)


public interface EventHandler<T> {
void handle(T event);
}

class CancelAction implements EventHandler<ActionEvent> {


public void handle(ActionEvent event) {
System.out.println("User pressed no!");
}
}

Button cancelButton = new Button("Cancel");


cancelButton.setOnAction(new CancelAction());
***
Lambda
Ever since logician Alonzo Church (check wiki) used lambda to mark parameters
of an mathematical function all parameterized expressions are called lambda
** Multi-line lambda
(String first, String second) -> {
int difference = first.length() < second.length();
if(difference < 0) return -1;
else if(difference > 0) return 1;
else return 0;
}

** Single line lambda


(String first, String second) -> first.length() - second.length()

Without parameter just write empty braces ()

If type can be inferred then remove type from parameters


Comparator <String> comp = (first, second) -> first.length() -
second.length();

If type can be inferred and there is only single parameter one can remove the
braces as well
EventHandler <ActionEvent> listener = event -> System.out.println("Oh
noes!");

As there is no specific return type, it is inferred


(String first, String second) -> first.length() - second.length()
The above can be used in context of int, Integer, long, double

Functional Interface
These are interfaces with single abstract method, example Comparator
These interfaces can be replaced by a lambda expression
So,
Arrays.sort(friends, (first, second) -> first.length() - second.length());

Behind the scene sort will receive an object of some class that implements
Comparator<String>
***
In Java, there is only one thing you can do with a lambda expression: put it
in a variable whose type is a functional interface, so that it is converted to an
instance of that interface.

Predicate functional interface


public interface Predicate<T> {
boolean test(T t);
// additional default and static methods can be there
}

ArrayList has a function removeIf which takes in an Predicate object


We can use an lambda expression here
list.removeIf(e -> e == null);

Method Reference
Some times the work we are doing with lambda is already being done by some
method, for example
We want ignore case when comparing the strings
Arrays.sort(friends, (first, second) -> first.compareToIgnoreCase(second));

Here the lambda calls only a single method and returns the value, instead we
can do

Arrays.sort(friends, String::compareToIgnoreCase)

String::compareToIgnoreCase is a method reference


-------------------------------------------------
Object.isNull(x) is equivalent to x == null
so instead,
list.removeIf(e -> e == null);
we can do
list.removeIf(Objects::isNull);
-------------------------------------------------
list.forEach(x -> System.out.println(x));

can be replaced by

list.forEach(System.out::println);

The above three represents the following three type of method reference
Class::instanceMethod
Class::staticMethod
object::instanceMethod

For the first case the instance method will be called on first parameter of
lambda and second argument will passed to it
String::compareToIgnoreCase

For the second case both parameters will be passed to the method
Object::isNull

For the third case it will be called on the specified instance and arguments
will be passed to the method
System.out::println

this::someMethod
or in case of Outer Class
EnclosingClass.this::method is also allowed

Constructor Reference
Employee::new
For example say we have an list of names
List<String> names = ...
Now we want to initialize Employee object with each name
Stream<Employee> stream = names.stream().map(Employee::new);
More about streams later

We can also form constructor reference with array type


Employee[]::new

It is equivalent to
n -> new Employee[n]

The stream's toArray method returns an array of "Object" type, there is


another version of toArray that accepts an constructor reference
Employee[] buttons = stream.toArray(Employee[]::new);

Processing lambda
Accepting a lambda for deferred execution
To accept a lambda as argument we need to use one of the functional interface
or declare one if required
Say we want to execute some task 10 times

repeat(10, () -> System.out.println("Hello World"))

Now here we can use runnable interface


public static void repeat(int n, Runnable action) {
for(int i = 0; i < n; i++) { action.run(); }
}

Say we want to pass the loop index as an argument to the passed lambda, we
need to choose a different functional interface

public interface IntConsumer {


void accept(int value);
}

public static void repeat(int n, IntConsumer action) {


for(int i = 0; i < n; i++) { action.accept(i); }
}

repeat(10, i -> System.out.println("Count down " + (9 - i)));

Some of the common functional interfaces are


Runnable -> run() -> returns void
Supplier<T> -> get() -> returns T
Consumer<T> -> accept(T) -> returns void
BiConsumer<T, U> -> accept(T, U) -> returns void
Function<T, R> -> apply(T) -> returns R
BiFunction<T, U, R> -> apply(T, U) -> returns R
UniaryOperator<T> -> apply(T) -> returns T
BinaryOperator<T> -> apply(T,T) -> returns T
Predicate<T> -> test(T) -> returns boolean
BiPredicate<T, U> -> test(T, U) -> returns boolean

Most of these functional interfaces have non abstract methods


Predicate.isEqual(a) is equivalent to a::equals (equal checking using a's
equals method with something else) but the first one works even if a is null (nulls
do not have equals method)

This interface and/or/negate


Predicate.isEqual(a).or(Predicate.isEqual(b))
is equivalent to
x -> a.equals(x) || b.equals(x)

Use specialized functional interface for primitive types to reduce autoboxing

BooleanSupplier -> getAsBoolean() -> returns boolean


IntSupplier -> getAsInt() -> returns int
LongSupplier -> getAsLong() -> returns long
-- same for double (DoubleSupplier) --
IntConsumer -> accept(int) -> returns void
-- same for Long/long --
-- same for Double/double --
ObjIntConsumer<T> -> accept(T, int) -> returns void
-- same for Long/long --
-- same for Double/double --
IntFunction<T> -> apply(int) -> returns T
-- same for Long/long --
-- same for Double/double --
IntToDoubleFunction -> applyAsDouble(int) -> returns double
Form : PToQFunction -> applyAsQ(p) -> returns q
-- same for Long/long --
-- same for Double/double --
ToIntFunction<T> -> applyAsInt(T) -> returns int
-- same for Long/long --
-- same for Double/double --
ToIntBiFunction<T, U> -> applyAsInt(T,U) -> returns int
-- same for Long/long --
-- same for Double/double --
IntUnaryOpearator -> applyAsInt(int) -> returns int
-- same for Long/long --
-- same for Double/double --
IntBinaryOperator -> applyAsInt(int, int) -> returns int
-- same for Long/long --
-- same for Double/double --
IntPredicate -> test(int) -> returns boolean
-- same for Long/long --
-- same for Double/double --

** Avoid autoboxing as much as possible **


Custom functional interface
@FunctionalInterface
public interface PixelFunction {
color apply (int x, int y);
}

due to the annotation, compiler does the checking to see if only a single
abstract method is present

Now we can write a function


BufferedImage createImage(int width, int height, PixelFunction f) {
....
Color cl = f.apply(x,y)
....
}

createImage( 150, 100, (x, y) -> x < 50 ? Color.BLUE : x < 100 ?


Color.WHITE : Color.RED);

Variable scoping inside lambda


There is no separate scope boundary for lambda and all of the variables belongs
to same scope of the block of the code holding lambda

'this' inside lambda refers to 'this' parameter of the method that creates the
lambda

Closure and lambda


If a lambda is accessing outside variables other than those passed to it as
argument, it captures these variables and saves the values so even if the lambda is
executed much later, values of these variables are available.
public static void repeatMessage(String text, int count) {
Runnable r = () -> {
for(int i = 0; i < count; i++) {
System.out.println(text);
}
};
new Thread(r).start();
}
In the above case the values of 'count' and 'text' are saved with the data
structure that saves the lambda.

But we can not use a variable to capture with lambda if the value of that
variable is changing.
for(int i = 0; i < n; i++) {
new Thread(() -> System.out.println(i)).start(); // Error— cannot capture
i
}
Here value of i is changing so compiler gives an error, The rule is that a
lambda expression can only access local variables from an enclosing scope that are
effectively final.

But the following is legal


for (String arg : args) {
new Thread(() -> System.out.println(arg)).start(); // OK to capture arg
}
The variable of an enhanced for loop is effectively final since its scope is
a single iteration.

** lambda also can not mutate captured values


This mutation restriction can be circumvent by using an array of size 1,
int[] counter = new int[1];
button.setOnAction(event -> counter[0]++);
The counter variable is final as it never changes and always refers to the same
array
(This is same as circumventing always pass by value restriction by using an
object with a single instance variable)
The above code is not thread-safe

Higher order function (function returning function)


public static Comparator<String> compareInDirection(int direction) {
return (x, y) -> direction * x.compareTo(y);
}
The call compareInDirection( 1) yields an ascending comparator, and the call
compareInDirection(-1) a descending comparator. This can be used like

Arrays.sort(friends, compareInDirection(-1));
Here we are returning a function, well not a function but an object of a
class which implements the functional interface (Comparator<String>)

The following is supposed to reverse a comparator


public static Comparator<String> reverse(Comparator<String> comp) {
return (x, y) -> comp.compare(x, y);
}
Here we are accepting one function (functional interface object) and returning
a modified one. (Need to check how the reversing works)

Comparator methods
Comparator interface have some static methods which that generates functions

For example there is a comparing function which takes another function


reference which can be used to extract the key to compare from a complex data
structure
Say we need to sort an array of people by the name, but we have Person
objects in an array, so to sort them based on name we need tell the comparator to
use the function getName of Person class the get the name (String) and compare
using it

Arrays.sort(people, Comparator.comparing(Person::getName));

Here the comparing static function is doing the exact thing specified above
We can also use multiple function chained like

Arrays.sort(people, Comparator.comparing(Person::getLastName)
.thenComparing(Person::getFirstName));

If we want to sort people by length of their name then,


Arrays.sort(people, Comparator.comparing(Person::getName,
(s, t) -> s.length() - t.length()));

Here we are customizing further my customizing the comparison algorithm used


with key extracted using the method mentioned as first parameter

For native datatypes


comparingInt
comparingLong
comparingDouble

If the key extractor function (Person::getName) is returning null then the


comparator will throw exception, to avoid that we can use nullsFirst and nullsLast
to rank them at the beginning or the end, these function takes in a comparator we
can use the generalized comparator generator naturalOrder()
So the final call looks like,
Arrays.sort(people, Comparator.comparing(Person::getMiddleName,
Comparator.nullsFirst(
Comparator.naturalOrder()
)));

Local class
If some one cares only about the interface and not the class implementing them,
then there is a classic way of doing this without the functional interfaces and
lambda expressions as well
private static Random generator = new Random();
public static IntSequence randomInts(int low, int high) {
class RandomSequence implements IntSequence {
public int next() {
return low + generator.nextInt( high - low + 1);
}
public boolean hasNext() {
return true;
}
}
return new RandomSequence();
}

Here we only care about the interface IntSequece and not the class, so we
define the class locally, it is not visible from outside (so don't need
private/public)

Anonymous class
In the above example the class name is not very important as we do not use it
much, this can be replaced by an anonymous class

public static IntSequence randomInts(int low, int high) {


return new IntSequence() {
public int next() {
return low + generator.nextInt( high - low + 1);
}
public boolean hasNext() {
return true;
}
}
}

The expression
new Interface() { methods }

means: Define a class implementing the interface that has the given methods,
and construct one object of that class.

Inheritance

this is a reference to an object, however super is directive to bypass dynamic


method lookup and invoke a specific method instead

For method overriding the parameter types can not be changed, but the return type
can be changed. We can use @Override annotation to make sure we are actually
overriding and not creating a different function with same name (overloading)

The access specifier on subclass method should provide atleast as much visibility
as super class method's access specifier.
So if the superclass method is public then the subclass method also need to be
public

public class Employee {


private String name;
private double salary
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}

public double getSalary() {


return this.salary;
}
}

public class Manager extends Employee {


private double bonus;
public Manager(String name, double salary){
super(name, salary);
bonus = 0;
}

public double getSalary() {


return super.getSalary() + bonus;
}
}

Here the super() calls the super class constructor, and it must be the first
statement of subclass constructor

We can assign a sub class object to a super class reference


Employee emp;
emp = new Manager('John', 2000);

Now if we call emp.getSalary(), Java will invoke the method of Manager class,
the virtual machine will look into the actual class and call the overridden version
of the method. This is called dynamic method lookup;

Employeep[] staff = new Employee[...];


staff[0] = new Employee(...);
staff[1] = new Manager(...);
staff[2] = new Janitor(...);
...
double sum = 0;
for(Employee empl : staff) {
sum += empl.getSalary();
}

In the above case the individual object will be calling different version of
getSalary() method

Assigning super class to sub class


Manager[] bosses = new Manager[10];
Employee[] empls = bosses; // Legal in Java
empls[0] = new Employee(...); // Runtime error

Here compiler will throw an ArrayStoreException at run time. This will be


accepted by compiler as Java arrays are covariant. (??)

Cast
If a subclass object is assigned to a super class reference, it can not call
methods define in subclass in that case we can cast the object to its original type

Employee empl = new Manager(...);


empl.setBonus(1000); // this is incorrect and will result in a compile time
error
if(empl instanceof Manager) {
Manager mgr = (Manager) empl;
mgr.setBonus(1000); // legal
}

Final Methods and Classes


Final methods can not be overridden, and a final class can not be extended

Previously virtual machine used to convert final methods to inline methods for
more efficiency but now a days it will smartly decide and make small methods inline
if they are not overridden even if they are not declared final, it will not make
things inline if subclass of the class with overridden method is loaded as well.

Some of the JAVA internal final classes are String, LocalTime, URL etc

Abstract Class
Abstract class can contain both concrete and abstract method. Abstract methods
are only declaration, so the sub classes are forced to implement that method.
Abstract class can not be instantiated, but can be used to hold reference of sub
classes.

public abstract class Person {


private String name;

public Person (String name) { this.name = name; }


public final String getName () { return name; }

public abstract int getId();


}

public class Student extends Person {


private int id;

public Student(String name, int id) {


super(name);
this.id = id;
}

public int getId() {


return id;
}
}

Protected Access
Members which are marked protected can be accessed through subclass even from
different package.
(All classes of same package can access protected members ??)

Anonymous Subclasses
Extending some class using anonymous class can be handy for debugging

ArrayList<String> names = new ArrayList<String>(100) {


public void add(int index, String element) {
super.add(index, element);
System.out.println("Adding %s at %d\n", element, index);
}
}

Here we are overriding the add method to peek and report which elements are
getting added

If we want to create an anonymous ArrayList we can use this trick of anonymous


subclassing

ArrayList<String> friends = new ArrayList<>();


friends.add("Harry");
friends.add("Sally");
invite(friends);

Here we are passing the ArrayList to a function, so we may not need the
ArrayList again. If we create an Anonymous ArrayList then it is difficult to insert
elements in it,

So,
invite(new ArrayList<String>(){{ add("Harry"); add("Sally"); }});

Here we are using double brace technique where the first brace provides a
anonymous subclass and second brace defines an initialization block inside it. This
technique is not recommended (equals method may not work properly).

** If both super class and implemented interface contains methods of same name
(default method for interface) then Class implementation always wins, it is not
required to resolve the conflict.

Method expression of super


As we have seen earlier that method expression can be used with functional
interface, we can do this using "super" as well

public class Worker {eifjccgiicttrrfucndddndhudjkrtkfjvhhkhvdciik

public void work() {


for(int i = 0; i < 100; i++) {
System.out.println("It is working...");
}
}
}

public class ConcurrentWorker extends Worker {


public void work() {
Thread t = new Thread(super::work);
t.start();
}
}

Thread implements the Runnable interface whose run method calls the work
method of the superclass

Object -> The cosmic super class


All class in Java, directly or indirectly inherits from Object super class

Object introduces following instance methods,

String toString() -> String representation of an Object, by default Class


Name and Hash Code will be printed
A toString implementation for Employee class
public String toString() {
return getClass().getName() + "[name=" + name + ", salary=" + salary +
"]";
}

Here we are using getClass().getName() without hard-coding the name of


the class

Java will call the toString method automatically if we concatenate the


object with a String or just want to print it
Point p = new Point(10,20);
String txt = "" + p;

Using toString on arrays


int[] primes = {2, 5, 7, 10};

primes.toString(); // this will print something like I@124560 ('I'


denotes array of integers)

We need to use
Array.toString(primes); // prints all array element [2,5,7,10]
Array.deepToString is used for printing multi dimensional array

boolean equals(Object other) -> Returns true if object should be considered


equal to 'other', false if other is null or different from other
A null safe alternative of this method is
Object.equals(obj, other) in this case if 'obj' itself is null it won't
generate an exception

If we override the equals method we need to provide a hashcode method


override as well
Implementing equals method in a class
public class Item {
private String description;
private double price;
public boolean equals(Object otherObject) {
// check if they are identical
if (this == otherObject) return true;

// if the passed object is null


if(otherObject == null) return false;

// Check if other object belongs to the same class


if(getClass() != otherObject.getClass()) return false;

// Test if instance variables have identical values


Item other = (Item) otherObject;
return Object.equals(description, other.description) && price ==
other.price;
}

public int hashCode() {

}
}

Arrays.equal() static method can be used to check if two arrays are equal
(in length and in content)

It is good to call super class's equal method first


public class DiscountedItem extends Item {
private double discount;
public boolean equals(Object otherObject) {
if(!super.equals(otherObject)) return false;
DiscountedItem other = (DiscountedItem) otherObject;
return discount == other.discount;
}
}

Sometimes
if(getClass() != otherObject.getClass()) return false;
is replaced by
if (!( otherObject instanceof Item)) return false;

In this case object of DiscountedItem can be compared with Item (sub


class type can also be checked) but equals need to be symmetric by definition so
x.equals(y) should produce same result as y.equals(x)
So an DiscountedItem can be compared with Item because equals method at
Item won't be checking the discount value but not the other way around

If equality is decided based upon some fixed set of attributes all


introduced at super class then using instanceOf to check type is good because even
if it is a subclass object which is getting compared it is essentially same if they
posses equal value for that fixed set of attributes

int hashCode() -> Provides an hash code of an object which should equal for
equal objects
hashCode is an integer derived from an object and represents each object
uniquely
String uses following algorithm to calculate them
int hash = 0;
for (int i= 0; i < length(); i++)
hash = 31 * hash + charAt(i);

if x.equals(y) that means x.hashCode() == y.hashCode();


So when we are overriding the equals method we should override hashCode
method as well, if the do not match for equal objects then it will not be possible
to track them inside hash set or hash map
class Item {
...
public int hashCode(){
return Objects.hash(description, price);
}
}
Object.hash can accept variable arguments, compute hash code of the
arguments and then combine them
If we have array instance variable then we should compute hashCode using
Array.hashCode() static method then pass the result to Object.hash()

We can never define equals, toString and hashCode in a default method in an


interface because as per the class win rule the implementation at Object will
always win

Class<?> getClass() -> Yields a Class object describing the class to which
the object belongs

protect Object clone() -> Makes copy of an object (default shallow copy)
protect void finalize() -> this method is called when the object is reclaimed
by garbage collector (not recommended for overriding)

wait, notify, notifyAll -> will be introduced later

Cloning an object
Object.clone makes a shallow copy which is fine if the instance variables are
primitive or immutable. But for complex datastructure like ArrayList, the clone
will share the reference and modification in one place will affect other one

So in those cases developer need to implement the clone method and make sure
to take a deep clone

Some times it is very challenging to clone an object (example Scanner) and


not worth the trouble

If we decide to not make our objects clonable then we don't need to do


anything. Because Object.clone is protected method so no user of the class will be
able to access it.

If we decide to use the Object.clone to clone our object then we need to


implement Cloneable interface. This interface contains no methods (these type of
interfaces are called tagging or marker interface) but Object.clone method sees if
this interface is implemented to understand the desire of the programmer that the
object can be cloned using Object.clone() otherwise it will throw
CloneNotSupportedException
We also need to make sure the clone method is public and return type is
proper as the default return type is Object
And we need to declare (because subclass can choose to throw it by not
supporting cloning) or catch (if the class is final) CloneNotSupportedException

public class Employee implements Cloneable {


public Employee clone() throws CloneNotSupportedException {
return (Employee)super.clone();
}
}

If we want to do a deep copy and not use Object.clone then we call the
super class clone and also clone all the mutable members
ArrayList implements a clone method but this is a shallow clone so, if type
of value is something mutable or provides a reference then the clone need to be
called on them as well (or make a manual copy)
ArrayList.clone returns an Object type object so we need to cast it
manually.
If we do
cloned.recipients = (ArrayList<String>) recipients.clone();
// This will give an warning because the cast can not be fully checked
at run time

We can suppress it using annotations


public Message clone() {
try {
Message cloned = (Message) super.clone();
@SuppressWarnings("unchecked") ArrayList<String> clonedRecipients =
(ArrayList<String>) recipients.clone();
cloned.recipients = clonedRecipients;
return cloned;
} catch (CloneNotSupportedException ex) {
return null;
}
}

Cloning array
cloned.recipients = recipients.clone(); // No cast required

Enumeration
public enum Size { SMALL, MEDIUM, LARGE, EXTRA_LARGE }

Size notMySize = Size.valueOf("SMALL");


// sets notMySize to Size.SMALL, will throw exception if value not found

Size[] allValues = Size.values();


// creates an array of Size.SMALL, Size.MEDIUM etc

The above values method can be used to iterate through the enumeration object
for(Size s : Size.values()) {
System.out.println(s);
}

ordinal() method returns the position/index of the value in the Enumeration


Size.MEDIUM.ordinal() returns 1 (considering SMALL at 0, MEDIUM at 1 and so
on)

Every enumeration object implements Comparable<E> interface allowing


comparison between its objects using ordinal value.

Constructors, Methods and Fields of Enumeration

public enum Size {


SMALL("S"), MEDIUM("M"), LARGE("L"), EXTRALARGE("XL");

public String abbreviation;

Size(String abbreviation) {
this.abbreviation = abbreviation;
}

public String getAbbreviation() {


return this.abbreviation;
}
}

Above we can see we have declared a constructor for the Size enumeration.
When declaring the values we are passing the corresponding abbreviation.
Constructor of a enumeration is always private. So we can omit the explicit
declaration of private, it is a syntax error to make them public or protected

Body of an instance
public enum Operation {
ADD {
public int eval(int arg1, int arg2) {
return arg1 + arg2;
}
}

SUBTRACT {
public int eval(int arg1, int arg2) {
return arg1 - arg2;
}
}

public abstract int eval(int arg1, int arg2);


}

Operation op = Operation.ADD;
int result = op.eval(10, 20);

All of these constants belong to a anonymous subclass named Operation (in


this case) so, what ever we can put in a class we can put in the body of members.
Members naturally override the methods placed as abstract (or normal) by
enumeration.

Static members of Enumeration


Enumeration can have static members but they can not be used in
constructor as Enumeration Constants (values) are constructed before the static
members. We can use a static block for similar effects.

public enum Modifier {


PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, ABSTRACT;
private int mask;
static {
int maskBit = 1;
for (Modifier m : Modifier.values()) {
m.mask = maskBit;
maskBit *= 2;
}
}
...
}

Switching based on Enumeration


switch(op) {
case ADD: result = arg1 + arg2; break;
case SUBTRACT: result = arg1 - arg2; break;
}

op is an enumeration instance

To refer the enumeration instances by name (SMALL instead of Size.SMALL)


import static Size.*

Class class
If we call getClass() on an object then it will return an object of type Class

Object obj = ...;


Class<?> cl = obj.getClass();

We can get the class name using


System.out.println(cl.getName());

If we can also get the class from name stored in a String


Class<?> cl = Class.forName("java.util.Scanner");

This is a technique to get the Class object if the name of the class is not
known at the compile time.

If we know the name we can use


Class<?> cl = java.util.Scanner.class;

Class can hold other types and not only classes, it can hold interfaces,
primitive type and array type as well

Class<?> cl = String[].class; // Describes array type

Class<?> cl = Runnable.class; // Describes Runnable interface

Class<?> cl = int.class; // Describes primitive type

Class<?> cl = void.class; // Describes void type

getName() method will return weird name some times, these are archaic ways
to representing sometimes

String[].class.getName(); // returns "[Ljava.lang.String;"

int.class.getName(); // returns "[I"

In these cases we should use getCanonicalName(), for String arrays it will


return "java.lang.String[]"

But Class.forName method will only accept archaic names, we can not use
canonical names with that

We can do following
if(other.getClass() == Employee.class) {
...
}

Useful methods from "Class" class


To get Class objects describing a Class
static Class<?> forName(String className);

To get names of classes


String getCanonicalName()
String getSimpleName()
String getTypeName()
String getName()
String toString()
String toGenericString()

Get superclass, interfaces, packages etc


Class<? superclass T> getSuperClass()
Class<?>[] getInterfaces();
Package getPackage();
int getModifiers();

Testing types
boolean isPrimitive();
boolean isArray();
boolean isEnum();
boolean isAnnotation();
boolean isMemberClass();
boolean isLocalClass();
boolean isAnonymousClass();
boolean isSynthetic();

Getting enclosing component


Class<?> getComponentType(); // get component type of an Array
Class<?> getDeclaringClass(); // Declaring class for a nested class
Class<?> getEnclosingClass(); // Enclosing class for a local class
Constructor getEnclosingConstructor(); // Enclosing Constructor for a
local class
Method getEnclosingMethod(); // Enclosing method for a local class

Checking subtype of class of an object or a class


boolean isAssignableFrom(Class<?> cls); // tests Class cls is subtype
of this type
boolean isInstance(Object obj); // checks if class of obj is subtype of
this type

Creating instance from a class describer (only no argument constructors


can be used)
T newInstance();

ClassLoader getClassLoader(); // Class loader that loaded this class

Load the requested resource from the same location from where the class
was loaded
InputStream getResourceAsStream(String path)
URL getResource(String path)

Get fields, constructors (public or all)


(only public but includes inherited members as well)
Field[] getFields();
Field getField(String name);

Method[] getMethods();
Method getMethod(String name, Class<?>... parameterTypes);

Constructor[] getConstructors();
Constructor getConstructor(Class<?>... parameterTypes);

(all but not members of super class)


Field[] getDeclaredFields();
Field getDeclaredField(String name);

Method[] getDeclaredMethods();
Method getDeclaredMethod(String name, Class<?>... parameterTypes);

Constructor[] getDeclaredConstructors();
Constructor getDeclaredConstructor(Class<?>... parameterTypes);

static String toString(int modifiers);


static boolean isAbstract(int modifiers);
// The above method is also same for
(Abstract | Interface | Native | Private | Protected | Public | Static |
Strict | Synchronized | Volatile)

Loading Resources

Class class can also load resource from the path of actual class
InputStream stream = MyClass.class.getResourceAsStream("config.txt");
Scanner in = new Scanner(stream);

MyClass.class.getResourceAsStream("/config/menus.txt") // locates config/


menus.txt in the directory that contains the root of the package to which MyClass
belongs.

Class Loaders
Class file contains the instruction for a specific class or interface. These
files are loaded as required using ClassLoaders. There are three type of class
loaders
The bootstrap class loader
Loads Java library classes (from jre/lib/rt.jar)
There is no ClassLoader object corresponding this class loader so
String.class.getClassLoader() will return null

| The extension class loader


| loads standard extensions (from jre/lib/ext)
|
| The system class loader
| Loads the application classes, locates the classes and JAR files
provided in classpath
|
|----- These two loader are implemented and we can object of them. These are
instances of URLClassLoader

To know class path relative to the program


((URLClassLoader) MainClass.class.getClassLoader()).getURLs()

To load any class from a directory or a JAR

URL[] urls = {
new URL("file:///path/to/directory"),
new URL("file:///path/to/Jarfile.jar")
};

String className = "com.Something.SomeClass";

try(URLClassLoader loader = new URLClassLoader(urls)) {


Class<?> cl = Class.forName(className, true, loader);
}

Here we are creating a class loader instance with bunch of URL to look into
specific path for a class and passing that to forName() method. The second
parameter to forName method makes sure to do static initialization if set to true.
It is not advised to use ClassLoader.loadClass(), it does not run the static
initialization.

URLClassLoader loads class from file system, to load class from somewhere
else we need to override findClass method
public class MyClassLoader extends URLClassLoader {
...
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
byte[] bytes = ... // the bytes of the class file
return defineClass(name, bytes, 0, bytes.length);
}
}
If we write a method to load class dynamically, where the method is in a
Class which itself was loaded through class loader, any classes loaded by that
method will be using the class loader used to load the class where the method
exists. This class loader may not look at appropriate locations for the class file

For example
public class Util {
Object createInstance(String className) {
Class<?> cl = Class.forName(className);
...
}
...
}
This class is loaded by System class loader
Now if we want to load a plugin class which need to be loaded using
another class loader which loads classes from a JAR file and executes following
type of code to load the class
Util.createInstance("com.mycompany.plugins.MyClass")
But in above case the class loader which loads classes from JAR file
won't be used (System class loader), rather it will use the class loader used to
load the Util class (system class loader in this case)

** The remedy is to pass the class loader instance to createInstance


method which in turn will be passed to the forName method

public class Util {


Object createInstance(String className, ClassLoader loader) {
Class<?> cl = Class.forName(className, true, loader);
...
}
}

** Another remedy is to use the context class loader of the current


thread. By default the thread created will inherit the context class loader of the
parent thread, so naturally all of the threads will by default have system class
loader as their context class loader. We can also change the class loader of
current thread by following process
Thread th = Thread.currentThread();
th.setContextClassLoader(loader);

Now in the Util's createInstance method we can use the class loader of
current thread to load the class before creating instance
public Object createInstance(String className) {
Thread t = Thread.currentThread();
ClassLoader loader = t.getContextClassLoader();
Class<?> cl = Class.forName(className, true, loader);
...
}
So before calling the plugin loader we should change the class loader of
the current thread to the class loader which can load stuff from JAR file (special)
and then revert back the class loader after the plugin loading and method calling
is done

Service Class Loader


When implementing a plug-in system, a system developer might want to give
an interface which should be implemented by the plug-in developer, so user can have
multiple option to choose from but they all follow same interface
ServiceLoader makes it easy to load classes that conform to a common
interface

Suppose we want to develop classes which should follow certain interface


named Cipher

package com.corejava.crypt;

public interface Cipher {


byte[] encrypt(byte[] source, byte[] key);
byte[] decrypt(byte[] source, byte[] key);
int strength();
}

An implementing class looks like


package com.corejava.crypt.impl;

public class CaesarCipher implements Cipher {


public byte[] encrypt(byte[] source, byte[] key) {
byte[] result = new byte[source.length];
for (int i = 0; i < source.length; i++)
result[i] = (byte)(source[i] + key[0]);
return result;
}

public byte[] decrypt(byte[] source, byte[] key) {


return encrypt(source, new byte[] { (byte) -key[0] });
}
public int strength() { return 1; }
}

All though it is not mandatory for the class to implement the interface
but they should all have no argument constructor

The second step is to add the class names to a UTF-8 encoded text file
META-INF/services -> directory that a class loader can find

There we need to create a file with the interface name


META-INF/services/com.corejava.crypt.Cipher

Add the class name


com.corejava.crypt.impl.CaesarCipher

The third step, now we need to initialize the service loader


public static ServiceLoader<Cipher> cipherLoader =
ServiceLoader.load(Cipher.class);

We need to do this only once in the code, now we can iterate through
the existing implementations of the interface/class

public static Cipher getCipher(int minStrength) {


for(Cipher cipher: cipherLoader) { // implicitly calls iterator
if(cipher.strength() >= minStrength) return cipher;
}
return null;
}

Reflection
java.lang.reflect has three classes
Field
Describes fields of a class
Has a getName() method
Has a getType() method which returns a Class<?> Object that describes field
type

Constructor
Has getName() and getParameters()

Method
Has getName(), getParameters() and method for getting return type (Class<?>
object)

All of them have method getModifiers() which returns an integer with various
bits turned on or off, this can be analyzed using Modifier.isPublic(int modifier),
Modifier.isStatic(int modifier) etc.

As state above
(only public but includes inherited members as well)
Field[] getFields();
Field getField(String name);

Method[] getMethods();
Method getMethod(String name, Class<?>... parameterTypes);

Constructor[] getConstructors();
Constructor getConstructor(Class<?>... parameterTypes);

(all but not members of super class)


Field[] getDeclaredFields();
Field getDeclaredField(String name);

Method[] getDeclaredMethods();
Method getDeclaredMethod(String name, Class<?>... parameterTypes);

Constructor[] getDeclaredConstructors();
Constructor getDeclaredConstructor(Class<?>... parameterTypes);

Superclass of Method and Constructor is Executable which implements the


getParameters() method
The names of the parameters are only available at runtime if the class has been
compiled with the -parameters flag.

To get a list of all methods of a class


Class<?> cl = Class.forName(className);
while(cl != null) {
for(Method m : cl.getDeclaredMethods()) {
System.out.println(Modifier.toString(m.getModifiers()) + " " +
m.getReturnType().getCanonicalName() + " " + m.getName() + "(" +
Arrays.toString(m.getParameters()) + ")");
}
cl = cl.getSuperclass();
}

To get every fields and corresponding values


Object obj = ...;
for(Field f : obj.getClass():getDeclaredFields()) {
f.setAccesible(true);
Object value = f.get(obj);
System.out.println(f.getName() + " : " + value);
}

Private methods and fields need to be made accessible before accessing there
value thus we are calling f.setAccessible(true) here. JVM by default runs without
any Security Manager, so setAccessible will unlock the field for modification and
reading. How ever this can be protected by using a security manager with JVM.
Thus we can do the following as well
Field f = obj.getDeclaredField("salary");
f.setAccessible(true);
double value = f.getDouble(obj); // getDouble
f.setDouble(obj, value * 1.1);

getDouble, getInt can be used to get double or integer values and we can use
other corresponding methods as well other wise get will return Object type.

To invoke a method from Method object


Method m = ...
Object result = m.invoke(obj, arg1, arg2, ....)

for static methods the first argument need to be null

Person p = ...;
Method m = p.getClass().getMethod("setName", String.class);
p.invoke(obj, "********");

To construct object
Using no argument constructor
Class<?> cl = ...
Object obj = cl.newInstance();

For parameterized constructors


Constructor constr = cl.getConstructor(int.class); // constructor which
takes a single int as argument
Object obj = constr.newInstance(42);

AccessibleObject is a super class of Field, Method and Constructor


Exposes
void setAccessible(boolean flag)
static void setAccessible(AccessibleObject[] arrayofObjects, boolean flag)

Parameters of a Method or Constructor have certain methods


boolean isNamePresent()
String getName()
Class<?> getType()

If the class was not compiled using -parameters flag then the actual names of
parameters are not retained then getName will return synthesized names like arg0,
arg1 etc

JavaBeans and attribute accessors (a term from Rails)


A JavaBean is a class that has no argument constructor and getter/setter in a
specific format. Getters should be get<Name of the Property with first letter
capitalized> and Setter should be set<Name of the Property with first letter
capitalized>. If the first two letters are upper case then the name will be taken
exactly. getURL() will result in a constant named URL.
It is a good idea to use the standard classes for JavaBeans support whenever
you need to work with arbitrary properties.

We can obtain a BeanInfo object


Class<?> cl = ...;
BeanInfo info = Introspector.getBeanInfo(cl);
PropertyDescriptor[] props = info.getPropertyDescritors();

// Now we can search for a specific property

String propertyName = ...;


Object propertyValue = null;
for(PropertyDescriptor prop : props) {
if(prop.getName().equals(propertyName)) {
propertyValue = prop.getReadMethod().invoke(obj); // getReadMethod will
get the corresponding read method by convention
}
}

Working with Arrays


A method to write equivalent of copyOf method which taken in an array and
length and copies the provided array in that.

If we want to do a generic implementation of that our idea will be to create an


array of Object type with the given length and copy all elements there but the
problem with this approach is, an array started as Type T can go back to Object and
return back to Type T but array started as Object[] can not again go back to Type
T.

So a proper way of implementing this will be


public static Object goodCopyOf(Object array, int newLength) {
Class<?> cl = array.getClass();

// Check if it is truly array


if(!cl.isArray()) {
return false;
}

// Get the component type


Class<?> componentType = cl.getComponentType();
int length = Array.getLength();

// create new array with that component type


Object newArray = Array.newInstance(componentType, newLength);

for(int i = 0; i < Math.min(length, newLength); i++) {


Array.set(newArray, i, Array.get(array, i));
}

return newArray;
}

Proxy Class
The Proxy class can create, at runtime, new classes that implement a given
interface or set of interfaces. If the interfaces are not known during the compile
time.

** A proxy class has all methods required by the specified interfaces, and all
methods defined in the Object class. The methods are proxied in the Proxy class.
Creating a proxy object
We use Proxy.newProxyInstance() which takes in three arguments
- A class loader or null if default class loader need to be used
- An array of "Class" object, for each interface that need to be
implemented
- An invocation handler obj
-> This is an object of a class which implements InvocationHandler
interface
InvocationHandler interface makes sure that the class implements
invoke() method
Object invoke( Object proxy, Method method, Object[] args)

So we can do something like


Object[] values = new Object[1000];

for (int i = 0; i < values.length; i++) {


Object value = new Integer(i);

values[i] = Proxy.newProxyInstance(null,
// interfaces of the Integer class
value.getClass().getInterfaces(),

// Lambda expression for invocation handler


(Object proxy, Method m, Object[] margs) -> {
System.out.println(value + "." + m.getName() +
Arrays.toString(margs));
return m.invoke(value, margs);
});
}

So after printing the content of the call it is propagating the method call
to specific class, in this case Integer class. So instead of creating an array of
Integer objects we are creating an array of proxies, which will trap the calls to
actual Integer object, print it and then call the actual function.

** when no arguments are present the margs will be null instead of a zero
length array

Exceptions
Exceptions are thrown if an abnormal event takes place.
private static Random generator = new Random();

public static int randInt(int low, int high) {


if(low > high) {
throw new IllegalArgumentException("low should be less than high");
}

return low + (int)(generator.nextDouble() * (high - low + 1));


}

Hierarchy
Throwable (super class of all exceptions)
|
|-----Error
| |
| |---- Sub classed are unchecked exception (unrecoverable)
|
|-----Exception
|
|---- RuntimeException -- Sub classes are unchecked exception
|
|---- Sub classes are checked exception

Unchecked and Checked exceptions


Unchecked exceptions represents a scenario where the error condition can not be
handled and the code should be debugged to mitigate the issue.

Checked exceptions are anticipated exception, a method should kind of declared


its anticipated exceptions. Any method that might give rise to a checked exception
must declare it in the method header with a throws clause:

public void write(Object obj, String filename) throws IOException,


ReflectiveOperationException

Here write method can raise different kind of exceptions which are sub
classes of IOException, we have grouped all those exceptions by declaring that the
write method can throw IOException (super class) when required. We should not
bucket them all under Exception because it will defeat the cause of checked
exception.

Overridden methods can not throw new checked exception which is not thrown by
the parent method and it can not throw any checked exception if parent one is not
throwing any.

We can document throw of checked exception using @throws tag


More details https://techblog.bozho.net/checked-and-unchecked-exceptions-in-
java/

[People recommend to throw unchecked exceptions even goes to limit of


catching checked exception wrapping them under RuntimeException (thus making them
unchecked) and throw them, avoid checked exception as it is theoritically good but
practically makes the code ugly by adding those throws clauses]

if a lambda expression can throw a checked exception, then we can pass it to


a functional interface whose method declares that exception.

Catch block
try {
statements
} catch(ExceptionClass ex) {

} catch(ExceptionClass2 ex) {

or

try {
statements
} catch(ExceptionClass | ExceptionClass2 ex) {

Try with resources


We can use
try(ResourceType1 res1 = init1; ResourceType2 res2 = init2; ....) {

This try block will automatically call close() method on these resource
irrespective of exception occurrence, but all of the resources should belong from a
class which implements AutoCloseable interface (this actually forces to implement
close() method)

In the above case res2.close() will be called before res1.close()

If any of the close() is throwing exception in that case this exception will
be pushed to the suppressed list of the primary exception

try {
...
} catch(IOException ex) {
Throwable[] secondaryExceptions = ex.getSuppressed();
}

to push an expression to supressed list explicitly, we need to call


ex.addSuppressed(secondaryException)

This addSuppressed method only works for try with resources.

"finally" block is used to execute some code when try block come to an end
either by exception or normal execution, we might want to handle some stuff here
which does not have the close() method that can be handled by try with resources.

Avoid throwing exception in finally block because it can mask the actual
exception thrown in try block
Avoid doing return in finally because it will modify return value of try
block if it is executed with out exception and actually trying to return a valid
information

"Try with resources" is recommended to be used mostly.

Chaining exception
If we want to change type of an exception which makes more sense for a
secondary system then we should use the "cause" technique

One exception class can provide two type of constructor one which accepts a
string and another one accepting a string and an exception object.

public class SomeException extends IOException {


public SomeException(String msg) {
super(msg);
}

// Additionally we can only support exception chaning as well


public SomeException(Throwable cause) {
initCause(cause);
}

public SomeException(String msg, Throwable cause) {


super(msg);
initCause(cause);
}
}

Now we can chain exception like


catch(OtherInternalException ex) {
throw new SomeException("Some thing went wrong", ex);
}

We retrieve the cause back like


Throwable cause = ex.getCause();

If we do not have the constructor we can do,

catch(SQULexception ex) {
Throwable ex2 = new CruftyOldException("database error");
ex2.initCause(ex);
throw ex2;
}

All uncaught exception on a thread can be caught and logged using


Thread.setDefaultUncaughtExceptionHandler((thread, ex) -> {
// Record the exception
});

We can print the Stack Trace when we do not know what to do with the exception
ex.printStackTrace();

or have the stack trace in a string

ByteArrayOutputStream out = new ByteArrayOutputStream();


ex.printStackTrace(out);
String desc = out.toString();

or Analyze stack trace further using

StackTraceElement[] frames = ex.getStackTrace();

requiredNonNull() is a function which can raise NullPointerExceptions


intentionally
public void process(String directions) {
this.directions = Objects.requireNonNull(directions);
...
}

Here we can certainly know that directions can not be blank instead of getting
this one at more deep level.

We can optionally pass a string as additional messaging as a second argument.

Assertions
Assertions are used to programatically add or remove additional checking "code"
from the source code

Consider a scenario where we want to check if my arguments are non negative,


but do not want the checking code to be there in source during production,

we can write
assert x >= 0;

If this condition is not met, it will throw an AssertionError. If we do assert


condition : expression; then this expression will be converted into String and then
added as the message of AssertionError or if it is of type Throwable then it will
added as the cause of AssertionError

We can enable assertions using -ea/-enableassetions option of java, do not need


to recompile the class

java -ea MainClass

java -ea:com.mycompany.mylib ... MainClass ## this will turn on assertion


for the complete package mylib

we can disable assertion for specific class -da

Programatically using

void ClassLoader.setDefaultAssertionStatus(boolean enabled);


void ClassLoader.setClassAssertionStatus(String className, boolean enabled);
void ClassLoader.setPackageAssertionStatus(String packageName, boolean
enabled);

As with the -enableassertions command-line option, the


setPackageAssertionStatus method sets the assertion status for the given package
and its subpackages.

Enable system class assertion using -esa/-enablesystemassertions

Logging
To log into default global logger, get the logger using Logger.getGlobal()

Logger.getGlobal().info("Opening file"+someFileName);

This will log something like


Aug 04, 2014 09: 53: 34 AM com.mycompany.MyClass read INFO: Opening file
data.txt

If we do not want to log info we can set it off by calling


Logger.global.setLevel(Level.OFF);

If we do not want to create the string we can use a lambda


Logger.getGlobal().info(() -> "Opening file" + someFileName);

To create a logger and not log everything using global


Logger logger = Logger.getLogger("com.mycompany.myapp");
// first call will create the logger and all subsequent calls will return the
same logger.

Here the package hierarchy matters, if deactivate logging for com.mycompany


then child logger com.mycompany.app will be deactivated as well.

Logging levels
SEVERE,
WARNING,
INFO,
CONFIG,
FINE,
FINER,
FINEST.
So if we set level to FINE then all level above it are logged.
logger.setLevel(Level.FINE)

Level.ALL to log everything


Level.OFF to log nothing

by default SEVERE, WARNING and INFO are logged

Naturally we get a level method for each level like logger.fine(),


logger.info() etc
If level is dynamic we can do
Level level = Level.FINE;
logger.log(level, message);

There are some useful methods for debugging purposes in Logger


void entering(String className, String methodName)
void entering(String className, String methodName, Object param)

void entering(String className, String methodName, Object[] params)


void exiting(String className, String methodName) void exiting( String
className, String methodName, Object result)

Usage
public int read(String filename, String patter) {
logger.entering("com.mycompany.mylib.Reader", "read", new Object[]
{ filename, pattern });
.. do stuff ..
logger.exiting("com.mycompany.mylib.Reader", "read", result);

return result;
}

These calls generate log records of level FINER that start with the strings
ENTRY and RETURN.

For logging unexpected exceptions


void log(Level l, String message, Throwable t)
void throwing( String className, String methodName, Throwable t)

try {
...
} catch(IOException ex) {
logger.log(Level.SEVERE, "Cannot read configuration", ex);
}

If we are re-throwing this


if (...) {
IOException ex = new IOException("Cannot read configuration");
logger.throwing("com.mycompany.mylib.Reader", "read", ex);
throw ex;
}
The throwing call logs a record with level FINER and a message that starts
with THROW.

If compiler optimizes any call log may show incorrect class, in that case use
logp method
Localization of logs
void logrb(Level level, String sourceClass, String sourceMethod,
ResourceBundle bundle, String msg, Object... params)
void logrb(Level level, String sourceClass, String sourceMethod,
ResourceBundle bundle, String msg, Throwable thrown)

Logging configuration
Default
jre/lib/logging.properties

Override
java -Djava.util.logging.config.file=<some other configFile> MainClass

To change the default logging level change


.level=INFO

We can change for defined loggers as well


com.mycompany.myapp.level=FINER

we just append the .level at the end of logger name

As logger and handlers are different then we can do


java.util.logging.ConsoleHandler.level = FINE
to see FINE level messages in console.

Log Handlers
Logger actually sends the information to handlers which will in turn log the
information. Actually they will send to parent handler which will in turn send the
message to its parent until it hits the top one which will log the information
using ConsoleHandler.

Handlers also have level, if the level threshold for logger and handler both
agree for a specific level, then only messages of that log level will be
registered.

We can set our own handler


Logger logger = Logger.getLogger("com.myapp");
logger.setLevel(Level.FINE);
logger.setUseParentHandlers(false);

Handler handler = new ConsoleHandler();


handler.setLevel(Level.FINE);

logger.addHandler(handler);

If we do not setUseParentHandler(false) then it will send the message to both


parent and attached handler, and it may get logged twice

Instead of ConsoleHandler we can use FileHandler which will send the log
messages to a file or SocketHandler which will send the information to a specific
host and port.

FileHandler sends the messages to a file java<n>.log; n for unique naming


The created files are XML files

We can modify the behavior of FileHandler using


FileHandler(String pattern)
FileHandler(String pattern, boolean append)
FileHandler(String pattern, int limit, int count)
FileHandler(String pattern, int limit, int count, boolean append)

limit provides a limit on the byte size written to the log, then a new file
will be opened
pattern is the file name pattern
Example : %h/ myapp.log
%h for user home directory
%t system temp directory
%u unique number
%g generation number for rotated logs
%% escape and use the percent sign

count is the number logs in the rotation sequence, 1 means no rotation, if


rotation is on then it will automatically create myapp.log.0, myapp.log.1, ...,
every time a new file is created the oldest log .0 will be deleted and a new .0
will be created

Filter and Formatters


We can attach additional filters which implements the Filter interface which is
a functional interface forcing to implement the method
boolean isLoggable(LogRecord record)

we can use setFilter of logger or handler to attach the filter, but once at a
time.

Formatter
To define our own formatter of log message one should extend Formatter class
and Override
String format(LogRecord record)

In the format method we might want to modify the record and return the
String
To format the message part we should call
String formatMessage(LogRecord record)

To format head and tail override following (for example this is


required because it need to wrapped in a root element)
String getHead(Handler h)
String getTail(Handler h)

Finally call setFormatter() to use the formatter

Generics
Generic Class
public class Entry<K, V> {
private K key;
private V value;

public Entry(K key, V value) {


this.key = key;
this.value = value;
}

public K getKey() {
return this.key;
}
public V getValue() {
return this.value;
}
}

If we use this class like Entry<String, Integer> (but it won't work with
primitive types so Entry<String, int> is not valid)
Entry<String, Integer> en = new Entry<>("Jake", 10);
// here at the RHS we don't have to give the type information again, it is
inferred

Generic Method
Generic method can be part of a generic class or a normal class

public class Arrays {


public static <T> void swap(T[] array, int i, int j) {
T temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
The type parameter is placed after modifiers

During call we don't need to specify the type as it is inferred from argument,
but we can if we want (better error reporting)

Arrays.<String>swap(friends, 0, 1)

Type bounds (restricting type argument)


We want to write a method which should be able to close all resources (thus the
resources should implement AutoCloseable interface),

public static <T extends AutoClosable> void closeAll(ArrayList<T> elems)


throws Exception {
for(T elem : elems) {
elem.close();
}
}

Here we are bounding the T to make sure it implements AutoClosable, we can


chain as many interfaces as possible "T extends Runnable & AutoCloseable" but if we
specify a class that need to be extended then that have to be mentioned at the
beginning of the chain and the chain should contain only one class.

We need to use type parameter here for ArrayList<T>, for a simple array we
could have written AutoClosable[]

If Manager is a subclass of Employee, you can pass a Manager[] array to a


method which accepts Employee[], since Manager[] is a subtype of Employee[]. This
behavior is called covariance.

ArrayList<PrintStream> is not a subtype of ArrayList<AutoCloseable> although


PrintStream is a subtype of AutoCloseable.

Even if B is a sub class of A there is no relation between ArrayList<A> and


ArrayList<B>
So we can not do
ArrayList<B> alb = new ArrayList<>();
ArrayList<A> ala = alb; // Compile time error
To do this we need to do
ArrayList<? extends B> alb = new ArrayList();
- or -
ArrayList<B> alb = new ArrayList();

ArrayList<? extends A> ala = alb; // legal for both of the above cases

But we can not manipulate the list using this object


ala.add(...). will result in a run time exception.

In this case we can say ArrayList<B> or ArrayList<? extends B> is a sub type
of ArrayList<? extends A>

A very good post on Stack Overflow regarding extend and super with Wild Card
--- extends ---

The wildcard declaration of List<? extends Number> foo3 means that any of
these are legal assignments:

List<? extends Number> foo3 = new ArrayList<Number>(); // Number "extends"


Number (in this context)
List<? extends Number> foo3 = new ArrayList<Integer>(); // Integer extends
Number
List<? extends Number> foo3 = new ArrayList<Double>(); // Double extends
Number

Reading - Given the above possible assignments, what type of object are you
guaranteed to read from List foo3:
You can read a Number because any of the lists that could be assigned to foo3
contain a Number or a subclass of Number.
You can't read an Integer because foo3 could be pointing at a List<Double>.
You can't read a Double because foo3 could be pointing at a List<Integer>.
Writing - Given the above possible assignments, what type of object could you
add to List foo3 that would be legal for all the above possible ArrayList
assignments:
You can't add an Integer because foo3 could be pointing at a List<Double>.
You can't add a Double because foo3 could be pointing at a List<Integer>.
You can't add a Number because foo3 could be pointing at a List<Integer>.
You can't add any object to List<? extends T> because you can't guarantee
what kind of List it is really pointing to, so you can't guarantee that the object
is allowed in that List. The only "guarantee" is that you can only read from it and
you'll get a T or subclass of T.

--- super ---

Now consider List <? super T>.

The wildcard declaration of List<? super Integer> foo3 means that any of
these are legal assignments:

List<? super Integer> foo3 = new ArrayList<Integer>(); // Integer is a


"superclass" of Integer (in this context)
List<? super Integer> foo3 = new ArrayList<Number>(); // Number is a
superclass of Integer
List<? super Integer> foo3 = new ArrayList<Object>(); // Object is a
superclass of Integer
Reading - Given the above possible assignments, what type of object are you
guaranteed to receive when you read from List foo3:
You aren't guaranteed an Integer because foo3 could be pointing at a
List<Number> or List<Object>.
You aren't guaranteed a Number because foo3 could be pointing at a
List<Object>.
The only guarantee is that you will get an instance of an Object or subclass
of Object (but you don't know what subclass).
Writing - Given the above possible assignments, what type of object could you
add to List foo3 that would be legal for all the above possible ArrayList
assignments:
You can add an Integer because an Integer is allowed in any of above lists.
You can add an instance of a subclass of Integer because an instance of a
subclass of Integer is allowed in any of the above lists.
You can't add a Double because foo3 could be pointing at an
ArrayList<Integer>.
You can't add a Number because foo3 could be pointing at an
ArrayList<Integer>.
You can't add an Object because foo3 could be pointing at an
ArrayList<Integer>.

PECS
----
Remember PECS: "Producer Extends, Consumer Super".
---------------------------------------------------
"Producer Extends" - If you need a List to produce T values (you want to read
Ts from the list), you need to declare it with ? extends T, e.g. List<? extends
Integer>. But you cannot add to this list.
"Consumer Super" - If you need a List to consume T values (you want to write
Ts into the list), you need to declare it with ? super T, e.g. List<? super
Integer>. But there are no guarantees what type of object you may read from this
list.
If you need to both read from and write to a list, you need to declare it
exactly with no wildcards, e.g. List<Integer>.

public class Collections {


public static <T> void copy(List<? super T> dest, List<? extends T> src) {
for (int i = 0; i < src.size(); i++)
dest.set(i, src.get(i));
}
}

Note how the source list src (the producing list) uses extends, and the
destination list dest (the consuming list) uses super
(Courtesy : https://stackoverflow.com/questions/4343202/difference-between-
super-t-and-extends-t-in-java)

Unbounded Wildcard
If we do not type and type does not matter then we can use only <?>, for
example if we want to write a function to check if any element of an array list is
null then we do not care about type
public static boolean hasNulls(ArrayList<?> elements) {
for (Object e : elements) {
if (e == null)
return true;
}
return false;
}
If we write ArrayList<Object> the purpose will be defeated as it will not
accept ArrayList<Integer> or ArrayList<String> as it is not subtype of
ArrayList<Object>

We can also write public static <T> boolean hasNulls(ArrayList<T> elements)


as well

Capturing wildcard and using helpers


public static void swap(ArrayList <?> elements, int i, int j) {
? temp = elements.get( i); // Won't work
elements.set(i, elements.get(j));
elements.set(j, temp);
}

Wildcard can not be used as a type but we can work around this using

public static void swap(ArrayList<?> elements, int i, int j) {


swapHelper(elements, i, j);
}

private static <T> void swapHelper(ArrayList<T> elements, int i, int j) {


T temp = elements.get(i);
elements.set(i, elements.get(j));
elements.set(j, temp);
}

As we can see the swapHelper was able to capture the actual wild card type
sent from actual caller and use it in it's body

Generic in Virtual Machine


All the dynamic type information are erased and replaced by "Object" in VM, if
they are like <T extends AClass> then these will be replaced by AClass, also
compiler will insert casting to type where it is referring to Dynamic Type
public class Entry<K, V> {
private K key;
private V value;
...
}

Will be replaced by

public class Entry {


private Object key;
private Object value;
}

Cast Insertion
Entry <String, Integer> entry = ...;
String key = entry.getKey();

will be converted to

String key = (String) entry.getKey();

Bridge Method
Say we have a class like
public class WordList extends ArrayList <String> {
public void add(String e) {
return isBadWord(e) ? false : super.add(e);
}
...
}

Now consider a usage like following

WordList words = ...;


ArrayList<String> string = words; // this perfectly OK

strings.add("C++");

Now the above is calling an erased(converted) method which looks like -->
add(Object)
due to type erasing

Now if we might expect this to invoke the add() method on WordList class
but we need to keep in mind that the method in WordList is actually --> add(String)

So this might actually call the method in ArrayList class instead of the
intended call to the add() method of WordList class.

Compiler will add one bridge method to WordList class to avoid this
situation which looks like

public void add(Object e){


add((String) e);
}

Here we can see compiler is introducing a similar signature to make sure


the dynamic method look up works properly and will call the actual method.

Bridge method can also introduced for different return type although they
may have same signature (name and parameter type ). In VM a method is specified by
its return type, name and parameter type.

Restrictions of Generic
Can not construct array of Parameterized Types
Entry<String, Integer>[] entries = new Entry<String, Integer>[100]; //
Error — cannot construct an array with generic component type

Although the type Entry<String, Integer>[] is perfectly legal


@SuppressWarnings("unchecked") Entry<String, Integer>[] entries =
(Entry<String, Integer>[]) new Entry <?, ?>[ 100];

Or we can use ArrayList as well

ArrayList<Entry<String, Integer>> entries = new ArrayList<>( 100);

** If variable argument list is used with generic type (which is an array


in disguise) then this restriction is bypassed!
public static<T> ArrayList<T> asList(T... elements) {
ArrayList<T> result = new ArrayList<>();
for (T e : elements)
result.add(e);
return result;
}

Compiler may raise an warning here, use @SafeVarargs


Can not create static members with type variables
public class Entry<K, V> {
private static V somevars; // Error - V in static context
}

Can not create which will crash with other method after conversing (erasure)
public boolean equals(T value) {
...
}

This will convert to the signature boolean equals(Object) after erasure


thus clashing with Object class's equals() method

Can not throw or catch objects of a generic class. In fact, you cannot even
form a generic subclass of Throwable:
public class Problem<T> extends Exception // Error— a generic class can't
be a subtype of Throwable

public static<T extends Throwable> void doWork(Runnable r, Class<T> cl) {


try {
r.run();
} catch(T ex) {
// Error— can't catch type variable
Logger.getGlobal().log(..., ..., ex);
}
}

But we can use it in throws


public static<V, T> V doWork(Callable<V> c, T ex) throws T {

Collections
<<interface>> Iterable -------<<interface>> Iterator -------<<interface>>
ListIterator
|
|
<<interface>> Collection
|
|
--------<<interface>> List
|
|
--------<<interface>> Set ------<<interface>> SortedSet ------<<interface>>
NavigableSet
|
|
--------<<interface>> Queue ------<<interface>> Deque

<<interface>>Map ------ <<interface>>SortedMap ------ <<interface>>NavigableMap

<<interface>>RandomAccess

Some methods of Collection interface


add, addAll - To add elements, addAll accepts another collection object and
ensures all elements in that collection object are added to the current object

remove, removeAll, retainAll, removeIf, clear - First two works as above,


retainAll will retain the stuff sent to it and delete all else, remove if accepts a
functional interface Predicate, so it will accept a lambda to identify what to
delete, clear will delete everything

isEmpty, contains, containAll

iterator, stream, parallelStream, spliterator

toArray, size

Some methods of List interface


add - can be used to add single item or a collection of items
get - get the element of given index
set(int index, E element) - set the element with value of given index
remove

indexOf
lastIndexOf

listIterator

replaceAll

sort

subList

It is advised to use as general interface as possible when writing methods


which will process Collections. For example Collection, List or Map
Other useful methods of Collection
disjoint -> Takes in two collection and check if no common elements
copy(dest, src) -> takes in two lists and copy from src to dest
replceAll(list, oldVal, newVal)
fill(list, obj) -> replace all elements of list with obj
nCopies(number, obj) -> returns an immutable list of "number" copies of "obj"
frequence(collection, obj) -> no of elements in collection equals to obj

indexOfSublist(list, sublist)
lastIndexOfSubList() -> returns the index of first or last occurrence of the
target list with in source list

binarySearch(list, key, [object of Comparator Interface])

sort(list)
sort(list, comparator)

swap, rotate, reverse, shuffle

singleton, singletonList, singletonMap -> yields singleton Set, List or Map

emptyList, emptySet ... etc -> yields an empty view

Iterator
This is a super interface of collection
Provides two methods (as design pattern)
hasNext() -> to check any more element present
next() -> get next element

also provides a remove() method to remove last fetched element from


collection
remove() can not be called twice with out calling next()/previous() in
between

or we can use col1.removeIf(e -> e matches the condition) where col1 is a


Collection object

ListIterator is a subtype of iterator


provides some extra functionality like
previous()
add() -> add new element
set() -> replace existing element

List<String> friends = new LinkedList<>();


ListIterator<String> iter = friends.listIterator();
iter.add("Fred"); // Fred |
iter.add("Wilma"); // Fred Wilma |
iter.previous(); // Fred | Wilma
iter.set("Barney"); // Fred | Barney

If you have multiple iterators visiting a data structure and one of them
mutates it, the other ones can become invalid. An invalid iterator may throw a
ConcurrentModificationException if you continue using it.

Set
Unique set of elements but does not remember order of insertion
Two concrete implementation HashSet (uses hash) and TreeSet (uses binary tree)
add() to add elements
contains() to check elements

TreeSet returns the element in sorted order, so the elements of the list
should implement Comparable interface or we need to provide a comparator as the
constructor argument
The TreeSet class implements the SortedSet and NavigableSet interfaces, they
introduces some other useful methods

Map
Key value pair
put(key, value) method can be used to add new record or update the existing
information
get(key) to get a value corresponding to a key, if the key is not present
then null
getOrDefault(key, defaultValue) if key not present then the default value

Some useful methods


get, getOrDefault
put, putIfAbsent
merge(key, value, BiFunction) Applies the bi function on "value" with the
value of "key" if present
compute, computeIfPresent, computeIfAbsent
putAll
remove, replace
size
isEmpty
forEach
replaceAll
contains, containsValue
keySet, values, entrySet

Other collections
Properties
The Properties class implements a map that can be easily saved and loaded
using a plain text format. Such maps are commonly used for storing configuration
options for programs. For example:

Properties settings = new Properties();


settings.put("width", "200");
settings.put("title", "Hello, World!");
try (OutputStream out = Files.newOutputStream(path)) {
settings.store(out, "Program Properties");
}

The result is the following file:

#Program Properties
#Mon Nov 03 20: 52: 33 CET 2014
width = 200
title = Hello, World\!

Load the config back as


try (InputStream in = Files.newInputStream(path)) {
settings.load(in);
}

Then get back a property using


String title = settings.getProperty("title", "New Document");
// if the key is not present then the second argument value will be used as
default value

BitSet
The BitSet class stores a sequence of bits. A bit set packs bits into an
array of long values, so it is more efficient to use a bit set than an array of
boolean values. Bit sets are useful for sequences of flag bits or to represent sets
of non-negative integers, where the ith bit is 1 to indicate that i is contained in
the set.

This provides useful methods like set, clear, bit, get, xor, and, andNot etc

EnumSet
enum Weekday { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
};
Set <Weekday> always = EnumSet.allOf(Weekday.class);
Set <Weekday> never = EnumSet.noneOf(Weekday.class);
Set <Weekday> workday = EnumSet.range(Weekday.MONDAY, Weekday.FRIDAY);
Set <Weekday> mwf = EnumSet.of(Weekday.MONDAY, Weekday.WEDNESDAY,
Weekday.FRIDAY);

We can use Set class methods with EnumSet

EnumMap is also there

Stack, Queue, Deques, Priority Queues


ArrayDeque <String> stack = new ArrayDeque <>();
stack.push("Peter");
stack.push("Paul");
stack.push("Mary");
while (!stack.isEmpty())
System.out.println(stack.pop());
With a queue, use add and remove.

Queue <String> queue = new ArrayDeque <>();


queue.add("Peter");
queue.add("Paul");
queue.add("Mary");

while (!queue.isEmpty())
System.out.println( queue.remove());

A priority queue retrieves elements in sorted order after they were inserted
in arbitrary order. That is, whenever you call the remove method, you get the
smallest element currently in the priority queue.
public class Job implements Comparable <Job> { ... }
...
PriorityQueue <Job> jobs = new PriorityQueue <>();
jobs.add(new Job(4, "Collect garbage"));
jobs.add(new Job(9, "Match braces"));
jobs.add( new Job(1, "Fix memory leak"));

WeakHashMap
This data structure cooperates with the garbage collector to remove key/
value pairs when the only reference to the key is the one from the hash table
entry.

Technically, the WeakHashMap uses weak references to hold keys. A


WeakReference object holds a reference to another object — in our case, a hash
table key. Objects of this type are treated in a special way by the garbage
collector. If an object is reachable only by a weak reference, the garbage
collector reclaims the object and places the weak reference into a queue associated
with the WeakReference object. Whenever a method is invoked on it, a WeakHashMap
checks its queue of weak references for new arrivals and removes the associated
entries.

Views
This is an object which will implement a collection interface but does not
store the data. It provides a "view" inside a collection.
Map's keySet() and values() method returns views
Array's asList method which returns a List<T> object backed by array elements

View does not support all functionalities of the interface

Different types of Views


Ranges
List <String> sentence = ...;
List <String> nextFive = sentence.subList(5, 10);

This view accesses the elements with index 5 through 9. Any mutations of
the sublist (such as setting, adding, or removing elements) affect the original.

Empty or Singleton View


The Collections class has static methods yielding an immutable empty
collection of every type (list, set, sorted set, navigable set, map, sorted map,
navigable map, iterator, list iterator, or enumeration)

or Map or Set with a single element


Usage:
doWork(Collections.emptyMap()); // for empty list
doWork(Collections.singletonMap("id", id));

instead of creating a heavyweight HashMap or TreeMap object.

Unmodifiable View
Collections.unmodifiableList(friends);

This produces a view which can not be modified thus not affecting the
actual data structure

Stream
Stream is like collection as it is also used for processing a set/list of items.
But in Stream we do not specify how to process the data, we only specify what need
to be done and it is the responsibility of the Stream to optimize the performance
of operation (may be by parallelizing it) while the end result will be correct.

For example if we want to gather all long words from a book, in a traditional way
we might do something like

String contents = new String(File.readAllBytes(Path.get("book.txt")),


StandardCharsets.UTF_8);

List<String> words = Arrays.asList(contents.split("\\PL+"));

// Now we iterate on words


int count = 0;
for(String word : words) {
if(word.length() > 12) count++;
}

All of the above operation when represented using Stream looks like

word.stream().filter(word -> word.length() > 12)->count()

We can replace the stream() with parallelStream() and the filtering will be
done in a parallel manner

Stream Properties
- Stream does not store the elements
- Stream operation does not mutate the source, here filter will return a new
stream
- Stream operations are lazy when possible, if we ask for first five words that
match our criteria then filter will only produce that much and stop there

Workflow of a Stream
1. Create a stream
2. Specify intermediate operations (one or more)
3. Terminal operation to produce result, this will force the execution of lazy
operations

Creating a stream
From Collection
Collections has stream() and parallelStream() method

From Array
Stream<String> st = Stream.of(SomeStringArray);

Using Arrays' stream method


Arrays.stream(array, from, to)
Empty stream
Stream<String> silence = Stream.empty();

Using generate()
generate() method takes a function with no arguments and when ever the data
is requested that function will be called
Stream<String> echos = Stream.generate(() -> "Echo"); // will always return
"Echo" infinite stream

Stream<Double> random = Stream.generate(Math::random);

Using iterate()
To generate an infinitely long series of numbers 0, 1, 2, 3 ....

Stream<BigInteger> integers = Steam.iterate(BigInteger.ZERO, n ->


n.add(BigInteger.ONE));

iterate() starts with the first argument value which in this case is 0 and
then applies seed value (BigInteger.ONE) on the last element.
So it will do 0, 0+1, 1+1, 1+2 ....

Other methods
Stream<String> words = Pattern.compile("\\PL+").splitAsStream(content); //
returns Stream of words

Files.lines also returns a stream of lines Stream<String> lines =


Files.lines(path);

Processing Stream
filter
filter(word -> word.length() > 12)
Produces a new stream which has the properly filtered elements
Accepts a Predicate(T) functional interface which will produce boolean result
from T type

map
To modify elements of stream and produce a new stream out of it
Suppose we want to convert all characters to lower cases
Stream<String> lowercaseWords = words.stream().map(String::toLowerCase)

Or get the stream of only first letters


Stream<String> firstLetters = words.stream().map(w -> w.subString(0, 1));

flatMap
If we have a method which produces stream
public static Stream<String> letters (String s) {
List<String> letters = new ArrayList<>();
for(int i = 0; i < s.length(); i++) {
letters.add(s.substring(i, i+1));
}
return letter.stream();
}

The above function will take a String "boat" and return a Stream of letters
["b", "o", "a", "t"]

Now we can apply the whole function on each words of a Sentence


Stream<Stream<String>> result = word.stream().map(w -> letters(w));
Now result contains stream of streams [["Y", "o", "u"], ["b", "o", "a",
"t"] ...]

Now if we want to flatten it to a single stream of letters ["Y", "o", "u",


"b" ...]

We should use flatMap instead


Stream<String> result = word.stream().flatMap(w -> letters(w));

Extracting and combining stream


limit() method can be use to take a specific number of elements
Stream <Double> randoms = Stream.generate(Math::random).limit( 100);

skip() method can skip first n elements ...stream().skip(n)

Stream.concat(stream1, stream2) concatenates two streams but make sure first


one is not an infinite stream

distinct() can be used to keep only the distinct elements of a stream ..


stream().distinct()

sorted() method can be used to sort a stream which accepts a comparator or


works with Comparable elements
words.stream().sorted(Comparator.comparing(String::length).reversed());

peek() method yields a stream which exactly equal to original but it takes a
function which lets us peek into the stream with out disturbing it, mainly used for
debugging purposes

Object[] powers = Stream.iterate(1.0, p -> p * 2).peek(e ->


System.out.println(" Fetching " + e)).limit(20).toArray();

Reduction
These are terminal method which will actually produce output, previously we saw
count, it also has max, min etc

They return data in an object which is a Optional<T> type object, this indicate
if it has value or contains nothing (due to empty stream). Stream's do not return
null because it can lead to null pointer exception. Here is how we can use Optional
objects
Optional<String> largest = words.max(String::compareToIgnoreCase);
System.out.println(largest.getOrElse(""));

So if null the Optional object returns the value passed to getOrElse() method

findFirst()
Gets the first element, works good with a filter
Optional<String> startsWithQ = words.filter(s ->
s.startsWith("Q")).findFirst();

findAny()
If we just want to grab any match (does not matter first or last), then we
can use this with parallel stream for better performance
Optional<String> startsWithQ = words.parallel().filter(s ->
s.startsWith("Q")).findAny();

//parallel method can be used on a stream to enable parallelism?

allMatch, noneMatch, anyMatch methods accepts a predicate argument (lambda) so


we can avoid using filter, allMatch or noneMatch returns boolean values.

Optional<T>
Optional value represents either a value or none, it gives multiple useful
functions regarding that
String result = optionalString.orElse(""); // so we get the value or ""

or we can pass a method and that will be called when the value is not present
(works well while working with configurations)

String result = optionalString.orElseGet(() ->


System.getProperty("user.dir"));

or we can throw an exception

String result = optionalString.orElseThrow(IllegalStateException::new);

or we can send the value if it is there

optionalValue.ifPresent(v -> results.add(v)); // here we are adding the value


to the results if the value is present
optionalValue.ifPresent(results::add); // this will work as above

ifPresent will not return any value, for returning value we need to use map()

Optional <Boolean> added = optionalValue.map(results::add);

isPresent() can be used to check if the value is present


getOrElse(defaultValue)
get() will get the value or raise exception if not present

Creating optional value


Optional.of(someVal);
Optional.empty()

public static Optional<Double> inverse(Double x) {


return (x == 0) ? Optional.empty() : Optional.of(1/x);
}

Optional.ofNullable(obj) returns Optional.of(obj) if obj is not null, or


Optional.empty() if null

If some method is returning optional of Class T, then we can not chain a method
of Class T on the returning object directly because it will be an optional object
So g() is returning x object of Class X and y is an instance method of Class
X, so we can call ..g().y()
but if it is returning optional object we can not do that, we need to do
g().flatMap(X::y)

the above mentioned inverse method will be a good example


Optional <Double> result = inverse(x).flatMap(MyMath::squareRoot);

this is Optional.flatMap method not Stream.flatMap

Collection of data
iterate() method on top of Stream gives an iterator
forEach() takes an lambda and applies that to each element
stream.forEach(System.out::println)
forEachOrdered() same as forEach but sorted access (loose all benefits of
parallelism)
toArray() to return an array of Object[] type, for a specific type send the
array constructor as argument
stream.toArray(String[]::new)

To convert to list or set use the collect() method, this accepts an object of
that collection, Collector class provides factories for common collection objects

List<String> result = stream.collect(Collectors.toList())

Set <String> result = stream.collect(Collectors.toSet());

If we want to get a specific type of set


TreeSet <String> result =
stream.collect(CollectorstoCollection(TreeSet::new));

If we want to collect all strings in a stream by concatenating them


String result = stream.collect(Collectors.joining());

We can pass a delimiter to the joining() method.. ", " <- like this

If we want to summarize the stream into sum, average, maximum or minimum we can
use the summarizingInt, summarizingDouble or summarizingLong methods which returns
(Int|Long|Double)SummaryStatistics object respectively. From these summary
statistics object we can get the required data

IntSummaryStatistics summary =
stream.collect(Collectors.summarizingInt(String::length));
double averageWordLength = summary.getAverage();
double maxWordLength = summary.getMax();

To collect information in a Map we can use the Collectors.toMap() which take tw


function, first one will yield id (key) and second one will yield value
Map <Integer, String> idToName =
people.collect(Collectors.toMap(Person::getId, Person::getName));

If we want to have the actual object as the value then use


Function.identify()

Map <Integer, Person> idToPerson =


people.collect(Collectors.toMap(Person::getId, Function.identity()));

If there are more than one value for a given key it will raise an
IllegalStateException, we an avoid this by providing a third argument (function)
which will resolve the conflict

Map <Integer, Person> idToPerson =


people.collect(Collectors.toMap(Person::getId, Function.identity(), (existingValue,
newValue) -> existingValue ));

Or we can maintain a Set of all values

Map <Integer, Set<Person>> idToPerson =


people.collect(Collectors.toMap(Person::getId, l -> Collections.singleton(l),
(existingValue, newValue) -> {
Set<String> union = new HashSet<>(existingValue);
union.addAll(newValue);
return union;
}));
Above we are creating a singleton set then merging them with new value when
found

to use a tree map send the constructor as fourth argument of


Collectors.toMap(....., TreeMap::new)

Map <String, Set<String>> countryLanguageSets = locales.collect(


Collectors.toMap(Locale::getDisplayCountry,
l -> Collections.singleton(l.getDisplayLanguage()),
(a, b) -> { // Union of a and b
Set <String> union = new HashSet <>(a);
union.addAll(b);
return union;
}));

This will collect all languages of each country

"Switzerland" -> [French, German, Italian]


...

We can achieve the same thing using groupingBy method

Map <String, List <Locale>> countryToLocales =


locales.collect(Collectors.groupingBy(Locale::getCountry));

We can look up using


List <Locale> swissLocales = countryToLocales.get("CH"); // yields
[it_CH, de_CH, fr_CH]

en_US means english in USA

check for partitionBy() for partitioning the list, groupingBy will


partition the list if a function returning boolean value (predicate) is passed to
it

Downstream Collectors
groupingBy will return List, if we want a set then do
Map <String, Set <Locale>> countryToLocales =
locales.collect(Collectors.groupingBy(Locale::getCountry, Collectors.toSet()));

counting() to produce count of the collected element


Map <String, Long> countryToLocales =
locales.collect(Collectors.groupingBy(Locale::getCountry, Collectors.counting()));

summing(Int|Double|Long) to produce their sum by applying a function


(accepted as argument)

check maxBy, minBy, mapping

Reduce
reduce() method can be used to compute value for a stream
List<Integer> values = ...;
Optional<Integer> sum = values.stream().reduce((x,y) -> x+y)

Second form of reduce is to supply a starting element as the first argument


Integer sum = values.stream().reduce(0, (x,y) -> x+y);

here it starts with 0, (for multiplication we should use 1); if the list is
empty then it will return 0
also the x is the last sum here... so we can have different types of x and
y, x is an Integer but y can be a string and we can do x + y.length()
To handle parallelism, we can pass a function as a third argument

Integer sum = values.stream().reduce(0, (x,y) -> x+y, (total1, total2) ->


total1+total2);

although a much simpler approach ...stream().mapToInt(String::length).sum()

Primitive type stream


IntStream, DoubleStream, LongStream

To create IntSteam, can use IntStream.of()


IntStream stream = IntStream.of(1, 1, 2, 3, 5);

Or stream method of array


stream = Arrays.stream(values, from, to); // values is an int[] array

along with iterate and generate method, they have range, rangeClosed method
IntStream zeroToNinetyNine = IntStream.range(0, 100); // Upper bound is
excluded
IntStream zeroToHundred = IntStream.rangeClosed(0, 100); // Upper bound is
included

Check CharSequence interface and codePoints(), chars() methods

A stream of objects can be transformed to a primitive type stream with the


mapToInt, mapToLong, or mapToDouble methods.

From primitive to object


Stream <Integer> integers = IntStream.range(0, 100).boxed();

Optional class here is OptionalInt, OptionalDouble ... they has methods


getAsInt, getAsDouble etc

summaryStatistics() yields IntSummaryStatistics, LongSummaryStatistics


etc

For parallel stream if we want to make operations parallelism efficient we can do


following stuff
- We can drop the requirement for ordering when not required by calling
unordered()
- distinct(), limit() benefits from this

Input/Output Streams
Input stream is used for reading byte from a source and output stream is used for
writing

Source can be a file, url or an byte array


Creating input and output stream

InputStream in = Files.newInputStream(path);
OutputStream out = Files.newOutputStream(path);

Stream from URL


URL url = new URL("https://some.com/");
InputStream in = url.openStream();

Byte array input stream


byte[] bytes = ...;
InputStream in = new ByteArrayInputStream(bytes);

Write to byte array using stream


ByteArrayOutputStream out = new ByteArrayOutputStream();
// write to out
byte[] bytes = out.toByteArray();

To read a byte we can call


int b = in.read();

To read a bunch (read until the send array is full or reached end of stream )
byte[] bytes = ...
int actualBytesRead = in.read(bytes);
actualBytesRead = in.read(bytes, start, length);

To read all bytes (direct method is not there)


public static byte[] readAllBytes(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
copy(in, out);
out.close();
return out.toByteArray();
}

To read all bytes of a file


byte[] bytes = Files.readAllBytes(path);

write() method of output stream can write individual byte or byte arrays
OutputStream out = ...;
int b = ...;
out.write(b);

byte[] bytes = ...;


out.write(bytes);
out.write(bytes, start, length);

Closing the output stream is done best with try-using


try(OutputStream out = ...) {
out.write(bytes);
}

Copying input stream to output stream


public static void copy(InputStream in, OutputStream out) throws IOException {
final int BLOCKSIZE = 1024;
byte[] bytes = new byte[BLOCKSIZE];
int len;
while ((len = in.read(bytes)) != -1) {
out.write(bytes, 0, len);
}
}

To save input stream of a file


Files.copy(in, path, StandardCopyOption.REPLACE_EXISTING);

Java uses the Unicode standard for characters. Each character or “code point”
has a 21-bit integer number. There are different character encodings— methods for
packaging those 21-bit numbers into bytes. The most common encoding is UTF-8, which
encodes each Unicode code point into a sequence of one to four bytes.
Another common encoding is UTF-16, which encodes each Unicode code point into
one or two 16-bit values. Actually, there are two forms of UTF-16, called “big-
endian” and “little-endian.” Consider the 16-bit value 0x2122. In big-endian
format, the more significant byte comes first: 0x21 followed by 0x22. In little-
endian format, it is the other way around: 0x22 0x21. To indicate which of the two
is used, a file can start with the “byte order mark,” the 16-bit quantity 0xFEFF.
The user should understand and discard this value when reading. Unfortunately java
does not do that, so we need to strip leading \uFEFF when found.

There is no reliable way to automatically detect the character encoding from a


stream of bytes. Some API methods let you use the “default charset”— the character
encoding that is preferred by the operating system of the computer.

While converting bytes from a file one should provide the character state

String str = new String(bytes, StandardCharsets.UTF_8);

Available constants
StandardCharsets.UTF_8
StandardCharsets.UTF_16
StandardCharsets.UTF_16BE
StandardCharsets.UTF_16LE
StandardCharsets.ISO_8859_1
StandardCharsets.US_ASCII

Text Input
To read text input we should use reader,
InputStream inStream = ...;
Reader in = new InputStreamReader(inStream, charset);

We can use in.read();

Other options
String content = new String(Files.readAllBytes(path), charset);

List<String> lines = Files.readAllLines(path, charset);

or process them lazily as a Stream

try(Stream<String> lines = Files.line(path, charset)) {


...
}

To read numbers or words from a file


Scanner in = new Scanner(path, "UTF-8");
while (in.hasNextDouble()) {
double value = in.nextDouble();
...
}

We can override the default delimiter scanner works with


in.useDelimiter("\\PL+"); // now it will read words

If the input stream is not from a file we want to wrap it in BufferedReader

try (BufferedReader reader = new BufferedReader(new


InputStreamReader(url.openStream()))) {
Stream <String> lines = reader.lines();
...
}

It has method readLine()

If a method asks for a Reader and you want it to read from a file, call
Files.newBufferedReader(path, charset).

To write text we need a writer


OutputStream outStream = ...;
Writer out = new OutputStreamWriter(outStream, charset);
out.write( str);

To get a writer for a file


Writer out = Files.newBufferedWriter(path, charset);

PrinterWriter is another type of writer which gives methods like println(),


printf() etc, convenient to use

PrintWriter out = new PrintWriter(Files.newBufferedWriter(path, charset));

If we need to write to another stream


PrinterWriter out = new PrinterWriter(outputStream, "UTF-8"); // we can not
pass a Chartset object here, it needs a string

Write text to file


String content = ...;
Files.write(path, content.getBytes(charset));

or

Files.write(path, lines, charset);

Here, lines can be a Collection <String>, or even more generally, an


Iterable <? extends CharSequence>

both of the write method above takes in a last argument


StandardOpenOption.APPEND to append to the given file

Reading and writing binary data


The DataInput and DataOutput interface is responsible for this

byte readByte()
int readUnsignedByte()
char readChar()
short readShort()
int readUnsignedShort()
int readInt()
long readLong()
float readFloat()
double readDouble()
void readFully( byte[] b)
.. and corresponding write methods from DataOutput

The binary files are efficient. For a writing an integer or some other type the
space needed is the same for each value of a given type, which speeds up random
access. Also, reading binary data is faster than parsing text. The main drawback is
that the resulting files cannot be easily inspected in a text editor.

Data input and output stream


DataInput in = new DataInputStream(Files.newInputStream(path));
DataOutput out = new DataOutputStream(Files.newOutputStream(path));

Random access files


RandomAccessFile class can be used to randomly access any position of the file

RandomAccessFile file = new RandomAccessFile(path.toString(), "rw");

use "r" or "rw" for only read and read write respectively

seek() method can be used to move file pointer to a specific position, which
accepts values between 0 to length of the file (Long integer)
length() method can be used to get length of the file
getFilePointer() to get the correct file pointer

The RandomAccessFile class implements both the DataInput and DataOutput


interfaces. To read and write numbers from a random-access file, use methods such
as readInt/ writeInt (methods of these interface as discussed above "Reading and
writing binary data")

int value = file.readInt();


file.seek(file.getFilePointer() - 4);
file.writeInt(value + 1);

Memory mapped files


Efficient for random access but have complete different set of APIs
FileChannel channel = FileChannel.open(path, StandardOpenOption.READ,
StandardOpenOption.WRITE);

Then map the area of a file, if not big the whole file

ByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0,


channel.size());

Now
int offset = ...;
int value = buffer.getInt(offset);
buffer.put(offset, value + 1);

can use get, getInt, getDouble to read and put to write

File lock
To lock a file for writing (for multi threading) get a channel then call either
lock or tryLock() method

FileChannel channel = FileChannel.open(path);


FileLock lock = channel.lock();
// this will block the execution and wait until it can get a lock

FileLock lock = channel.tryLock();


// this will return immediately, either with a lock or null if it was not able
to lock the file

If the channel is not closed then the file will be locked until the channel is
closed so it is better to use try with resources
try(FileLock lock = channel.lock()) {

Path
Path homeDir = Paths.get("/", "home", "ssen");

Path workPath = homeDir.resolve("myapp/work");

- or -

Path workPath = homeDir.resolve(new Path("myapp", "work"));

resolveSibiling resolves the path on parent of current path


Path tempPath = workPath.resolveSibling("temp");

if workPath is /x/y/z, then tempPath is now is /x/y/temp

relativize
Path.get("/home/ssen").relativize(Path.get("/home/xyz/app"));
// result is ../xyz/app, get the relative path of the given path

normalize() will remove any redundant or ., .. components


/home/cay/../fred/./myapp -> /home/fred/myapp

toAbsolutePath
The toAbsolutePath method yields the absolute path of a given path. If the
path is not already absolute, it is resolved against the “user directory”— that is,
the directory from which the JVM was invoked. For example, if you launched a
program from /home/cay/myapp, then Paths.get("config").toAbsolutePath() returns
/home/cay/ myapp/config.

Other methods
Path p = Paths.get("/home", "cay", "myapp.properties");
Path parent = p.getParent(); // The path /home/cay
Path file = p.getFileName(); // The last element, myapp.properties
Path root = p.getRoot(); // The initial segment / (null for a relative path)
Path first = p.getName( 0); // The first element
Path dir = p.subpath(1, p.getNameCount()); // All but the first element, cay/
myapp.properties

To iterate over components of a path variable, we can use for each loop as it
implements iterable interface

for(Path component : path) {

Creating directory and files


Files.createDirectory(path) -> all but last component in the path should exists
Files.createDirectories(path) -> create a path similar to mkdir -p
Files.createFile(path) -> create an empty file

Files.exists(path) to check if a file or directory exists


To check if it is a directory or file use Files.isDirectory() /
..isRegularFile() method

Creating a temp file on predefined location or system specific location


Path tempFile = Files.createTempFile(dir, prefix, suffix);
Path tempFile = Files.createTempFile(prefix, suffix);
Path tempDir = Files.createTempDirectory(dir, prefix);
Path tempDir = Files.createTempDirectory(prefix);

Here, dir is a Path, and prefix/ suffix are strings which may be null. For
example, the call Files.createTempFile(null, ".txt") might return a path such as
/tmp/ 1234405522364837194.txt.

Files.copy(fromPath, toPath)
To replace destination and to copy all file attributes (we can provide them
together)
Files.copy(fromPath, toPath, StandardCopyOption.REPLACE_EXISTING,
StandardCopyOption.COPY_ATTRIBUTES);

Other options
READ, WRITE, APPEND, TRUNCATE_EXISTING, CREATE_NEW, CREATE, DELETE_ON_CLOSE,
SPARSE, SYNC|DSYNC
ATOMIC_MOVE, COPY_ATTRIBUTES, REPLACE_EXISTING
NOFOLLOW_LINKS
FOLLOW_LINKS

Files.delete(path) // throws exception if file does not exists


boolean deleted = Files.deleteIfExists(path); // preferred way

Files.list(path) // returns a Stream<Path>, this read stuff lazily, making it


efficient to process directories with large no of items
as this need system resources to be closed use list with a try with resources
block

list will not visit inside sub directories, we need to use walk method, which
visits all descendant in a depth first order

try (Stream <Path> entries = Files.walk(pathToRoot)) {


// Contains all descendants, visited in depth-first order
}

Second argument to walk method is deapth till which walk need to go


walk also takes in FileVisitOptions, one important to apply is
FileVisitOptions.FOLLOW_LINKS

Copying one directory to another


Files.walk(source).forEach( p -> {
try {
Path q = target.resolve(source.relativize(p));
if(Files.isDirectory(p))
Files.createDirectory(q);
else
Files.copy(p, q);
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
});

using walk() method to delete a directory tree is not possible because we first
need to delete the children,
Here we can use walkFileTree() method, this takes an object of FileVisitor
interface
And certain function of this object is called during certain events
1. Before a directory is processed:
FileVisitResult preVisitDirectory(T dir, IOException ex)

2. When a file or directory is encountered:


FileVisitResult visitFile(T path, BasicFileAttributes attrs)

3. When an exception occurs in the visitFile method:


FileVisitResult visitFileFailed(T path, IOException ex)

4. After a directory is processed:


FileVisitResult postVisitDirectory(T dir, IOException ex)

We can use these hooks to perform certain actions, and here are few objects of
FileVisitResult (return type of all hooks) that we can use to signal walkFileTree
method to perform some actions
If we return
FileVisitResult.CONTINUE // continue visiting next file
FileVisitResult.SKIP_SUBTREE // continue the walk but with out visiting the
entries in this directory
FileVisitResult.SKIP_SIBLINGS // continue walk but do not visit siblings of
this file
FileVisitResult.TERMINATE // terminate the walk

Here is a way to delete directory


Files.walkFileTree(root, new SimpleFileVisitor <Path>() {
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}

public FileVisitResult postVisitDirectory(Path dir, IOException ex) throws


IOException {
if (ex != null) throw ex;
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});

Processing ZIP files


FileSystem zipfs = FileSystems.newFileSystem(Paths.get(zipname), null);

If we want to copy a file from zip


Files.copy(zipfs.getPath(sourceName), targetPath);

To walk all files in a zip


Files.walk(zipfs.getPath("/")).forEach(p -> {
...Process p ...
});

Creating a zip file


Path zipPath = Paths.get("myfile.zip");
URI uri = new URI("jar", zipPath.toUri().toString(), null);

// Constructs the URI jar:file:// myfile.zip

try (FileSystem zipfs = FileSystems.newFileSystem(uri,


Collections.singletonMap("create", "true"))) {
// To add files, copy them into the ZIP file system
Files.copy(sourcePath, zipfs.getPath("/").resolve( targetPath));
}
To communicate with URL
Read from URL by calling the getInputStream method on an URL object. However,
if you want additional information about a web resource, or if you want to write
data, use the URLConnection class.

URLConnection connection = url.openConnection();

For an HTTP URL, the returned object is actually an instance of


HttpURLConnection.

If desired, set request properties:


connection.setRequestProperty("Accept-Charset", "UTF-8, ISO-8859-1"); // if
key has multiple values separate them by commas

To send data to server


connection.setDoOutput(true);
try (OutputStream out = connection.getOutputStream()) {
Write to out
}

If you want to read the response headers and you haven’t called
getOutputStream, call connection.connect();
Then query the header information:
Map <String, List <String>> headers = connection.getHeaderFields();

For each key, you get a list of values since there may be multiple header
fields with the same key.

Read the response


try (InputStream in = connection.getInputStream()) {
Read from in
}

The URLConnection class automatically sets the content type to application/x-


www-form-urlencoded when writing data to a HTTP URL, but you need to encode the
name/value pairs:

URL url = ...;


URLConnection connection = url.openConnection();
connection.setDoOutput(true);

try (Writer out = new OutputStreamWriter(connection.getOutputStream(),


StandardCharsets.UTF_8)) {
Map <String, String> postData = ...;
boolean first = true;
for (Map.Entry <String, String> entry : postData.entrySet()) {
if (first) {
first = false;
}
else {
out.write("&");
}

out.write(URLEncoder.encode(entry.getKey(), "UTF-8"));
out.write("=");
out.write(URLEncoder.encode(entry.getValue(), "UTF-8"));
}
}

try (InputStream in = connection.getInputStream()) {


...
}

Regular Expression
Check if a string conforms to a pattern
String regex = "[+-]?\\d+";
CharSequence input = ...;
if(Pattern.matches(regex, input)) {
...
}

We can compile a regular expression if that need to be used multiple times


Pattern pattern = Pattern.compile(regex);
Matcher matcher = Pattern.matcher(input);
if(matcher.matches()) {
...
}

If we need to filter a Stream using a regex then we can turn it into predicate

Stream<String> strings = ...;


Stream<String> result = strings.filter(pattern.asPredicate());

To find all matches of a pattern in an input string


Matcher matcher = Pattern.matcher(input);
while(matcher.find()) {
String match = matcher.group();
...
}

We can refer a match for a specific capture group n using


matcher.group(n)
group(0) is the whole string

Posix character classes for java regex


POSIX character classes (US-ASCII only)
\p{Lower} A lower-case alphabetic character: [a-z]
\p{Upper} An upper-case alphabetic character:[A-Z]
\p{ASCII} All ASCII:[\x00-\x7F]
\p{Alpha} An alphabetic character:[\p{Lower}\p{Upper}]
\p{Digit} A decimal digit: [0-9]
\p{Alnum} An alphanumeric character:[\p{Alpha}\p{Digit}]
\p{Punct} Punctuation: One of !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
\p{Graph} A visible character: [\p{Alnum}\p{Punct}]
\p{Print} A printable character: [\p{Graph}\x20]
\p{Blank} A space or a tab: [ \t]
\p{Cntrl} A control character: [\x00-\x1F\x7F]
\p{XDigit} A hexadecimal digit: [0-9a-fA-F]
\p{Space} A whitespace character: [ \t\n\x0B\f\r]

java.lang.Character classes (simple java character type)


\p{javaLowerCase} Equivalent to java.lang.Character.isLowerCase()
\p{javaUpperCase} Equivalent to java.lang.Character.isUpperCase()
\p{javaWhitespace} Equivalent to java.lang.Character.isWhitespace()
\p{javaMirrored} Equivalent to java.lang.Character.isMirrored()
Classes for Unicode scripts, blocks, categories and binary properties
\p{IsLatin} A Latin script character (script)
\p{InGreek} A character in the Greek block (block)
\p{Lu} An uppercase letter (category)
\p{IsAlphabetic} An alphabetic character (binary property)
\p{Sc} A currency symbol
\P{InGreek} Any character except one in the Greek block (negation)
[\p{L}&&[^\p{Lu}]] Any letter except an uppercase letter (subtraction)

We can name the capture groups


(?<item>\p{Alnum}+(\s+\p{Alnum}+)*)\s+(?<currency>[A-Z]{3})(?<price>[ 0-9.]*)

Now we can refer like group("item")

Using split to split strings


Pattern commas = Pattern.compile("\\s*,\\s*");
String[] tokens = commas.split(input); // "1, 2, 3" turns into ["1", "2", "3"]

if there are many tokens (split parts) then we can create a stream and fetch
them lazily

Stream <String> tokens = commas.splitAsStream(input);

or we can use String::split if we do not want to compile or produce stream


String[] tokens = input.split("\\s*,\\s*");

If we want to replace
Matcher matcher = commas.matcher(input);
String result = matcher.replaceAll("|");

or

String result = input.replaceAll("\\s*,\\s*", "|");

Advance replace using groups


String result = "3:45".replaceAll("(\\d{1,2}):(?<minutes>\\d{2})", "$1 hours
and ${minutes} minutes");
//returns 3 hours 45 minutes

Regex flags
provide during compilation
Pattern.compile(regex, Pattern.CASE_INSENSITIVE |
Pattern.UNICODE_CHARACTER_CLASS);

or put it in the pattern


String regex = "(?iU:expression)";

Pattern.CASE_INSENSITIVE or i: Match characters independently of the letter


case. By default this flag takes only US ASCII characters into account
Pattern.UNICODE_CASE or u: When used in combination with CASE_INSENSITIVE,
use Unicode letter case for matching.
Pattern.UNICODE_CHARACTER_CLASS or U: Select Unicode character classes
instead of POSIX. Implies UNICODE_CASE.
Pattern.MULTILINE or m: Make ^ and $ match the beginning and end of a line,
not the entire input.
Pattern.UNIX_LINES or d: Only '\n' is a line terminator when matching ^ and $
in multiline mode.
Pattern.DOTALL or s: Make the . symbol match all characters, including line
terminators.
Pattern.COMMENTS or x: Whitespace and comments (from # to the end of a line)
are ignored.
Pattern.LITERAL: The pattern is taking literally and must be matched exactly,
except possibly for letter case.
Pattern.CANON_EQ: Take canonical equivalence of Unicode characters into
account. For example, u followed by ¨ (diaeresis) matches ü.

Serializing or Marshalling an Object


To make an object serializable the class should implement a Serializable.

To achieve perfect serialization all instance variables should be primitive, enum


or objects whose class also implements the Serializable interface
Serializable interface is a marker interface as it does not have any classes.

To serialize we need an ObjectOutputStream, which will be backed by other


OutputStream to write/save

ObjectOutputStream out = new ObjectOutputStream(Files.newOutputStream(path));

// then use the out to write

Employee peter = new Employee("Peter", 7000);


Employee joe = new Employee("Joe", 8000);

out.writeObject(peter);
out.writeObject(joe);

To read the object back


ObjectInputStream in = new ObjectInputStream(Files.newInputStream(path));
Employee el = (Employee) in.readObject();
Employee el2 = (Employee) in.readObject();

If same object is referred by multiple objects then during serialization it is


not written twice rather they are written only once and they maintain an unique
serial number which during retrieval make sure they are created only once. All
primitive data are written in binary format.

We might wish to not include some information when serializing like database
connection or some cached value. Mark those member as 'transient' modifier and it
will not be part of serialization process, the same need to be done for non
serializable members

To tweak searialization method define two methods with following signature


private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException
private void writeObject(ObjectOutputStream out) throws IOException

Then, the object headers continue to be written as usual, but the instance
variables fields are no longer automatically serialized. Instead, these methods are
called.

For example say we are using the Point2D class's object which are not
serializable, we can use the following trick to make them serializable
First make the member transient
public class LabeledPoint implements Serializable {
private String label;
private transient Point2D point;
...
}
then implement the following stuff
First write the non transient stuff
then save information to re create the transient object later

private void writeObject(ObjectOutputStream out) throws IOException {


out.defaultWriteObject(); // this will write all the non transient members,
this is a special method and should only be called from writeObject
out.writeDouble(point.getX());
out.writeDouble(point.getY());
}

private void readObject(ObjectInputStream in) throws IOException,


ClassNotFoundException {
in.defaultReadObject(); // read all automatically written stuff
double x = in.readDouble();
double y = in.readDouble();
point = new Point2D(x, y);
}

Create a singleton class by creating a single enum


public enum PersonDatabase {
INSTANCE;

public Person findById(int id) {


...
}
}

As enum objects are constructed only once using a private constructor, so it is


by definition is singleton

If we want to mask the serialization process and use the same behavior to
serialize something else, we can return a proxy of the object from a method named
writeReplace
this is not the proxy as we saw earlier

public class Person implements Serializable {


private int id; // Other instance variables
...
private Object writeReplace() {
return new PersonProxy(id);
}
}

The proxy class should implement a readResolve which will get the id
information when constructed and readResolve will be called during de-serialization

public class PersonProxy implements Serializable {


private int id;
public PersonProxy(int id) {
this.id = id;
}

public Object readResolve() {


// fetch the object from database or something
return PersonDatabase.INSTANCE.findById(id);
}
}

Versioning
Suppose after creation of a object dump the class was changed, may be the new
version of the class does not support the old dump to be restored any more. To keep
versioning of class we can add a property
public static final long serialVersionUID = 1L; // version 1

During serialization this information is kept and later checked during de-
serialization. If not same then a InvalidClassException will be thrown. If not
provided this value will be automatically calculated using the hash values of all
non transient members. The developer may wish to keep the version number same even
if class changed very much. If the version matches then the non-transient members
will be written, all extra members will be set to the default value
zero/false/null, all extra information read but do not correspond to an actual
member will be ignored.

If you want to implement a more sophisticated versioning scheme, override the


readObject method and call the readFields method instead of the defaultReadObject
method. You get a description of all fields found in the stream, then do what ever
required.

Thread - Concurrent Execution


In Java tasks are specified using Runnable interface
public interface Runnable {
void run();
}

The code for run method will be executed in a thread.

In Java an executor executes the tasks

Runnable task = () -> { ... };


Executor exec = ...;
exec.execute(task);

There are different factory methods to get different kind of executor


exec = Executor.newCachedThreadPool();

This yields an executor optimized for programs which are short lived and
mostly spend its time sitting idle. Each task is executed on an idle thread if
possible, but a new thread is allocated if all threads are busy. Threads that are
idle for an extended time are terminated.

exec = Executor.newFixedThreadPool(nTHreads);

This will yield a pool with a fixed number of threads. When you submit a
task, it is queued up until a thread becomes available. This is a good choice for
computationally intensive tasks. You can derive the number of threads from the
number of available processors, which you obtain as

int processors = Runtime.getRuntime().availableProcessors();

Concurrency
public static void main(String args[]) {
Runnable hellos = () -> {
for(int i = 0; i < 1000; i++) {
System.out.println("Hello " + (i+1));
}
};

Runnable goodByes = () -> {


for(int i = 1; i <= 1000; i++) {
System.out.println("Good byte" + i);
}
};

Executor executor = Executor.newCachedThreadPool();


executor.execute(hellos);
executor.execute(goodByes);
}

Future object
If we need to return some value then we need to use Callable interface

public interface Callable<V> {


V call() throws Exception;
}

It can throw exceptions as well, then we need to use ExecutorService interface


to execute Callable objects.
ExecutorService exec = Executors.newFixedThreadPool();
Callable <V> task = ...;
Future <V> result = exec.submit( task);

ExecutorService returns a Future object which will give data at some future
time
V get() throws InterruptedException, ExecutionException

V get(long timeout, TimeUnit unit) throws InterruptedException,


ExecutionException, TimeoutException;

boolean cancel(boolean mayInterruptIfRunning)


boolean isCancelled()
boolean isDone()

get() is a blocking call which can wait until Future value produces some
result of times out
cancel() method attempts to cancel the task, if not running it won't be
scheduled, if running and "mayInterruptIfRunning" is set to "true"

To make a task interruptible we need to check for interrupt periodically


Callable <V> task = () -> {
while (more work to do) {
if (Thread.currentThread().isInterrupted()) {
return null;
}

Do more work
}
return result;
};

If we have a collection of Callable objects then we can call invokeAll on


them
Here is a code segment which will get number of occurrences of a word in a
set of files
String word = ...;
Set <Path> paths = ...; // set of path to files where the counting needs to
be done

List <Callable<Long>> tasks = new ArrayList <>();


for (Path p : paths)
tasks.add(() -> {
return number of occurrences of word in p
});
List <Future<Long>> results = executor.invokeAll(tasks); // invokeAll will
invoke all callable of a Collection
long total = 0;

for (Future <Long> result : results) {


total + = result.get();
}

If we want to process the output of any Callable as soon as it is available,


instead of waiting for a large task where a small task is already complete but we
are stuck at get() method of the long task. We can use ExecutorCompletionService,
it returns the future objects in the order of completion.

ExecutorCompletionService service = new


ExecutorCompletionService(executor);
for(Callback<T> task : tasks) {
service.submit(task);
}

for(int i = 0; i < tasks.size(); i++) {


Process service.take().get(); // here we are not using the for loop index
at all, the take() method should be able to return proper future instance
}

invokeAny()
invokeAny is similar to invokeAll but it will return as soon as one of task
is submitted (or completed??) with out throwing error, it will cancel other tasks.
It will return the Future object for the submitted task

The following will locate a file containing a words


String word = ...;
Set <Path> files = ...;
List <Callable<Path>> tasks = new ArrayList <>();
for (Path p : files) {
tasks.add(() -> {
if (word occurs in p)
return p;
else
throw ...
});
}

Path found = executor.invokeAny(tasks);

Concurrency Issues and solution


Visibility
private static boolean done = false;
public static void main(String[] args) {
Runnable hellos = () -> {
for (int i = 1; i <= 1000; i++)
System.out.println(" Hello " + i);

done = true;
};

Runnable goodbye = () -> {


int i = 1;

while (!done)
i++;

System.out.println("Goodbye " + i);


};

Executor executor = Executors.newCachedThreadPool();


executor.execute(hellos);
executor.execute(goodbye);
}

In this case the goodbye() task will for the hellos() task to complete
because at the end hellos will switch done flag to true which will let goodbye() to
get out of an endless loop. The goodbye will print the goodbye message only once.

But the problem here is after the code optimization by compiler and VM and
also due to usage of processor cache the variable ("done") change may not be
visible to the goodbye task and it will run endlessly.

The solution to establish visibility is to make the variable final, volatile


or static

Here we will make it "public static volatile boolean done;"

Race condition
When more than one thread is modifying a resource, it can lead to race
condition, think of the following situation

for (int i = 1; i <= 100; i++) {


int taskId = i;
Runnable task = () -> {
for (int k = 1; k <= 1000; k++)
count++;

System.out.println( taskId + ": " + count);


};
executor.execute(task);
}

Here we are trying to spawn 100 threads which are trying to modify the
counter variable, we will see output like this
At starting
1: 1000
3: 2000
2: 3000
6: 4000
After a while, it looks a bit scary:
72: 58196
68: 59196
73: 61196
71: 60196
69: 62196

We can see already we are getting inconsistent value because of race


condition

Strategies for parallel execution


confinement - try not to share data between tasks, it is better to have one
final task which will combine the result
immutability - use immutable objects and ultimately combine them
locking - lock the resource modification as critical path, but this could
also lead to dead lock and less efficient parallelism

Designing immutable data structures


Be sure to declare instance variables final. There is no reason not to, and
you gain an important advantage. The virtual machine ensures that a final instance
variable is visible after construction.

Of course, none of the methods can be mutators. You may want to make them
final, or declare the class final, so that methods can’t be overridden with
mutators.

Don't leak mutable state, none of the private method should return mutable
state of internal data structure, also while calling other methods of other classes
it should not pass such references.

Don’t let the this reference escape in a constructor. In the constructor do


not expose this, so other can view the data structure in an incomplete state.
Examples are starting a thread in a constructor whose Runnable is an inner
class (which contains a this reference), or, when constructing an event listener,
adding this to a queue of listeners. Simply take those actions after construction
has completed.

Some of the Arrays parallel algorithm


fills an array with values computed by a function.
Arrays.parallelSetAll(values, i -> i % 10);

parallel sort
Arrays.parallelSort(words, Comparator.comparing(String::length));
Arrays.parallelSort(values, values.length/2, values.length); // Sort the
upper half

For other parallel operations on arrays, turn them into streams.

The collections in the java.util.concurrent package have been cleverly


implemented so that multiple threads can access them without blocking each other,
provided they access different parts. These collection give out weakly consistent
iterators which will iterate only on a part of data structure that is currently
visible to current thread and will not throw a ConcurrentModificationException if
the collection is modified elsewhere, this is thrown by normal iterators.

ConcurrentHashMap
A ConcurrentHashMap is, first of all, a hash map whose operations are
threadsafe. No matter how many threads operate on the map at the same time, the
internals are not corrupted. May be some thread get temporarily blocked.
But the primitive variables used as values are not thread safe, so again if
we modify the "value" from more than one thread it will be messed
ConcurrentHashMap <String, Long> map = new ConcurrentHashMap <>();
...
Long oldValue = map.get(word);
Long newValue = oldValue == null ? 1 : oldValue + 1;
map.put(word, newValue); // Error— might not replace oldValue

Here we are trying to find the frequency of words in a parallel fashion.


This is not thread safe. Instead we should use compute method which does atomic
operation

map.compute(word, (k, v) -> v == null ? 1 : v + 1);

It is called with a key and a function to compute the new value. That
function receives the key and the associated value, or null if there is none, and
computes the new value.

There are also variants computeIfPresent and computeIfAbsent that only


compute a new value when there is already an old one, or when there isn’t yet one.

Another atomic operation is putIfAbsent. A counter might be initialized


as
map.putIfAbsent(word, 0L);

merge
map.merge(word, 1L, (existingValue, newValue) -> existingValue +
newValue);

If the value does not exists it will use the second argument to
initialize it and if present it will call the lambda passed as third argument

Blocking Queue
This can be used to co-ordinate data between two tasks. Producer tasks
insert items into the queue, and consumer tasks retrieve them.
When you try to add an element and the queue is currently full, or you try
to remove an element when the queue is empty, the operation blocks. In this way,
the queue balances the workload. If the producer tasks run slower than the consumer
tasks, the consumers block while waiting for the results. If the producers run
faster, the queue fills up until the consumers catch up.

Methods
puts -> adds an element to tail, blocks if queue is full
take -> remove from head, block if empty
add -> add element to tail, throw exception if full
remove -> remove from head, throw exception if empty
element -> return the head element, throw exception if empty
offer -> add an element and return true, return false otherwise
poll -> remove and return the head element, return null if empty
peek -> Returns the head element, return null if empty

offer with timeout


boolean success = q.offer(x, 100, TimeUnit.MILLISECONDS); // will wait
for 100ms if queue is full

poll with timeout


Object head = q.poll(100, TimeUnit.MILLISECONDS);

A LinkedBlockingQueue is based on a linked list, and an ArrayBlockingQueue


uses a circular array.

Other Thread safe data structure


ConcurrentSkipListMap
ConcurrentSkipListSet
CopyOnWriteArrayList
CopyOnWriteArraySet
ConcurrentHashSet
ConcurrentHashMap

Atomic Datatypes
java.util.concurrent.atomic package provides some classes which uses safe and
efficient machine level instructions to facilitate atomic operations
Counter can be created easily
public static AtominLong nextNumber = new AtomicLong();

//in some thread


long id = nextNumber.incrementAndGet(); // this will increment the value and
return it, when incrementing it won't be interrupted

If we want to keep the largest value following would be an incorrect approach


public static AtomicLong largest = new AtomicLong();

// In some thread
largest.set(Math.max(largest.get(), observed)); // race condition

instead use
largest.updateAndGet(x -> Math.max(x, observed));
- or -
largest.accumulateAndGet(observed, Math::max);

Some of the classes we can use


AtomicInteger
AtomicIntegerArray
AtomicIntegerFieldUpdater
AtomicLongArray
AtomincLongFieldUpdater
AtomicReference
AtomicReferenceArray
AtomicReferenceFieldUpdater

When very large number of threads simultaneously accessing a value update


operations performance can suffer

LongAdder can be used to upgrade performance in this case instead of


AtomingLong
LongAdder has increment method, add() to add some value, sum() to retrieve
total

Locks
Locks can be used to implement thread safe data-structure, it is the way to
implement critical section

Lock countLock = new ReentrantLock(); // shared among multiple threads


int count; // shared variable
...
countLock.lock();
try {
count++;
}
finally {
countLock.unlock();
}

In java locking is done with intrinsic lock, we naturally do not need to lock
explicitly like above, it is more natural to use synchronized key word,

synchronized(obj) {
// critical section
}

The above is equivalent to


obj.intrinsicLock.lock()
try {
critical section
} finally {
obj.intrinsicLock.unlock()
}
If we declare a method as synchronized, then its body is locked on receiver
parameter this.

public synchronized void method() {


body
}

Declaring a counter
public class Counter {
private int value;
public synchronized int increment() {
value++;
return value;
}
}

Synchronized also effects visibility


In the visibility problem we saw that we were not able to share data between
threads if we do not make it Volatile.

If both the getter and setter of the variable is synchronized then both will
see the value

Going back to the problem of controlling two threads using queue, where one
thread was producer and one thread was consumer. We saw blocking queue had a method
called take() which actually blocks the process if the queue is empty and waits
till some producer can push some value to queue. If we want to implement that we
need to do some thing like this
public synchronized Object take() throws InterruptedException {
while(head == null) wait();
...
}

wait() method will make sure that the consumer will be blocked till one value
is pushed to queue, and it will also gives up the lock, this is called waiting on a
condition.

A thread called wait() will go into wait state until some one calls notifyAll()
method.
public synchronized void add(Object newValue) {
...
notifyAll();
}

This will signal waiting threads which will be scheduled again. But they can
again go to wait if the condition is not yet fulfilled. notifyAll() will just wake
them up, but it is up to them to get out of loops lile
if(head == null) wait();

notify() will unblock a single thread but if the unblocked thread again goes to
wait() then it can generate a deadlock

Thread
If we want to use raw threads instead of executing through executor

Runnable task = () -> { ... };


Thread thread = new Thread(task);
thread.start();

To make a thread sleep we can call the static sleep() method from with in thread
body
Runnable task = () -> {
...
Thread.sleep(millis);
}
It will sleep for the provided milliseconds

If you want to wait for a thread to finish, call the join method:
thread.join(millis);

We can use thread interruption to cancel a thread, (for situations when we may be
satisfied with the first positive search result and we want to cancel all other
search request)

Runnable task = (). -> {


while(more work to do) {
if(Thread.currentThread().isInterrupted) {
return;
}

... or do what ever we want to do


}
}

We need to keep an eye on the interruption if we are expecting the thread to be


interrupted
If a thread is in sleeping state and then it gets an interruption then it will
woke up immediately and raise an InterruptedException we can catch it in the run
method

Runnable task = (). -> {


try {
while(more work to do) {
if(Thread.currentThread().isInterrupted) {
return;
}

... or do what ever we want to do


}
} catch(InterruptedException ex) {
// do nothing
}
}

If we get an InterruptedException from sleep() we should set the status of


current thread,

try {
Thread.sleep(millis)
} catch(InterruptedException ex) {
Thread.currentThread().interrupted();
}

Thread Local Variables


Through this we can create instance of an class once per thread to remove data
sharing or corruption of data structure due to concurrency

For example
public static final NumberFormat currencyFormat =
NumberFormat.getCurrencyInstance();

Now NumberFormat class is not thread and if this is used to format currency
in different the internal data structure may get corrupted.

We can do

public static final ThreadLocal<NumberFormat> currencyFormat =


ThreadLocal.withInitial(() -> NumberFormat.getCurrencyInstance());

To access the actual formatter

String amountDue = currencyFormat.get().format(total);

The first time the get() method will be called it will used the lambda to
create an instance and return that instance every time else inside a thread.

CompletableFuture is the equivalent to JavaScript promises in Java

Process
To run a separate program use the ProcessBuilder and Process classes. The
Process class executes a command in a separate operating system process and lets
you interact with its standard input, output, and error streams. The ProcessBuilder
class lets you configure a Process object.

First create ProcessBuilder object

ProcessBuilder builder = new ProcessBuilder("gcc", "myapp.c");


// here we can also pass a List<String>

The first string must be an executable command, not a shell builtin. Shell
builtins need to be executed using shell executable

By default, a process has the same working directory as the virtual machine,
which is typically the directory from which you launched the java program. We can
use the directory method to change this

builder = builder.directory(path.toFile());
Each method of ProcessBuilder returns itself so we can chain commands
Process p = new ProcessBuilder(command).directory(file).... start();

Getting all the streams


OutputStream processIn = p.getOutputStream();
InputStream processOut = p.getInputStream();
InputStream processErr = p.getErrorStream();

To redirect these streams to files


builder.redirectInput(inputFile)
.redirectOutput(outputFile)
.redirectError(errorFile)

These files will be truncated for each process, to append use


builder.redirectOutput(ProcessBuilder.Redirect.appendTo(outputFile));

Merge the output and error stream


builder.redirectErrorStream(true)

To set environment variables


Map <String, String> env = builder.environment();
env.put("LANG", "fr_FR");
env.remove("JAVA_HOME");
Process p = builder.start();

Starting process
Process p = new ProcessBuilder("/bin/ls", "-l")
.directory(Paths.get("/tmp").toFile())
.start();
try (Scanner in = new Scanner(p.getInputStream())) {
while (in.hasNextLine())
System.out.println(in.nextLine());
}

Wait for the process to be finished

int result = p.waitFor();

If we do not want to wait for infinity

long delay = ...;


if (p.waitfor(delay, TimeUnit.SECONDS)) {
int result = p.exitValue(); // check if it was completed successfully
...
} else {
p.destroyForcibly(); // send SIGKILL; destroy() only will send SIGTERM
}

Annotations
Annotation can be used like modifiers. They can be used to provide some
information to some system regarding the annotated method, class or variable

public class CacheTest {


...
@Test public void checkRandomInsertion()
}

The @Test annotations are used by Junit, which will call methods which are
annotated with @Test

We can also pass value it is upto the reader of annotation to process this
@Test(timeout=10000)

An annotation element is one of the followings


primitive
String
object of a Class
instance of Enum
An annotation
An array of preceding (but not an array of arrays)

Example
@BugReport(showStopper=true, assignedTo="Harry", testCase=CacheTest.class,
status=BugReport.Status.CONFIRMED);

null is not supported to be a value

Annotation elements can have default value, like for timeout of @Test the
default value is 0L
so @Test is equivalent to @Test(timeout=0L)

If the property name is value and that is the only value we need to pass then
we do not need to specify that
@SuppressWarnings("unchecked") this is equivalent to
@SuppressWarnings(value="unchecked")

To specify array
@BugReport(reportedBy=("Harry", "Fred"))

if a single value even for array then we do not need to give parenthesis

To specify another Annotation


@BugReport(ref=@Reference(id=1234), ...)

Multiple and Repeated Annotations


@Test @BugReport(...) public void ...()

If the author allows we can repeat the annotation

@BugReport (...) @BugReport(...) public void ... ()

Annotation can be applied with


Class (before class keyword)
@Entity public class User { ... }

Variables (before type)


@SuppressWarnings("unchecked") List <User> users = ...;
public User getUser(@Param("id") String userId)

Type parameter in generic class/method


public class Cache<@Immutable V> { ... }

A package is annotated in a file package-info.java that contains only the


package statement preceded by annotations.
/**
Package-level Javadoc
*/
@GPL(version="3")
package com.horstmann.corejava;
import org.gnu.GPL;

Annotations for local variables and packages are discarded when a class is
compiled. Therefore, they can only be processed at the source level.

Uses of annotating types


public User getUser(@NonNull String userId)

here userId will be asserted as not null, this annotation is a part of


CheckerFramework. With this we can include assertion in the program.

Places where type annotations can appear


Generic : List <@NonNull String>
For Arrays :
@NonNull String[][] words (words[i][ j] is not null),
String @NonNull[][] words (words is not null),
String[] @NonNull [] words (words[i] is not null).

while extending super classes or implementing interfaces


class Warning extends @Localized Message

while invoking constructor


new @Localized String(...)

for nested type


Map.@Localized Entry

With casts and instanceof checks:


(@Localized String) text,
if (text instanceof @Localized String).

With exception specifications:


public String read() throws @Localized IOException.

With wildcards and type bounds:


List <@Localized ? extends Message>,
List <?extends @Localized Message>

With method and constructor references:


@Localized Message::getText.

Few location where it is not possible to use annotation


@NonNull String.class // Error— cannot annotate class literal
import java.lang.@NonNull String; // Error— cannot annotate import

If we are using instance method then the arguments can be easily annotated but
the object on top of which the method is getting called is difficult to annotate.
There is a syntax to do this
public class Point {
public boolean equals(@ReadOnly Point this, @ReadOnly Object other);
}

Here the first argument need to be named "this" which is referencing the self.
This is not possible to do with constructors

Defining annotation
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)

public @interface Test {


long timeout() default 0L; // default is optional and this provides the
default value
// to represent empty array in default we do "default {}"
...
}

The @interface will declare an actual interface. Tools which will process the
annotation will actually get an object which implements the annotation interface.

Each of the element in annotation are actually different methods, but they can
not have
- any arguments
- any throw clause
- any generic type

Target and Retention are two meta annotations

Target specifies on which type of elements this annotation can be used, this
takes in an array of ElementType objects

@Target({ElementType.TYPE, ElementType.METHOD})

ElementType has following constants


ANNOTATION_TYPE - Annotation type declaration
PACKAGE
TYPE - Class and interfaces and enum
METHOD
CONSTRUCTOR
FIELD - instance variables
PARAMETER - Method and consturctor parameters
LOCAL_VARIABLE
TYPE_PARAMETER
TYPE_USE - Uses of a type

The @Retention meta-annotation specifies where the annotation can be


accessed. There are three choices.
1. RetentionPolicy.SOURCE: The annotation is available to source
processors, but it is not included in class files.

2. RetentionPolicy.CLASS: The annotation is included in class files, but


the virtual machine does not load them. This is the default.

3. RetentionPolicy.RUNTIME: The annotation is available at runtime and can


be accessed through
the reflection API.

You cannot extend annotation interfaces, and you never supply classes that
implement annotation interfaces. Instead, source processing tools and the virtual
machine generate proxy classes and objects when needed.

Standard Annotations
Override - Checks that a method overrides a superclass method
Deprecated - Marks item as deprecated, applicable to all
SuppressWarnings - Suppress warnings of a given type (all except package)
SafeVarargs - Asserts that the varargs parameters are safe to use (methods and
constructors)
FunctionalInterface - Marks an interface as functional (interfaces)
@FunctionalInterface
public interface IntFunction<R> {
R apply(int value);
}
PostConstruct/PreDestroy - The method should be invoked immediately after
construction or before removal of an injected object (methods)
used in environments that control the lifecycle of objects, such as web
containers and application servers. Methods tagged with these annotations should be
invoked immediately after an object has been constructed or immediately before it
is being removed.
Resource - On a class or interface, marks it as a resource to be used
elsewhere. On a method or field marks it for dependency injection.
Resources - Specifies an array of resources
The @Resource annotation is intended for resource injection. For example,
consider a web application that accesses a database. Of course, the database access
information should not be hardwired into the web application. Instead, the web
container has some user interface for setting connection parameters and a JNDI name
for a data source. In the web application, you can reference the data source like
this:

@Resource(name ="jdbc/ employeedb")


private DataSource source;

Generated - Marks an item as source code that has been generated by a tool
A code editor can hide the code or a code generator can remove older version
of generated code, each annotation must contain a unique identifier for the code
generator. A date string and a comment string is optional
@Generated(value="com.xyz.generator", date="2015-01-04T12:08:56.235-0700")
Target - Specifies the location to which this annotation need to be applied
(meta)
Retention - Where this annotation can be used (meta)
Documented - specifies this annotation should be included in the documentation
of annotated items(meta)
Inherited - Specifies that this annotation is inherited by subclasses (meta)
The @Inherited meta-annotation applies only to annotations for classes. When
a class has an inherited annotation, then all of its subclasses automatically have
the same annotation. This makes it easy to create annotations that work similar to
marker interfaces (such as the Serializable interface). Suppose you define an
inherited annotation @Persistent to indicate that objects of a class can be saved
in a database. Then the subclasses of persistent classes are automatically
annotated as persistent.
@Inherited @interface Persistent {}
@Persistent class Employee { . . . }
class Manager extends Employee { . . . } // Also @Persistent

Repeatable - specifies this can be applied multiple times (meta)


@TestCase(params ="4", expected ="24")
@TestCase(params ="0", expected ="1")
public static long factorial(int n) { ... }

the implementor of a repeatable annotation needs to provide a container


annotation that holds the repeated annotations in an array.

@Repeatable(TestCases.class)
@interface TestCase {
String params();
String expected();
}

@interface TestCases {
TestCase[] value();
}
Processing an annotation at run time
one can write a generic toString method using reflection that simply includes
all instance variable names and values. But suppose we want to customize that
process. We may not want to include all instance variables, or we may want to skip
class and variable names. For example, for the Point class we may prefer [5,10]
instead of Point[ x = 5, y = 10].

@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ToString {
boolean includeName() default true;
}

Annotate class
@ToString(includeName=false)
public class Point {
@ToString(includeName=false) private int x;
@ToString(includeName=false) private int y;
...
}

@ToString
public class Rectangle {
@ToString(includeName=false) private Point topLeft;
@ToString private int width;
@ToString private int height;
...
}

The intent is that rectangle objects will be represented as Rectangle[[5,10],


width=20,height=30]
At runtime, we cannot modify the implementation of the toString method for a
given class. Instead, let us provide a method that can format any object,
discovering and using the ToString annotations if they are present.

Here are some methods provided by AnnotatedElement interface


T getAnnotation(Class <T>)
T getDeclaredAnnotation( Class <T>)
T[] getAnnotationsByType( Class <T>)
T[] getDeclaredAnnotationsByType( Class <T>)
Annotation[] getAnnotations()
Annotation[] getDeclaredAnnotations()

* the methods with "declared" in its name only get the annotation declared in
current item and not the inherited annotations, other will include inherited
annotations as well

Get the annotations ToString


Class cl = obj.getClass();
ToString ts = cl.getAnnotation(ToString.class); // getAnnotation is used to
get non repeated annotations
if(ts != null && ts.includeName()) ...

getAnnotation will return null if no annotations are present


for repeated annotation we should call getAnnotationsByType (if we call
getAnnotation we will get null) this returns array of annotations.

getAnnotations get all the annotations with the repeatable annotations


wrapped into containers.

public class ToStrings {


public static String toString(Object obj) {
if(obj -- null) return null;
Class<?> cl = obj.getClass();
ToString ts = cl.getAnnotation(ToString.class);
if(ts == null) return obj.toString();
StringBuilder result = new StringBuilder();
if(ts.includeName()) result.append(cl.getName());
result.append("[");
boolean first = true;
for(Field f : cl.getDeclaredFields()) {
ts = f.getAnnotation(ToString.class);
if(ts != null) {
if(first) first = false; else result.append(", ");
f.setAccessible(true);
if(ts.includeName()) { // checking the includeName property of the
annotation
result.append(f.getName());
result.append("=");
}
try {
result.append(ToString.toString(f.get(obj)));
} catch (ReflectiveOperationException ex) {
ex.printStackTrace();
}
}
}
result.append("]");
return result.toString();
}
}

When a class is annotated with ToString, the method iterates over its fields
and prints the ones that are also annotated. If the includeName element is true,
then the class or field name is included in the string.

Source Level Annotation Processing


We can generate code/configuration/scripts/others using annotation processing
during compilation

javac -processor ProcesserClassName1, ProcessorClassName2... sourcefiles

The compiler locates the annotations of the source files. 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.

An annotation processor implements the Processor interface by extending


AbstractProcessor.
@SupportedAnnotationTypes("com.xyz.annotations.ToString")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class ToStringAnnotationProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement) annotations,
RoundEnvironemnt currentRound) {
...
}
}

A processor can claim specific annotation types


"com.horstmann.*" all annotation in the package or any sub package
"*" all annotations

The process method is called once for each round, with the set of all
annotations that were found in any files during this round, and a RoundEnvironment
reference that contains information about the current processing round.

The language model API is used to analyze source code annotations. Compiler
produces a tree whose nodes are instances of classes that implement the
javax.lang.model.element.ELement interface and its subinterfaces TypeElement,
VariableElement, ExecutableElement and so on. The compile time analogs are
Class(Type). Field/Parameters(Variable), Method/Constructor (Executable)

Some details of this API


The RoundEnvironment gives you a set of all elements annotated with a
particular annotation, by calling the method
Set<? extends Element> getElementsAnnotatedWith(Class<? extends Annotation>
a)

AnnotateElement interface equivalent here is AnnotatedConstruct


A getAnnotation(Class<A> annotationType)
- and -
A[] getAnnotationsByType(Class<A> annotationType)

A TypeElement represent a class or interface. The getEnclosedElements method


yields a list of its fields and methods

Calling getSimpleName on an Element or getQualifiedName on a TypeELement yields


a Name object that can be converted to a string with toString()

Implementing ToString at compile level


as annotation can not modify existing source code we need to have a new class
ToString where we will add the methods

public class ToStrings {


public static String toString(Point obj) {
generated code
}

public static String toString(Rectangle obj) {


generated code
}

...
public static String toString(Object obj) {
return Object.toString(obj);
}
}
Now here is how we do it
We don't want to use reflection, we annotate accessors methods, not fields

@ToString
public class Rectangle {
...
@ToString(includeName=false) public Point getTopLeft() {
return topLeft;
}

@ToString public int getWidth() {


return width;
}

@ToString public int getHeight() {


return height;
}
}

The annotation process should generate the following code

public static String toString(Rectangle obj) {


StringBuilder result = new StringBuilder();
result.append("Rectangle");
result.append("[");
result.append(toString(obj.getTopLeft()));
result.append(",");
result.append("width =");
result.append(toString(obj.getWidth()));
result.append(","); result.append("height =");
result.append(toString(obj.getHeight()));
result.append("]");
return result.toString();
}

Following is an outline of method that produces the toString method for a


specific TypeELement (Class/interface)

private void writeToStringMethod(PrintWriter out, TypeElement te) {


String className = te.getQualifiedName().toString();
// -> Print method header and declaration of string builder
ToString ann = te.getAnnotation(ToString.class);
if (ann.includeName()) // -> Print code to add class name
for (Element c : te.getEnclosedElements()) {
ann = c.getAnnotation(ToString.class);
if (ann != null) {
if (ann.includeName()) // -> Print code to add field name
// -> Print code to append toString( obj.methodName())
}
}
// -> Print code to return string
}

Following is the outline of process method, this will create the source file
for the helper class and writes the class header and one method for each annotated
class

public boolean process(Set <? extends TypeElement > annotations,


RoundEnvironment currentRound) {
if (annotations.size() == 0) return true;
try {
JavaFileObject sourceFile = processingEnv.getFiler().
createSourceFile("com.horstmann.annotations.ToStrings");
try (PrintWriter out = new PrintWriter( sourceFile.openWriter())) {
// -> Print code for package and class
for (Element e : currentRound.getElementsAnnotatedWith( ToString.class))
{
if (e instanceof TypeElement) {
TypeElement te = (TypeElement) e;
writeToStringMethod(out, te);
}
}
//-> Print code for toString(Object)
} catch (IOException ex) {
processingEnv.getMessager().printMessage(Kind.ERROR, ex.getMessage());
}
}
return true;
}

S-ar putea să vă placă și