Week 02

Your First Program, Simple Output, and Simple Arithmetic
Version 1


 


A Simple Program: Hello World

  It is a long standing tradition (well, as long standing as any tradition can be in a field that's only forty years old) that the first example program that is presented in any language is the hello world program. This is a simple program whose only task is to print the words "hello world" on your screen.

Hello world makes a nice example because, since it does so little, it shows you exactly what the minimal structure of a program is in a given language. That is, the stuff you need to put into every program to make it acceptable to the compiler. (Recall that the compiler is the program that converts the text of a program in a high-level language to an equivalent assembly language program the computer can actually run.) Every programming language has a certain amount of structural overhead that it makes you put into every program, just so the compiler can tell it is a program. Starting with a simple example also insures that you know the series of steps needed to run the compiler to turn the text form of the program into an executable version the computer can run.

In Java, the hello world program is written like this:

Click Here To Run This Program On Its Own Page
// Program: Hello World
// Author:  Joshua S. Hodas
// Date:    July 26, 1996
// Purpose: To display a phrase on the screen
 
class HelloWorld {
 
  public static void main(String args[]) {
 
    System.out.println("Hello World!");
 
  }
 
}

To run this program type the text of the program into emacs, creating a file named HelloWorld.java in your Orion account. (To save typing you could copy the text from your browser window and paste it into you telnet window while in emacs.) Then, at the prompt, type javac HelloWorld.java to compile the program. If you have not made any mistakes then the compiler should have created a file named HelloWorld.class in your current directory. In order to run the program you then type java HelloWorld. The reason you need to run both javac and java relates to the way Java was designed to be embedded in web pages.


Understanding Hello World

 
Comments Identify and Clarify The first few lines of the hello world program (the ones beginning with //) are not really part of the program at all, at least from the computer's perspective. These lines are comments, which are completely ignored by the compiler. They are there only to help the human reader of the program. Every program you write should begin with a comment giving at least this much information, to make it easy for the reader to identify the program and its purpose.

Comments can also be inserted as annotations anywhere inside a program. They are often used to clarify parts of the code whose behavior or purpose might not otherwise be immediately clear, and are an important part of good programming style. Of course it is possible to over-comment a program. The example programs in these notes can be used to get a sense of the proper level of commenting. Your graders will note on your programs where they feel you are over- or under-commenting.

Java supports two different styles of comments, marked with different symbols. The comment marker // indicates that everything past the marker on that line is a comment. This marker allows you to make single line comments, or comments appended to the right of a line of code. These comments are most useful for providing a short explanation of a line of code. A comment can also be marked by the beginning and ending comment markers (or delimiters) /* and */. These delimiters make everything between them (even over multiple lines, or in the middle of a single line) a comment. Thus the opening comment in the Hello World program could also have been written:

/*
   Program: HelloWorld
   Author:  Joshua S. Hodas
   Date:    July 26, 1996
   Purpose: To display a phrase on the screen
*/ 

  It is important to note that comments made using the second form cannot be nested. That is, you can't put one comment inside another. This is because once the compiler sees the characters /* it simply ignores all further text until it encounters the characters */. If one comment is nested inside another the delimeter intended to close the inner comment will actually close the outer comment. The compiler will then attempt to interpret anything left in the outer comment as program source. For example, consider the following attempt to nest a pair of comments:
/*
   Here is a comment
   /* inside another comment */
   that will not work
*/ 
The compiler sees it like this, where we have highlighted what the compiler thinks are the opening and closing delimeters:
/*
   Here is a comment
   /* inside another comment */
   that will not work
*/ 
Thus the part of the outer comment after the inside comment is no longer actually in a comment.

Why should you care? Well when you are trying to debug a program you often just temporarily comment out a part that's not working by wrapping it in a pair of comment delimiters. You have to be careful that the part that you comment out does not contain a comment (constructed with /* */) or the program may not compile or may compile but behave strangely. For this and other reasons, some authors feel that it is best to use just the first kind of comment, since they are less prone to create problems.

  Of course, some authors say that adding a multi-line comment to a program by using the first kind of comment (putting the // comment delimiter a the beginning of each line) is the way that's bad. They feel that a problem arises when you try to add text in the middle of one of the lines and the rest of the line wraps around onto the next line. Now that new line doesn't begin with the comment characters and causes problems. So, it looks like you can't really win. It's up to you to decide which method you want to use to type multi-line comments. From our viewpoint both are pretty much ok.

Java actually supports a third, special kind of comment, using the delimeters /** and */ (note the extra star on the opening delimiter). If you pass your source code (that is, recall, the text of the program as you write it, as opposed to the object code generated by the compiler) through the program javadoc, it will read comments with those delimiters and use them to create online documentation for your program.

The Heart Of The Program The heart of the Hello World program is the line:

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

This line is a single Java statement. It tells Java to print the string Hello World on the screen. The semicolon at the end of the line is the statement terminator and must appear at the end of each statement.

Why is the command name System.out.println so long?

Java Is Object Oriented Java is what is known as an object oriented language. In traditional languages the programmer writes functions or procedures which manipulate data. The data itself is considered to be passive. For example, a function might take a list of data as something to work on and tell you whether a particular value is in the list.

In object oriented languages this view is turned on its head. Data are active objects that know how to perform tasks. I.e., a list might be able to respond to a query about whether it contains a particular value. In this setting, programming consists of defining the different kinds of objects and their behaviors. In place of functions, one defines methods which are the instructions for an object on how to carry out some task.

Sending a Message System.out is an object that corresponds to the screen. One of the things it knows how to do is to display data values on the screen. To ask this object to display something on the screen for you, you send it the message println (which is short for "print line") along with the value you want it to display. System.out responds by executing whatever code it has in the method for performing that task. The value you send to be printed is called the argument or parameter of the message.

Some methods do not require parameters, they act in a way that is independent of the current context. In such cases, the method is called by writing the method name with an empty pair of parentheses after it. For example, System.out has a method name flush which is used to force output to appear on the screen at a particular point in the execution of a program (this is explained in the next lecture). To call it, you write:

System.out.flush(); 

Some methods can be called either with or without an argument. For example, if you call:

System.out.println() 
like that, with no argument, it will just advance the cursor on the screen to the beginning of the next line (like hitting carriage return on the typewriter).

Some authors (including me) sometimes blur the distinction between the point where the message is sent and the point where the message is received by an object which selects a method responding to it. Such authors will refer to invoking the println method of System.out. You may also encounter references to calling a function. This is a throwback to non-object-oriented terminology.

Packages Note that System is actually a special bundle (called a package or, in older parlance, a library) of objects that is available at any time within Java. System.out is just one of several objects contained in that package. In fact, this package is actually a sub-package of a larger one. Its full name is java.lang.System. However, we don't need to use the full name, because all the packages in java.lang are automatically made available to every Java program. We will talk more about packages in the next lecture.

All Java Programs Define Objects While C++ is, like Java, an object-oriented language, for historical reasons it also allows the programmer to program in the older function-oriented style. In Java, all programming is object-oriented. Every program defines some kind (or class) of object and the tasks that objects of that class know how to perform.

  In the example above, our program defines a class of HelloWorld objects. Of course, they are very simple objects. All they know how to do is print "Hello World" on the screen, which they do when the method main is invoked.

But We Will Ignore That For Now I know this is kind of confusing! Therefore, for most of this course we will pretty much ignore the object-oriented nature of Java, until we get some programming basics under our belts. Words like public, static, void, and such are all important keywords that tell the java compiler about how parts of the program behave and fit together. But for now you don't need to know what each one means. For now, just consider the rest of the Hello World program outside the heart of main like some magical incantation that you have to include in every program. We will explain the pieces of that incantation in phases as it becomes necessary for you to move along.

So, for example, if the name of your program is Foo (Foo?!?) your program should look like the following, without your worrying about what all the little bits mean:

// Program: Foo
// Author:  A. Programmer
// Date:    July 26, 1996
// Purpose: To show the basic structure of a 
//          Java program
 
class Foo {
 
  public static void main(String args[]) {
 
    // ... The Guts Of Your Program Go Here ...
 
  }
 
}

The Method main is a Special Method Note that we never explicitly invoke main ourselves. It is a specially named method that must be present in every application program (as opposed to an applet). It is invoked by the system when the class is called from the command line, as when we typed java HelloWorld.


Naming Programs And Files

  The last program was named Foo because the program didn't do anything, so it would be hard to pick a good name for it. In general, though, you should make an effort to pick names for your programs that are descriptive, like HelloWorld, without being too long, like FileBasedTelephoneAndAddressBook.

Writing Multi-Word Names You have probably noticed by now that when we want to make a name from several words we do it by capitalizing the words and smashing them together. The reason for this is that Java, like most programming languages, does not allow you to use spaces as part of an identifier (a fancy word for a name). The characters allowed in a valid Java identifier are the upper-case and lower-case alphabetic characters, the digits 0 through 9 (though not as the first letter of an identifier), and the characters $ and _. The letters and digits are referred to together as the alphanumeric characters.

Different styles exist for writing multi-word identifiers. Many people use the underscore character in place of a space, writing, for example, hello_world. The style we are using (with capitals rather than underscores used to mark word boundaries) is the most accepted one for Java. In the case of program and class names, all of the words in the name should be capitalized. In the case of variable and method names (discussed later) the first word is not capitalized. We encourage you to use this style in your programs.

  Once you have picked the name for your program (or class), the file containing the program should ideally have exactly the same name, but with .java appended to the end. The capitalization in the file name should be exactly the same as in the program/class name. So, for example, the HelloWorld program above should be stored in a file named HelloWorld.java.

When the program is compiled the compiler will create an object code file named with the name of the class and with .class appended. If you have followed this naming convention then the source file and object file names will differ only in their extension (the part after the dot). While following this convention is not strictly necessary, it is helpful in many circumstances, and is a good habit to get into.

Notice, by the way, whenever we include numbers in program and file names in this course, for numbers less than 10 we use a leading 0. This makes all numbers two digits and insures that program names appear in the right order when they are sorted alphabetically (as they normally are in a Unix directory listing). If we didn't do this then the program file JsmithHW10PR1.java would appear between JsmithHW1PR1.java and JsmithHW2PR1.java instead of after JsmithHW9PR1.java. If you had a directory in which you had files that were going to be numbered and you thought you might eventually have more than one hundred of them, then you should use three digits for your numbers, and so on.

Reserved Words Java, like most languages, bars some words from being used as identifiers because they are already used for other purposes in the language. If they were also allowed to be used as identifiers, it would make it difficult to determine if a program were syntactically correct. The full list of Java reserved words is:

abstract boolean break byte byvalue
case cast catch char class
const continue default do double
else extends false final finally
float for future generic goto
if implements import inner instanceof
int interface long native new
null operator outer package private
protected public rest return short
static super switch synchronized this
throw throws transient true try
var void volatile while  

If you do use one of these words as an identifier, the compiler will generate an error. Unfortunately, current Java compilers are not very bright, and the error will likely not be something as obvious as "{code("Error: Reserved word used as identifier.")}. It is more likely that the compiler will just become very confused and complain about something in the general area of the actual error.


Println vs. Print

  In the program HelloWorld we used the method System.out.println to send some text to the screen. The behavior of this method is that it displays whatever value you give it, and then moves down to the beginning of the next line on the screen. Any subsequent printing will occur on that next line. Sometimes, however, it is desirable not to move down to the next line, as later you might want to print something more on that same line. For this purpose there is another command, System.out.print. The following program shows the difference between these two commands:

Click Here To Run This Program On Its Own Page
// Program: PrintVsPrintln
// Author:  Joshua S. Hodas
// Date:    July 26, 1996
// Purpose: To demonstrate the difference between print 
//          and println
 
class PrintVsPrintln {
 
  public static void main(String args[]) {
 
    System.out.print("This text is on the first line.");
    System.out.println(" This is right after it.");
    System.out.println("This is on the second line.");
 
  }
 
}

  Two things you should note about this program. First, there is a space inside the quotes at the beginning of the second item that is printed. If that space were not there, then the output would look like:
This text is on the first line.This is right after it.
This is on the second line. 
with the word This on the first line right after the period from the preceding item. With the space the output comes out as:
This text is on the first line. This is right after it.
This is on the second line. 

The computer doesn't know that there should be a space after a period. It just prints exactly what you tell it to. Second, if we had used print instead of println in the last command of the program, then when the program finished and Unix went to display its system prompt to get your next command it would have put the prompt on the same line as the final output from the program. For this reason, you should always be careful that the last output of a program is done with println.


String Literals

  In the preceeding programs, the texts in quotes that were sent to System.out to be printed are examples of string literals. A string is a value consisting of a group of characters. A literal is any value that you put into the source code of a program explicitly. String literals are always typed inside a pair of double quotes to avoid confusing them with other Java expressions.

For example, suppose you wanted the string:

3 + 3 
to appear in the output. You can't write:
System.out.println(3 + 3); 
because then Java would think you meant to do the calculation and display its result:
6 
In order to display exactly those characters, without the sum being computed, you would put the expression in quotes, as in:
System.out.println("3 + 3"); 

A string literal can contain zero, one, or more characters. The string with no characters in it, written "", is called the empty string. Note that a string literal must always be typed on a single line; it may not span several lines of the source code. That's about the only circumstance in which the Java compiler cares about how statements are broken up into lines.


Escape Characters

 
  Here's a puzzle: How would you get System.out to send the string "Hello World!", including the quotes, to the screen? You can't type:

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

because the characters between the parentheses are now four separate items: two instances of the empty string with two identifiers, Hello and World! between them. (Just as with comments, trying to nest string literals causes problems.) This just isn't grammatically acceptable in Java and the compiler will complain bitterly about it. (In fact, the careful reader will notice that World! isn't even a valid identifier since the exclamation point isn't allowed to be used in identifiers.)

We need a way to tell the compiler that the second and third quotes are not intended to be the kinds of quotes that open and close string literals, but rather are just literal characters in the string themselves. You do this by putting a backslash character, \, before the offending quotes. The instruction then becomes:

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

When this is executed, Java will not display the backslashes. They aren't there as characters in the string. They are just there to indicate that the characters following them (the quotes) are not to be interpreted in their usual way.

Formatting Codes Besides the quote there are a number of characters that have special meaning when they are preceeded by the backslash inside a string literal. For example, \n stands for the newline character, and when it is sent to the screen (or other output device) it causes the cursor to move down to the beginning of the next line before continuing with output. This allows you to produce a multi-line output with a single print command, as in:
System.out.println("First Line.\nSecond Line."); 
which would print:
First Line.
Second Line. 

In general, though, it is considered better style to use separate invocations of println for this, because the use of \n is hard to notice when you are skimming a program. So, in this case we should write:

System.out.println("First Line.");
System.out.println("Second Line."); 
The presence of the newline character in Java is mostly a throwback to C which did not have a command equivalent to println. Recall that you can also use println to print just a blank line, by sending the message with no arguments, as in:
System.out.println(); 

Printing a Slash Here is another puzzle: how would you print a backward slash in the output? For example, suppose we wanted the string:
\n 
in our output. How do you print the backslash? Easy, just put a backslash before the backslash, as in:
System.out.println("\\n"); 
The first backslash says that the next backslash is not an instruction to treat the n specially, but rather is just the ordinary character \.

The full set of special characters (sometimes called escape characters) used in Java is:

\b Backspace
\f Form Feed (New Page)
\n New Line (Move Left And Down)
\r Carriage Return (Move Left But Not Down)
\t tab
\\ Backslash
\" Double Quote
\' Single Quote

Note that the last escape code isn't needed for use in string literals. In that context you can just type the single quote character like any other character. But, as we shall see later, in character literals the literal is surrounded by single quotes. It is in that context that we need this escape code.

ASCII Codes As we discussed in the first lecture, all information in the computer is stored as numbers. It is up to the program to interpret what those numbers stand for in a given context. In the early days of computing every computer manufacturer had their own scheme for representing text. One manufacturer might have used a scheme where the characters of the alphabet were numbered according to the ordering "AaBbCc...Zz" while another might have used the ordering "ABC...Zabc...z" (and lets not even discuss where they put the digits and the punctuation marks). This made it almost impossible to transfer information from one computer to another without a lot of translation in between.

In the mid 1970's everyone agreed on a common encoding system called ASCII, the "American Standard Code for Information Interchange", to be used when transfering information between computers. ASCII numbers the characters from 0 to 127. This gave a standard encoding (into a 7-bit value) for all the usual characters, as well as for 32 non-printing characters (or control codes), like newline and tab, that were used to control the behavior of output devices. While ASCII was intended initially for communications between computers, by the early 1980's almost all systems were using it for their internal representation as well.

Here is a chart with all the ASCII code and the corresponding character. The non-printing characters (the first 32) are represented by their official three-letter name. This chart is taken from the online Unix documentation. You can get a copy at any time by typing

man ascii 
at the Unix prompt.

|  0 NUL|  1 SOH|  2 STX|  3 ETX|  4 EOT|  5 ENQ|  6 ACK|  7 BEL|
|  8 BS |  9 HT | 10 NL | 11 VT | 12 NP | 13 CR | 14 SO | 15 SI |
| 16 DLE| 17 DC1| 18 DC2| 19 DC3| 20 DC4| 21 NAK| 22 SYN| 23 ETB|
| 24 CAN| 25 EM | 26 SUB| 27 ESC| 28 FS | 29 GS | 30 RS | 31 US |
| 32 SP | 33  ! | 34  " | 35  # | 36  $ | 37  % | 38  & | 39  ' |
| 40  ( | 41  ) | 42  * | 43  + | 44  , | 45  - | 46  . | 47  / |
| 48  0 | 49  1 | 50  2 | 51  3 | 52  4 | 53  5 | 54  6 | 55  7 |
| 56  8 | 57  9 | 58  : | 59  ; | 60  < | 61  = | 62  > | 63  ? |
| 64  @ | 65  A | 66  B | 67  C | 68  D | 69  E | 70  F | 71  G |
| 72  H | 73  I | 74  J | 75  K | 76  L | 77  M | 78  N | 79  O |
| 80  P | 81  Q | 82  R | 83  S | 84  T | 85  U | 86  V | 87  W |
| 88  X | 89  Y | 90  Z | 91  [ | 92  \ | 93  ] | 94  ^ | 95  _ |
| 96  ` | 97  a | 98  b | 99  c |100  d |101  e |102  f |103  g |
|104  h |105  i |106  j |107  k |108  l |109  m |110  n |111  o |
|112  p |113  q |114  r |115  s |116  t |117  u |118  v |119  w |
|120  x |121  y |122  z |123  { |124  | |125  } |126  ~ |127 DEL|

Java lets you designate any character by its ASCII value written as a three digit octal value preceeded by the backslash. Here is the same ASCII chart, but with the numbers given in octal (this is also part of the output from the command man ascii):

|000 NUL|001 SOH|002 STX|003 ETX|004 EOT|005 ENQ|006 ACK|007 BEL|
|010 BS |011 HT |012 NL |013 VT |014 NP |015 CR |016 SO |017 SI |
|020 DLE|021 DC1|022 DC2|023 DC3|024 DC4|025 NAK|026 SYN|027 ETB|
|030 CAN|031 EM |032 SUB|033 ESC|034 FS |035 GS |036 RS |037 US |
|040 SP |041  ! |042  " |043  # |044  $ |045  % |046  & |047  ' |
|050  ( |051  ) |052  * |053  + |054  , |055  - |056  . |057  / |
|060  0 |061  1 |062  2 |063  3 |064  4 |065  5 |066  6 |067  7 |
|070  8 |071  9 |072  : |073  ; |074  < |075  = |076  > |077  ? |
|100  @ |101  A |102  B |103  C |104  D |105  E |106  F |107  G |
|110  H |111  I |112  J |113  K |114  L |115  M |116  N |117  O |
|120  P |121  Q |122  R |123  S |124  T |125  U |126  V |127  W |
|130  X |131  Y |132  Z |133  [ |134  \ |135  ] |136  ^ |137  _ |
|140  ` |141  a |142  b |143  c |144  d |145  e |146  f |147  g |
|150  h |151  i |152  j |153  k |154  l |155  m |156  n |157  o |
|160  p |161  q |162  r |163  s |164  t |165  u |166  v |167  w |
|170  x |171  y |172  z |173  { |174  | |175  } |176  ~ |177 DEL|

Thus, the exclamation point, whose decimal ASCII code is 33, which is 41 in octal, can also be written \041. (If you are not sure why decimal 33 is octal 41, review the interactive mini-lessons on conversion .

Of course, this way of designating characters is most useful for characters with no printed representation. For example, decimal ASCII 7 (which is also octal 7), is a non-printing character that will make most terminals (and terminal emulators) ring a bell once. (Try adding \007\007 to the end of one of the string literals in the last example program, and see what happens when you compile and run it.)

ASCII is actually now being suplanted by Unicode which defines a much larger standard character set (with over 65,000 characters specified!). If you want to know a little bit about it, read this.


Numeric Literals

  Numeric literals are just numbers that are typed into the source code of a program. Numeric Literals can be either whole numbers (called integers), or decimal values (called floating point numbers).

Very large or small floating point numbers can be written using a variation of scientific notation by appending the letter "e" (or "E") followed by a positive or negative exponent which represents a power of ten by which to multiply the main part of the number. For example, the value 123456.987, which in scientific notation is written 1.23456987x105, could be written as 123456.987, or as 1.23456987e5. Actually, you don't have to use proper scientific notation, with just one digit to the left of the decimal point. Java will also let you write that value as 123.456987e3, or even as 1234569.87e-1 (though that looks a bit odd), or in a number of other ways.

  One important thing to remember: when typing either kind of literal, do not use commas to group digits of the number. The compiler will not allow it.


Other Types of Literals

  The output commands will accept any of the kinds of literals discussed so far as their argument. There are several other types of literals, corresponding to the other kinds of data that Java programs can manipulate. These will be discussed in the next lecture.


Simple Arithmetic

  Java includes most of the standard arithmetic operators you are used to, and expressions built from them can be used anywhere a literal can be used, including, as you saw earlier, as the argument to the output commands.

The following program uses this idea to display the areas of a square and a circle each 3 units across:

Click Here To Run This Program On Its Own Page
// Program: LiteralAreas
// Author:  Joshua S. Hodas
// Date:    July 26, 1996
// Purpose: To demonstrate simple calculations
 
class LiteralAreas {
 
  public static void main(String args[]) {
 
    System.out.print("Area of a 3 by 3 square: ");
    System.out.println(3 * 3);
    System.out.print("Area of a circle of diameter 3: ");
    System.out.println(1.5 * 1.5 * 3.14159);
 
  }
 
}

Basic Arithmetic Operators Notice that the symbol used for multiplication is the asterisk and not an x. The other basic arithmetic operators are: + for addition, - for subtraction, / for division.

The Modulus Operator In addition, Java, like most programming languages defines the operator % for modulus (or remainder). The modulus operator tells you what is left after an even division. For example, since 3 goes into 11 three times with 2 left over, 11 % 3 is 2. Unlike most programming languages, Java allows you to use modulus with floating point numbers as well. So, for example, 11.4 % 3.2 evaluates to 1.8, since 3.2 goes into 11.4 3 times with 1.8 left over.

  Even though you probably think you won't have much use for the modulus operator, you actually use it quite a bit without thinking about it, and it turns out, therefore, to be very important for programming purposes.

For example, how do you tell if a number is even or odd?

It's even if there is no remainder when it is divided by 2. That is, x is even if x % 2 is equal to zero, and odd if x % 2 is equal to one. In general, the number x is divisible by the number n if x % n is equal to zero.

Binary vs. Unary Operators All of the operators discussed above are binary infix operators. That is, they work on a pair of arguments and are written between the two arguments. The minus sign also works as a unary prefix operator in which case it is written in front of its single argument. (I.e. -3 is the unary minus operator applied to the number 3, and the expression has the value -3).

Operator Precedence When more than one operator is used in an arithmetic expression the order in which the operators are applied is determined by their precedence. If the expression does not include parentheses, then the order in which the operators are evaluated is the same as the one you learned in algebra:

  1. Unary Minus
  2. Multiplication, Division, and Modulus
  3. Addition and Subtraction

If there is more than one operator from any one of these groups, the operators in that group are evaluated left to right. For example, in the expression:

3 + 4 / 3 - 2 * 2 
the division is done first, then the multiplication (because that is their left-to-right order), then the addition and finally the subtraction. That is, it is evaluated as though it were written:
((3 + (4 / 3)) - (2 * 2)) 

When operator precedence does not provide the order you want, you use parentheses to force a particular ordering. If an operator tries to evaluate its operands and finds that one of them is a parenthesised expression, it drops what it is doing and evaluates the expression in parentheses first. So, for example, we could force the division in the last expression to be evaluated last by writing the expression as:

(3 + 4) / (3 - 2 * 2) 

Types Affect Operator Behavior While you were reading the last paragraph you probably assumed that the first example expression, 3 + 4 / 3 - 2 * 2, evaluated to 0.333333... (to whatever precision the computer stores floating point numbers). It turns out, though, that in Java (and C++) the expression is evaluated to 0! What's wrong? Is Java just stupid?

  It's not that Java is stupid, it's just a little lazy. Whenever you apply an operator to two integer arguments, Java assumes you are only interested in an integer result. Obviously, for all the operators other than division this doesn't make any difference. (Mathematicians would say that this is because the integers are closed under those operations: combining two integers by multiplication, addition, subtraction, or remainder, will always yield an integer result.) But for division it can make a big difference, and you must be careful. So, when the system did the division of 4 by 3, the answer it got was 1, because 3 goes into 4 once. The remaining computation then became 3 + 1 - 2 * 2, which evaluates to 4 - 4 which, in turn, evaluates to 0.

If either of the arguments to a binary operator is a floating point number, then the other argument is first lifted (or cast) to be a floating point number, and the computation is then done using floating point arithmetic. So, if we write the expression as 3 + 4.0 / 3 - 2 * 2 then the 3 will be cast to 3.0 and the result of the division is 1.333333. This in turn will cause the other arguments to the addition and subtraction to be cast to a floating point value and the final value of the whole expression will be 0.333333.

  Remember, the determination of whether to use integer or floating point arithmetic (and whether to cast one of the arguments) is made on an operator-by-operator basis. If we write the expression as 3.0 + 4 / 3 - 2 * 2 the division will still yield a 1, only then will that value be cast to a floating point number so that it can be added to the 3.0, yielding 4.0. The product 2 * 2 will be computed using integers, and the result, 4, will then be converted to the float value 4.0 so that it can be subtracted from the other 4.0, and the final result will be 0.0.

String Addition In addition to being used for numerical computation, the addition operator is also defined for strings in Java. The result of adding one string to another is just what you'd expect: a string consisting of the text in the first string followed by the text in the second string. So, for example,
"Hello" + " World!" 
evaluates to:
"Hello World!" 

Java will also allow you to add a number to a string. In that case, the number is replaced in the addition by its string representation. For example, the result of evaluating:

"six is the word for " + 6 
is computed by first converting the value 6 to the string "6" and then evaluating:
"six is the word for " + "6" 
to get:
"six is the word for 6" 

Of course, this is most useful when one of the arguments is actually the result of a larger computation. For instance, we could get the same result as above from typing:

"six is the word for " + (3 + 3) 

Note that the parentheses are needed in that last example. Without them, the natural order of operations would have led the computation to behave as thought it were written:

(("six is the word for " + 3) + 3) 
which would have computed the result:
"six is the word for 33" 

This is a useful feature that can save alot of calls to println. Using this idea, we can rewrite the last program as:

Click Here To Run This Program On Its Own Page
// Program: StringPlusNumAreas
// Author:  Joshua S. Hodas
// Date:    July 26, 1996
// Purpose: To show string addition behavior
 
class StringPlusNumAreas {
 
  public static void main(String args[]) {
 
    System.out.println("Area of a 3 by 3 square: "
                     + (3 * 3));
    System.out.println("Area of a circle of diameter 3: "
                     + (1.5 * 1.5 * 3.14159));
 
  }
 
}

Notice that we have again used parentheses around the numeric part of the output expression. They are not strictly necessary in this case, since the multiplication has precedence over the addition here. However, they help to make it clear what is going on.


Overloading

  By the way, when an operator is defined to work for several different combinations of type, like + is, we say that the operator is overloaded.


A Word about Whitespace

  In the last program, the call to System.out was formatted across two lines. This was done to keep the lines short enough to fit in the frame within the text, and to highlight the two parts of the argument to the command. In general, Java does not care about the presence of whitespace characters (spaces, tabs, newlines, etc.) in your program. A single space is the same as arbitrary whitespace. The only exception to this rule is inside string literals. As we mentioned earlier, a string literal must be contained on a single line, and inside the string literal spaces are significant.

  The effect of this is that a single statement may be stretched over several lines, or (though this is discouraged) several statements may appear on a single line. That is why the semicolons are used as statement terminators. It is the semicolons, rather than the whitespace, which determine the structure of the program. Therefore, whitespace can and should be used to improve the readability of your programs. Blank lines should be used to separate logical blocks of the program. Indenting should be used to indicate the nesting structure of the program. As with other matters, you may take the examples on these pages as a guide to good style.

While you don't need to keep the lines of your program as short as those used here (where we are constrained by embedding the code in this narrow text), you should always keep your lines shorter than 80 characters wide. That is the standard width of a terminal screen, and the width of a typewritten page in 12 point monospaced characters.

Last modified August 29 for Fall 99 cs5 by mike@cs.hmc.edu


This page copyright ©1998 by Joshua S. Hodas. It was built with Frontier on a Macintosh . Last rebuilt on Tue, Oct 20, 1998 at 9:32:05 PM.
http://www.cs.hmc.edu/~hodas/courses/cs5/week_02/lecture/lecture.html