The Way of the Java/Variables and types
As I mentioned in the last chapter, you can put as many statements as you want in main. For example, to print more than one line:
class Hello // main: generate some simple output public static void main (String args) System.out.println ("Hello, world."); // print one line System.out.println ("How are you?"); // print another
Also, as you can see, it is legal to put comments at the end of a line, as well as on a line by themselves.
The phrases that appear in quotation marks are called strings, because they are made up of a sequence (string) of letters. Actually, strings can contain any combination of letters, numbers, punctuation marks, and other special characters.
println is short for print line, because after each line it adds a special character, called a newline, that causes the cursor to move to the next line of the display. The next time println is invoked, the new text appears on the next line.
Often it is useful to display the output from multiple print statements all on one line. You can do this with the print command:
class Hello // main: generate some simple output public static void main (String args) System.out.print ("Goodbye, "); System.out.println ("cruel world!");
In this case the output appears on a single line as Goodbye, cruel world!. Notice that there is a space between the word Goodbye and the second quotation mark. This space appears in the output, so it affects the behavior of the program.
Spaces that appear outside of quotation marks generally do not affect the behavior of the program. For example, I could have written:
class Hello public static void main (String args) System.out.print ("Goodbye, "); System.out.println ("cruel world!");
This program would compile and run just as well as the original. The breaks at the ends of lines (newlines) do not affect the program's behavior either, so I could have written:
class Hello public static void main (String args) System.out.print ("Goodbye, "); System.out.println ("cruel world!");
That would work, too, although you have probably noticed that the program is getting harder and harder to read. Newlines and spaces are useful for organizing your program visually, making it easier to read the program and locate syntax errors.
One of the most powerful features of a programming language is the ability to manipulate variables. A variable is a named location that stores a value. Values are things that can be printed and stored and (as we'll see later) operated on. The strings we have been printing ("Hello, World.", "Goodbye, ", etc.) are sequences of values.
In order to store a value, you have to create a variable. Since the values we want to store are strings, we will declare that the new variable is a string:
This statement is a declaration, because it declares that the variable named fred has the type String. Each variable has a type that determines what kind of values it can store. For example, the int type can store integers, and it will probably come as no surprise that the String type can store strings.
You may notice that some types begin with a capital letter and some with lower-case. Java is a case-sensitive language, so you should take care to get it right.
To create an integer variable, the syntax is int bob;, where bob is the arbitrary name you made up for the variable. In general, you will want to make up variable names that indicate what you plan to do with the variable. For example, if you saw these variable declarations:
String firstName; String lastName; int hour, minute;
you could probably make a good guess at what values would be stored in them. This example also demonstrates the syntax for declaring multiple variables with the same type: hour and second are both integers (int type).
Now that we have created some variables, we would like to store values in them. We do that with an assignment statement.
fred = "Hello."; // give fred the value "Hello." hour = 11; // assign the value 11 to hour minute = 59; // set minute to 59
This example shows three assignments, and the comments show three different ways people sometimes talk about assignment statements. The vocabulary can be confusing here, but the idea is straightforward:
- When you declare a variable, you create a named storage location.
- When you make an assignment to a variable, you give it a value.
As a general rule, a variable has to have the same type as the value you assign it. You cannot store a String in minute or an integer in fred.
On the other hand, that rule can be confusing, because there are many ways that you can convert values from one type to another, and Java sometimes converts things automatically. So for now you should remember the general rule, and we'll talk about special cases later.
Another source of confusion is that some strings look like integers, but they are not. For example, fred can contain the string "123", which is made up of the characters 1, 2 and 3, but that is not the same thing as the number 123.
fred = "123"; // legal fred = 123; // not legal
You can print the value of a variable using the same commands we used to print Strings.
class Hello public static void main (String args) String firstLine; firstLine = "Hello, again!"; System.out.println (firstLine);
This program creates a variable named firstLine, assigns it the value "Hello, again!" and then prints that value. When we talk about printing a variable, we mean printing the value of the variable. To print the name of a variable, you have to put it in quotes. For example: System.out.println ("firstLine");
If you want to get a little tricky, you could write
String firstLine; firstLine = "Hello, again!"; System.out.print ("The value of firstLine is "); System.out.println (firstLine);
The output of this program is:
The value of firstLine is Hello, again!
I am pleased to report that the syntax for printing a variable is the same regardless of the variable's type.
int hour, minute; hour = 11; minute = 59; System.out.print ("The current time is "); System.out.print (hour); System.out.print (":"); System.out.print (minute); System.out.println (".");
The output of this program is
The current time is 11:59.
WARNING: It is common practice to use several print commands followed by a println, in order to put multiple values on the same line. But you have to be careful to remember the println at the end. In many environments, the output from print is stored without being displayed until the println command is invoked, at which point the entire line is displayed at once. If you omit println, the program may terminate without ever displaying the stored output!
A few sections ago, I said that you can make up any name you want for your variables, but that's not quite true. There are certain words that are reserved in Java because they are used by the compiler to parse the structure of your program, and if you use them as variable names, it will get confused. These words, called keywords, include public, class, void, int, and many more.
The complete list is available at this Java doc.
Rather than memorize the list, I would suggest that you take advantage of a feature provided in many Java development environments: code highlighting. As you type, different parts of your program should appear in different colors. For example, keywords might be blue, strings red, and other code black. If you type a variable name and it turns blue, watch out! You might get some strange behavior from the compiler.
Operators are special symbols that are used to represent simple computations like addition and multiplication. Most of the operators in Java do exactly what you would expect them to do, because they are common mathematical symbols. For example, the operator for adding two integers is +.
The following are all legal Java expressions whose meaning is more or less obvious:
1+1 hour-1 hour*60 + minute minute/60
Expressions can contain both variable names and numbers. In each case the name of the variable is replaced with its value before the computation is performed.
Addition, subtraction and multiplication all do what you expect, but you might be surprised by division. For example, the following program:
int hour, minute; hour = 11; minute = 59; System.out.print ("Number of minutes since midnight: "); System.out.println (hour*60 + minute); System.out.print ("Fraction of the hour that has passed: "); System.out.println (minute/60);
would generate the following output:
Number of minutes since midnight: 719 Fraction of the hour that has passed: 0
The first line is what we expected, but the second line is odd. The value of the variable minute is 59, and 59 divided by 60 is 0.98333, not 0. The reason for the discrepancy is that Java is performing integer division.
When both of the operands are integers (operands are the arguments of an instruction), the result must also be an integer, and by convention integer division always rounds down, even in cases like this where the next integer is so close.
A possible alternative in this case is to calculate a percentage rather than a fraction:
System.out.print ("Percentage of the hour that has passed: "); System.out.println (minute*100/60);
The result is:
Percentage of the hour that has passed: 98
Again the result is rounded down, but at least now the answer is approximately correct. In order to get an even more accurate answer, we could use a different type of variable, called floating-point, that is capable of storing fractional values. We'll get to that in the next chapter.
Order of operations
precedence order of operations
When more than one operator appears in an expression the order of evaluation depends on the rules of precedence. A complete explanation of precedence can get complicated, but just to get you started:
Multiplication and division take precedence (happen before) addition and subtraction. So 2*3-1 yields 5, not 4, and 2/3-1 yields -1, not 1 (remember that in integer division 2/3 is 0).
If the operators have the same precedence they are evaluated from left to right. So in the expression minute*100/60, the multiplication happens first, yielding 5900/60, which in turn yields 98. If the operations had gone from right to left, the result would be 59*1 which is 59, which is wrong.
Any time you want to override the rules of precedence (or you are not sure what they are) you can use parentheses. Expressions in parentheses are evaluated first, so 2 * (3-1) is 4. You can also use parentheses to make an expression easier to read, as in (minute * 100) / 60, even though it doesn't change the result.
Operators for Strings
In general you cannot perform mathematical operations on Strings, even if the strings look like numbers. The following are illegal (if we know that fred has type String)
fred - 1 "Hello"/123 fred * "Hello"
By the way, can you tell by looking at those expressions whether fred is an integer or a string? Nope. The only way to tell the type of a variable is to look at the place where it is declared.
Interestingly, the + operator does work with Strings, although it does not do exactly what you might expect. For Strings, the + operator represents concatenation, which means joining up the two operands by linking them end-to-end. So "Hello, " + "world." yields the string "Hello, world." and fred + "ism" adds the suffix ism to the end of whatever fred is, which is often handy for naming new forms of bigotry.
So far we have looked at the elements of a programming language---variables, expressions, and statements---in isolation, without talking about how to combine them.
One of the most useful features of programming languages is their ability to take small building blocks and compose them. For example, we know how to multiply numbers and we know how to print; it turns out we can do both at the same time:
System.out.println (17 * 3);
Actually, I shouldn't say at the same time, since in reality the multiplication has to happen before the printing, but the point is that any expression, involving numbers, strings, and variables, can be used inside a print statement. We've already seen one example:
System.out.println (hour*60 + minute);
But you can also put arbitrary expressions on the right-hand side of an assignment statement:
int percentage; percentage = (minute * 100) / 60;
This ability may not seem so impressive now, but we will see other examples where composition makes it possible to express complex computations neatly and concisely.
WARNING: There are limits on where you can use certain expressions; most notably, the left-hand side of an assignment statement has to be a variable name, not an expression. That's because the left side indicates the storage location where the result will go. Expressions do not represent storage locations, only values. So the following is illegal: minute+1 = hour;.
- variable A named storage location for values. All
variables have a type, which is declared when the variable is created.
- value A number or string (or other thing to be named later)
that can be stored in a variable. Every value belongs to one type.
- type A set of values. The type of a variable
determines which values can be stored there. So far, the types we have seen are integers (int in Java) and strings (String in Java).
- keyword A reserved word that is used by the compiler
to parse programs. You cannot use keywords, like public, class and void as variable names.
- statement A line of code that represents a command or
action. So far, the statements we have seen are declarations, assignments, and print statements.
- declaration A statement that creates a new variable and
determines its type.
- assignment A statement that assigns a value to a variable.
- expression A combination of variables, operators and
values that represents a single result value. Expressions also have types, as determined by their operators and operands.
- operator A special symbol that represents a simple
computation like addition, multiplication or string concatenation.
- operand One of the values on which an operator operates.
- precedence The order in which operations are evaluated.
- concatenate To join two operands end-to-end.
- composition The ability to combine simple
expressions and statements into compound statements and expressions in order to represent complex computations concisely.