Circle theBall = new Circle(10, 20, 30);The stuff on the left of the '=' is the kind of thing we are naming and the name we have chosen. But what's that stuff on the right? What happens to it? Before we give the thing a name we need to figure out what it really is. To figure out what something really is, we need to evaluate it. Evaluation just means that the stuff we write (which we call an expression) is allowed to express its true self. What kinds of expressions can we write? An expression can be:
new
) 1 "hello" aSquare aSquare.width() new Square(10, 20)The first two items are literal representations of objects; the third is a name of an object; the fourth is a message send; and the final line shows a request to have a new object created.
We can now slightly formalize our naming pattern:
<The kind of thing> <the name> = <expression>;
Java provides us with mathematical operators that allow us to write mathematical expressions. The basic operators are:
Symbol | Meaning | Example Expression | Value if y is 11 |
---|---|---|---|
+ | add | y + 5 | 16 |
- | subtract | y - 5 | 6 |
* | multiply | y * 5 | 55 |
/ | divide | y / 5 | 2 |
% | remainder | y % 5 | 1 |
We sometimes call the operators in the above table binary operators because they operate upon two subexpressions. What if I want to negate a value? In Java you can use the minus symbol in a unary manner to do this, just like in regular math:
int q = x * - y;Mostly, these operators work just like they work in normal math, with the standard precedence rules. If you're unsure about precedence, you can always use parenthesis to make yourself sure. Here are some examples:
int y = 4; int x = 2; int m = x + y * 8; // Q: What's the value of m? A: 34 int n = (x + y) * 8; // Q: What's the value of n? A: 48Wait, what's the weird stuff after the "//" on the right? If you think it doesn't really look like Java, you're right. Java lets us add comments to programs which it dutifully ignores. A comment serves to make a program more readable to another human. Everything from the "//" to the end of the line is ignored by Java.
Note that division between integers behaves somewhat differently than you might expect. If I ask you, "What is 5 divided by 2?", you'll correctly answer "Two and a half". But now, let's look at the following Java fragment:
int x = 5; int y = x / 2; // Q: What's the value of y? A: 2In the above example, we're in a little bit of a pickle because y is an integer. It can only represent whole numbers. "Two and a half" is not a valid Java
int
any more than it is a valid real
world integer. So what happens? Java will truncate (ie. drop) any
remainder that results from a division between integers. Hence, the
result that y
will be bound to is two.
What if we want to know the remainder? Java provides us with an operator that can answer this question for us. It's called the remainder or sometimes the modulus (or just mod for short) operator. Here's an example:
int x = 5; int y = x / 2; int theRemainder = x % 2;Depending on the scenario, it may be appropriate to use a different kind of number that can represent fractions, such as the
double
.
double x = 5; double y = x / 2; // Q: What's the value of y? A: 2.5What happens if we write the following:
int x = 5; double y = x / 2; // Q: What's the value of y?Try it and see. Is the answer what you expected? Why or why not?
Let's look at a few expressions again. Notice that you can tell me what "kind" of thing each of these expressions evaluates to.
"hello" aSquare aSquare.width() aSquare.length() * 23In Java, when we give a thing a name, we have to be sure that we also say what kind of thing we're naming. That's why we're always saying something like this during naming:
String greeting = "hello";The word
String
is there to state what the kind of thing
it is that we're naming.
It doesn't make much sense to say something like: "Her age is green." In that sentence there's a mismatch between "green" and "age". What is it? When we think of age, we think it should be a quantity, a number. But "green" is a color. They're not the same "kind" of thing, so it seems like non-sense. From now on, we'll use the term type to mean "kind of thing." Java is very picky about this kind of non-sense (we'll call them type mismatches) and will catch us on it every time. For instance, Java will gripe about the following:
String greeting = 7; int someNumber = "hello";Although it may seem annoying at first, this is actually a good thing. For one thing, imagine what would happen if Java let you add Strings and numbers. What would the meaning of that be? Since it is never the case that a programmer intends to mismatch types, the Java language rightly forbids it in practice.
int x 7; int velocity = distance / ; String foo = "hello" 56;The second Bushism contains a semantic error: we think of pies getting bigger and smaller, but we don't typically think of pies getting higher any more than we think of plants screaming, or pigs flying. Semantic errors in Java are usually type mismatches. Here are a few:
String myName = 7; aSquare.move("hello"); // assume the move method wants an integer! int area = length * "width";The third Bushism is more subtle, and we may call it a pragmatic error. It reflects an unconventional usage of the English language. An equivalent in Java would be poor coding style. Incomprehensible variable names or poor formatting might make your program difficult or impossible to read, even though it's legal by the rules of the Java language.
Recall our basic pattern for sending a message:
<object-name>.<message-name>(<some information>);When we send messages to objects, we often pass along some other objects that are required for it to answer in an interesting manner. For instance, if we want to move a square, the square wants to know how far to move. If we add something to a collection, the collection needs to know what to add. The objects we pass along with the message are called arguments or parameters. Note that messages are often really picky about what kind and number of arguments are acceptable. For example, if we ask a rectangle to move, passing along two numbers seems reasonable. For instance:
aRectangle.move(10, 20);What happens when we pass along another rectangle or a String?
aRectangle.move("hello", 20); aRectangle.move(35);Neither of the above statements make sense to us, and they don't make sense in Java either. The first makes no sense because the move message expects two integers, but we have provided a string and an integer. This is an example of a semantic error. The second makes no sense because we have only provided one parameter, in a situation where two were expected. This is also an example of a semantic error.
While we can often intuit what kind of arguments are acceptable, to really figure out what kinds of arguments are acceptable, we need to look at the interface (or sometimes signature)of the method. An interface to a method is a description of the behavior of the method. It defines the the name of the method itself, the number and types of arguments required by the method, and the type of object returned by the method, if any. Often, the interface will also consist of some commentary which describes the behavior or semantics of the method. Here is an example, for the move and area methods for Rectangles:
// Change the position of the shape by the given deltas. // parameters: // deltaX: the X distance to move // deltaY: the Y distance to move void move(int deltaX, int deltaY); // Answer the area of the shape. int area();The keyword
void
means that the move method does not
return or answer with any value. The interface shows us the pattern
that we must follow if we are to call the method correctly. In particular,
for the move method it states that we must provide two arguments, both
integers. Furthermore, it defines the meaning of those two parameters.
The interface to the area method, tells us that it takes no parameters
but returns a value, an integer, which is the area of the rectangle.
Before the message is sent, the expressions that represent the arguments are evaluated. Look at the following example:
aRectangle.move(10, aRectangle.width() / 2);Both arguments are evaluated before the message is sent. Of course, the first expression isn't very interesting, and it just evaluates to the number 10. The second evaluates to half the width of the rectangle before being sent. We can now formalize our message sending pattern:
<object-name>.<message-name>(<expressions>); where <expressions> is zero or more expressions depending on the interface of the method.
We often need to do things that require more than one step: baking a cake, washing our hair, changing the oil in the car. Java allows us to express this notion by stringing together statements. Think of each statement as a command to the machine. Each statement is executed, and when it's finished executing, the machine executes the next one. Let's string together some statements that get something interesting done.
int width = 20; Rectangle square = new Rectangle(width, width); square.move(35, 10);Notice that we separate statements by using semi-colons. The semi-colon is similar to the full-stop "." in written English. It is used to separate sentences. Java isn't picky about how we write our statements, but its considered bad style to put more than one statement on a single line. Why? Look at the above example rewritten:
int z=20;Rectangle square=new Rectangle(z,z);square.move(35, 10);Notice that we have not only placed all three statements on one line, but we also not chosen very good names. We've managed to make it very difficult to understand what this fragment is supposed to do.
In today's computer systems, input typically comes from the keyboard and/or a pointing device called a mouse, and output goes to the computer screen. However, there are other unseen sources of input and destinations for output, such as files that hold data on disk drives, network devices that allow our computers to communicate with each other, and printers.
We'll hide many of the details of doing input for now, and imagine that we have a simple interface for performing input. Here is the interface for reading an integer. Reading other simple values occurs through a similar interface.
// Prompt the user and read and return an integer // If they do not provide an integer, they are re-prompted. // parameters: // prompt: a String to display int readInt(String prompt);Here's a sample interaction (in the interpreter), using this interface.
prompt> Input input = new Input(); prompt> int width = input.readInt("What is the width of the box?"); What is the width of the box? 8 prompt> int height = input.readInt("What is the height?"); What is the height? hello Not a valid integer, please try again. 4 prompt> int area = width * height;
Performing simple, textual output in Java is pretty simple, although the
syntax may seem a little strange for now. The system provides us with
a well-known object, called System.out
that has the following
simple interface.
// Print a textual representation of the given object, // followed by a newline (carriage return) // parameters: // o: any object to display void println(Object o); // Print a textual representation of the given object, // without a trailing newline // parameters: // o: any object void print(Object o);Here's another sample interaction (in the interpreter), using this interface.
prompt> Rectangle r = new Rectangle(10, 20, 30, 40); prompt> System.out.println(r) [Rectangle: x=10, y=20, width=30, height=40]