| CSCI A201/A597Lecture Notes 29 Spring 2000 |
If we have a mathematical function f from the set of
positive integers N to the set of positive integers
N and with the following definition:
then we can write it in Java as follows:f(x) = 3x + 1
int f(int n) {
return 3x + 1;
}
The domain and codomain of the function as well as the number of
arguments are specified in this definition. A return
statement is used to pass back the result.
Functions are encapsulating computations. In Java functions are called
methods. Let's suppose we now want to implement a (still simple) but more
complicated function, that computes the sum of the first n
positive numbers.
We can do it in several ways:
a) iterative approach
int sum (int n) {
int sum;
for (int i = 0; i <= n; i++) {
sum += 1;
}
return sum;
}
b) closed form formula approach
int sum(int n) {
return n * (n + 1) / 2;
}
c) recursive approach
int sum(int n) {
if (n == 1) return 1;
else return n + sum(n - 1);
}
The iterative approach is very constructive. It uses a local
variable, sum.
The closed form is OK as long as we can prove that the formula
we use does indeed compute the sum of the first n
positive integers. To prove that the formula is correct we can
use mathematical induction. To come up with a formula
it's a different story however.
Exercise: write a function that computes the sum of the squares
of the first n positive integers. Write another that
computes the sum of the cubes of the first n integer
numbers.
The recursive approach is an elegant approach.
Functions can also be mutually recursive, for example consider this
definition of when a given positive integer number n is
odd or even:
boolean odd(int n) {
if (n == 0) return false;
else return even(n - 1);
}
boolean even(int n) {
if (n == 0) return true;
else return odd(n - 1);
}
We notice that the codomain of the function is boolean. In Java there are eight primitive types:
boolean
byte
short
int
long
char
float
double
Now we know how to write functions, but where do we put them. Functions can't exist on their own in Java. They must be located either inside objects or classes. We'll first put them in an object. But for this we need to create an object, so we need to talk about objects and classes.
We create a type of object Abacus and put the methods in it.
class Abacus {
int sum(int n) {
if (n == 1) return 1;
else return n + sum(n - 1);
}
boolean odd(int n) {
...
}
boolean (even int n) {
...
}
}
Classes and objects:
class Point {
double x;
double y;
}
We can draw a picture of a point of type Point.
Objects are being created with new.
An invocation of new activates a constructor.
Every class gets a default
no-args constructor by default if no constructor is specified. If at least one
constructor is specified then there is no default constructor whatsoever.
So to create a Point object with the current definition:
should appear somewhere in the body of a method.new Point();
Reference types
To store a reference to a newly created Point one needs to
use a variable of type Point.
We could draw a picture of that.Point p = new Point();
The instance variables x, and y are initialized
to 0.0 by default. That's different from the local variables
used by methods.
If we add a new constructor to class Point like that
class Point {
double x, y;
Point (double initialX, double initialY) {
x = initialX;
y = initialY;
}
// no default no-args constructor now!
}
we would not be able to create a point like we did before
but we could create one in which we specify the initial values of the coordinates:Point p = new Point(); // this doesn't compile now.
To have the no-arg constructor we need to specify it explicitly, when other constructors have been defined:Point p = new Point(-1.0, -3.5);
class Point {
double x, y;
Point (double initialX, double initialY) {
x = initialX;
y = initialY;
}
// explicit no-args constructor
Point() {
x = 0.0;
y = 0.0;
}
}
Access of members Data members (fields) are accessed like this:
while methods are accessed as follows:objectReference.fieldName
We're are getting closer to explaining the components that will help us write a full-blown program and run it, to test all these things.objectReference.methodName()
Java programs are organized as sets of packages. To start with we
will be working with the default package, essentially "the current
directory". The default visibility for instance variables is
public within the current package.
We look at the following examples:
and draw a diagram for it, and then modify the diagram to includePoint p = new Point(); p.x = 3.0; p.y = 5.0;
So what we have been written so far are snippets of code that should appear somewhere in a method.p = new Point(); p.x = -1.0; p.y = -2.0;
Instance members are of two kinds: (data) fields, and methods (that encapsulate behaviour).
Let's give an example of an instance method for objects of type
Point():
double squareOfDistanceToOrigin() {
return x * x + y * y;
}
Let's define a more general one:
double squareOfDistanceToPoint(Point p) {
return (x - p.x) * (x - p.x) + (y - p.y) * (y - p.y);
}
Note: we could have written the above as
double squareOfDistanceToPoint(Point p) {
return this.x * p.x + this.y * p.y;
}
this is a reference to the object to which the method
belongs to. It's a reference like p. We'll come back to
this later. So we have discussed about instance variables (fields) and about instance methods. We now need the bigger picture so we have the following classification:
Members are:
static).
static variable and a static method
to class Point:
class Point {
...
static int howMany;
static void count() {
howMany += 1;
}
...
}
Just like for instance members we would access the static
method as follows
and thePoint.count();
howMany variable
We mention the convention that classes names are capitalized.Point howMany();
We could use count() in the constructors and keep track of
how many Points have been generated in our program. The main
point though is to remember that access of class members has a similar
syntax to those of instance members.
To write a full-blown Java program you need at least a class. To run
it you need at least one of your classes to implement a method called
main with the following look:
class One {
public static void main(String[] args) {
...
}
}
Note: the name of a function together with the number and types of
the arguments are called the signature of that function. Let's
now make a few more observations on static members
before we move ahead to writing our first full-blown Java program.
(Once that is done we could start writing programs to test all the
concepts and examples discussed in this lecture).
In class Point the following definition
class Point {
...
static Point origin = new Point();
...
}
defines a class member, an object of type Point. We could define some more:
class Point {
...
static Point bearsPlace = new Point(-2.0, -1.5);
static Point lindleyHall = new Point(-1.0, 10.5);
...
}
Exercises 1. Assume the following lines of code:
What's the contents ofPoint p = new Point(3.2, 5.1); double val = Point.origin.squareDistanceToPoint(p);
val at the end of the code. 2. Same question for
Now let's look closer at this line:Point q = new Point(3.2, 5.1); double val = Point.bearsPlace.squareDistanceToPoint(lindleyHall);
and compare it with this linePoint.origin.squareDistanceToPoint(p)
System.out.println("Hello, world!")
The lines are almost identical, in a sense, except that you
may have seen the second one much more often than the first.
The structure of the lines is as follows: System, Point)
static member of that class is accessed
(out, origin)
println(...), squareDistanceToPoint(...))
(Note: the java.lang is imported by default).
So now we can write a full-blown Java program, compile it, and run it.
(We can also use Math.sqrt() in the instance methods of class
Point that compute distances).
To illustrate a full-blown program let's compile and run this program:
class Puzzle {
public static void main(String[] args) {
Puzzle p = new Puzzle();
System.out.println("Final result: " + p.fun(6));
}
int fun(int n) {
int result;
if (n == 0) return 0;
else {
// [1]
result = n + fun(n - 1);
// [2]
return result;
}
}
}
What's the program computing? Exercises
in place of the first comment. Explain the change in output.System.out.println(n);
in place of the second comment, thus leaving the first comment unchanged.System.out.println(n);
Draw a diagram for the objects of type Pair defined below.
class Pair {
int value;
Pair nextPair;
Pair(int initialValue, Pair initialNext) {
value = initialValue;
nextPair = initialNext;
}
}
Define a class of list processor objects that can compute the
length of a list implemented with Pair objects. Place
the main method in the list processor (LisP)
class and have LisP objects generate a random list at
creation time, that they would keep as an instance variable.
class LisP {
Pair myList;
// define your constructors
public static void main(String[] args) {
// define your main function here
}
// define your method length here
}
Last modified: Apr 25, 2000 for A201 by Adrian German