|
Second Summer 2002
|
Lecture Notes Five: Syntax. The structure of main
.
What is a number?
|
That much we know.
|
Let's say: an integer or a floating point number.
|
We know all about integers and floating point numbers,
I'd say.
|
What is an operator?
|
You want a long answer or a short one?
|
Short.
|
+ , - , * , / are operators.
|
What is an expression?
|
A number, is a (very simple) expression. A symbolic name is
also a (very simple, or atomic) expression.
|
What is an expression followed by an
operator followed by another expression?
|
That would also be an expression, wouldn't it?
|
Yes, indeed. What do we have so far?
|
We have this table:
|
Term defined | Composition |
expression | number |
| variable |
| (expression operator expression)
|
|
Do we need the parentheses?
|
Not really, but we want to emphasize the structure.
|
Correct. Now, is ((3 + 4) * a) an expression?
|
It is. Do you want to show why with a diagram?
|
I sure do.
|
Very well, there you go:
|
That's interesting that we can define a concept
(such as expression) in terms of itself.
|
This is called a recursive definition. An
important part of a recursive definition is specifying
a set of fixed points,
|
... without which defining
something in terms of itself could go on for ever.
|
Exactly. Thank goodness for numbers and
variable names without which our definition
would be irreversibly circular.
|
What is an assignment statement?
|
Its structure is as follows: variable name, followed
by an equal sign, followed by an expression,
and then by a semicolon.
|
a = 3 + 5;
a = b;
r = new Rectangle(2, 2, 10, 10);
What are we trying to get at?
|
The structure of all Java programs.
|
What is a declaration?
|
It is a type, followed by a variable name and a
semicolon...
|
int m;
Rectangle r;
double x, y, z;
|
I see you can declare several variables at the same time.
|
Yes, that's relatively obvious by now, I hope.
|
|
... and it can also be
a type, followed by an assignment statement
(as defined above).
|
You should be building a few examples following these definitions,
or take some statements and analyze them the way we analyzed the simple
expression a few lines above.
|
int m = 25;
int n = 34, p;
Rectangle r = new Rectangle (5, 10, 8, 16);
OK, I see what you're getting at, let's move on.
|
Are we really going to be extremely precise and cover all possible cases?
|
Not really. For that we'd have to sacrifice some of the intuitive structure
of all these.
|
But we'll go far enough for you to get a good grasp of the general
structure.
|
Are you ready for something really deep?
|
Go ahead.
|
What is a function call?
|
A function name followed by open parenthesis, followed by zero or
more arguments separated by commas, followed by closed parenthesis.
|
System.out.println();
System.out.println("Wow!");
Math.sqrt(2);
r.translate(3, 3);
What is an argument?
|
I suppose any expression would work as one.
|
System.out.println("tom" + "ate".substring(0, 2) + "a dog".charAt(3));
I've seen length() and substring() being
invoked on String s, but what's charAt() ?
|
Exactly what you're thinking that it might be.
|
Based on its name?
|
Yes. And we'll talk more about char s tomorrow.
|
OK, let's summarize what we have so far:
|
|
Term defined | Composition |
expression | number |
| variable |
| (expression operator expression)
|
funCall | funName ( ) |
| funName ( arguments ) |
arguments | expression |
| expression, arguments
|
|
Any questions about function names?
|
Not really, I suppose they're basically
of the "absolute path" kind, like
System.out.println
|
Good assumption.
|
Are function calls expressions themselves?
|
I'm glad you asked. The answer is "yes" if the function returns a value.
|
Then we are now dealing with an even bigger infinity of expressions.
|
Note though that not all functions return values.
|
Yes, println from System.out does not
return a value, but sqrt from class Math
returns the square root of the argument, so it can be used in an
expression.
|
Let's update our table. We'll put a star (*) next to
remind ourselves that it's a logic error to use a function
call in an expression if the function does not return a value.
|
|
Term defined | Composition |
expression | number |
| variable |
| (expression operator expression) |
| funCall * |
funCall | funName ( ) |
| funName ( arguments ) |
arguments | expression |
| expression, arguments
|
|
|
The update is minimal, but I think I need to
look at more examples before I become too dizzy.
|
You've already seen examples of expressions, as defined by the table above.
|
This table is a table of syntactic categories described in terms of other syntactic categories,
|
... an enterprise aimed at describing the (grammatical structure of our simple) language.
|
Here are some more examples of expressions.
|
Take them apart, fit them in the table, don't just accept them and then move on.
|
|
|
Don't worry. Let's take a look:
|
Math.sqrt(a + Math.sqrt(b))
This is easy:
|
|
Math.sqrt(Math.sqrt(Math.sqrt(Math.sqrt(a))))
Just as easy:
|
|
Math.pow(a, (1.0 / 16.0))
Same as above:
|
|
Math.sqrt(Math.pow(Math.sqrt(Math.pow(Math.sqrt(2)), 2)), 2)
A bit messy, perhaps, but easy:
|
|
(6 + (5 + (4 + (3 + (2 + 1)))))
A statement is a
- declaration or
- an assignment statement,
|
|
|
Or a function call, as in:
|
System.out.println("Hello, world!");
public class Template
{ public static void main(String[] args)
{
<methodBody>
}
}
It's the template we're using, and methodBody
is composed of one or more statements.
|
That is, declarations and statements
in any order, with the following final table describing the
entire structure of the language (so far).
|
Term defined | Composition |
statement | declaration |
| assignment |
| funCall |
declaration | type variable ; |
| type variable = assignment ; |
assignment | variable = expression ; |
expression | number |
| variable |
| (expression operator expression) |
| funCall * |
funCall | funName ( ) |
| funName ( arguments ) |
arguments | expression |
| expression, arguments
|
|
This table covers the syntax of the Java programs that we
are going to be writing for a while.
|
Note that not all syntactically correct programs are logically correct.
|
For example declaring a variable a twice is
a semantic error, although having two declarations
in a program is not a syntactic error...
|
... but if the variable is one and the same the semantic part
of the compiler will signal that.
|
Suppose you compile and run the program below.
|
What's its output?
|
class One {
public static void main(String[] args) {
int m = 2;
System.out.println(m);
int m = 3;
System.out.println(m);
}
}
The program won't compile.
|
One cannot declare a variable twice.
|
All right, let's move on. Have you heard of the
latest late policy on assignments and such?
|
There's no new policy, everything is still the same:
you need to turn everything on time. Try your best to
meet the deadlines.
|
Just trying to get your attention.
|
Sure. Let's move on.
|
Fine. What is an int ?
|
It's an integer number between -231 (which is about -2 billion)
and (231 - 1). If you need to refer to these boundaries in your program,
use the constants Integer.MIN_VALUE and Integer.MAX_VALUE
|
... which are defined in a class called Integer like Math.PI is
defined in the Math class.
|
Convention says: name your constants using all caps
for the name of the constant.
|
How do you define constants?
|
Mark them final when you declare them.
|
Here's a program, what does it produce:
|
Overflow.
|
public class Test
{ public static void main(String[] args)
{ int n = Integer.MAX_VALUE;
System.out.println(n);
n = n + 1;
System.out.println(n);
}
}
Have you run it?
|
Yes, it's an eye-opening experience.
|
Why does it happen?
|
Representation is finite.
|
What if we need bigger integers?
|
Use long .
|
What's a long ?
|
It's a type that allows for the representation of bigger integers. The range is
now -263 (which is about -9 billion billions) to (263 - 1).
|
What if we need bigger integers?
|
Then work with objects of class BigInteger .
|
How do I do that?
|
We'll see that in a minute. What is a floating-point number?
|
A double or a float .
|
float spans the range from -3.4E38 to 3.4E38. double
is much wider: from -1.7E308 to 1.7E308 but both suffer from the same problem:
|
... precision.
|
Yes, what's the output of this program?
|
public class Test
{ public static void main(String[] args)
{ double a = 30000000000000000000000.0;
System.out.println(a - (a - 0.5));
}
}
It should be 0.5 by algebra.
|
Yes, but is that what the program prints?
|
Try it.
|
Also, try to initialize the double variable
with a value that doesn't contain the decimal point.
|
In that case the compiler catches the overflow before it happens.
|
Overflow happens even for double type.
|
The following program produces Infinity .
|
You're kidding me!
|
public class Test
{ public static void main(String[] args)
{ double a = 1.5E308;
System.out.println(a * 10);
}
}
For most of the programming projects in this book, the limited
range and precision of int and double
are acceptable.
|
Just bear in mind that overflow or loss of precision occur.
|
Another kind of loss of precision occurs in what is known as a
roundoff error.
|
What's that?
|
In the processor hardware, numbers are represented in the binary number system,
not in decimal.
|
You get roundoff errors when binary digits are lost, they just may
crop up at different places than you might expect.
|
Here's an example:
|
Another eyeopener.
|
System.out.println(4.35 * 100);
What do we do?
|
Keep a cool head. For example in this last case first round
then cast to an int ...
|
... if you want an int , ...
|
... and especially if you want the right one.
|
How about
|
Slightly off...
|
System.out.println(Math.pow(Math.sqrt(2), 2));
That's different, but related.
|
Yes, and we'll discuss how floating-point numbers should be tested for equality soon.
|
How do you use big numbers?
|
If you want to compute with really large numbers, you can use
big number objects.
|
Big number objects are objects of the BigInteger and BigDecimal classes in the java.math package.
|
Unlike int or double ,
big numbers have essentially no limits on their size and precision,
|
... however, computations with big number objects are much slower than those
that involve primitive types. To perform operations you need to use methods
|
-
add
-
subtract
-
multiply and
-
divide
|
... that big number objects have.
|
Here's
a + b * c
with big numbers.
|
import java.math.*;
public class Test
{ public static void main(String[] args)
{ BigInteger a = new BigInteger("100000000000000000000000000000000000000");
BigInteger b = new BigInteger("200000000000000000000000000000000000000");
BigInteger c = new BigInteger("300000000000000000000000000000000000000");
BigInteger d = a.add(b.multiply(c));
System.out.println(d);
}
}
This is good exercise in object notation.
|
You bet. We've seen rectangles, strings, and now
big numbers. We're getting even better.
|
So what should we have achieved by now?
|
I think we understand integer and floating point numbers.
|
We're able to write arithmetic expressions in Java.
|
We can appreciate the importance of comments and good code layout.
|
We can define and initialize variables and constants.
|
We know of the limitations of int and double types,
|
... and the overflow and roundoff errors that result.
|
We can read program input with ConsoleReader .
|
We know how to print program output.
|
We understand the structure of a method body ,
|
... which contains statements, such as declarations, assignments,
and function calls.
|
We've also talked about expressions.
|
We have used the String class to define and manipulate strings.
|
|
|
By the way can you draw a picture for me for the following situation:
|
String a = "Hello!";
String b = a.toUpperCase();
I sure can:
|
Thanks. It is the same with substring , isn't it?
|
|
I know it is. String objects are called immutable objects.
|
That's right: toUpperCase on a String works
like add on a big number...
|
... or like intersection on a Rectangle .
|
Last updated: Jun 16, 2002 by Adrian German for A201