Java 211 - Lecture II

Variables & Flow of Control

Yosef Mendelsohn

Variables

A few things to remember about variables:

-Choose your identifiers wisely:

-They should always begin with a lower case letter

-You can not have spaces between words. Typically, separate words are separated by either an underscore ‘_’, or by capitalizing every word:

-int myFirstVariable = 3;

-You must avoid using “reserved keywords”, that is, words that are reserved by the Java language. These include words like ‘main’, ‘public’, ‘class’, to name but a few

-Variables in Java are strongly typed. This means that if a variable is declared as an ‘int’, you cannot assign the value 3.14 to that variable. Doing so will give you a type mismatch. Therefore, when you have an assignment statement, the final result of the right-side must match the declared type of the variable on the left side.

-int y = 3 + 4.5; //type mismatch

Good or Bad?

int x1

int x 2;

float TotalAmount;

Constants

-Sometimes it is convenient to assign a value to an identifier, and you do NOT want the value to change. Perhaps you are storing the value of pi in a geometry program…

-final float PI = 3.1415;

-The value of PI can not be changed

-Note that the identifier is in capitals. This is a convention for constants.

-Using constants can also be helpful where you use a value multiple times in a program, and that value should not ever change.

More on Data Types

-There are 8 “primitive data types” in Java.

-Four integer types: int, short, byte, long

-Two floating types: float, double

-One character type: char

-One boolean type: boolean

-Each data type requires a different amount of memory (E.g. byte=8 bits and can range from –128 to 128; float requires 32 bits and ranges from about –3e48 to +3e48)

-In general, err on the side of caution. For example, unless you are absolutely certain that your value will be between –128 and +128, consider using an int as your data type.

-Literals: When you assign an explicit value to a variable in your program, it is called a ‘literal’. In all the programs we have seen to date, all our values have been stored as literals. By default, Java assumes that all literals are of data type ‘int’ or ‘double’ unless indicated otherwise. You can indicate a different data type by appending a letter to the end of the value: final float PI = 3.1415F;

Character Data Type (char)

You can declare variables that store single characters.

-There are various character sets that can be used, the most popular of which is the ASCII character set. This includes: Uppercase letters, lowercase letters, punctuation, digits, symbols, special characters (newline, null, end of file, etc), but is limited to only 256 characters.

-In Java, the developers elected to use an even larger character set called the ‘Unicode Character Set’ that supports over 65,000 characters. This is in keeping with Java’s ‘international’ scope.

-A character literal is expressed with single quiotes. Note that a String data type is entirely DIFFERENT from a character data type.

-char selection = ‘Y’;

Boolean Data Type (boolean)

Variables of type ‘boolean’ can store either a ‘true’ or ‘false’.

boolean flag = false;

String Data Type

You can declare a variable that holds a group of characters (letters, digits, symbols) together. Don’t confuse with the ‘char’ data type which holds only single characters.

String firstName = “Bob”;

String lastName = “Smith”;

System.out.println(firstName + “ “ + lastName);

Operators

Operators include the standard arithmatical ones: +, -, *, /, %

… and others such as comparison operators: <, <=, ==, >=, >

You have to watch your data types when dealing with operators. For example, if you multiply an int by a double and try to put the result in an int, what will happen? (See Shapes.java example)

With operators, you must respect precedence rules. (multiplication and division precede addition and subtraction, etc) Use brackets both for clarity and to ensure that you are carrying out your operations in the desired order.

When carrying out arithmatical operations, you can end up with some surprising results in terms of your data types. Consider the following:

int x=10, y=4;

double z;

z = x/y; //What will be the value of z?

The reason for this strange turn of events is that when you have an operation involving two ints, the result will be given to you as an…. int! Similarly, if you have an operation involving two floats, you’ll end up with a float. In the above example, the 2.5 gets truncated to a 2. (Note: We do not round up, instead, we simply chop off the decimal and subsequent values).

The arithmetic operators in Java are:

+ (sum)

* (multiplication)

- (subtraction)

/ (division)

Example:totalPeas = numberOfPods * peasPerPod;

count = count + 1;

All operators may be used with both integer and floating point types and even with a number of each type. However, the type of the number produced and the value of the result depends on the types of the numbers combined.If oprt is any of ‘+’, ‘-‘, ‘*’ or ‘/’, then

int oprt int = int

double oprt int = double

double oprt double = double

In other words, using double "promotes" the result to a double.

Example:7.0 / 2.0 = 3.5

7.0 / 2 = 3.5

7 / 2 = 3

8.0 / 2 = 4.0

8 / 2 = 4

Note that integer division produces a result that has only the whole part of the number; the number has been truncated. How can we get that information back? By using the % (mod) operator:

Example: 7 % 2 = 1

What does this mean? The mod operator gives you the remainder of the division of the first number by the second.

Example:2 goes into 7 three times, therefore:7 / 2 = 3

and produces a remainder of 1, therefore7 % 2 = 1

More examples:11 % 3 =

18 % 5 =

13 % 4 =

A word of caution: The mod operator (%) can behave differently for different implementations of Java if used it on negative numbers. Because of this it is advisable to use this operator only when you know that the operands will be positive integers. If you want to use % and / with negative numbers, then test it first to make sure it's working the way you expect it.

The arithmetic operators follow precedence rules that tell the compiler which operator binds more tightly.

Example: * binds more tightly than + so that a * b + c = (a * b) + c

However, it is usually wiser to just include parenthesis in your expressions; that way you don't have to look up or remember the precedence rules.

How would the following expressions be evaluated in Java? (Note: The ‘^’ operator has a few features assosicated with its use that we have not yet discussed).

a – c / b + d

a^2 + b^2 - c

x(x^2 - 3y)

1/(x + y)^2

More assignment statements

You can combine operators with the assignment operator to change a given variable by a certain amount.

Example:count = count + 2; is equivalent to count += 2;

In general this looks like:variable operator= expression

Which is equivalent to:variable = variable operator expression

For example, translate the following using the combination of operator and assignment:

x = x * 3;

count = count / 2;

sum = sum - val;

Increment and Decrement Operators

There is an even shorter way to write things like:

count += 1; // count++;

sum -= 1; // sum--;

We can use what are called the increment and decrement operators. These are unary operators, that is, they take a single argument. They are usually used on operands of type int.

Example:int n = 0;

System.out.println(“n’s value is: “ + n);

n++;

System.out.println(“n’s value is now: “ + n) n--;

System.out.println(“And now n’s value is: “ + n);

Narrowing and Widening, and Casting

Sometimes a variable needs to be converted (either permanently or temporarily) to another data type. In the above example, we probably want the value of ‘z’ to be 2.5 instead of two. The best way to do this is to temporarily convert one of the operands to a double or float. Then the result of the division will yield a float (since float <operator> int will return a float).

z = (double) x / y; //casting x to a double

In this case, we say that we have cast x to a double. Casting is temporary (x remains an int, we just temporarily convert the value stored by x into a double).

At other times, we may need to ensure that no information gets lost in the process when converting from one data type to another. Converting from a data type that holds more information to a data type that holds less is dangerous….

double x = 125.92;

int y = x; //y is set to 125

This is called narrowing.

However, converting to a data type that holds more information is permissible and usually safe…

int x = 10000;

double y = x; //y still holds 10000

This is called widening.

-Note in the above example that widening can be accomplished automatically using an assignment statement.

Flow of Control

Generally, a program begins at the beginning (e.g. first line of main() method) and proceeds from line to line until the end. However, the programmer can alter the order in which lines of code are executed. For example, when a method is invoked, the control jumps to and executes the code of that method. When the method terminates, the control returns to the location from where the method was first invokved. Another way control can be modified is through the use of loops and conditionals.

A loop is a piece of code that can be executed more than one time. A conditional allows us to determine whether a piece of code will be executed or not, based on some boolean expression (a condition). By boolean expression, we mean a situation that can be evaluated as being true or false. The “decisions” that alter flow of control are built around boolean expressions, so to begin our discussion of loops and conditionals, we must first develop a thorough understanding of these expressions.

Understanding Boolean Expressions

Before we can write code that chooses between two options, we need to talk about boolean expressions. A boolean expression is any expression that can be tested to see if it is true or false.

The simplest form of a boolean expression is an expression that involves two variables and a comparison operator. The comparison operators are:

==(equality. Note the use of two equal signs)

!=(not equal)

(less than)

<=(less than or equal)

(greater than)

>=(greater than or equal)

Example: The following boolean expressions are all false:

'a' == 'b'

3 > 7

'a' < 'A'

(This is where we can see that symbols are really just small numbers)

We can also put several boolean expressions together using the logical operators which are:

(Logical AND) is true if both its arguments are true

||(Logical OR)|| is true if one of its arguments is true

!(logical NOT)! is true if its argument is false

Example:(1 < 2) & (4 > 7)

(1 < 2) || (4 > 7) 

!(1 == 1)

Altering Flow of Control: Conditions and Loops

Conditions and loops are without question, one of the fundamental tools of programming.

Condtions: the ‘if’ statement

double sales = 43032.33;

double requiredSales = 40000;

double salary = 50000;

double bonus = 1000;

if ( sales > requiredSales ) {

System.out.println(“Congratulations!”);

salary = salary + bonus;

}

-The statement in brackets following the ‘if’ is called the ‘boolean expression’. A boolean expression must evaluate to true or false.

-Typically, your boolean expression is built around relational operators that can evaluate to true or false: <, <=, >, >=, ==, !=

-Note: to check to see if two items are identical, you must use two equal signs. (What is indicated why one equal sign?)

-If the expression evaluates to true, the statements inside the braces get executed. If the expression evaluates to false, the control jumps to the closing brace following the expression.

-Notice the indentation inside the if-statement

You can (but are not required) to have an ‘else’ clause that follows the ‘if’ statement:

if ( sales > requiredSales ) {

System.out.println(“Congratulations!”);

salary = salary + bonus;

}

else

System.out.println(“Please work harder next time.”);

-Notice that in the ‘else’ clause, there are no braces. This is because the ‘else’ segment has only one statement. If a block of code inside a loop or condition has only one statement, you do not need to have braces (although you can certainly put them there if you want to!).

‘if’ Statements can be nested. See Listing 3.4, p. 118.

Switch statements

char grade = '...';

switch (grade)

{

case 'A':

System.out.println("Perfect score, well done!");

break;

case 'B':

System.out.println("Well above average, nice going.");

break;

case 'C':

System.out.println("Passing grade.");

break;

case 'D':

System.out.println("Passing, but you could work harder...");

break;

case 'F':

System.out.println("Below average. Please see the instructor...");

break;

default:

System.out.println("Sorry, this is not a grade I understand.");

}

Each case of the switch must be exclusive, e.g. we can't have two different sections that have case 's' in front of them.

IMPORTANT: Why do we put the break statements? Because a switch is evaluated by the compiler by jumping to the code that appears after the correct case and then evaluating statements until it encounters a break or drops off the end of the switch statement. If you leave off a break, the case will evaluate code from the next batch. See what happens with the last example if you leave off the break from the first case and the user enters 's'.

This odd behavior is why we can have more than one label in front of a single piece of code. In fact we can have as many as we like. Typically, we want to put some type of error in the default that let's us know that the value of the variable wasn't one of the cases we expected. The reason we do this is that we usually want the switch statement to show all of the cases we consider possible.

The controlling expression in a switch-statement, must always return a value of type int, char, boolean, or enum.

You should always include a 'default' section. (For error checking if for no other reason)

Simple Loop Mechanisms

Often we want to repeat some portion of code a large number of times. For example, we may want to calculate the volume for a large number of shapes or calculate the salary for all of a company's employees. Programming languages have looping mechanisms to allow us to do this. One of these statements is called a while-loop. Consider the following program:

public static void main (String[] args)

{

int countEnd, count = 0;

System.out.println("How high do you want me to count?");

//Read in a value from the user into the variable 'countEnd'

countEnd = 5; //for testing purposes

while (count <= countEnd)

{

System.out.println(count + " ");

count = count + 1; //What would be another way??

}

// What if we included a 'System.out.println(count);' statement here?

}

Exercise: What gets printed on each of these inputs: 3, 0, -1

The general form of a while-loop is:

while (Logical_expression)

{

Statement1;

..

Statementn;

}

or

while (Logical_expression)

Statement;

The meaning of such statements is "while the boolean expression is true do the following statements". How does it work?

  1. Evaluate the boolean expression.
  2. If it's true, execute all the statements.
  3. until the boolean expression becomes false, it continues executing the statements in the body of the while-loop.
  4. If the boolean expression is never true then the statements in the body will never be executed.
  5. If the boolean expression is always true, then the body will be executed infinitely (or, more likely, until the user forces the program to terminate catastrophically)

A slight variation of the while-loop exists: If you always know that you want to execute the statements in the body of the loop at least once, then you can use a do-while-loop.

do

{

Statement1;

...

Statementn;

} while (Logical_expression); //note the semicolon!

or

do

Statement

while (Logical_expression); //notice the semicolon

This type of loop executes the statements first and then tests the Logical_expression. It then works just like a normal while-loop. This is particularly useful for creating loops that do something as often as the user wants.

Example:

public static void main(String[] args)

{

char answer;

do

{

System.out.println("Hello!");

System.out.println("Do you want another greeting? "

+ "Press Y or N");

// Read input from user into the variable 'answer'

// It should be a Y (or 'y') or N (or 'n')

} while (answer == 'y' || answer == 'Y');

//Notice the semicoon after the boolean expression...

System.out.println("Goodbye!");

}

Infinite loops

Because the while (or do-while) loop keeps executing the statement(s) in its body until the boolean expression is false, you need to be careful in designing your boolean expressions. For example, consider the following counting program.

public static void main(String[] args) {

int count, countFrom=10;

System.out.println("I will count from " + countFrom

+ " down to 0.");

count = countFrom;

while (count != 0)

{

System.out.println(count + " ");

count--;

}

}

What happens when this is executed with countDown = -1?

Consider another example of code containing a while loop. Suppose that we want to compute the sum of the number from 1 to some input value of n.

Example: the sum from 1 to 6 is 1 + 2 + 3 + 4 + 5 + 6 = 21

public static void main (String[] args)

{

int sum=0;

int count = 1, n=6;

System.out.println("This program will compute the sum” +

“of numbersfrom 1 to n.”);

while (count <= n)

{

sum += count;

count++;

}

System.out.println(“The sum of the integers from 1 to n is”

+ sum);

}


Exercise: what gets printed for n = 3, 5?

‘for’ Loops

Another looping construct is called the ‘for’ loop. Deciding between a while vs a for loop is often just a matter of personal preference, but typically, you use a for-loop when you know in advance how many times you want to repeat a give group of code. The syntax is: