Chapter 3 Fundamental Programming Structures in Java
3.1 A Simple Java Program
public class FirstSample
{
public static void main(String[] args)
{
System.out.println("We will not use 'Hello, World'");
}
}
Java is case sensitive
Everything in Java lives inside a class
—a container for the program logic that defines the behavior of an application.
The keyword public
is an access modifier.
Java classes must begin with a letter. After that, they can have any combination of letters and digits.
Class naming convention is that classes are nouns that start with an uppercase letter. If the class name is multiple words, capitalize each word. (i.e., CamelCase).
The file name is the same as that of the public class with .java
appended (e.g., FirstSample.java
.
Compiling sourcecode creates bytecode. The java compiler automatically names the bytecode file FirstSample.class
and stores it in the same directory as the source file.
Launch the program by issuing the following command:
java FirstSample
The Java Virtual Machine (JVM) always starts execution with the code in the main
method in the class you indicate. You must have a main method in the source file for the code to execute.
According to the Java Language Specification the main
method must be declared public.
See:
http://docs.oracle.com/javase/specs/jls/se8/html/index.html
Braces { } delineate code blocks e.g., methods and classes. Braces mark the beginning and end of the body of a method.
In Java, all methods are functions of some class.
Method calls have the structure: object.method(parameters)
System.out
= object. println
= method. "We will not use 'Hello, World'"
= parameter.
Java statements are like sentences, and each ends with a semicolon: ;
.
System.out.println
adds a newline, whereas System.out.print
does not.
3.2 Comments
Note the three types of commenting Java offers in the following code:
/**
* Documentation comment - note the: /**
* This is the first sample program in Core Java Chapter 3
* @version 1.01 1997-03-22
* @author Gary Cornell
*/
public class FirstSample
{
public static void main(String[] args)
{
System.out.println("We will not use 'Hello, World!'");
// Single line comment.
}
}
/*
* Multi
* Line
* Comment
*/
3.3 Data Types
Java is a Strongly-typed language. This means that every variable has to have a declared type.
There are eight Primitive Types in Java:
Four of them are Integer Types int, short, long, byte
Two of them are Floating Point Number Types float, double
One is the Character Type, char
One is the boolean Type
Note: Java has an arbitrary-position arithmetic package. However, "big numbers" are Java objects, not a new Java type.
3.3.1 Integer Types
For numbers (positive or negative) witout fractional parts.
Java Integer Types:
Type | Storage Requirement | Range |
---|---|---|
int
|
4 bytes | -2,147,483,648 to 2,147,483,647 |
short
|
2 bytes | -32,768 to 32,767 |
long
|
8 bytes | -9,223,372,036,854,775,808 to -9,223,372,036,854,775,807 |
byte
|
1 byte | -128 to -127 |
The int
is the most practical and common. long
is for larger numbers, byte
and short
types are for specialized applications, i.e., low-level file handling or large arrays when storage space is at a premium.
In Java, the ranges of the above integer types are the same on every machine making it easier to move software from one platform to another or between operating systems. In contrast, C and C++ use the most efficient integer type for each processor, meaning that programs that run well on 32-bit may exhibit integer overflow on 16-bit systems.
Long Integer Numbers have a suffix: L
or l
e.g., 40000000L
.
Hexidecimal Numbers (e.g., HEX colors) have the prefix: 0x
or 0X
e.g., 0xCAFE
Octal Numbers have the prefix: 0
e.g., 010
is 8
Binary Numbers have the prefix: 0b
or 0B
e.g., 0b1001
is 9.
You can add underscores to integer types to make the numbers easier to read, e.g.; 1_000_000
or 0b1111_0100_0010_0100_0000
both equal 1,000,000.
3.3.2 Floating-Point Types
Floating Point Types are for numbers with fractional parts.
Java Floating Point Types:
Type | Storage Requirement | Range |
---|---|---|
float
|
4 bytes | Approximately ±3.40282347E+38F (6-7 significant decimal digits) |
double
|
8 bytes | Approximately ±1.79769313486231570E + 308 (15 significant decimal digits) |
The name double
means these numbers have twice the precision of the float type. AKA double-precision numbers.
float
s have limited precision. Use them only when working with a library that requires them or when you need to store a very large number of them.
Floats have a suffix f
or F
e.g., 3.14F
. Floating-point numbers without the F
are considered to be of type double
.
Also, Doubles can have the suffix: D
or d
e.g., 3.14D
.
You can specify floating-point literals in hexadecimal: 0.125 = 2 -3 can be written as: 0x1.0p-3
(The mantissa is written in hexadecimal and the exponent is written in decimal and has base 2 [not 10]).
There are three special floating-point values to denote overflows and errors:
- Positive Infinity
- Negative Infinity
- NaN (not a number)
The result of dividing a positive number by 0 is positive infinity. 0/0 or the square root of a negative number yields NaN.
Floating point numbers are not suitable for financial calculations in which round-off errors cannot be tolerated. Floating point numbers are represented by the binary number system and, for example, there is no precise binary representation of the fraction 1/10 just as there is no accurate representation of the fraction 1/3 in the decimal system.
The BigDecimal
class can be used for precise numerical computations.
3.3.3 The char
Type
The char
type was originally intended to describe individual characters.
Unicode has been added to over the years and while some Unicode characters can still be described with one char
value, others now require two.
Literal values of type char
are enclosed in single quotes
'A'
is a character constant with value 65.
Values of type char
can be expressed as hexadecimal values from \u0000
to \uFFFF
.
Escape sequences can be used inside quoted character literals and strings e.g., '\u2122'
or "Hello\n"
.
The \u escape sequence (but not the others) can be used outside of quoted character constants and strings, for example:
public static void main(String\u005B\u005D args)
Unicode escape sequences are processed before the code is parsed—so be wary of using \u
in comments etc.
Escape Sequences for special characters
Escape Sequence | Name | Unicode Value |
---|---|---|
\b
|
Backspace |
\u0008
|
\t
|
Tab |
\u0009
|
\n
|
Linefeed |
\u000a
|
\r
|
Carriage return |
\u000d
|
\"
|
Double Quote |
\u0022
|
\'
|
Single Quote |
\u005c
|
3.3.4 Unicode and the char
Type
Historically, the byte was the number of bits used to encode a single character of text in a computer.
Where a byte had 8 bits, this allowed for 256 (0 to 255) or 28 characters.
Unicode was developed in the late 1980's to address the problem of multiple character encoding schemes
Unicode coded each character with 2 bytes and thus offered 216 or 65,536 characters.
In Java, beginning in Java SE 5.0, A code point is a code value that is associated with a character in an encoding scheme.
Unicode has code points that are grouped into 17 code planes.
The basic multilingual plane contains "classic" Unicode characters U+0000
to U+FFFF
.
Sixteen additional planes with code points U+10000
to U+10FFFF
hold supplementary characters.
The values in the basic multilingual plane are represented as 16-bit values called, code units.
The supplementary characters are encoded as consecutive pairs of code units, and these code units are from what's called the surrogates area—a range of 2048 unused values from the multilingual plane.
3.3.5 The boolean
Type
The boolean
type has two values: false and true. It is used for evaluating logical conditions and you cannot convert between integers and boolean
values.
3.4 Variables
In Java, every variable has a type, and a variable is declared by placing the type before the variable name:
double salary;
int vacationDays;
long earthPopulation;
boolean done;
3.4.1 Initializing Variables
A variable is initialized with an assignment statement — variable name on the left, equals sign ( = ), and a Java expression with an appropriate value on the right.
int vacationDays
vacationDays = 12
double salary = 65000.0
In Java it is considered good practice to declare variables as closely as possible to where they are first used.
3.4.2 Constants
In Java, you use the keyword final
to denote a Constant.
final double CM_PER_INCH = 2.54;
The keyword final
indicates that you can assign to the variable only once. It is customary to name Constants in all UPPERCASE.
Class Constants are available to multiple methods inside a single class. A Class Constant is set up with the keywords static final
(usually directly inside the class scope before any constructors/methods).
public static final double CM_PER_INCH = 2.54;
3.5 Operators
Arithmetic operators +, -, *, / denote addition, subtraction, multiplication and division.
The / denotes integer division if both numbers are integers and floating point division otherwise.
The % denotes integer remainder or modulus.
15 / 2 = 7
15 % 2 = 1
15.0 / 2 = 7.5
3.5.1 Mathematical Functions and Constants
The Math
class contains numerous mathematical functions
double x = 4;
double y = Math.sqrt(x);
System.out.println(y); // prints 2.0
double y = Math.pow(4, 2);
System.out.println(y); // prints 16.0
The pow
method's parameters are both of type double
and it returns a double
as well.
The documentation for Java's Math class.
3.5.2 Conversions between Numeric Types
Conversions between numbers in Java can sometimes result in information loss as shown in the image below:
For example, a large integer such as 123456789
has more digits than the float
type can represent.
int n = 123456789;
float f = n; // f is 1.23456792E8
Type Conversion For Two Values
When two values are combined with a binary operator (e.g., n + f
where n
is an integer and f
is a floating point value) both operands are converted to a common type before the operation is carried out.
-
If either of the operands is a
double
the other one will be converted to adouble
. -
Otherwise, if either of the operands is a
float
the other will be converted to afloat
. -
Otherwise, if either of the operands is a
long
the other will be converted to along
. -
Otherwise, both operands will be converted to an
int
.
3.5.3 Casts
The syntax for casting is to give the target type in parentheses followed by the variable name.
double x = 9.997;
int nx = (int) x;
Now, the variable nx
has the value of 9 because casting a floating point number to an integer discards the fractional part.
To round a floating point number to the nearest integer, use the Math.round
method:
double x = 9.997;
int nx = (int) Math.round(x);
Now, the variable nx
has the value of 10. Note the cast to (int)
. Math.round
normally returns a long
.
3.5.4 Combining Assignment with Operators
An alternative to using binary operators in assignment:
x += 4;
Is equivalent to:
x = x + 4;
3.5.5 Increment and Decrement Operators
/** POSTFIX FORM **/
int n = 12;
n++ // Returns 13
int x = 5;
x-- //Returns 4
4++ // NOT LEGAL - these operators change the value of a variable.
/** PREFIX FORM **/
// The difference appears when they are used inside expressions.
// Prefix form does addition first.
// Postfix form evaluates to the old value of the variable.
int m = 7;
int n = 7;
int a = 2 * ++m // now a is 16, m is 8
int b = 2 * n++; // now b is 14, n is 8
3.5.6 Relational and boolean
Operators
3 == 7 // EQUALITY (is false)
3 != 7 // INEQUALITY (is true)
3 < 7 // LESS THAN (is true)
3 > 7 // GREATER THAN (is false)
3 >= 7 // GREATER THAN OR EQUAL TO (is false)
3 <= 7 // LESS THAN OR EQUAL TO (is true)
x > 5 && x < 10 // && is the LOGICAL AND OPERATOR
x > 20 || x < 10 // LOGICAL OR OPERATOR
x != 0 // ! is the LOGICAL NEGATION OPERATOR
// SYNTAX
// expression1 && expression2
// if the first expression is false, the second isn't calculated:
x != 0 && 1 / x > x + y // prevents division by 0
// TERNARY OPERATOR
// SYNTAX:
// condition ? expression1 : expression2
x < y ? x : y // gives the smaller of x and y
3.5.7 Bitwise Operators
/**
BITWISE OPERATORS
& // ("and")
| // ("or")
^ // ("xor")
˜ // ("not" or "compliment") "flips" bits
<< // ("left shift") The left operands value is moved left by
the number of bits specified by the
right operand.
>> // ("right shift") The left operands value is moved right by
the number of bits specified by the right
operand.
>>> // ("zero fill right shift") The left operands value is moved
right by the number of bits specified
by the right operand and shifted
values are filled up with zeros.
a = 0011 1100
b = 0000 1101
-----------------
a&b = 0000 1100 which is 12
a|b = 0011 1101 which is 61
a^b = 0011 0001 which is 49
~a = 1100 0011 which is -61
a << 2 = 1111 0000 which is 240
a >> 2 = 1111 which is 15
a >>> 2 = 0000 1111 which is 15
**/
int fourthBitFromRight = (n & 0b1000) / 0b1000;
3.5.8 Parentheses and Operator Hierarchy
If no partentheses are used, operations are performed in the heirarchical order indicated in the table below.
Operators on the same level are processed from left to right except for those that are right-associative.
Since && has a higher precedence than ||
a && b || c
means
(a && b) || c
Since += associates right to left...
a += b += c
means
a+= (b += c)
Operators | Associativity |
---|---|
[] . () (method call)
|
Left to Right |
! ~ ++ -- + (unary) - (unary) () (cast) new
|
Right to Left |
* / %
|
Left to Right |
+ -
|
Left to Right |
<< >> >>>
|
Left to Right |
< <= > >= instanceof
|
Left to Right |
== !=
|
Left to Right |
&
|
Left to Right |
^
|
Left to Right |
|
|
Left to Right |
&&
|
Left to Right |
||
|
Left to Right |
?:
|
Right to Left |
= += -= *= /= %= &= |= ^= <<= >>= >>>=
|
Right to Left |
3.5.9 Enumerated Types
Sometimes, a variable should only hold a restricted set of values. For example pizza or clothes can be sold in four sizes: small, medium, large, extra large. We could use integers 1, 2, 3, 4 or characters S, M, L, XL, but this is an error-prone setup. It's too easy to use the wrong value (0 or m, for example).
You can define an enumerated type — a type with a finite number of named values:
enum Size = {SMALL, MEDIUM, LARGE, EXTRA_LARGE};
Now, you can declare a variable of the Size
type:
Size s = Size.MEDIUM;
A variable of type Size
can only hold one of the values listed in the type declaration or null
.
3.6 Strings
Java strings are sequences of Unicode Characters. Java does not have a built-in string type, but instead contains a pre-defined class called String
. Each quoted string is an instance of the String
class.
String e = ""; // an empty string.
String greeting = "Hello";
The Java String class documentation.
3.6.1 Substrings
Extract a substring with the substring
method:
Positions are zero-indexed.
The first parameter is the first letter to be included.
The second parameter is the first letter to be excluded.
The length of s.substring(a, b)
always has length b - a
String greeting = "Hello";
String s = greeting.substring(0, 3);
// s = "Hel"
3.6.2 Concatenation
String h = "Hello, "; // note space
String w = "World";
String message = h + w;
// message = "Hello, World";
// When you concatenate a String with a non-string,
// the non-string is converted to a String.
int age = 13;
String rating = "PG" + age;
// rating = PG13
// "" (empty string) can be used to force non-strings to Strings:
System.out.println("" + 5);
// To put strings together with a delimiter, use the join() method:
String all = String.join(" / ", "S", "M", "L", "XL");
// all = "S / M / L / XL"
3.6.3 Strings Are Immutable
You cannot change the individual characters in a Java String - they are immutable. You can, however, make a string variable refer to a different string.
String greeting = "Hello";
greeting = greeting.substring(0, 3) + "p!";
// greeting = "Help!"
Isn't it inefficient to build a new string from scratch rather than just altering the code units of the existing string? Yes, but the Java compiler can arrange that strings are shared.
Think of the various strings as sitting in a common pool. String variables point to locations in the pool. If you copy a string variable, both the original and copy point to the same string.
3.6.4 Testing Strings for Equality
Use the equals
method to test strings for equality - do not use the ==
operator. The ==
operator only determines if two strings are stored in the same location. It is entirely possible to store multiple copies of identical strings in different places.
String greeting = "Hello";
"Hello".equals(greeting); // true
greeting.equalsIgnoreCase("hello") // true
greeting == "Hello" // probably true
greeting.substring(0, 3) == "Hel" // probably false
Only string literals are shared, not strings that are the result of operations like +
or substring
.
3.6.5 Empty and Null Strings
An empty string is a String
(a Java object) with length 0. A null string indicates that no object is currently associated with the value.
String str = ""; // An empty String
String str2 = "non-empty string";
String n; // A null String
str2 != null && str2.length() > 0 //true
str.equals("") // true
str.length() == 0; // true
n == null // true
n.length() //ERROR!
//can't call method on null value;
3.6.6 Code Points and Code Units
Java strings are implemented as sequences of char
values.
The char
data type is a code unit for representing Unicode code points in UTF-16 encoding.
The most commonly used Unicode characters can be represented with a single code unit. The supplementary characters require a pair of code units.
// The length() method yields the number of CODE UNITS
// required for a given string in UTF-16.
String greeting = "Hello";
greeting.length(); // is 5.
// BUT REMEMBER: some characters require two CODE UNITS
// To get the number of CODE POINTS, call:
int cpCount = greeting.codePointCount(0, greeting.length());
// s.charAt(n) returns the CODE UNIT at position n
// where n is between 0 and s.length() -1.
char first = greeting.charAt(0); // first "H"
char last = greeting .charAt(4); // last "o"
// To get at the ith CODE POINT:
int index = greeting.offsetByCodePoints(0, i);
int cp = greeting.codePointAt(index);
// To traverse each CODE POINT in a String:
int cp = sentence.codePointAt(i);
if (Character.isSupplementaryCodePoint(cp))
{
i += 2;
}
else i++
// Note the wrapper class, Character, for the primitive
// data type, char.
// We can traverse a string backwards:
i--;
if (Character.isSurrogate(sentence.charAt(i))) i--;
int cp = sentence.codePointAt(i);
// An easier way is with the codePoint() method
// which yields a stream of int values - one for each code point.
int[] codePoints = str.codePoints().toArray();
// Conversely, to turn an array of code points to a string:
String str = new String(codePoints, 0, codePoints.length);