6.170 Recitation 1
Thursday, February 5, 2004
Contents:
- PS0 due on Fri 9pm
- PS1 out today, due next Thu
- Lots of LA hours this week, Thu evening, Fri from 1pm-7pm
- Informal "Lab" in W20 on Fri from 1pm-7pm (TAs and LAs will
attend) to guide through PS0 and answer any/all Java questions.
Please take advantage if you are new to Java.
6.170 is a class where you will learn to design and implement
software systems. In this recitation we will review Java syntax
and object oriented programming concepts. By the end of this
recitation you should be familiar with Java syntax and writing
specifications. The material covered in this recitation should
prepare you for problem set 0.
We are introducing new tools into 6.170 this term. You will be
using CVS for all of your psets, and we are encouraging you to use
eclipse. You can find tutorials and documentation on the course
website, and PS0 is intended to introduce you to these tools.
Please send e-mail to your TA if you are struggling with these
tools; we want to make sure they are working for you.
In lecture we got a glimpse of object oriented programming. Now
we need to introduce more Java syntax which you will be using
for the rest of the term.
Take a look at the provided code: ComplexNumber.java and ComplexNumberMain.java. This is
the code we will be dissecting in this recitation.
A Java program is made up of 1 or more classes. The complex
number example has two. One is used to interface to the command
line, and the other defines the complex number class. Each
class has its own .java file, with the same name.
Each Java file has one class declaration. This includes the
visibility of the class, the keyword class, the name
of the class, optionally the classes and interfaces it extends
or implements, and the body of the class enclosed in curly
braces. The class ComplexNumber is defined like
this:
public class ComplexNumber {
// Fields go here
// Constructors go here
// Methods go here
}
At the top of the class's body are field declarations followed
by constructors, then methods.
There are some java keywords in the example:
- public - visible to all classes
- private - visible only to current
class.
- static - independent of any instance
data.
In this course we will also use the following notations when we
talk about program structures:
- class - a data type for an object.
- instance - a single item of information which
represents a class.
- requires - precondition: that which a method
assumes
- modifies - a list of everything which a method
modifies
- effects - the result (return and side effects) of
a method.
- Mutable - data may be observably modified. A
mutable object can change its state over time. (such as
array)
- Immutable - no observable changes may be made.
After the object is creation, the value will never change.
(such as string)
Fields are where data is stored for each class. Fields may be
public or private. They also may be static or not. Generally,
it is good practice to make all of your fields private, except
in special cases. In ComplexNumber there are two
fields, real and imaginery.
private double real;
private double img;
- What are static fields good for?
- Answer
Static fields are shared by all instances of the same class.
They are useful for information that is not specific to any
particular instance of a class, but can be applied to the
class as a whole. A private static field might be useful if
you want to count the number of objects instantiated from a
class. System.out is a frequently used public static
field. Constant are often created by declaring a final static
field.
- What dangers do you run into if your fields are not
private? How is this related to the representation invariant,
and provably correctness of the program?
- Answer
Public fields give other classes access to the data stored in
a class. This may give them the ability to modify a value and
invalidate or unintentionally destroy the data in a class.
This leads in to representation invariants; keep this in mind
when you learn more about them.
A method body is made up of statements. These include method
calls, assignments, and flow control. HelloWorld has an example
of a statement which is a method call. Many statements end in a
semicolon. Assignments look like id = expr;. Here
expr may be any expression. An expression may be a
method call, a variable, or any combination of these with the
operators.
A constructor is the piece of code which is executed to create
a new instance of a class. In the ComplexNumber
example there is one constructor.
public ComplexNumber(int realPart, int imgPart) {
this.real = realPart;
this.img = imgPart;
}
A constructor looks very much like a method declaration, except
that the function name is the name of the class, and does not
not have a return type.
- Would new ComplexNumber() compile?
- Answer
No, the default no-arg constructor is suppressed once another constructor has been created in the class. In general, you should always provide your own constructor, even if you only wish to provide a no-arg constructor. Remember, you are writing code not just for the compiler, but for the user, as well
A method declaration defines a new method for a class. In Java
all methods are associated with a class. A method takes zero or
more arguments and returns a single result. The abs
method in the ComplexNumber class is an example:
public double abs() {
return Math.sqrt(real*real + img*img);
}
In this example, the first identifier is the visibility, but it
is optional. The second identifier is the return type. This is
the type of the value returned by the method. There is a
special return type void which indicates that no value
is returned. Next is the method name. Then are the parameters
with their types, which in this method, there is none. Finally
it is the method body. In functions which have a non-void
return type, there must be a return statement in the body.
There may be many return statements, and they may be anywhere
in the body, even in deeply nested loop bodies.
The method body here is just one line. The expression
following return is to be evaluated as the return value of the
method. Math is the name of a class in java.lang; it is
followed by a dot. This operator is used to select a method or
a field from the object on its left. Math.sqrt refers to the
square root method of the Math class.
- What use are static methods? Can any method which can be
declared static also be declared not static? Is this true the
other way around?
- Answer
A static method is independent of instances states. It can
also be declared not static, but declaring it static makes it
more convenient to call because it can be called without an
instance. It is not true that all non-static methods can be
declared static. Do you know why?
This is the first thing everyone learns in a new language, and
it covers a lot of important constructs in Java.
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
(Note: instead of public static void main(String[] args), it is
also legal to use public static void main(String args[]).)
You are already familiar with class and method declarations,
but there are a few new things here too. You will notice that
there are three identifiers before the method name here. The
keywords public and static are prepended to
the method declaration. Their meanings we mentioned earlier.
This particular method declaration is the method which is
always called when this class is invoked. System is
the name of a class, and System.out refers to the
out field of the System class.
System.out.println refers to the println
method of that field. This method is then passed the parameter
"Hello, World!".
It is likely that you will encounter some bugs in your code.
Java uses exceptions to handle any abnormal condition,
including errors, generated during the program's execution.
Here are some frequently encountered exceptions.
- NullPointerException - Thrown when an
application attempts to use null in a case where an
object is required.
- ClassCastException - Thrown to indicate that the
code has attempted to cast an object to a subclass of which
it is not an instance.
- ClassNotFoundException - Thrown when an
application tries to load in a class but no definition for
the class with the specifed name could be found.
- IndexOutOfBoundsException - Thrown to indicate
that an index of some sort (such as to an array, to a string,
or to a vector) is out of range. (also look at
ArrayIndexOutOfBoundsException and
StringIndexOutOfBoundsException)
Literals are non-object values in Java; it can be literally
specified in the code as a character sequence that conforms to
specific syntax based on the value's type. Literals include
integers (int and long), floating point
numbers (float and double), characters
(char), booleans, strings, and null.
In every class there should be a equals method, for comparing
the current instance to its input.
- If two objects are
.equals to each other,
are they indistinguishable? Is your answer the same for both
mutable and immutable objects?
- Answer
They may be distinguishable. As was pointed out in lecture,
two mutable objects, even if their values are identical may
be distinguished by modifying one, and seeing if the other
has changed. Two immutable objects if .equals should
be functionally indistinguishable. (Except of course for the
== operator.)
Consider this:
String aStringLiteral = "abc";
String aStringObject = new String("abc");
String anotherStringObject = new String("abc");
What should be the output of the following statements?
1. aStringLiteral == "abc";
2. aStringLiteral.equals("abc");
3. aStringObject == "abc";
4. aStringObject.equals("abc");
5. aStringLiteral == aStringObject;
6. aStringObject == anotherStringObject;
7. aStringObject.equals(anotherStringObject);
Answers
1. true 2. true
3. false 4. true
5. false 6. false
7. true
Immutable objects should not be compared to its literal
counterparts or another object of the same type using
==, if what you want is to check whether they have the
same value. == checks whether two literals are the
same, or whether two statements evaluate to point to the same
object.
The default equals function an object has is inherited from
the java Object class. When you are implementing
immutable class, you should define your own equals
method.
What does the following code print out:
String ta = "noto";
ta.concat("widigdo");
System.out.println(ta);
Strings are immutable in Java; therefore this code will print out
"noto". Why are Strings immutable? Bloch (Item 13) gives several
benefits: simple, easily shared, good building blocks,
thread-safe. It's no free lunch, though; immutable objects can
sometimes be space inefficient (but not always).
All java classes have a toString methods that is
either inherited from the Object class or implemented
by the class. The method returns a string that represents the
current state of the object. In the ComplexNumber
class, toString returns the string a + bi, in
which a is the real part and b is the imaginary part.
public String toString() {
if (img >= 0)
return real + " + " + img + "i";
else
return real + "-" + (-img) + "i";
}
When you define a new class, you should implement your own
toString method. It makes outputing easier, and is
good for debugging as well.
Consider the following simple Java method:
/**
This takes an integer array, a begin index into the array, and an
end index into the array, and returns the sum of the array elements
from the begin index, up to, but not including, the end index.
*/
public int computeSum(int[] elementArray, int beginIndex, int endIndex) {
int result;
result = 0;
for (int i=beginIndex; i<endIndex; ++i)
result += elementArray[i];
return result;
}
This seemingly innocent program is fraught with peril! The
following must be true in order for the program to work
correctly:
- elementArray != null (if not, results in
NullPointerException)
- beginIndex >= 0 (if not, results in
ArrayIndexOutOfBoundsException)
- endIndex < elementArray.length (if not, results in
ArrayIndexOutOfBoundsException)
To ensure program correctness, either this method must check
these conditions, or every method that calls this one must
ensure that it passes in arguments that meet these
requirements. This is by no means the end of the world for this
program. In fact, this isn't even a problem with the code. It's
only a matter of specification.
// comments one line
/* ... */ comments a region
/* comment /* comment */ not comment */ These may not
be nested.
/**
* This is a JavaDoc comment block. Note that
* it begins with two stars after the slash.
* The vertical stars are ignored, and just make
* it clearer that it is a comment.
**/
// You can also make block comments
// like this. This is not a JavaDoc
// comment.
Comments may be used to temporarily remove code from a program.
The most effective comment for this is // placed at
the beginning of every line you intend to remove.
(/* ... */ comments are worse because they do not
nest and because it is hard to tell what code is commented out,
especially in printouts or when syntax highlighting is not used.)
Code removed
with comments should never be left in a final version of your
program.
Comments may be used to explain tricky parts of your program
in English. It is also good to put a comment before every
function describing what it does. If you have any trouble
reading the comments in the ComplexNumber example, or in the
problem set 1 code, feel free to ask a TA or LA to explain any
of the comments.
- Review the code again. Notice how comments are used at
the beginning to specify some information about the file.
There is also a comment detailing the purpose of the class.
Every method has its own comment, and there are some comments
within the methods.
From the staff: start early; get help; send e-mail to TAs
regularly.
From Bloch (Chapter 7): know the APIs (List equality, sort, copy
constructors, StringBuffer); minimize variable scope to prevent
bugs
Talk about the decision in the Date class to have setMonth indexed
from 0-11. Date is used a LOT in JDBC (SQL), which indexes months
1-12. This is the source of many bugs DB-backed sysystems.