Consider the following program:
In-Class Exercise 1:
Type, compile and execute the above program.
Now let's point out a few things:
- First, the structure of the overall program: a class
with three methods inside:
- The three are: main, printBigM, and printBigO.
- Next, observe that the word printBigM appears twice:
- It's essential to distinguish between the two.
- The single-line use is a method call or
method invocation.
- The bigger structure with lines of code is
called the method declaration (or definition).
- There is similarly, a declaration for
printBigO.
- But there are two calls for printBigO.
- A method can have only a single declaration, but
can be called any number of times.
=> In fact, that is the whole point of methods.
- Jargon alert: in other programming languages, methods are
referred to as functions, procedures or subroutines.
In-Class Exercise 2:
Write your own animal sound that uses one method at least
thrice with an exclamation mark at the end, e.g., print
the big version of BAAA!.
Once your program is working, say the sound out aloud
to the class.
Next, let's see how methods "work" by
drawing an analogy:
- Think of the class as a building.
- Think of the method main as the entry point
=> Lobby or main office.
- A Java program will always start executing with
the first statement in main.
- Each method corresponds to a room in the building.
- Here, a method call is a command to go to that
particular room.
- Each room has its own commands (Java statements).
=> These are executed upon entry to the "room".
- Important: When you complete the statements in a room,
you go back to the place in main just after where
the "room" was invoked.
Using numbers, let's trace each step in sequence:
In-Class Exercise 3:
Try these questions for the above program:
- What is the 12-th statement to be executed?
- What step-number corresponds to the second method call
to printBigO?
- What is the 15-th statement to be executed?
Calling methods from other methods
Consider this program:
- Yes, we can write our methods that call our own
methods.
- Incidentally, did you notice the escape sequences?
=> We improved the output.
In-Class Exercise 4:
Re-write your own animal sound using this idea.
That is, use a single method for the letter that
repeats, then call a single method from main
that then has the repetitive method calls.
Once again, let's trace through some steps:
In-Class Exercise 5:
Which step corresponds to the question mark above?
Where in the program would we be at the 15 step?
Mental execution:
- We will use the term mental execution
for the above exercise of tracing through the execution
without actually compiling and running the program.
- Note: Mental execution is extremely important in
developing programming skill
=> Please be sure to practice this with every program you read or write.
- We can't emphasisize this enough. Really.
Method parameters
To see how methods work, let's start with a simple example:
In-Class Exercise 6:
Edit, compile and execute the above program.
Then, just before the declaration of j but
after the first invocation of incrementAndPrint in
main, print the value of i.
In-Class Exercise 7:
Print out the value of i
within incrementAndPrint and
see what happens.
Let's examine method parameters step by step:
- First, method names are like variable names:
usually a collection of letters and numbers.
=> e.g., incrementAndPrint.
- The capitalization inside the name
(incrementAndPrint)
has no effect on the compilation/execution
=> It's merely for readability.
- Next, let's distinguish between invocation
and definition:
- Let's focus on as few aspects of the definition.
When you read this, say to yourself
- "The method takes one parameter, an integer."
- "The method returns nothing" (void).
- Next, let's examine the flow of execution with
the first invocation:
- At the next invocation:
- What's important to remember: the value in
j gets copied into the parameter variable k.
=> Thus, the value in j is not affected inside
incrementAndPrint.
- It's possible to use the same name for the parameter
variables, even though they are different:
Here, we say that the scope of the variables
i
and
j
in the method
incrementAndPrint
is limited to all the code inside the method.
In-Class Exercise 8:
Fill in the code in the method below so that the output
of the program is:
*****
***
*
Multiple parameters
Consider the following example:
- Here, the method checkPythagoreanTriple is
defined with three parameter variables.
=> All happen to identically be int's but don't have to be.
- The values at the invocation are given to the
method in the order the parameters are declared:
- The first value in the invocation goes to the first
parameter variable.
- The second value in the invocation goes to the second
parameter variable.
- A method can be invoked in various ways:
In-Class Exercise 9:
Fill in the code in the method below so that the output
of the program is 3 and 5, respectively.
Reading and Writing
First, let's talk about writing:
- As usual, when writing methods, type in both
parens and both braces before typing what's in between.
- Generally, use the style we have been using:
- Proper alignment of braces under the p of public.
- A space between the method name and the parens.
- You can make up method names, but follow the preferred style:
- Start with a lowercase letter.
- Capitalize the start of different parts of the name.
- Note: class names (like AnimalSounds)
should start with a capital letter.
An important thing to understand about identifiers:
- Consider the method name printBigM.
- This is a name (identifier) we chose.
- We could just as easily have used myCrazyMethod:
- In other words, the compiler does not look into the
English meaning of identifiers.
- We choose identifiers to help us read programs.
A few more writing issues:
- It is possible to write a method declaration before
or after any invocation. For example, we could have written:
- There are three conventions typically used:
- Always declare methods before their first invocation.
- Try to declare methods near their first invocation (just before
or just after).
- Or, group method declarations according to common theme.
(For large classes with many methods.)
- For main, there are also two conventions:
- main is the first method in the class.
- main is the last method in the class.
- What cannot be done: write a method declaration outside
a class:
- Also, we cannot declare a method inside another method, as in:
- Not that you'd want to, but
you can declare a method but not invoke it anywhere.
- You can declare any number of methods inside a
class.
In-Class Exercise 10:
What would happen if we changed the order of method
invocation? For example:
About name clashes:
- Java allows two methods to have the same, provided
they are different in some ways defined by the language.
- This is a somewhat complex issue at this point,
so we will simply give different method names.
- One can also use the class name as
a method name, but this is considered poor stylistic practice.
Return Values
Observe the following program:
public class ReturnValues {
public static void main(String[] args)
{
int val;
val = square(8);
System.out.println(val);
}
public static int square(int x)
{
return x * x;
}
}
public class ReturnValues {
public static void main(String[] args)
{
int val;
val = square(8);
System.out.println(val);
}
public static int square(int x)
{
return x * x;
}
}
Method return values are specified with the type in the method
signature, and if this type is not void,
the method must include at least
one return statement.
The type of the expression that is returned from the method must
match the return type of the method. The expression that invokes
the method must use the return value as the type that is
returned.
public class ReturnValues {
public static void main(String[] args)
{
int val;
val = square(8); /* square(8) evaluates to 8 * 8, thus 64 */
System.out.println(val);
}
public static int square(int x)
{
return x * x;
}
}
When reading methods and method invocations, you want to
follow, statement by statement, what's executing. When you hit
a return statement, replace the value being
returned where the method is invoked.
public class ReturnValues {
public static void main(String[] args)
{
int val, x = 8;
val = square(8);
System.out.println(val);
x = square(x);
System.out.println(x);
System.out.println(square(8));
}
public static int square(int x)
{
return x * x;
}
}
Variables in one function are different from variables in
another function. A variable only exists within enclosing
own {...}.
You can pass constants or variables as arguments.
Methods can be invoked anywhere a variable of the method's
return type can be used.
public class SimpleDivide {
public static void main(String[] args)
{
System.out.println(div(40, 4));
System.out.println(div(40, 10));
System.out.println(div(40, 0));
}
public static double div(int numerator, int divisor)
{
return (double)numerator/divisor;
}
}
In-Class Exercise 11: What does the above
program print out? Type it out, and run it. Does the output meet
your expectation? How could you fix it, if it doesn't?
public class SimpleDivide {
public static void main(String[] args)
{
System.out.println(div(40, 4));
System.out.println(div(40, 10));
System.out.println(div(40, 0));
}
public static double div(int numerator, int divisor)
{
if (divisor == 0) {
return 0;
}
return (double)numerator/divisor;
}
}
Multiple return statements are fine!
Each return statement exits the method, returning the value
they specify.
Testing your Programs
Testing programs is the act of making sure that your implementation
does what you want it to do. Technically, we usually have a
"specification" for what we are supposed to implement. Testing checks
if our implementation adheres to the specification. Inputs to test
are always:
"Edge cases": Are there are values that will test your
conditionals well? Examples: zero in the divide example above, the
lat/lon boundaries in your coordinate transformation code?
Invalid inputs: Are there any inputs that should not be valid?
Examples: lat/lon outside of the bounding box. Question: What do
you return in such cases?
Valid inputs you know the proper return value for. Examples:
lat/lon directly in the center of the bounding box...the pixel
should be the center of the screen!
In-Class Exercise 12
The equation for a line is y = mx + b.
Write a function with the following prototype:
public static double solveForX(double y, double m, double b)
How will you test the function? What values
of y, m, and b should you choose? Choose
at least 4 sets of inputs.
public class SimpleDivide {
public static void main(String[] args)
{
assert (div(40, 4) == 10) : "divide doesn't properly divide 40 and 4";
assert (div(40, 10) == 4) : "divide doesn't properly divide 40 and 10";
assert (div(40, 0)) : "divide by zero broken";
}
public static double div(int numerator, int divisor)
{
if (divisor == 0) {
return 0;
}
return (double)numerator/divisor;
}
}
In-Class Exercise 13:
Break the example:
Return only numerator.
Remove the conditional.
What happens?
In-Class Exercise 14:
In module 5, you implemented three different versions of BMI
calculations with different conditional structures. It's time to
test these implementations!
- Create three separate methods, one for each version of your
BMI calculations.
- What should the parameters to these methods be?
- What should the return value from these methods be?
- How can you test your implementations?
When things go wrong
In-Class Exercise 15:
What is the compiler error you get when a method is
accidentally declared outside a class?
In-Class Exercise 16:
What is the compiler error you get when a method is
accidentally declared inside another method?
In-Class Exercise 17:
What is the compiler error if we misspell
printBigM in the first AnimalSounds program?