Wyo Java Ch. 3 Lecture Notes
Objective #1: List the primitive data types and their characteristics.
- Java requires you to formally declare variables before they are used in a method or class. Variables can more formally be called primitive variables. A declaration statement such as the following examples is used to declare a variable.
int num = 0;
double grade = 89.555;
boolean isFinished = false;
When declaring a variable you should assign it a legal and logical name and you must assign a specific data type and an initial value. By the way, a data type is sometimes more simply called a type. For the AP exam, you are ony responsible for using three of Java's primitive data types: int, double, and boolean. However, it is a good idea to familiar with the other 5 primitive types as well.
- Two or more variables may be declared and/or initialized in the same statement but it is not considered to be good style. The following statements will not cause compile errors:
int num1, num2;
double grade1 = 35.45, grade2 = 9.99, grade3;
- It is safe to initialize a variable to a value such as 0 within its declaration statement. Otherwise, if when you attempt to use an unitialized primitive variable in a later statement, a compile error will occur.
- String and other types are not primitive data types but are actually classes from which you can instantiate objects. In other words, a primitive variable is not considered to be an object.
- Primitive variables of the int data type can only store whole numbers and cannot store floating-point values (i.e. decimal numbers.) This data type is often referred to as the "integer" data type. An int variable has a size of 4 bytes.
- Primitive variables of the double data type can store whole numbers or floating-point values. Computer scientists refer to decimal numbers as "floating-point values". A double variable has a size of 8 bytes
- Variables of the boolean data type can either store the boolean values true or false. A boolean variable has a size of 1 bit.
- Here are all 8 of the Java primitive data types:
Type |
Stores |
Default Value |
Size |
Range |
| boolean |
true or false |
false |
1 bit |
true or false only |
| char |
Unicode character |
\u0000 |
2 bytes |
0 to 2^16 - 1 (\u0000 to \uFFFF) |
| byte |
signed integer |
0 |
1 byte |
-128 to 127 |
| short |
signed integer |
0 |
2 bytes |
-32768 to 32767 |
| int |
signed integer |
0 |
4 bytes |
-2147483648 to 2147483647 |
| long |
signed integer |
0 |
8 bytes |
-9223372036854775808 to 9223372036854775807 |
| float |
floating-point value |
0.0f |
4 bytes |
+- 1.4E-45 to +-1.797693134823157E+308 |
| double |
floating-point value |
0.0 |
8 bytes |
+-439E-324 to +-1.7976931348623157E+308 |
- Besides the familiar operators, *, /, +, and - for
multiplication, division, addition and subtraction, Java supports the use
of the % for modulus. Modulus
computes the remainder of dividing one integer by another. For example, num
= 8 % 3; would result with the variable num storing the value 2 since
2 is the remainder of 8 divided by 3. With the statement, num
= 3 % 8; would
cause 3 to be stored in num since 3 is the remainder of 3 divided by 8. In the order of operations, modulus ( % ) is performed along with multiplication and division,
from left to right. That is, the expression 11 % 3 * 4 - 9 % 4 evaluates as 7 since 11 % 3 is performed first and then 2 * 4 and then 9 % 4 and finally 8 - 1.
- Java also allows the use of the compound operators *=, /=, %=, +=, and
-=. That is instead of typing out the assignment statement
num = num + 2;
you can type the simpler
num += 2;
- Java allows the use of the incrementing and decrementing operators. The
incrementing operator ++ can be used to add one to a variable as in
num++;
Notice there is no space typed between the variable name and the ++ symbol.
This statement is equivalent to
num = num + 1;
and can even be rewritten as
++num;
The decrementing operator -- can be used to
subtract one from a variable as in
num--;
Objective #2: Explain problems that can occur when using int and double data types.
- A compile error is generated if you initialize or assign
a value to an int variable that would overflow the limitation
of the int data type. The maximum
value that can be stored in an int variable
is 2147483647 (i.e. roughly 2 billion) which equals 2 to the 31st power minus
1. The minimum value that can be stored in an int variable
is -2147483648 which equals -2 to the 31st power. These limits are due to
the fact that an int variable occupies 4
bytes of memory. The constants Integer.MAX_VALUE and Integer.MIN_VALUE from
the Integer class can be used to refer to
these limits. Because zero can be stored in an int variable
and the two's complement method that is used to store binary values, the
last digit in the positive upper limit (i.e. 7) is not the same as the last
digit (i.e. 8) in the negative lower limit. MAX_VALUE and MIN_VALUE are
legal to use because they are already declared as public constants in the Integer class
as in
public static final int MAX_VALUE = 2147483647;
The Integer class does not need to be imported
at the top of a Java program because it is found in the java.lang package
which is automatically imported to all Java projects. We will eventually
study why the word static is used in this
declaration statement.
Note that if you add two integers whose sum is greater than 2147483647 and
store that resulting value into an int variable, an error will not occur.
The error occurs only if you directly initialize or assign such a value to
the variable. In the following code segment
int num = 2147483647 + 1;
System.out.println(num);
the value
-2147483648 displays since Java "wraps around" the number line.
- When using the double data type to store floating-point values, you can store numbers up to roughly 10 to the 300th power. This high value makes overflow less of a problem with double variables. Since a double variable is stored in 8 bytes of memory, there is a limit though to the overall number of digits, both before or after the decimal point, that can be stored without a loss of precision. About 15 significant digits can be stored at most in a double variable. The statements
grade = 0.123456789012345678901234567890;
System.out.println(grade);
will not cause a compile error. But the actual value that is displayed will be 0.12345678901234568. Note in the example above a 7 digit was changed to an 8 at the end of the number. In the example below,
grade = 96.55555555555555;
System.out.println(grade);
the value that will be displayed is 96.55555555555554 where the last 5 is changed to a 4. Because of the translation of decimal values to binary values, the number in the last decimal place may increase, decrease, or stay the same.
Be wary, this loop does not display the values that you think it displays since 0.1, 0.05, and 0.01 don't have exact binary representations:
for (double y = 1; y <= 2; y += 0.1)
System.out.println(y);
Try it out for yourself.
- In some ways, the int type is easier for the computer to work with than the double type. An int is only 4 bytes as opposed to 8 so it uses less memory per variable. Also, it can be argued that mathematical computations with int's work faster on the computer's processor than double's. Also, it is occasionally safer to use an int since loss of precision and rounding errors affect double's in ways that int's are not affected. However, even with the int type a roundoff error (and not a lack of precision) can cause errors. As our author demonstrates on p. 104, the code segment
double f = 4.35;
int n = (int) (100 * f);
System.out.println(n);
causes the value 434 to be printed out and not 435
as you might expect. It is safer in this situation to use the round static
method from the Math class
as in
int n = (int) Math.round(100 * f);
Notice that the round method
is a static method and not an instance method. It is called by typing
the name of
its class in front of it and the dot
operator. It
is not
necessary
to
declare
a
Math object
and call the round method
on that object. The use of (int) is called
casting and is explained below.
- Decimal numbers are referred to as floating-point
values by computer scientists. An int variable
cannot store a floating-point value in Java. Unlike Visual Basic which
rounds a floating-point value to the nearest integer value, a "possible
loss of precision" compile error is generated if you try to initialize
or assign a value to an int variable
as in
int num = 1.2;
Be careful not to even assign a floating-point value to an int variable;
the compiler will generate an error. The following statement is not allowed in
Java even though there aren't any nonzero digits stored as decimal places in myDouble:
double myDouble = 1;
int myInt = 3 + myDouble;
However, you use casting (aka typecasting)
to purposefully but temporarily turn a double variable
into an int variable.
In the following example, no compile error occurs since myDouble is
casted to an int before
it is assigned to the int variable myInt.
double myDouble = 1.99;
int myInt = 3 + (int) myDouble;
System.out.println(myInt); //
the value 4 prints, not 4.99 or 5
In this code segment, int is
called a cast operator. In Java, casting a double to
an int does not
cause the floating-point value to be rounded. In the code segment, the 1.99 is
truncated to 1 before it is added to the value 3. But the
variable myDouble is
treated as a double variable
later
in the program and still stores the value
1.99.
You cannot cast an int or
a double into
a String or vice
versa. Casting only
applies to primitive data types.
- Be wary of integer division which is what we call the result of dividing one integer by another integer. This result is truncated to an integer even if the result would technically be a decimal number. The code segment
int num = 9;
double result = num / 2;
System.out.println(result);
causes the value 4 to be displayed even though 9 divided
by 2 is 4.5 to a mathematician. To avoid integer division, you can cast either one of the two division operands to a double. The other divisor is then automatically promoted to a double value as well. Therefore in the code segment
int num = 9;
double result = (double) num / 2;
System.out.println(result);
the programmer is casting the int variable
to a double to
avoid the problem of integer division. The value 2 is promoted by the Java
compiler to the double value
2.0 so that two double's
are being divided on the computer's processor.
- But integer division and the % operator can be used to pull apart the digits in a large number. Notice how the digits of 123 are extracted here
int num = 123;
int onesDigit = num % 10;
int tensDigit = (num % 100) / 10;
int hundredsDigit = (num %1000) / 100;
- There is a curious side effect from using the addition compound operator +=.
int total = 0;
total = total + 5.4; // causes loss of precision compiler error
total += 5.4; // compiles and executes with x = 5 afterwards
The latter statement total += 5.4; is the same as total = (int) (total + 5.4);
Objective #3: Use the Integer and Double wrapper classes.
- The makers of Java created a class that allows you to work with integers in a more efficient manner than using int primitive variables. The Integer class is called a wrapper class because an Integer object wraps itself around a primitive int variable but gives a client programmer additional flexibility.
- The statement
Integer num = new Integer(5);
declares and instantiates an Integer object.
- The Double class allows you to work with Double wrapper objects that can store floating-point values such as 5.43.
- The Integer and Double classes are immutable because there are no modifier methods in these classes.
- autoboxing - more info coming soon
- auto-unboxing - more info coming soon
Objective #4: Use the String type.
- There is no data type that can be used to create a primitive variable that can store a string (i.e. sequence of characters such as a word or phrase). Therefore, it is useful to use objects of the String type. String is a class that is available for use in any Java program without the necessity of having to include an import statement at the top of the program.
- Unlike other objects, you don't have to use the new operator in a string object's declaration statement. The statement
String name = "John";
declares the object name and initializes it with the string value "John" (not including the double quotation marks of course.)
- The assignment statement,
name = "Sally";
changes the value of the object name (that has already been declared) to the value "Sally".
- The concatenation operator + can be used to join two strings together. The following code segment
String firstName = "Jane";
String wholeName = firstName + " Smith";
System.out.println(wholeName);
causes the "Jane Smith" to be displayed.
- It is often useful to use the Integer class's parseInt method
to turn the value of a string object, which happens to contain a number,
into an integer value that can be assigned to an actual int variable.
This process of turning a String object into a primitive int value is not considered to be casting. Casting only occurs when a programmer turns an int into a double or vice versa. The parseInt method
is similar to the CInt method
and the Val function
in Visual Basic. In the following code segment,
String number = "12";
int num = Integer.parseInt(number);
System.out.println(num + 3);
will cause cause the integer value 15 to be displayed. It is necessary to "parse" the value stored in the String object to convert it into a value that can be properly stored in an int primitive variable. Within the println method call, the sum of num plus 3 will simplify to 15 since mathematical addition occurs.
However the following code
String number = "12";
System.out.println(number + 3);
will cause the string output "123" to be
displayed. Since number is a string object and not an integer primitive variable,
Java interprets the plus symbol to be a string concatenation operator and
not a mathematical addition operator. Even though the digit 3 is a numerical
value it ends up being concatenated and not added to number. The rule is
that if either one of the + operator's arguments are a String object,
the + operator is treated as a concatenation operator. Only if the arguments
on both sides of the plus symbol are integer or floating-point values will
it be treated as a mathematical addition operator.
A neat aspect of the parseInt method is that
it can be use to convert strings made up of binary digits into decimal numbers
if the optional second parameter
2 is used. Since the binary number 1110 equals the decimal number 14, the
variable num
stores
the number 14
after the following statement executes:
int num = Integer.parseInt("1110", 2);
In fact, this works for any numbering system including hexadecimal (base
16) and octal (base 8).
int num = Integer.parseInt("1F", 16); // num stores 31
int num = Integer.parseInt("77", 8); // num stores 63
The toString method of the Integer class
performs the opposite function of the parseInt method in this sense. The toString method
will return the binary equivalent to a decimal number expressed as a string. For example, the string value "1110"
will be stored in binaryNum after the following statement executes.
String binaryNum = Integer.toString(14,
2);
- The parseDouble method of the Double class can be used to convert the value stored in a String object to a floating-point value and then store it into a double variable as in
String userPrice = "13.99";
double price = Double.parseDouble(userPrice);
The parseInt and parseDouble methods are static
methods of the Integer and
Double classes not instance methods like most
that we've studied in this course so far. It is not necessary and not desirable
to instantiate a Double object and calling
the
parseDouble method
with that
object. Rather,
the name of the class Double is typed followed
by the dot operator and then the name
of the static method parseDouble.
- The substring method of the String class can be used to extract part of a string from a larger string value. The following code segment
String message = "abcdefghijklmnopqrstuvwxyz";
String firstPart = message.substring(5, 10);
System.out.println(firstPart);
would cause the whole message "fghij" to
display. The substring method causes a string starting at the character in position 5 to be extracted. The first letter of a string is considered to be the zero position, the second letter is considered to be the 1 position, and so on. So, in this example, all the characters starting with the character 'f' up through BUT NOT INCLUDING the character in position 10 are extracted and stored into the string firstPart.
The substring method can also be called with only one integer argument. The following code segment
String message = "Four score and seven years ago";
String lastPart = message.substring(5);
System.out.println(lastPart);
would cause the phrase "score and seven years ago" to display since every character from position 5 to the end of the string is extracted from message and then stored in lastPart.
- The length method of the String class can be used to obtain the length of a string object or string literal as counted by the number of characters (i.e. letters, digits, and symbols) that are stored there. The following code segment
String message = "Hello World";
int length = message.length();
System.out.println(length);
causes the value 11 to be displayed, since there are
eleven characters including the blank space in the String object message.
The length method can be used to determine
the last letter of a string using this technique
System.out.println(name.substring(name.length()
- 1));
- A set of characters (i.e. letters, digits, and symbols) placed inside of double quotes is called a string literal though it can also be considered a String object. Many String class methods can be used on a string literal.
"Hello World".length(); // 11
"Hello World".substring(0, 5); // "Hello"
- The += operator can also be used to concatenate two strings. The code segment
String word1 = "Hello";
String word2 = "World";
word1 += word2;
displays the string word1 to be have the string value "HelloWorld". Note that the following two statements are equivalent:
word1 += word2;
word1 = word1 + word2;
- The equals method
is used to compare two strings. The expression
string1.equals(string2) returns true if and only if string1 and string2 store the same values.
- The compareTo method
is used to alphabetically compare two strings. The expression
string1.compareTo(string2)
returns a positive number if string1 is greater than string2. It returns the value zero if they are equal. It returns a negative number if string1 is less than string2.
- The indexOf method is used to find a first occurrence of a substring (one or more characters) in a string. If the specified substring is not found in the string, the value -1 is returned.
String word = "score";
String message = "Four score and seven years ago";
int position = message.indexOf(word);
System.out.println(position);
causes 5 to be displayed since the s in "score" is in position 5 of the string message. Remember that the very first character in a string is considered to be position zero.
- The charAt method is used to return a character from a string.
String name = "Smith";
char letter = name.charAt(0);
assigns the char variable letter to 'S'.
- You can learn many other useful methods of the String class by viewing its Java API.
- No string method can change the string object it
is being called upon. In other words, none of the methods in the String class
are modifiers (aka mutators). For this reason, strings are considered to
be immutable. Most other classes that we will work with
in this course are not immutable.
In the following code segment,
String name1 = "Smith";
String name2 = name1;
name1 = name1.substring(0, 2);
name1 becomes "Sm" but name2 is still "Smith". If strings were not immutable name2 would also be "Sm" at the end of the code segment.
However, suppose you have a Fish class where a Fish object has a weight property.
In the following code segment
Fish fish1 = new Fish(10);
Fish fish2 = fish1;
fish1.setWeight(20);
fish1 has a new weight
of 20 and so does fish2! In other words, what happens
to fish1 also
happens to fish2 since Fish objects are not immutable.
Here is another example, illustrating how immutable String objects are different
from most other kinds of objects.
String name1 = "Fred";
String name2 = "Sally";
name2 = name1;
name1 += " Smith";
System.out.println(name1); // Fred Smith
System.out.println(name2); // Fred
But consider this code segment:
Fish nemo1 = new Fish(10); // weight is 10
Fish nemo2 = new Fish(); // weight is 0
nemo2 = nemo1;
nemo1.gainWeight(5);
System.out.println(nemo1.getWeight()); //
15
System.out.println(nemo2.getWeight()); //
15
Objective #5: Use the Math class for routine mathematical
tasks.
- The Math class is automatically imported with Java programs. It contains many useful methods and constants.
- You can use a reasonably good approximation of pi by referencing the constant Math.PI in a Java program. You can use Euler's contant, e, by referencing the constant Math.E.
- You can use a number of Math class methods (i.e. static methods) including:
- Math.sqrt(x) - which obtains the square root of a value
- Math.pow(x, y) - which is used to compute x to the yth power
- Math.abs(x) - to
compute the absolute value of x
- Math.max(x, y) -
returns x or y, whichever is greater
- Math.min(x, y) -
returns x or y, whichever is least
- Math.round(x) - to
round x to the closest integer
- Math.ceil(x) - to
find the smallest integer that is greater than or equal to x
- Math.floor(x) - to
find the largest integer that is less than or equal to x
- Math.random() -
returns a pseudorandom floating-point value greater than or equal to
zero but less than 1; that is a value in the range [0, 1)
- Math.sin(x) - to compute the sine of x in radians
- Math.cos(x) - to compute the cosine of x in radians
- Math.tan(x) - to compute the tangent of x in radians
- Math.toRadians(x) - to convert x radians to degrees (i.e. returns x * 180/Math.PI)
- Math.toDegrees(x) - to convert x degrees to radians (i.e. returnx x * Math.PI/180)
- Math.exp(x) - to compute e to the xth power
- Math.log(x) - to
compute the natural log of x (i.e. ln(x) where x > 0)
- The methods above are called static methods. You
do not need to instantiate a Math object
in order to use the methods. You simply type the name of the class Math followed
by a dot operator and then the name of the method. We learn more about
static methods later in this
course.
- Here is a neat way to display the maximum value of
three values without using
an if statement:
System.out.println(Math.max(Math.max(x, y), z));
Objective #6: Read program input.
- On the AP exam, you will not be tested on how to read
input from the keyboard or a text file. However, you will be given questions
where the test authors provide you with a method that gets input and you
are to assume that the work correctly. For example, you might be told to
assume there is a static method named readInt of
the fictitious IO class
that allows the user to input an integer and then given this code
int num = IO.readInt();
- You can use the Scanner class to obtain user input however. To use the Scanner class, you must import it at the top of your Java source file with the statement
import java.util.Scanner;
- To instantiate a Scanner object, you can use the following statement
Scanner keyboard = new Scanner(System.in);
In this statement, keyboard could be any variable name of your choice but it emphasizes that this statement connects the Scanner object with the keyboard which is known as System.in.
- The next method of the Scanner class can be used to read a String value as in
String word = keyboard.next();
The next method returns the String value consisting of the next keyboard characters up to, but not including, the first delimiter character. The default delimiter character is a blank space or new line character (\n). The delimiter character is left in the keyboard buffer. This can cause potential problems if it is followed by a call to nextLine since the nextLine method will read the \n as the next line. So you should probably include an extra call to nextLine after any use of next.
- The nextInt method can be used to read a numerical value and store it in an int or double variable as in
int num = keyboard.nextInt();
or
int num = keyboard.nextDouble();
Any new line character that is entered after the user's numerical value is left in the buffer however. This can cause problems if the nextLine method is used immediately after. So you should always include an extra call to nextLine after any use of nextInt or nextDouble.
- The nextLine method is used to read a line of text that can include spaces as in
String sentence = keyboard.nextLine();
But be careful. If you previously inputted an integer or double with a recent call of nextInt or nextDouble, you will need an extra call to nextLine to get rid of the new line character that's still "hanging out" in the buffer. This is called "clearing" or "flushing" the buffer. The nextInt and nextDouble methods consume (i.e. overlook) leading whitespace but not trailing whitespace while nextLine does the opposite.
- The nextBoolean method is used to read a true or false value from the keyboard. Any combination of upper and lowercase letters may be used in the spelling of "true" and "false".
- View the following code segment that illustrates a few Scanner methods
Scanner keyboard = new Scanner(System.in);
System.out.print("Enter your name: ");
String name = keyboard.nextLine(); // using next() would not input a name that includes spaces
System.out.println("Hello " + name);
System.out.print("Enter your test scores separated by spaces: ");
int test1 = keyboard.nextInt();
int test2 = keyboard.nextInt();
int test3 = keyboard.nextInt();
int sum = test1 + test2 + test3;
System.out.println("Your total test score sum is " + sum);
- Another way to instantiate a Scanner object would be to use the following statement
Scanner stringInput = new Scanner("1 2 3 4");
which allows you to "pick off" these integers one at a time and then use them as input in your program.
- You can also read data from an external data file using Scanner. In this code segment
Scanner file = new Scanner(new File("numbers.txt"));
while (file.hasNext())
{
int num = file.nextInt();
file.nextLine();
System.out.println(num);
}
a set of integers found on separate lines of a file named numbers.txt is displayed on separate lines of the output window. The nextLine method invocation is necessary
to advance to the next line since nextInt doesn't automatically do that.
In order to use File objects you must import java.io.File and you need to import java.IOException and modify your main method by adding throws as in
public static void main(String[] args) throws IOException)
The
following example works for reading text from a file named dictionary.txt
Scanner file = new Scanner(new File("dictionary.txt"));
ArrayList<String> lines = new ArrayList<String>();
while (file.hasNext())
{
String nextWord = file.nextLine();
lines.add(nextWord);
System.out.println(nextWord);
}
- More explanation on the Scanner class can be found at http://techcenter.davidson.k12.nc.us/scanner.swf and, of course, in the Java API.
- Our textbook author provides two ways to obtain input from the user through
the keyboard. One method works in the console window and the other uses a
GUI dialog box. As far as chapter tests or the AP exam goes, you do not have to be familiar with these methods. The information below on BufferedReader or JOptionPane is not covered on chapter tests or the AP Exam.
- To read input through the console window, you can use a BufferedReader object. Here is a compact way to instantiate a BufferedReader object that
can then be used to read user input through the console window
BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
Then, you can use the readLine method of the BufferedReader class to read
input with a statement such as
String userName = console.readLine();
Realize that any indentifier could be used instead of console.
Or, you can
read an integer with the statement
int age = Integer.parseInt(console.readLine());
In order to use this method of reading console input, you must add the specifier
"throws IOException" to the header of your main method as in
public static void main(String[] args) throws IOException
We will learn more about throwing and handling exceptions later.
- To read input through a dialog box similar to an InputBox's
in Visual Basic, you can use the showInputDialog static
method of the JOptionPane class.
The statement
String userName = JOptionPane.showInputDialog("Enter your name:");
allows the user to input his name. If you would like the user to input an integer,
you can use the statement
int num = Integer.parseInt(JOptionPane.showInputDialog("Enter your age:"));
In order to use the JOptionPane class in a program, you must add import javax.swing.JOptionPane; to the top of your program.
In any program that uses showInputDialog method,
you must add the statement
System.exit(0);
to the end of your program in order to force the extra thread created by the
graphical user interface to close. Threads are not covered on the AP exam but
you can read more about them
in
our textbook.
Objective #7: Explain how primitive types and object
references are copied and be able to draw a supporting diagram.