The use of the term 'compilation' with computer programs means
'translation' from the source code we write to a form that can be executed.
There are several implementations of java compiler and
tools.
I will describe the tools from Oracle's JDK (software development
kit).
The compiler is a program javac.
Java programs should be written and saved in in files with extent .java such
as Hello.java.
This file is compiled with the javac compiler:
javac Hello.java
The result is a new file named Hello.class
The Hello.class file is not a text file (it isn't composed of
'lines' of text), but it also doesn't contain machine code.
It contains an intermediate form of code called java
byte code.
The java byte code in the Hello.class file is similar to
machine code, but is not the same and cannot be executed directly
like programs that have been compiled (translated) to machine
code.
Instead, another program called java, opens the
Hello.class file and reads and executes the byte code
instructions in that file.
The java program plays the same role in executing
byte code as the hardware machine does in executing machine
instructions.
For this reason, the java program is referred to as the
java virtual machine.
The java program only works for .class files and assumes
that any file given to it will have the .class extent.
So the .class part of the name should be omitted when
executing Hello.class:
java Hello
Even the simplest java program requires quite a lot of
syntactic elements:
1 public class Hello
2 {
3 public static void main(String[] args)
4 {
5 System.out.println("Hello, world!");
6 }
7 }
Line 1:
All java code must be inside a class.
A file that contains the public class Hello
should be named Hello.java
Line 3:
Every java program executed by the java virtual
machine must have a method ( = function ) called
main.
The return type of main must be
void
main must be qualified to be public and static
The single parameter must be of type an array of
Strings.
Note: The name of the parameter to main is typically chosen to
be args, but can be any programmer chosen name.
To write and execute Java programs on your machine, you will
need to first install the java JDK.
Instructions are provided on the class Documents page.
Next, you will need a text editor or an IDE (Integrated
Development Environment) to write your .java file(s).
Do not use Microsoft Word or WordPad. Word inserts hidden
formatting and may capitalize first letters of java keywords
that it shouldn't.
Notepad would be ok, but there are much better choices if you
are going to use a simple text editor.
Although a bit more complicated to learn, an IDE has many
advantages initially and also as you become a more expert java
programmer.
I will recommend using the Eclipse IDE and will use it in
class examples.
Another very similar IDE is NetBeans, which can be downloaded
from Oracle's site together with the JDK.
Both these IDE's provide a single place to:
- Write java programs
- Compile
- Execute
- Debug (E.g., step through execution one instruction at a time)
Instructions for installing and using Eclipse are also on the Documents page.
Note that the JDK should be installed first and then Eclipse
(except for Mac's).
Every variable or expression in Java has a type.
In Java, these types fall into exactly two categories:
- Basic types
- Class types
Variables of basic type have storage allocated of the correct
size to hold a value of that type.
Variables of class type have storage allocated only to hold a
reference to a value of that type.
References are essentially addresses and addresses are the
same size regardless of the value to which they refer.
The basic types are familiar numeric and boolean types:
boolean true, false
char 16 bit unicode representation of a character
byte 8 bit signed integer
short 16 bit signed integer
int 32 bit signed integer
long 64 bit signed integer
float 32 bit IEEE floating point number
double 64 bit IEEE floating point number
Using the "new" operator allocates memory on the "heap" for an
instance of the type.
Declaring a local variable in a method, allocates memory
for the variable on the call stack.
The base types are value types; that is, variables
declared of these types are assigned memory locations of the size
determined by the type without having to allocate memory
explicitly using "new".
The array type is not a basic type in Java; it is a class
type.
Example declaration
int[] arr;
This declaration does NOT create a array. Like all class type
variables, storage for arr is just for a reference.
To create an array object, the new operator is
necessary:
int[] arr; // declares the type of arr
arr = new int[10]; // creates storage for an array of 10
// each gets the default value of int type - 0
int[] brr;
brr = arr; // This only copies the reference, it does NOT
// create a new integer array
brr[0] = 10;
// Now arr[0] is also 10
This example uses Sedgewick's stdlib classes.
public class Average {
public static void main(String[] args) {
StdIn.fromString ("10.0 5.0 6.0 3.0 7.0 32.0");
int count = 0; // number input values
double sum = 0.0; // sum of input values
// read data and compute statistics
while (!StdIn.isEmpty()) {
double value = StdIn.readDouble();
sum += value;
count++;
}
// compute the average
double average = sum / count;
// print results
StdOut.println("Average is " + average);
}
}
This example uses the standard Java API classes:
1 import java.util.Scanner;
2
3 public class AverageX {
4
5 public static void main(String[] args) {
6
7 Scanner stdin = new Scanner(System.in);
8
9 int count = 0; // number input values
10 double sum = 0.0; // sum of input values
11
12 // read data and compute statistics
13 while (stdin.hasNextDouble()) {
14 double value = stdin.readDouble();
15 sum += value;
16 count++;
17 }
18
19 // compute the average
20 double average = sum / count;
21
22 // print results
23 System.out.println("Average is " + average);
24 }
25 }
This is the same example, but reads input from a file and uses
the Java API Scanner class for input.
1 import java.util.Scanner;
2
3 public class AverageY {
4
5 public static Scanner openInput(String fileName) {
6 Scanner in = null;
7 try {
8 in = new Scanner(new File(fileName));
9 } catch(FileNotFoundException e) {
10 System.out.println("Cannot open input file: " + fileName);
11 System.exit(0);
12 }
13 return in;
14 }
15
16 public static void main(String[] args) {
17
18 Scanner stdin = new Scanner(System.in);
19 String fname;
20
21 System.out.print("Input file: ");
22 fname = stdin.next();
23
24 Scanner in = openInput(fname);
25
26 int count = 0; // number input values
27 double sum = 0.0; // sum of input values
28
29 // read data and compute statistics
30 while (in.hasNextDouble()) {
31 double value = in.readDouble();
32 sum += value;
33 count++;
34 }
35
36 // compute the average
37 double average = sum / count;
38
39 // print results
40 StdOut.println("Average is " + average);
41 }
42 }
Classes can define types. Here is a toy CashRegister
class.
- It has no main method, so it can't be executed
by itself.
- It has both static and non-static data members.
- It has a Constructor
- It has non-static methods.
1
2 public class CashRegister
3 {
4 public static final double QUARTER = 0.25;
5 public static final double DIME = 0.10;
6 public static final double NICKEL = 0.05;
7 public static final double PENNY = 0.01;
8
9 private double purchase;
10 private double payment;
11
12 public CashRegister() {
13 purchase = 0;
14 payment = 0;
15 }
16
17 public void recordPurchase(double amount) {
18 purchase += amount;
19 }
20
21 public void enterPayment(int dollars, int quarters, int dimes,
22 int nickels, int pennies) {
23 payment = ...;
24
25 }
26
27 public double giveChange() {
28 double change = payment - purchase;
29 purchase = 0;
30 payment = 0;
31 return change;
32 }
33
34 }
1 /**
2 * A class to test a CashRegister class.
3 */
4
5 public class CashRegisterTester {
6
7 public static void main(String[] args) {
8 CashRegister register = new CashRegister();
9 double price1, price2;
10 double payment;
11 price1 = 29.50;
12 price2 = 9.25;
13 payment = 50.00;
14
15 register.recordPurchase(29.50);
16 register.recordPurchase(9.25);
17 register.enterPayment(50);
18
19 double change = register.giveChange();
20 System.out.printf("Your change is %.2f. Have a nice day!\n", change);
21
22 System.exit(0);
23 }
24 }
Note: After line 16, this program cannot access the total purchase
amount although it is stored in the member
register.purchase
because purchase is private.
Local variables in the method main declared as the basic type double:
price1, price2, payment and change
The call stack is storage for local variables of methods.
Storage for local variables is allocated on the top of the
stack when a method begins and is removed from the top of the
stack when the method finishes (returns).
Local variable register is of type CashRegister
which is a user defined class type.
A class type has methods that can be called that require a
value of that type plus 0 or more additional parameters. The
number of parameters depends on the particular method.
The user defined CashRegister type has these public methods:
void recordPurchase(double amt)
void enterPayment(double amt)
double giveChange()
A CashRegister instance stores the total dollar amount
of all purchases until payment is made in the private member
purchase. For each call to
recordPurchase, this total is updated.
When enterPayment is called, another CashRegister private
member, payment,
stores the amount of the payment.
Finally when giveChange is called, the change is calculated
(payment - purchase) and is returned.
Each instance of the CashRegister type keeps its own stored
payment and purchase amounts.
To call an CashRegister instance method requires a
CashRegister instance.
The dot operator is required:
CashRegister register = new CashRegister();
register.recordPurchase(29.50);
^ ^
| |
CashRegister CashRegister
instance instance method
The basic types are value types; that is, variables
declared of these types are assigned memory locations of the
size determined by the type without having to allocate memory
explicitly using "new".
Assignment of value types makes
a copy of the value and stores the copy in the target of the
assignment.
short s1 = 512;
short s2;
s2 = s1;
s2++;
Now s2 is 513, but s1 is 512.
A Java class defines a type.
An instance of a class is a value of that type.
A variable declared as a class type is not allocated memory to
hold a value of the size of the type.
A variable declared of class type is automatically allocated
memory to hold a reference, either
null or the address of a class instance.
Declaring a local variable in a method of class type allocates
memory for the reference (address or null) only on the call stack.
Class instances can only be allocated using "new" and so
instance values are always located on the heap, not on the call stack.
Assignment of reference types does not make a copy of the value
referenced (a copy of the address is made);
StringBuffer s1 = new StringBuffer("abc");
StringBuffer s2;
s2 = s1;
s1.append("de");
Now s1 and s2 both reference the StringBuffer with value
"abcde"; there is only one StringBuffer.
There are only a few basic types, but Java library of class
types is huge and continues to grow.
This library is an Application Programmer Interface (API)
of class types that makes programming applications
more productive.
You don't have to build everything from scratch;
there is often some existing class type or types in the Java API
that can be used.
It isn't necessary or feasible to remember
all of the class types and all the methods for
each class type in the Java API.
The Java API documentation plus documentation on the java
compiler and other tools is readily available in html format on Oracle's web
site and can also be downloaded to your machine.
http://docs.oracle.com/javase/6/docs/
The API index itself is at
http://docs.oracle.com/javase/6/docs/api/index.html
For integers, addition, subtraction and multiplication have the ususal
meanings and division truncates the decimal part. The mod
operator % computes the integer remainder
int x = 25, y = 10;
int ans;
ans1 = x + y; // ans1 is 35
ans1 = x - y; // ans1 is 15
ans1 = x * y; // ans1 is 250
ans1 = x / y; // ans1 is 2
ans1 = x % y; // ans1 is 5
int x = 5;
int y = 10;
double z = 3.4;
Post increment operators increment the variable after
computing its current value.
| Expression |
Value |
Changed Variables |
x++ y++ z++ |
5 10 3.4 |
x is 6 y is 11 z is 4.4 |
int x = 5;
int y = 10;
double z = 3.4;
Pre increment operators increment the variable before
computing its value.
| Expression |
Value |
Changed Variables |
++x ++y ++z |
6 11 4.4 |
x is 6 y is 11 z is 4.4 |
Two numeric but different base types: byte, short, long, float,
double cannot be added without first converting one of them so
that values of the same numeric type added.
Conversions can be made between any of these types with the
possible loss of precision due to the differences in size or
representation.
The types have an ordering:
byte -> short -> int -> long -> float -> double
A conversion of any one of these types to a type farther to the
right in the ordering is called a widening conversion.
A conversion of one type to a type to its left is called a
narrowing conversion.
Widening conversions are done automatically by the compiler.
byte b = 127;
short s;
s = b; // Ok. A widening conversion byte -> short
Narrowing conversions require a cast.
short s = 512;
byte b;
b = (byte) s;
The char type is the same memory size as a short.
A char value can be converted to a short and the other way
around as well.
However, neither is a widening conversion. Ordering including char:
byte -> short -> int -> long -> float -> double
/
/
char --/
That is, char -> int is a widening conversion. So
Ex1.
char ch = 'A';
int n;
n = ch; // Ok. A widening conversion.
n = 66;
ch = (char) n; // narrowing conversion requires a cast
But,
Ex2.
short s = 65;
char ch;
ch = (char) s; // Can be converted, but not widening; reqires cast
ch = 'B';
s = (short) ch; // Can be converted, but also not widening; reqires cast
Variable can be declared as constant so that no subsequent
changes are allowed. The purpose is to have a symbolic
name for a value that indicates more clearly its use.
Java syntax:
final int MAX_SCORE = 120;
MAX_SCORE = 100; // ERROR!
The String class type has many convenient instance
methods. For example,
- String replace(char oldchar, char newchar)
- String toUpperCase()
- String toLowerCase()
- String substring(int startPos, int endPos)
- boolean startsWith(String prefix)
- int length()
Remember, these methods cannot be called without using the
dot operator and a String instance.
Replace all i's with the character '1' and all s's with the
character '$' in the string "Mississippi".
/**
* Description: Exercise p2.9. Test string replace method.
*
* @author Glenn Lancaster
*
*/
public class ReplaceTester
{
public static void main(String[] args)
{
String original = "Mississippi";
String newstring;
String expected = "M1$$1$$1pp1";
newstring = original.replace('i', '1');
newstring = newstring.replace('s', '$');
System.out.println("Original String: " + original);
System.out.println("Replaced String: " + newstring);
System.out.println(" Expected: " + expected);
}
}
Note that the + operator with String operands is overloaded
to mean concatenation of strings.
The Java API class BigInteger allows "infinite" precision
integer arithmetic.
But the usual operator symbols: + - * / cannot be used.
Instead the BigInteger class has instance methods:
- BigInteger add(BigInteger second)
- BigInteger subtract(BigInteger second)
- BigInteger multiply(BigInteger second)
- BigInteger divide(BigInteger second)
- BigInteger pow(int exponent)
import java.math.BigInteger;
public class ex3 {
public static void main(String[] args) {
BigInteger bi;
bi = new BigInteger("2");
bi = bi.pow(1000);
System.out.println(bi);
}
}
Output:
107150860718626732094842504906000181056140481170553360744375038
837035105112493612249319837881569585812759467291755314682518714
528569231404359845775746985748039345677748242309854210746050623
711418779541821530464749835819412673987675591655439460770629145
71196477686542167660429831652624386837205668069376
For class types methods can be either
- instance methods, or
- static methods
So far we have looked only at instance methods.
To call either kind of method, you must use the dot
operator.
For an instance method, the operand to the left of the dot
must be an instance of the class.
But for a static method, no instance is needed. In that case,
the operand to the left of the dot is just the class name.
The Java Math class has many static methods
including:
- double sqrt(double x)
- int abs(int x)
- double abs(double x)
- double pow(double base, double exponent)
- int max(int x, int y)
- double max(double x, double y)
- int min(int x, int y)
- double min(double x, double y)
public class ex4
{
public static void main(String[] args)
{
double x = 2.0;
double y = Math.sqrt(x);
System.out.println("square root of " + x + " is " + y);
System.out.printf("square root of %.1f is %.6f\n", x, y);
}
}
Output:
square root of 2.0 is 1.4142135623730951
square root of 2.0 is 1.414214
System.out is an instance of type PrintStream
PrintStream methods
- void print(..)
- void println(..)
- void println()
- void printf(String fmt, ...)
The first two are designed to convert the argument to a suitable
character string.
The second inserts newline in the output.
The third only outputs a newline.
The printf method provides formatting of the output.
The number of parameters to printf depends on the number of
conversion specifications in the first parameter - the format string.
1
2 public class PrintfTester
3 {
4 public static void main(String[] args)
5 {
6 double x, y, z, sum;
7 x = Math.random() * 100;
8 y = Math.random() * 100;
9 z = Math.random() * 100;
10
11 sum = x + y + z;
12
13 System.out.printf("%10s %6.2f\n", "first", x);
14 System.out.printf("%10s %6.2f\n", "second", y);
15 System.out.printf("%10s %6.2f\n", "third", z);
16 System.out.printf("%10s ------\n", "");
17 System.out.printf("%10s %6.2f\n", "sum", sum);
18 }
19 }
Output:
first 93.60
second 3.13
third 49.83
------
sum 146.56
If the number of character positions in a format
specification is larger than needed, spaces are added.
By default spaces are added to the beginning of the value so
that it appears to be right justified in the
output.
To get left justification insert a minus sign; e.g. replace
all the %10s format specifications by %-10s in the previous example.
Then the output would be
first 93.60
second 3.13
third 49.83
------
sum 146.56
System.in is an instance of type InputStream
InputStream methods are not so convenient.
int read()
This method returns one byte from the input each time it is
called. It returns -1 at end of file.
How would you read the integers in a file?
Scanner is a type.
There are no predefined instances of this type and no useful
static methods..
We must declare a variable of this type and initialize it to
use the Scanner methods.
Scanner methods:
- String next()
- String nextLine()
- int nextInt()
- double nextDouble()
- boolean hasNext()
- boolean hasNextLine()
- boolean hasNextInt()
- boolean hasNextDouble()
import java.util.Scanner;
/**
* A class to test the CashRegister class.
*/
public class CashRegisterTester {
public static void main(String[] args) {
CashRegister register = new CashRegister();
Scanner in = new Scanner(System.in);
System.out.println("Price for first item:");
double price1 = in.nextDouble();
System.out.println("Price for second item:");
double price2 = in.nextDouble();
System.out.println("Payment amount:");
double payment = in.nextDouble();
register.recordPurchase(price1);
register.recordPurchase(price2);
register.enterPayment(payment);
double change = register.giveChange();
System.out.printf("Your change is %.2f. Have a nice day!\n",
change);
System.exit(0);
}
}
import java.util.Scanner;
1 public class ScannerInputTester
2 {
3 public static void main(String[] args)
4 {
5 Scanner in;
6 int first, second, larger;
7
8 in = new Scanner(System.in);
9 System.out.print("Enter first integer: ");
10 first = in.nextInt();
11 System.out.print("Enter second integer: ");
12 second = in.nextInt();
13 larger = Math.max(first, second);
14 System.out.printf("The larger of %d and %d is %d\n",
15 first, second, larger);
16 }
17 }
The JOptionPane class provides a graphical interface for
prompting for small amounts of input or for displaying
messages or relatively small amount of output.
import javax.swing.JOptionPane;
/**
* A class to test the CashRegister class.
*/
public class CashRegisterTester2 {
public static void main(String[] args) {
CashRegister register = new CashRegister();
double price1, price2, payment, change;
String reply;
reply = JOptionPane.showInputDialog("Price for first item:");
price1 = Double.parseDouble(reply);
reply = JOptionPane.showInputDialog("Price for second item:");
price2 = Double.parseDouble(reply);
reply = JOptionPane.showInputDialog("Payment amount:");
payment = Double.parseDouble(reply);
register.recordPurchase(price1);
register.recordPurchase(price2);
register.enterPayment(payment);
change = register.giveChange();
JOptionPane.showMessageDialog(null, "Your change is " + change);
System.exit(0);
}
}
-
This example uses yet another useful static method from
the wrapper class Double. It converts the String parameter,
str, to a double value and returns the double:
double parseDouble(String str)
-
At the end of main there is a call to the static method
exit in the System class:
void exit(int exitValue)
This call will terminate a program whenever it is
called. It can be placed in any method, not just main.
It is useful when using JOptionPane dialogs to avoid a
delay in program termination.
F(0) = 0
F(1) = 1
F(N) = F(N - 1) + F(N - 2) if N > 1.
In java:
1
2 public class Fibonacci {
3 public static int F (int N) {
4 if (N == 0) return 0;
5 if (N == 1) return 1;
6 return F (N - 1) + F (N - 2);
7 }
8
9 public static void main (String[] args) {
10 for (int N = 0; N < 25; N++) {
11 System.out..println (N + " " + F(N));
12 }
13 }
14 }
1
2 import stdlib.*;
3 import java.util.Arrays;
4 public class BinarySearch {
5
6 /**
7 * find the first index in array a where key occurs
8 * @param key the value to search for in a
9 * @param a the array
10 * @returns the first index in array a where key occurs
11 * or -1 if key does not occur in array a
12 */
13 public static int rank1(int key, int[] a) {
14 for (int i = 0; i < a.length; i++)
15 if (a[i] == key) return i;
16 return -1;
17 }
18
19 /**
20 * find the first index in the sorted array a where key occurs;
21 * this is the same as the number of array elements < key.
22 * @param key the value to search for in a
23 * @param a the array; a is required to be sorted!
24 * @returns the first index in array a where key occurs
25 * or -1 if key does not occur in array a
26 */
27 public static int rank2(int key, int[] a) {
28 int lo = 0;
29 int hi = a.length - 1;
30 while (lo <= hi) {
31 // key is in a[lo..hi] or not present.
32 int mid = (lo + hi) / 2;
33 if (key < a[mid]) {
34 hi = mid - 1;
35 } else if (key > a[mid]) {
36 lo = mid + 1;
37 } else {
38 return mid;
39 }
40 }
41 return -1;
42 }
43
44 /**
45 * Recursive version of rank2
46 */
47 public static int rank3(int key, int[] a) {
48 return rank (key, a, 0, a.length - 1);
49 }
50 public static int rank3(int key, int[] a, int lo, int hi) {
51 if (lo > hi) {
52 return -1;
53 } else {
54 int mid = (lo + hi) / 2;
55 if (key < a[mid]) {
56 return rank3(key, a, lo, mid - 1);
57 } else if (key > a[mid]) {
58 return rank3(key, a, mid + 1, hi);
59 } else {
60 return mid;
61 }
62 }
63 }
64
65 public static void main(String[] args) {
66 String fname = "largeW.txt";
67 StdIn.fromFile ("largeT.txt");
68
69 int[] whitelist = In.readInts(fname);
70
71 Arrays.sort(whitelist);
72
73 // read key; print if not in whitelist
74 while (!StdIn.isEmpty()) {
75 int key = StdIn.readInt();
76 if (rank(key, whitelist) == -1)
77 StdOut.println(key);
78 }
79 }
80 }