Java Reference
Java is a high-level programming language that can run java applications on any operating system via the java virtual machine (JVM). Its signature phrase “Write Once, Run Anywhere”. Java is also the underlying language for the Android OS. The Java syntax is similar to C-style languages such as: C, C++, JavaScript. Although Java is slower in speed than the other languages the best feature of Java is that is dynamically manages memory for you. If you can learn and understand the Java language then learning other languages will be a walk in the park.
Table of Contents
- Intro
- Data Types
- Control Flow
- Complex Data Types
- Exception Handling
- Data Collections
- Classes
- Inheritance & Polymorphism
- Files
- App Development
- Reflection API
- Testing
- I/O Stream
- Multi-Threading
Intro
Resources
CLI Compile & Run
To compile your java class you need to navigate using your console to the src
directory. You then need to compile your java class using javac Name.java
and Java is case sensitive. Then to run the compiled app you use java Name
without the .class.
To view a list of all the javac
commands type javac
to view the entire list. If you want to see what java compiler is doing in the background use the -verbose
command and it will list every action being done while compiling.
Memory Management
Java manages memory usage automatically using the garbage collector. When you create an object they are stored in heap memory and as long as the variable references an object it is retained.
Variables expire in 2 ways. The first is if you are running a code block in which a variable is created then after the block has been executed then the variable that was created can be destroyed. The second way is for you to assign the variable to null
.
The garbage collector has its own set of algorithm to identify when to destroy and reclaim memory. You as the developer can design your program to use the least amount of memory as possible. If you need to know the amount of memory available use the below methods to assist.
- Runtime.maxMemory()
- Runtime.totalMemory()
- Runtime.freeMemory()
Data Types
Everything in Java is an object. Each data type has their own class for example: strings have their own class called String with several useful methods that can be used. Each time you create a data type you are creating an instance of a class.
Declare and Initialize Variables
There are two types of variables that Java has. Primitives are stored in fast memory and are Integers, Floats, Chars, or Booleans. The other data type is complex objects which can be Strings, Dates and everything else.
To declare a primitive data type in Java you need to 3 things.
- Data Type
- Variable Name
- Value (optional)
// data type - variable name = value
int myVar = 15;
To declare objects you also need to 3 things and the new
keyword.
// data type class - variable name = initial value from constructor
Dog fido = new Dog();
You can declare variables inside a function or outside which will change the variable’s scope visibility. If you declare it inside the function the variable can only be used inside the function. If it is declared outside then it is a class/field variable and can be used everywhere.
Numbers
A primitive data type has only one value and cannot hold complex objects such as strings.
Data Type | Bits | Minimum | Maximum |
---|---|---|---|
byte | 8 | -128 | 127 |
short | 16 | -32,768 | 32,767 |
int | 32 | -2,147,483,648 | 2,147,483,647 |
long | 64 | -9.22337E+18 | 9.22337E+18 |
float | 32 | See documentation | |
double | 64 | See documentation |
/* PRIMITIVE DATA TYPES */
byte b = 2;
short s = 15;
int i = 100;
/*
L, f and d should be included else the value will be cast from byte short int to long, float or double causing more memory to be used.
*/
long l = 1000L;
float f = 125.75f;
double d = 125.5d;
You can access each primitive value’s helper class which is typically the data type with the first letter being capitalized ex: byte -> Byte
. Only exception is int -> Integer
.
If you are doing big computational or currency and need precision then you need to use the BigDecimal
class. Create the BigDecimal
object from a string or else you will have floater values and will lose precision.
// create BigDecimal object
double d = 123.45;
String dStr = Double.toString(d);
BigDecimal bigDec = new BigDecimal(dStr);
System.out.println(bigDec.toString());
Convert Numbers
The primitive data types from the smallest to the largest memory usage and value storage are:
- byte
- short
- int
- long
- float
- double You can implicitly convert a number upwards from short to int to long by assigning the value of the smaller type to the bigger one.
int i = 15; // 15
long longUpcast = i; // 15.0
If you want to convert downwards then you need to explicitly tell the compiler via typecast. An alternative is to use a helper class method from the class of the type.
// typecasting
double dubVal = 15.74;
int intDowncast = (int)dubVal;
// helper class
double dValue = 5.55;
double doubleObject = new Double(dValue);
int i = doubleObject.intValue();
Operators
There are several types of operators that allow you to manipulate and evaluate expressions.
- assignment
- equality/relational
- mathematical
- conditional
- ternary
The assignment operator =
is used to assign a value from the right to the data type on the left ex: int i = 5;
Math operators are similar to how they are in other languages.
- addition
+
ex:int x = 15 + 5;
- subtraction
-
ex:int x = 15 - 5;
- multiplication
*
ex:int x = 15 * 5;
- division
/
ex:int x = 15 / 5;
- modulus
%
ex:int x = 11 % 5;
will give remainder - increment
++
ex:x++;
will increment by 1 - decrement
--
ex:x--;
will decrement by 1 - postfix
x++
will evaluate x then increment by one - prefix
++x
will increment x by one and then evaluate x - short addition
+=
ex:i += 5
will take value of i and add 5 - short subtraction
-=
ex:i -= 5
will take value of i and subtract 5 - short multiplication
*=
ex:i += 5
will take value of i and multiply 5 - short division
/=
ex:i /= 5
will take value of i and divide 5
Equality or Relational Operators
>
greater than<
less than>=
greater than or equal to<=
less than or equal to==
equal to (not strick)===
equal to and same class type!=
not equal to!false
changes false to true&&
both sides must evaluate to true||
at least one side must evaluate to trueinstanceof
Class membership ex:str instanceof java.lang.String
Characters
You can work with single characters by using the primitive data type of char
. To assign variable to a single character you must use single quotes. You can also assign unicode to characters. You can use the Character
class to find helper methods.
public class Main {
public static void main(String[] args) {
char chr1 = 'a';
char chr2 = 'A';
char chr3 = '3';
char pound = '\u00A3';
System.out.println(chr1);
System.out.println(chr2);
System.out.println(chr3);
System.out.println(pound);
char chr4 = 'y';
System.out.println(Character.toUpperCase(chr4));
}
}
Booleans
Booleans are true
or false
values thats it. Use the Boolean
class in order to use helper methods.
public class Main {
public static void main(String[] args) {
boolean x = true;
boolean y = false;
System.out.println(x); // prints true
System.out.println(y); // prints false
boolean b = !x;
System.out.println(b); // prints false
int i = 5;
boolean num = (i != 3);
System.out.println(num); // prints true
}
}
Strings
Java can print any number type as a string which it automatically does when using the print or println. In Java it doesn’t matter if you concatenate and begin the expression with a number because if there is one string involved the entire expression becomes a string. Every object in Java has a toString()
method. So if you were concatenating an object to a string it would call its toString()
method.
import java.util.Date;
public class Main {
public static void main(String[] args) {
int i = 1421313;
double d = 3.14;
System.out.println(i);
System.out.println(d);
System.out.println(1 + " string " + 5);
Date today = new Date();
System.out.println("The date is " + today);
}
}
Underscores (J7)
Long numeric literals can now have underscores in them to make readability easier.
// below both numbers read correctly but using _ makes reading much quicker
int bank = 1500000000;
int bank2 = 1_500_000_000;
Control Flow
Conditionals
Use the keyword if
to control the flow of the program. The syntax is if (condition)
followed by a code block. You can also add in the additional keywords else if
and else
for multiple condition checks. If you are comparing strings you will need to use methods from the string class to compare ex: equals(str)
str.equals(str2)
.
public class Main {
public static void main(String[] args) {
int i = 5;
if (i == 5) {
System.out.println("Excellent Rating!");
}
else if (i < 5 && i > 2) {
System.out.println("Good but not great.");
}
else {
System.out.println("Junk Rating");
}
}
}
Switch Statement
Use switch statements to evaluate a single int, byte, short, enum and string (Java 7 only). Use the switch
, case
, break
, and default
keywords. The break
keyword is used to exit a code block. You can also use enum
which are a list of constants and good to pair with switch statements.
// switch structure
switch (key) {
case value:
break;
default;
break;
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Rate this ad with a # between 1 - 5: ");
int rate = input.nextInt();
switch (rate) {
case 5:
System.out.println("Excellent");
break;
case 4:
System.out.println("Great");
break;
case 3:
System.out.println("Average");
break;
case 2:
System.out.println("Poor");
break;
case 1:
System.out.println("Bad");
break;
default:
System.out.println("Out of range select between 1 - 5");
break;
}
}
}
// enum example
public class Main {
public enum Days {
Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
}
public static void main(String[] args) {
Days day = Days.Tuesday;
System.out.println(day.Thursday);
}
}
Switch (J7)
You can now evaluate a string with switch statements starting with Java 7.
// you can now evaluate strings in switch case
switch ("yes") {
case "yes":
System.out.println("Of course!");
break;
case "no":
System.out.println("No thanks.");
break;
case "maybe":
System.out.println("Not sure.");
break;
default:
System.out.println("Thats not an answer.");
break;
}
Loops
There are several types of loops that can be helpful repeating the same code over and over or loop through and array. When creating loops you need to make sure that there will be a point in time when the condition returns false or else you will have an infinite loop.
The for
loop consists of three parts: for (int i = 0; i < 10; i++)
. The first is a counter variable. The second is the comparison that when return false will exit the loop. The last is an increment to the counter variable.
The for each
loop is used to loop through an entire array or hash once ex: for (Integer day : days)
.
The while
loop checks the condition first then runs the code ex: while (x != 0)
.
The do while
loop runs the code at least once and then checks the condition ex: do { code } while (x != 0);
.
public class Main {
public static void main(String[] args) {
int[] data = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
// For Loop
for (int i = 0; i < data.length; i++) {
System.out.println(data[i]);
}
// For Each
for (Integer num : data) {
System.out.println(num);
}
// While Loop
int i = 0;
while (i < data.length) {
System.out.println(data[i]);
i++;
}
// Do While Loop
int j = 0;
do {
System.out.println(data[j]);
j++;
} while (j < data.length);
}
}
Methods
Methods are equivalent to functions like in other languages. They are called methods because in OOP functions or an object are called methods and everything in Java is an object. Methods are good to create if you see yourself running the same code over and over again. Every method must be defined within a class. The one method you always see is public static void main(String[] args)
.
There are three types of methods you can create: public
, private
, protected
.
- public - method is available to the entire program as long as it can access it.
- private - method is only available to the class it is in.
- protected - method is available to the class and its inherited class.
The static
keyword means that the method is a class method vs an instance method. Static methods can call other static methods and instance methods can call other instance methods.
Next you declare the return type if you are returning a data type else just put void
. After you name the method using camel case followed by parentheses with optional arguments: myMethod()
.
public class Main {
public static void main(String[] args) {
saySomething();
}
private static void saySomething() {
System.out.println("You just ran this method.");
}
}
When creating your own method you have the option to allow it to pass in arguments. If you take in arguments you must specify the data type of the argument.
public class Main {
public static void main(String[] args) {
System.out.println(add(5, 7));
}
// returns double and takes in 2 double arguments
private static double add(double x, double y) {
return x + y;
}
}
If you do not know how many arguments may come through you can use the ...
to tell Java that there might be multiple values that are passed in ex: multiple(double ... values)
. Java will build an array of all the arguments passed.
public class Main {
public static void main(String[] args) {
System.out.println(add(5, 7, 12, 3, 4));
}
// returns double and takes in multiple double arguments
private static double add(double ... numbers) {
double sum = 0d;
for (double n : numbers ) {
sum += n;
}
return sum;
}
}
Method signature is the unique combination of the keywords and arguments that method receives. You can create multiple methods with the same name as long as the signatures are different. Creating multiple same named methods is called method overloading.
public class Main {
public static void main(String[] args) {
// run first add method with 2 args
System.out.println(add(5, 7));
// run second add method with 3 args
System.out.println(add(5, 7, 12));
// run third add method with 2 strings
System.out.println(add("15", "13"));
}
// returns double and takes in 2 double arguments
private static int add(int x, int y) {
return x + y;
}
private static int add(int x, int y, int z) {
return x + y + z;
}
private static int add(String one, String two) {
int val1 = Integer.parseInt(one);
int val2 = Integer.parseInt(two);
return val1 + val2;
}
}
When passing variables as arguments they are always passed by copy. Passing by copy means that a copy of the variable is passed through and not the variable itself. Passing by reference means that the original variable itself is being altered. Complex objects are references. A reference variable points to the location in memory. When you pass the variable into a method a new reference is created but both of these are pointing to the original object. Strings cannot be changed and are immutable so when passing in a string and altering it you are simply creating another string.
Complex Data Types
String Class
There are plenty of helpful methods to be used in the string class. You can create a string by using the string class ex: String str = new String("My string goes here");
.
If you need to compare two strings and case matters you need to use the equals(str)
method or else you can use the equalsIgnoreCase(str)
method. The toCharArray()
splits each character into an element via array.
public class Main {
public static void main(String[] args) {
// string literal
String str1 = "This is literal";
// string via String constructor
String str2 = new String("Create string via string class");
System.out.println(str2);
// use .equals method to compare two strings and case matters
// use .equalsIgnoreCase method to compare two strings without case sensitivity.
String s1 = "this";
String s2 = "this";
String s3 = "THIS";
if (str1.equals(str2)) {
System.out.println("matches");
}
else {
System.out.println("no match");
}
char[] characters = s3.toCharArray();
for (char c : characters) {
System.out.println(c);
}
}
}
Strings are immutable and cannot be concatenated. You can use the StringBuilder
or StringBuffer
to append, prepend or insert string.
public class Main {
public static void main(String[] args) {
String str = "I want to go to ";
StringBuilder strbuild = new StringBuilder(str);
strbuild.append("California!");
System.out.println(strbuild);
}
}
To find out the length of a string use the .length()
method. You can find out where a particular character or string starts using the indexOf(letter)
method. To extract a range of the string use the substring(index#)
method. To get rid of whitespace use the trim()
method.
public class Main {
public static void main(String[] args) {
String str = "This is a test string";
// use the length method to get the length of a string
System.out.println(str.length());
// use the indexOf method to return the first index pos of the matched string
System.out.println(str.indexOf("a"));
// extract a range of the string use substring
System.out.println(str.substring(5));
// trim all the surrounding whitespace by using trim method
String str1 = "whitespace ";
System.out.println(str1.trim());
}
}
Date Class
The Date
class is part of the java.util package and must be imported. You can have the date in Gregorian Calender by using the GregorianCalender
class.
import java.util.Date;
import java.text.DateFormat;
import java.util.GregorianCalendar;
public class Main {
public static void main(String[] args) {
Date date = new Date();
// standard no arguments output
System.out.println(date);
// gregorian calender
GregorianCalendar gc = new GregorianCalendar(2015, 4, 25);
// increment the day by one
gc.add(GregorianCalendar.DATE, 1);
// get full date string version with time
Date d2 = gc.getTime();
// returns the date in month, day, year format
DateFormat df = DateFormat.getDateInstance();
String strDate = df.format(d2);
System.out.println(strDate);
}
}
Exception Handling
Try-Catch & Throw
If you know a runtime error may occur you can handle them using try
and catch
. When an exception occurs then an exception object is created which you can use to display the errors.
public class Main {
public static void main(String[] args) {
try {
String[] str = {"Illinois"};
System.out.println(str[1]);
} catch (Exception e) {
e.printStackTrace();
System.out.println("Custom messages can be written.");
}
System.out.println("Program handled exception and made it through.");
}
}
You can declare throws
for code that might have runtime exceptions.
public class Main {
public static void main(String[] args) {
try {
returnArr();
} catch (Exception e) {
System.out.println("There was an array runtime error");
}
System.out.println("Program handled exception and made it through.");
}
private static void returnArr() throws ArrayIndexOutOfBoundsException {
String[] str = {"Illinois"};
System.out.println(str[1]);
}
}
Finally
If you use a resource that needs to be cleaned after a try-catch block use the finally
block. Finally block executes after a try
regardless of if an exception is thrown.
public class Main {
public static void main(String[] args) throws IOException {
// create the file and buffer reader
FileReader f = null;
BufferedReader buff = null;
// the finally block closes the reader streams regardless of an exception or not
try {
f = new FileReader("text.txt");
buff = new BufferedReader(f);
String str;
while ((str = buff.readLine()) ! = null) {
System.out.println(str);
}
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
}
finally {
if (f != null) {
f.close();
}
if (f != null) {
buff.close();
}
}
}
}
Try With Resources
Java 7 created a new syntax to clean up resources vs the old way of cleaning up (see above).
public class Main {
public static void main(String[] args) throws IOException {
// the try with resources allows you to instantiate the object within a try via ()
// these objects will be cleaned up automatically so you don't need the finally block anymore
try (
FileReader f = new FileReader("text.txt");
BufferedReader buff = new BufferedReader(f);
)
{
String str;
while ((str = buff.readLine()) ! = null) {
System.out.println(str);
}
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
}
}
}
Custom Exceptions
You can create your own custom exceptions classes. When creating a custom exception class the superclass should be Exception
. It is required to have a static final long <name>
field in the class.
package com.pratik.java.exceptions;
public class BadFileException extends Exception {
public static final long serialVersionUID = 34L;
@Override
public String getMessage() {
return "Bad file!";
}
}
// To use the class in main part of program.
try {
if (file.equals("correct")) {
System.out.println("This is the right file.");
} else {
// throw exception into the catch block
throw (new BadFileException());
}
} catch (BadFileException e) {
System.out.println(e.getMessage());
}
Data Collections
Arrays
Simple arrays are great for storing large sets of data but they are not flexible as you can only store one type of data type. They also cannot be resized once they are created; you need to use the Array<list>
class.
You can create a simple array literal via 3 methods: int[] arr = new int[3]
, int arr[] = new int[3]
, int[] arr = {1, 2, 3}
. To access data of the array specify the index between brackets (index starts at 0) use arr[index#]
.
You can also create multi dimensional arrays by putting an additional set of brackets when instantiating: double[][] arr = new Double[3][3]
public class Main {
public static void main(String[] args) {
// create 5 by 2 array
int[][] arr = new int[3][3];
// access array by specifiying first column index then row.
arr[0][0] = 1;
arr[0][1] = 2;
arr[0][2] = 3;
arr[1][0] = 4;
arr[1][1] = 5;
arr[1][2] = 6;
arr[2][0] = 7;
arr[2][1] = 8;
arr[2][2] = 9;
// using a double for loop is best way to run through each row and column
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j]);
}
System.out.println();
}
}
}
If you need dynamic amount of array size then you need to use Array Lists. To create an array list use: ArrayList<int> arr = new ArrayList<int>()
. The < >
are generics which means that this data will only carry a particular data type.
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
// create string list
ArrayList<String> arr = new ArrayList<String>();
// add items
arr.add("Jack");
arr.add("Jill");
arr.add("John");
System.out.println(arr);
// remove items
arr.remove(0);
System.out.println(arr);
// get item from list
System.out.println(arr.get(1));
// get index of and item
System.out.println(arr.indexOf("Jill"));
}
}
Hash Map
Hash maps are key value pairs. You instantiate a hash map via the HashMap
class: HashMap<String, String> map = new HashMap<String, String>();
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
// create hash map
HashMap<String, String> map = new HashMap<String, String>();
// add key values to hash map using put
map.put("Thai", "Pad Thai");
map.put("Indian", "Palak Paneer");
map.put("American", "Cheese Burger");
System.out.println(map);
// retrieve the value by using get
System.out.println(map.get("Thai"));
// to remove an item refer to the key
map.remove("Indian");
System.out.println(map);
}
}
Iterators
You can use iterators to loop through the entire collection. To loop through list use the ListIterator
: ListIterator<String> listIterator = list.listIterator();
. When looping through use the hasNext()
method to check to see if the next element exists. To grab the current element use the next()
method.
To iterate through a hash map use the Set
object: Set<String> keys = map.keySet();
. Next create an Iterator
object: Iterator<String> iterator = keys.iterator();
. Like the list use hasNext()
, next()
, and get
to check and get key value pairs.
import java.util.HashMap;
import java.util.ArrayList;
import java.util.ListIterator;
import java.util.Set;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
// loop through array list
ArrayList<String> arr = new ArrayList<String>();
arr.add("Jack");
arr.add("Jill");
arr.add("John");
arr.add("Jerry");
// create list iterator
ListIterator<String> listIterate = arr.listIterator();
// check to see if there is another element after
// use next to get the value
while(listIterate.hasNext()) {
String str = listIterate.next();
System.out.println(str);
}
//---------------------------------------------
// loop through hash map
HashMap<String, String> map = new HashMap<String, String>();
map.put("Thai", "Pad Thai");
map.put("Indian", "Palak Paneer");
map.put("American", "Cheese Burger");
map.put("Mexican", "Tacos");
// get the keys
Set<String> keys = map.keySet();
Iterator<String> iterator = keys.iterator();
// check to see if there is a k,v set after
// use next to get the key and get to get the value
while (iterator.hasNext()) {
String val = iterator.next();
System.out.println(val + ": " + map.get(val));
}
}
}
Hash Set
The hash set is a Set
which means that each object can only appear once in the set. The hash set is a bit faster than the tree set. The hash set output does not have any order the data comes out to; it will change each time.
public class Main {
public static void main(String[] args) {
Dog pg = new Pug();
Dog gs = new GermanShepard();
Dog bd = new Bulldog();
// define hash set class
HashSet<Dog> set = new HashSet<>();
set.add(pg);
set.add(gs);
set.add(bd);
// return how many in the set
System.out.println(set.size());
// try to add same object again
set.add(pg);
Sysetm.out.println(set.size());
// you can add one null
set.add(null);
Sysetm.out.println(set.size());
// you can remove item from set
set.remove(pg);
}
}
Tree Set
Tree set does everything that the hash set does but it keeps items in order that you can control. It uses an interface called Comparable
which must be added to the classes (you can just add it to the superclass). When adding to a tree set the objects will be put in alphabetical order; this drops performance because each time you add and object it must sort. The compareTo
method will return and integer value of -1, 0, -1. You must implement this method yourself
// to use the tree set the classes must have an interface of the Comparable class
public class Dog extends Comparable<Dog> {
//code
// must implement compareTo method from Comparable
@Override
public int compareTo(Dog obj) {
String s1 = this.dogName;
String s2 = obj.dogName;
return s1.compareTo(s2);
}
}
public class Main {
public static void main(String[] args) {
Dog pg = new Pug();
Dog gs = new GermanShepard();
Dog bd = new Bulldog();
// create tree set and need to implement interface called Comparable
TreeSet<Dog> set = new TreeSet<>();
set.add(pg);
set.add(gs);
set.add(bd);
}
}
Linked List
Linked lists are high performance and very easy to use. You can add items to any position in the list unlike list where you can only add them at the end: list.add(index#, data)
. You can add items to the beginning of the list by using the addFirst(data)
and remove them by remove(int index)
.
public class Main {
public static void main(String[] args) {
// create new linked list
LinkedList<Dog> list = new LinkedList<>();
list.add(new Pug());
list.add(new Bulldog());
// you can add items in any position. give it the index pos then the item
list.add(1, new GermanShepard());
list.addFirst(new Pug());
// remove item from list at index 2
list.remove(2);
display(list);
}
static private void display(Collection<Dog> col) {
System.out.println("List order: ");
Iterator<Dog> iterator = col.iterator();
while(iterator.hasNext()) {
Dog dog = (Dog iterator.next();
System.out.println(dog.dogName.toString());
}
}
}
Queues
Linked List class interfaces a class called Queues which allows for a FIFO type operations. To add use add(e) or offer(e)
, remove remove() or poll()
, and examine element() or peek()
. If you use the offer, poll or peak
it not only adds or removes the item but it returns the item that was just effected. There are a whole bunch of different queues that you can use see the docs.
public class Main {
public static void main(String[] args) {
LinkedList<Dog> list = new LinkedList<>();
list.add(new Pug());
list.add(new Bulldog());
list.add(1, new GermanShepard());
list.addFirst(new Pug());
display(list);
Dog o1 = list.peek();
System.out.println(o1.dogName.toString());
}
static private void display(Collection<Dog> col) {
System.out.println("List order: ");
Iterator<Dog> iterator = col.iterator();
while(iterator.hasNext()) {
Dog dog = (Dog iterator.next();
System.out.println(dog.dogName.toString());
}
}
}
Java 7 Enhancements
In Java 7 when declaring a collection such as, a list or hash map, you don’t need to declare the data type again in the constructor method and instead just leave an empty <>
.
// you don't need to write dog out twice anymore.
ArrayList<Dogs> dog2 = new ArrayList<>();
Classes
Encapsulation
Encapsulation means to package complex functionality to make it easy to use in the program. You should break the code out into different functionality or in other words pieces. Encapsulation allows user to use the methods without having to know how the data is stored or how the methods are constructed.
The benefits of encapsulation:
- splitting functionality into small units
- grouping functions and data together
- support testing of the software
Custom Classes
You can package methods that do similar tasks into their own class. Create classes that are reusable. You can only have one public class in a java file but if you have more they have to be private.
Below is a simple math class. To use the class you call on it and then the method you want ArithmeticMath.multiply(x, y)
public class ArithmeticMath {
public static double divide(String str1, String str2) {
double d1 = Double.parseDouble(str1);
double d2 = Double.parseDouble(str2);
return d1 / d2;
}
public static double multiply(String str1, String str2) {
double d1 = Double.parseDouble(str1);
double d2 = Double.parseDouble(str2);
return d1 * d2;
}
public static double add(String str1, String str2) {
double d1 = Double.parseDouble(str1);
double d2 = Double.parseDouble(str2);
return d1 + d2;
}
public static double subtract(String str1, String str2) {
double d1 = Double.parseDouble(str1);
double d2 = Double.parseDouble(str2);
return d1 - d2;
}
}
Packages
A package is just a collection of classes. When a class is anywhere but the default package you must import the package: package name
. In real world you usually create packages starting with the company website prefix such as com.pratik.math
. This helps avoid naming conflicts.
package helpers;
public class ArithmeticMath {
public static double divide(String str1, String str2) {
double d1 = Double.parseDouble(str1);
double d2 = Double.parseDouble(str2);
return d1 / d2;
}
public static double multiply(String str1, String str2) {
double d1 = Double.parseDouble(str1);
double d2 = Double.parseDouble(str2);
return d1 * d2;
}
public static double add(String str1, String str2) {
double d1 = Double.parseDouble(str1);
double d2 = Double.parseDouble(str2);
return d1 + d2;
}
public static double subtract(String str1, String str2) {
double d1 = Double.parseDouble(str1);
double d2 = Double.parseDouble(str2);
return d1 - d2;
}
}
Instance Methods
Instance methods are called from an instance of the class unlike class method which are called from the class itself.
To create an instance method you leave off the word static
from the method signature.
package com.pratik.juicer;
import com.pratik.juicer.fruit.Fruit;
import com.pratik.juicer.Juicer;
public class Main {
public static void main(String[] args) {
// create array of fruit objects and then a juicer
Fruit[] fruits = {new Fruit(), new Fruit(), new Fruit()};
Juicer machine = new Juicer();
// drop the fruit arrays into the machine
machine.blend(fruits);
}
}
package com.pratik.juicer;
public class Fruit {
// instance method
public void drop() {
System.out.println("You picked an fruit.");
}
}
package com.pratik.juicer;
import com.pratik.juicer.fruit.Fruit;
public class Juicer {
// juicer instance method
public void blend(Fruit[] fruits) {
// loop through the fruits and drop them
for (Fruit fruit : fruits) {
fruit.drop();
}
}
}
Instance Variables
Instance variables are called fields and are assigned at the class level. You declare each variable with an access type, data type, and a name. The data will persist as long as the object persists.
package com.pratik.juicer;
import com.pratik.juicer.fruit.Fruit;
import com.pratik.juicer.Juicer;
public class Main {
public static void main(String[] args) {
// create array list of fruit obejcts
ArrayList<Fruit> fruits = new ArrayList<Fruit>();
// delcare it once to use it multiple times
Fruit fruit;
// add three new fruits obejcts to fruits
fruit = new Fruit();
System.out.println(fruit.name);
fruits.add(fruit);
fruit = new Fruit();
System.out.println(fruit.name);
fruits.add(fruit);
fruit = new Fruit();
System.out.println(fruit.name);
fruits.add(fruit);
Juicer machine = new Juicer();
machine.blend(fruits);
}
}
package com.pratik.juicer.fruit;
public class Fruit {
// instance variables
public String name = "Apple";
public long color = 0xff0000;
private int oz = 3;
// return the amount of ounces
public int drop() {
return oz;
}
}
package com.pratik.juicer;
import com.pratik.juicer.fruit.Fruit
public class Juicer {
// change to take in array list of fruits
public void blend(ArrayList<Fruit> fruits) {
int oz = 0
for (Fruit fruit : fruits) {
oz += fruit.drop();
}
System.out.println("Your glass has " + oz + " oz of apple juice.");
}
}
Constructor Methods
A constructor method is a special kind of method that gets called when you create an instance of class. To create a constructor method: public NameOfClass()
. Use the this
keyword to reference the current instance of the class. It goes after instance variables but before methods. Constructors never return a value.
public class Fruit {
public String name = "Apple";
public long color = 0xff0000;
private int oz = 3;
// constructor calling the current instance's name
public Fruit() {
System.out.println("The fruit is " + this.name);
}
// constructor taking in an argument
public Fruit(int oz) {
this.oz = oz;
}
public int drop() {
return oz;
}
}
Setter Getter Methods
Fields should be private and you need to use the setter and getter methods to access them. Naming convention is just as it sounds setName(data x)
and getName()
.
public class Fruit {
public String name = "Apple";
public long color = 0xff0000;
private int oz = 3;
// getter for oz
public int getOz() {
return oz;
}
// setter for oz
public int setOz(int oz) {
this.oz = oz;
}
public Fruit() {
System.out.println("The fruit is " + this.name);
}
// constructor taking in an argument
public Fruit(int oz) {
setOz(oz);
}
public int drop() {
return oz;
}
}
Class Variables
You can also create class variables by using the word static
and final
. Its typically to set variables as a constant. An example would be public static final String COLOR = "black"
. The public would allow it to be accessible to any class. The static would mean its a class type and final would mean it is a constant. Constant names are always all uppercase.
public class Fruit {
// create constant class variable
public static final long RED = 0xff0000;
public String name = "Apple";
public long color = Fruit.RED;
private int oz = 3;
public int getOz() {
return oz;
}
public int setOz(int oz) {
this.oz = oz;
}
public Fruit() {
System.out.println("The fruit is " + this.name);
}
// constructor taking in an argument
public Fruit(int oz) {
setOz(oz);
}
public int drop() {
return oz;
}
}
Static Initializers
Static initializers run only one time before the constructor or main method is called.
public class DogHouse {
public static ArrayList<Dog> dogs;
// this will run once
static {
dogs = new ArrayList<>();
dogs.add(new Dog("GermanShepard", 0xaa7243));
dogs.add(new Dog("Pug", 0xFFFFFF));
dogs.add(new Dog("Bulldog", 0xaa7243));
}
}
Instance Field Initializers
Non static Initializers do not have the keyword static
in them. Its very handy when you have more than one constructor method but have certain type of code that always needs to be executed.
public class DogHouse {
public ArrayList<Dog> dogs;
// this will run once but it is not
{
dogs = new ArrayList<>();
dogs.add(new Dog("Rare", 0xFFFFFF));
}
// constructors
public DogHouse() {
System.out.println("Default constructor");
}
// you can then add as many objects as you like when instantiating
// ArrayList<Dogs> dogs = new DogHouse(4, "Pug", 0x000000).dogs;
public DogHouse(int nDogs, String dogName, long color) {
for (int i = 1; i <= nDogs; i++) {
dogs.add(new Dog(dogName, color));
}
}
}
Member Classes
Member classes are classes that are inside other classes. This helps with encapsulation and limiting who can manipulate what data.
public class DogHouse {
public ArrayList<Dog> dogs;
{
dogs = new ArrayList<>();
dogs.add(new Dog("Rare", 0xFFFFFF));
}
// constructors
public DogHouse() {
System.out.println("Default constructor");
}
public DogHouse(int nDogs, String dogName, long color) {
for (int i = 1; i <= nDogs; i++) {
dogs.add(new Dog(dogName, color));
}
}
// create method to be able to add a dog
public void addDog(String dogName, long color) {
dogs.add(new Dog(dogName, color));
}
// create a report to display all the dogs in the dog house
public void reportDogs() {
for (Dogs dog : dogs) {
System.out.println("This is a " + dog.dogName);
}
}
// we will make class Dog a member of DogHouse class and it can only be called here
class Dog {
public String name = 'fido';
public String type = 'dog';
public int age = 0;
private int speed = 10;
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public Dog() {
System.out.println("Woof! My name is " + this.name);
}
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public int run() {
System.out.println("Your dog is running at " + this.speed + " mph")
}
}
}
Inner Classes
Inner class is a class that is within a code block. It is only visible to the code block it is within because its private. You can only use instance methods so you will have to instantiate and instance of the class.
public void reportDogs() {
// class declared inside of the method is only available to the method.
class DogHouseDoor {
public void open() {
System.out.println("Door has been opened.");
}
}
// create an instance of DogHouseDoor and use open method.
new DogHouseDoor().open();
for (Dogs dog : dogs) {
System.out.println("This is a " + dog.dogName);
}
}
Anonymous Inner Class
An anonymous class doesn’t have a name and is defined and used once.
public void reportDogs() {
// class DogHouseDoor {
// public void open() {
// System.out.println("Door has been opened.");
// }
// }
//
// new DogHouseDoor().open();
// creating an anonymous function by calling Object class's constructor.
// call the function right after.
new Object() {
public void open() {
System.out.prinln("This is an anonymous function");
}
}.open();
for (Dogs dog : dogs) {
System.out.println("This is a " + dog.dogName);
}
}
Enumeration Classes
You can create and independent enum class that can be used throughout the application. If you have constant strings that are used throughout the app you can create an enum class to ensure that each time when you use the variable the string is spelled correctly.
Below the code is returning the string name into the constructor and saving it to the nameAsString variable. When calling the name the toString() method returns the string variable.
// create and enum to insure that the correct spelling of the name is being done.
public enum DogName {
GERMAN_SHEPARD("German Sherpard"), PUG("Pug"), BULLDOG("Bulldog");
private String nameAsString;
// enums can only have private methods.
private DogName(String nameAsString) {
this.nameAsString = nameAsString;
}
// ovverride string method to make it lowercase
@Override
public String toString() {
return this.nameAsString;
}
}
Inheritance & Polymorphism
Inheritance & Polymorphism Concept
Inheritance means that there is a relationship between multiple classes. Inheritance allows you to extend functionality from one class to many. In Java you can only inherit from one other class. The inheritance relationship can be described as Superclass/subclass
. Subclass extends the superclass.
Polymorphism means that when there is a relationship between classes you can deal with the object as it is in the subclass or superclass. When you instantiate a subclass, you can declare it as a superclass type. So lets take a dog there are many types of dogs but they all share similar characteristics. You can create a Dog
class that has attributes such as; eye color, fur color, name, owner, id etc… You can then use the Dog
class to create subclasses for each type of dog such as GermanShepard
, Pug
, Bulldog
etc…
Superclasses don’t need any code and any class can be a superclass. You can inherit all fields and methods unless it is private
. If the field is set to private
then only the superclass can deal with it directly.
In order for the class to inherit a superclass use the extends
keyword when defining the class: public class Pug extends Dog
. Once this relationship is established you are able to create all different types of classes under the superclass Dog
: Dog[] dogs = {new GermanShepard(), new Pug(), new Bulldog()};
Extending Classes
Looking below the Pug class we use the extends
keyword to inherit the Dog class. We also are able to use/change the variables in the Dog class and we also set the speed using the super
keyword.
public class Dog {
public String name = 'fido';
public String type = 'dog';
public int age = 0;
private int speed = 10;
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public Dog() {
System.out.println("Woof! My name is " + this.name);
}
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public int run() {
System.out.println("Your dog is running at " + this.speed + " mph")
}
}
package com.pratik.dogs
// create pug dog type that extends dog
public class Pug extends Dog {
public Pug() {
// the super calls the constructor from class Dog
// it also changes the name, type and age
super(5);
this.name = "Patrick";
this.type = "Pug";
this.age = 4;
}
}
Override Super Class
To override a super class method use the same signature and write out the new/modified code block. Putting a @Override
is not necessary but lets programmer know that you are modifying a method from the superclass. If you want to use the code from the superclass you can put a super.methodName()
inside the override method.
package com.pratik.dogs
public class Pug extends Dog {
public Pug() {
super(5);
this.name = "Patrick";
this.type = "Pug";
this.age = 4;
}
// the @Override tells the programmer that you are overriding a method from the super class.
@Override
public int run() {
System.out.println("The " + this.name + " is running at " + this.speed " mph!");
return super.run();
}
}
Casting Super Class
You can up-cast and down-cast subclasses to super classes like you do with primitive data types. To cast downward you simply put (Object)
before the other object ex: (GermanShepard)dogs.get(0);
.
Interfaces
Another way of creating an inheritance relationship via the interface. The interfaces allows you define the structure of the class, names, signatures of classes methods and final fields. You can then implement that interface with a class using keyword implements
. If class uses and interface then it must use all of the methods specified.
Abstract Classes & Methods
You create interfaces just like classes. You then add your methods signatures and final fields. No constructor methods. Its best to use interfaces when you are modeling behavior and not dynamic management of data. The methods must be either public
or abstract
as you cannot modify if they are set to private
. You can implement as many interfaces as you want.
public interface Machine {
public void getOz(Collection<Fruit> fruits);
public int totalOz();
public void setTotalOz(int totalOz);
}
public class Juicer implements Machine {
@Override
public void getOz(Collection<Fruit> fruits) {
// add implementing code here
}
@Override
public int totalOz() {
// add implementing code here
}
@Override
public void setTotalOz(int totalOz) {
// add implementing code here
}
}
Files
Managing Files
You can copy existing files using the File
class built in Java. To copy a file you need to create 2 file objects one is the file you want to copy and the other is the target file (can be existing or one you want to create). you will need to have the correct path unless you are in the root directory. In Java you can read files bytes at a time so you have the option of processing 1 byte at a time or chunks of bytes at a time (more memory). Once you are finished close both the in and out streams. Make sure to surround the statements with a try-catch
block in case of exceptions.
package com.pratik.files;
import java.io.*;
public class CopyFile {
public static void main(String[] args) {
try {
// create 2 file object
// f1 - file to copy
// f2 - file to target or file to create
File f1 = new File("mytext.txt");
File f2 = new File("create.txt");
// create two file streams one for input and other for output
// make sure to grab the correct objects from java.io
InputStream in = new FileInputStream(f1);
OutputStream out = new FileOutputStream(f2);
// create an array of bytes - 1024 bytes at a time
byte[] buffer = new byte[1024];
int len;
// loop through file until all the bytes have been copied
while ((len = in.read(buffer)) > 0) {
// write the buffered data to the new file. The 0 is the starting point
out.write(buffer, 0, len);
}
// close the streams once you are finished
in.close();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Apache Commons Files
The Apache Commons community has created maintainable reusable Java code to help ease common tasks when programming. Download the file and copy the .jar
file into your project bin
directory. You now need to create a build path
so you can use the library (if you right-click on eclipse and select build path it will automatically do this for you). Below is when you use the apache commons library.
package com.pratik.files;
import java.io.*;
public class CopyFile {
public static void main(String[] args) {
try {
File f1 = new File("mytext.txt");
File f2 = new File("create.txt");
// using apache commons library.
FileUtils.copyFile(f1, f2);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Reading Text From Network
You can use the apache commons library but below is the long way to reading a network file. You will need to use the URL
object to retrieve the address of the file.
import java.net.URL;
public class NetworkFile {
public static void main(String[] args) {
try {
// get the url location of the file
// open a stream from the url
// create a new buffer stream to be able to read the contents
URL url = new URL("http://services.explorecalifornia.org/pox/tours.php");
InputStream stream = url.openStream();
BufferedInputStream buffer = new BufferedInputStream(stream);
StringBuilder sb = new StringBuilder();
while (true) {
// the read command will return bytes until there is nothing left then it returns -1
int data = buffer.read();
if (data == -1) {
break;
}
else {
// convert the integer into a character and append it to the string
sb.append((char)data);
}
}
System.out.println(sb);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e ) {
e.printStackTrace();
}
}
}
Parsing XML File
Parsing the DOM is essential in the age of web. Use the DocumentBuilderFactory
class to read through xml. This is like a web scraper.
import java.xml.parsers.DocumentBuilder;
import java.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
public class ReadXML {
public static void main(String[] args) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse("http://services.explorecalifornia.org/pox/tours.php");
NodeList list = doc.getElementsByTagName("title");
System.out.println("There are " + list.getLength() + " items");
for (int i = 0; i < list.getLength(); i++) {
Element item = (Element)list.item(i);
System.out.println(item.getFirstChild().getNodeValue());
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e ) {
e.printStackTrace();
} catch (IOException e ) {
e.printStackTrace();
}
}
}
Path Class
In Java 7 there is a new system for working with directories and files Java.NIO (New input output). The core class in this system is called Path
.
public class Main {
public static void main(String[] args) throws IOException {
// create path object and use the get method to get the contents of the file or url
Path path = Paths.get("/tmp/text.txt");
// the toString method gives you the value that you passed in from the get method
// this will return "\tmp\text.txt"
System.out.println(path.toString());
// the get file name will send you the last part of the string which is the actual file name
// this returns "text.txt"
System.out.println(path.getFileName());
// returns integer value on how many folders the file is nested in
System.out.println(path.getNameCount());
// to get a section of the file path use the getName method. Data is list data type.
// to get actual name of the file in get name use .getNameCount - 1
System.out.println(path.getName(0));
// The too real path method only will work if you are pointing to an existing file
Path actualPath = path.toRealPath(LinkOption.NOFOLLOW_LINKS);
System.out.println(path.getName(actualPath));
}
}
Manage File & Directories
The Files
class can help copy, delete, and move files.
import java.nio.*;
public class Main {
public static void main(String[] args) throws IOException {
Path src = Paths.get("/tmp/text.txt");
System.out.println(src.getFileName());
// to copy the file you need the source path and then a target path
Path tgt = Paths.get("tmp/newtext.txt");
// to copy file use the copy method and put in the source path, target path, and then an optional copy option
Files.copy(src, tgt, StandardCopyOption.REPLACE_EXISTING);
// to delete a file get the file path to delete and use the delete method
Path del = Paths.get("files/deltext.txt");
Files.delete(del);
System.out.println("deleted!");
// to create a new directory retrieve the location of the new directory
// use the createDirectory method.
Path newdir = Paths.get("file/newfolder");
Files.createDirectory(newdir);
// to move a file use the move method and pass arguments of the file to move, where to move using
// the resolve method combines the newdir path with the file name from src: file/newfolder/newtext.txt
Files.move(src, newdir.resolve(src.getFileName()), StandardCopyOption.REPLACE_EXISTING);
}
}
Reading & Writing
In order to work with a text file you need to use an object called characterset from Charset
.
public class Main {
public static void main(String[] args) throws IOException {
Path src = Paths.get("files/mytext.txt");
Path tgt = Paths.get("files/newfile.txt");
// create a charset object to be able to read/write to text
Charset charset = Charset.forName("US-ASCII");
ArrayList<String> lines = new ArrayList<>();
// READING
// create a new buffered reader and use the newBufferedReader method
try (BufferedReader reader = Files.newBufferedReader(src, charset))
{
// loop through file and keep reading lines until it returns null
// add lines to the list
String line = null;
while ((line = reader.readLine()) != null) {
lines.add(line);
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
// WRITING
// create a new buffered writer and use the newBufferedWriter method
try (BufferedWriter writer = Files.newBufferedWriter(tgt, charset))
{
// create an iterator to loop through the lines list
// append the lines to the end of the file.
Iterator<String> iterator = lines.iterator();
while (iterator.hasNext()) {
String str = iterator.next();
writer.append(str, 0, str.length);
writer.newLine();
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
Directory Tree
You can easily walk up the directory tree with the new Files
class. Once you create/extend the SimpleFileVisitor
you can use the File
class’s walkFileTree
method.
public class Main {
public static void main(String[] args) {
// point to files directory
// create new object from the MyFileVisitor class which extends SimpleFileVisitor
Path fileDir = Paths.get("files");
MyFileVisitor visit = new MyFileVisitor();
Files.walkFileTree(fileDir, visit);
}
}
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
// the SimpleFileVisitor has 4 methods that are callback methods
// you can override whichever ones you want.
public class MyFileVisitor extends SimpleFileVisitor<Path> {
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
System.out.println("Visited " + dir);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
System.out.println("About to visit " + dir);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if (attrs.isRegularFile()) {
System.out.print("Regular File: ");
}
System.out.println(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, BasicFileAttributes attrs) throws IOException {
System.err.println(exc.getMessage());
return FileVisitResult.CONTINUE;
}
}
Finding Files
You can use the PathMatcher
to look at names of each file as you encounter them. To find a file you will want to make a class that extends SimpleFileVisitor
. After use the FileFinder
object to find the file you are looking for.
public class Main {
public static void main(String[] args) {
Path dir = Paths.get("files");
FileFinder finder = new FileFinder("file.txt");
Files.walkFileTree(fileDir, finder);
ArrayList<Path> foundFiles = finder.foundPaths;
if(foundFiles.size() > 0) {
for (Path path : foundFiles) {
System.out.println(path.toRealPath(LinkOption.NOFOLLOW_LINKS));
}
}
else {
System.out.println("No files found.");
}
}
}
public class MyFileVisitor extends SimpleFileVisitor<Path> {
// PathMatcher is an interface
private PathMatcher matcher;
// hold all the files found
public ArrayList<Path> foundPaths = new ArrayList<>();
// you can compare files using the glob or regex.
public FileFinder() {
matcher = FileSystems.getDefault().getPathMatcher("glob:" + pattern)
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Path name = file.getFileName();
if (matcher.matches(name)) {
foundPaths.add(file);
}
return FileVisitResult.CONTINUE;
}
}
Watch Directory Changes
Java allows you to create a watch service that watches a directory for any changes. You use the WatchService
object to accomplish this.
public class Main {
public static void main(String[] args) {
try (WatchService service = FileSystems.getDefault().newWatchService()) {
Map<WatchKey, Path> keyMap = new HashMap<>();
Path path = Paths.get("files");
keyMap.put(path.register(service,
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY),
path);
WatchKey watchKey;
do {
watchKey = service.take();
Path eventDir = keyMap.get(watchKey);
for (WatchEven<?> event : watchKey.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
Path eventPath = (Path)event.context();
System.out.println(eventDir + ": " + kind + ": " + eventPath);
}
} while (watchKey.reset());
} catch (Exception e) {
}
}
}
Application Development
Creating JAR Files
JAR file is a java archive file that packages up your code for deployment. For eclipse you go to file -> export -> java -> jar
select all the src
and deselect classpath
and project
. Select from the check boxes (make sure “Export generated class files and resources” is selected). Select the destination. Next x 2 and ok.
Classpath
In order to run apps outside of the IDE you need to specify to the OS the class path. The class path is a list of file locations. There are two ways to do this the command or as an environment variable.
- Windows
java -classpath .;JarFileName.jar com.site.dog.Main
set CLASSPATH=.;JarFileName.jar
and then you can typejava com.site.dog.Main
- Mac
java -classpath .:JarFileName.jar com.site.juicer.Main
set CLASSPATH=.:JarFileName.jar
and then you can typejava com.site.dog.Main
Java Docs
The first step to creating java docs is to add element comments
to your code. The element comment is like a block comment but adds an extra asterisk on the first line. In eclipse you can select file -> export -> JavaDocs
and select the files you will create docs for. You can then select where you will store the doc. Since the markup is in HTML you can add a little bit of HTML into your documentation.
/**
* This is the <b>main<b> class for the app
*@author Pratik
*@version 2.0
*/
public class Main {
public static void main(String[] args) {
}
}
Reflection API
The reflection api allows you to dynamically instantiate and interrogate classes.
Class Class
Each object you create in Java has an associated class it is from. The class class uses the <>
to specify the data type but you can enter a <?>
to say it is from some class. Once you have reference from the class and object is from you can retrieve all sorts of information (see docs).
public static void main(String[] args) {
Dog d = new Dog(DogName.PUG, 0xFFFFFF);
// retrieve information about dog class
Class<?> c = d.getClass();
// get full name
System.out.println(c);
// get just the name ex: com.pratik.dog
System.out.println(c.getName());
// get only the class name
System.out.println(c.getSimpleName());
}
Instantiate Class Dynamically
You can use the Constructor<?>
data type to store constructor methods which you can then use to instantiate and object.
Class<?> c = d.getClass();
// get an array of constructors
Constructor<?>[] constructors = c.getConstructors();
// get the first constructor
Constructor<?> con = constructors[0];
Object obj = null;
// the new instance method takes arbitrary number of arguments which YOU MUST know
// you need to wrap this around a try catch block due to any exceptions
try {
obj = con.newInstance(DogName.PUG, 0xFFFFFF);
} catch (Exception e) {
e.printStackTrace();
}
Inheritance Tree
Once you have a reference to an object you can walk up the hierarchy to its superclass. Use the getSuperClass()
method to move up the hierarchy. You can walk up the tree but not down.
public class Main {
public static void main(String[] args) {
// create new object bulldog
Object obj = new Bulldog();
// get base class
Class<?> c = obj.getClass();
System.out.println("Class name: " + c.getName());
// get the superclass
Class<?> sup = c.getSuperClass();
System.out.println("Super name: " + sup.getName());
// get the superclass's super
Class<?> sup2 = c.getSuperClass();
System.out.println("Super Super name: " + sup2.getName());
// you can also get the package
Package pack = c.getPackage();
System.out.println("Package name: " + pack.getName());
}
}
Testing
Assert Keyword
Assert is a way to testing a condition in your code. You create the assert
command and then the condition after it. If it is false it throws an exception. Assert works only after you enter a command in the CLI.
To add the assert command to the command line in eclipse go to Debug Configurations
. Next select the java app and in the tab Arguments
under VM arguments
type in -ea
.
// get string input and check to see if it can convert
String str1 = InputHelper.getInput("Enter a value: ");
assert inputCheck(str1);
String str2 = InputHelper.getInput("Enter a value: ");
assert inputCheck(str2);
// code
// create a private method to check if the input can be converted to string
private static boolean inputCheck(String str) {
try {
Integer.parseInt(str);
return true;
} catch (Exception e) {
return false;
}
}
IO Stream
Read Write Byte & Character Stream
Java supports input and output streams via FileInputStream
& FileOutputStream
classes.
Below is best approach for binary characters such as images.
public class Main {
public static void main(String[] args) {
// create input and out put stream reading from text.txt and writing to newimage
// this is good for binary files such as images
try (
FileInputStream in = new FileInputStream("image.jpg");
FileOutputStream out = new FileOutputStream("newimage.jpg");
) {
// intger c to read by a single byte at a time
int c;
while ((c = in.read()) != - 1) {
// write one character to output file
out.write(c);
}
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
If you are reading & writing to text files you should use the FileReader
& FileWriter
to be able to handle all characters.
public class Main {
public static void main(String[] args) {
// create input and out put stream reading from text.txt and writing to newimage
// this is good for binary files such as images
try (
FileReader in = new FileReader("text.txt");
FileWriter out = new FileWriter("newtext.txt");
) {
// intger c to read by a single byte at a time
int c;
while ((c = in.read()) != - 1) {
// write one character to output file
out.write(c);
}
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
Buffered Stream
With large text files you should buffer the IO operations so that you are managing memory by putting data in and then taking it out once used.
public class Main {
public static void main(String[] args) {
// use BufferedReader and BufferedWriter to read long files and have a more efficient memory usage
try (
BufferedReader in = new BufferedReader(new FileReader("long.txt"));
BufferedWriter out = new BufferedWriter(new FileWriter("newlong.txt"));
) {
// intger c to read by a single byte at a time
int c;
while ((c = in.read()) != - 1) {
// write one character to output file
out.write(c);
}
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
Scan Tokenized Text
One of the most common files you will see are files that are split by specific characters such as a comma delimiter text.
public class Main {
public static void main(String[] args) {
// the default token is a space but you can use scanner's useDelimiter(pattern) to change it
try ( Scanner s = new Scanner(new BufferedReader(new FileReader("comma.txt")))) {
s.useDelimiter(",");
while (s.hasNext()) {
System.out.println(s.next());
}
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
}
}
}
Multi-Threading
Thread Class
Multi threading is the process of have multiple things going on at the same time. You can create your own classes that implements Thread
or implement and interface.
public class Main {
public static void main(String[] args) {
int iterations = 3
MyThread thread = new MyThread();
// this will cause the run method to begin from custom class
thread.start();
try {
for (int i = 0; i < iterations; i++) {
System.out.println("From main process");
// sleep will take argument in milliseconds
// must call on class directly
Thread.sleep(3000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class MyThread extends Thread {
// you have to implement run method
@Override
public void run() {
int iterations = 5;
try {
for (int i = 0; i < iterations; i++) {
System.out.println("From secondary thread");
// sleep will take argument in milliseconds
sleep(2000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Runnable Interface
You can also implement and interface called Runnable
instead of using the Thread
class.
public class Main {
public static void main(String[] args) {
int iterations = 3
MyThread thread = new MyThread();
// this will cause the run method to begin from custom class
thread.start();
// must create runnable object
MyRunnable run = new MyRunnable();
// anonymous method
new Thread(run).start();
try {
for (int i = 0; i < iterations; i++) {
System.out.println("From main process");
Thread.sleep(2000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// You are implementing the Runnable interface.
public class MyThread implements Runnable {
// you have to implement run method
@Override
public void run() {
int iterations = 5;
try {
for (int i = 0; i < iterations; i++) {
System.out.println("From runnable");
// sleep will take argument in milliseconds
// when you implement Runnable you lose access to the Thread class's methods
Thread.sleep(4000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Interrupt Thread
The thread runs until it completes, or its interrupted or you explicitly interrupt it. You can use the interrupt method to break the thread.
public class MyThread extends Thread {
@Override
public void run() {
int iterations = 5;
try {
for (int i = 0; i < iterations; i++) {
System.out.println("From secondary thread");
sleep(2000);
}
} catch (InterruptedException e) {
System.err.println("Interrupted!");
}
}
}
public class Main {
public static void main(String[] args) {
int iterations = 3
MyThread thread = new MyThread();
thread.start();
try {
for (int i = 0; i < iterations; i++) {
System.out.println("From main process");
Thread.sleep(3000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
// interrupt a thread thats being executed.
thread.interrupt();
System.out.println("Call interrupt");
}
}
Synchronize Threads
In applications there are times when multiple threads need to share resources and you will have to synchronize so that the thread can only access the resources one at a time.
public class Main {
public static void main(String[] args) {
TargetClass tgt = new TargetClass();
// create multiple instances of MyThread object
MyThread t1 = new MyThread(1, tgt);
MyThread t2 = new MyThread(2, tgt);
MyThread t3 = new MyThread(3, tgt);
// start all of the threads
t1.start();
t2.start();
t3.start();
}
}
public class TargetClass {
public void call(int threadId) {
System.out.println("Call from " + threadId);
}
}
public class MyThread extends Thread {
private int threadId;
private TargetClass target;
// create constructor to save values as private fields
public MyThread(int threadId, TargetClass target) {
this.threadId = threadId;
this.target = target;
}
@Override
public void run() {
// create synchronized code block and pass in a target
// only one of the thread objects will be able to access this method at a time
// the execution does not guarantee what order the objects will be executed in
synchronized(target) {
try {
sleep(2000);
}
} catch (InterruptedException e) {
System.err.println("Interrupted!");
}
target.call(threadId);
}
}
}