![]() |
|
![]() |
Into Java, Part II - Lab Work
|
import java.io.*;
|
// 1
|
Line 1: A statement that informs the Java compiler to import from the io
class
of the common Java environment whenever needed to. In fact this line is redundant. Our applications will always
have full access to the io
class, and a few more classes -- the fundamental Java classes -- but we
use this line more as an illustration.
Line 2: The class header, providing the class name, BankAccount
.
The public
part tells the system that anyone, practically, could use this class to create their own
instances from. In spite of that, anyone will not have access to our objects, as we soon will see.
At the end of line two there is the { , the beginning of the body of the class. Along with
the finishing } it encompasses the entire class body. This far the body is nothing more than two data fields,
the name and the balance.
Line 3: We assume name
will be spelled with alphabet characters, as we usually
write names. Therefore, we declare name
to be of the String
class.
At this time we don't know anything about the holder, even more less his name, hence we do no initialization.
Line 4: Preferable we will only handle real dollars and never cents, that's why we declare
balance
to be an integer, an int
. Unless this bank will credit us with an initial amount as
a welcome gift, we must initiate the balance
to zero at the creation.
This initialization to zero is not necessary to do here, but it's convenient. Even though the bank will use
welcome gifts in the future, or only for certain BA's, it doesn't hurt to initiate to zero. On the contrary, think
of what could happen if we didn't initiate to zero, and we'll forget to give balance
a value upon
creating an instance of this class. What will happen if we later will try to redraw money from it? There is no
money, so we couldn't rob the bank, but the redraw
method will get in trouble, since it will find
null, which is more nonexistent than zero.
protected
at the beginning of line three and four? We said that the class is made
public
, so anyone could use it to make their own BA's from. But we will certainly not let anyone else touch
the stuff we have within our BA object. Therefore, we hide the information within the
class, we protect it so that no-one could not "see" or manipulate the data fields. Now only methods
within the class could change or access the data. There are other access modifiers as well, that we'll
discuss when we encounter them.The very first method, a method we will always use, is the toString()
. It is an easy
method to write and it's self-explanatory. Why use this method? If any thing goes wrong Java tries to give us
a clue of what happened. At that time it will present us the brief, or long if we like to, information we have
stuffed in toString()
. This is why it's a good practice to use toString()
, it will surely
save you expensive hours debugging your code.
toString()
will not print by itself through the System.out, but it's invoked by the Java run-time
environment. Or by ourselves if we like to. Usually it returns a String, telling us a few details, and so give
us an identifying description.
public String toString () {
|
// 6
|
Line 6 and 9: As the class is, methods are made public
. A future column will
discuss protected methods. String
tells the compiler that toString()
will return a text
string, and void
that this method will return nothing. Why so? you may ask. That way the compiler
makes sure we know what we are doing. We will not be allowed to request a String from a method that will not return
nothing.
What about the (int value)
part? As discussed in the theory chapter, this is the information receiver.
We have to tell the compiler what kind of information to expect, if any. We will leave it with that for now, but
there are really useful concepts out of that. Here we say that the sum to be received, and assigned
to value
, must be an int
.
Please note, whenever we mention a method, usually we will write x(),
and the parenthes denotes
we are discussing a method. This is because we are allowed using exactly the same name for data fields as well,
e.g. price
and price()
are a data field and a method respectively.
Line 10 and 12: Here we do a simple if - else
test, and I think the purpose is
obvious. It's always good to know that the cashier cannot mistakenly do a typo of minus one million dollars,
and drive you bankrupt the very week you sold your Intel shares. She will be directed to line 12 if she did wrong.
An else
is not necessary, we use it only whenever we actually need anything to be done as an alternative.
Another time we will learn more about how to use if, else, else if
and a few more.
Please note the { } encompassing the body of the else
. These are necessary as soon as more than
one statement are to be executed. Therefore, we do not need them for if
, which only have one statement.
Line 11: Add the sum of money to the balance. Within the object the data fields are visible.
They are only invisible to objects and methods outside the object they belong to, because we made them protected.
Line 13: A line with this text will be printed if the cashier made that typo, and nothing
will happen to your balance. Try to deposit again.
Line 15: The wrong value will be printed. Compared to the HelloWorld, we see that it would
have been possible to use the +
sign at line 14, to add further information to be printed. The only
reason of this new line is to show a tiny difference between print()
and println()
.
In the HelloWorld app we used print()
, but then we had to finish the line with the "\n"
operator, 'end-of-line'. The subtle difference between these two methods is that println()
does
a line feed by itself.
What is a BA if we cannot withdraw money from it? Let's continue:
public void withdraw (int value) {
|
// 18
|
Line 18: Despite we withdraw money, it isn't the withdraw()
method that hands
them to us. Hopefully we'll get them from the cashier. That's why it have void
as return type, but
withdraw()
will justify the balance.
Line 19: There is no big difference from the deposit(): if - else
line, except
two things, a small matter of taste, and a great opportunity to discuss how comparisons will evaluate. The most
obvious comparison is whether we try to withdraw more money than we are credited. If so, we are directed to the
else
alternative printout. Maybe you ask, "Why not tell the balance at the same time?" The simple
answer is, don't let a method do more than it's supposed to do. It's better to create another method doing that
part of the work, a querying method that we could use for other purposes as well. Admittedly, it's a matter of
taste.
In the middle of the comparison line there is a double &&
. This notation is used for AND.
It will guarantee us that both comparisons are true, we still have credit left AND the amount we want to withdraw
is correctly typed, a negative value would actually be a deposit. Cool, but unfortunately the bank will soon find
out.
Why did we write the "do we have enough money" check before the "typo" check?
Despite all those bugs we see too often, developers actually have been thinking. One thing with an AND
comparison is really trivial: both left side and right side have to be true. If the if
finds the
left part false, it is redundant to check the right side, so it does not. Smart, he? Then it's up to us to figure
out which comparison is most frequently false, and put that one first, and that way saving a few CPU cycles.
Exactly the same reasoning is true about OR comparisons, it's enough finding one true left OR true
right. Put the most frequently true to the left. Every composite comparison will evaluate from left to right,
and stop whenever a conclusion is made.
public String name () {
|
// 27
|
These two useful methods will give us an opportunity, the only one indeed, to have a look at the two data fields.
Since the fields are protected it isn't possible for anything, except public querying methods within the object,
to return those data.
Line 27 and 30: The double parentheses ( ) are empty, nothing is needed to be able to return
the data stored in the data fields. To show the difference, we will make a method used whenever we would like
to change a name. Maybe the customer got married, or whatever.
public void name (String newName) {
|
// 33
|
How come both methods could use the same name name()
? Because the compiler is viewing them as
two different methods, actually name(void)
(although void is not written, but understood) and
name(String)
. As Jones, James is not Jones, John. Powerful, isn't it?
Now we have a complete class, with two data fields and six methods. Everything is written within the encompassing
{ } parentheses of the class.
public BankAccount () {
|
// 36
|
Constructors looks a lot as methods, and they are in many respects. But we cannot invoke them, as we invoke
methods. And they never returns anything. Constructors will only listen to a special operator, the new
operator
discussed below. And they are named by the class name as we see.
What is super()
? Without going too far, we can say that it's a call to the System parent, to let
the environment constructor create a new general object. super()
is sometimes not written explicitly,
but it is always there, it's implied. If we from now on leave it out, it's understood.
Anything else isn't done within this constructor. The object is now created, we have our BankAccount instance
at hand. However, if we didn't initiate balance
to zero at line 4, we can do it here, in
the constructor. If so, we have to add a line balance = 0;
within the body of the constructor.
public BankAccount (String n) {
|
// 39
|
With these three more constructors we can create a BA any way we like, but maybe that one with a balance but no
owner is more for Swiss banks to use. The BankAccount class became 47 lines long, but
it surely is a lite BA. It's clear anyway that classes don't need to be several hundreds of lines. A few weeks
ago I made one only 10 lines long, but on the other side, I needed about 2,500 instances of it for my lab work.
To make this class work, we have to use the code found in MyBank.java. Objects like
BA are rarely running by themselves. MyBank is a short test application. It will create a few BA objects, assign
them owners and do a few transactions.
new
OS/2 - Window |
[X:\]javac MyBank.java
|
Compile and run your Home Java bank. |
new
operator. Above I stated that the constructors only listened
to a special operator, that's new
. This operator will order the creation of a new instance of the
actual class. It's as simple as that. Next time we will discuss it a little bit more.After you have edited MyBank.java, copy it into the Bank folder. As we did the last month, we compile this
Java file into Java byte code, and then run it.
Why don't we compile the class BankAccount.java? Simply because javac
is smart enough to understand
that it needs to compile that class too, since it is used by the MyBank class. That's convenient whenever making
minor editing on any class in a bigger app, only run javac
on the main class, and the compiler finds
out by itself that only a few *.java files are actually edited, and compiles them.
Please, experiment with MyBank as much as you like, nothing will be crashed or screwed up, the nasty and foul-mouthed
compiler will amuse you. Ctrl + C will stop every process out of control.
The data fields have to be declared and maybe initialized.
Initiation could be made at the declaration, or in the constructor. Neither is absolutely necessary, we might
give data field's values later on.
The importance of the penciling phase and of toString() was emphasized, since
it will save us a lot of late nights and brain work in the future. With this knowledge we now are prepared to
advance into the Java world of living creatures, objects and ways to master them all. Have a nice adventure. See
you next month!
|
|
|
![]() |
|
![]() |
Copyright © 1999 - Falcon Networking |
ISSN 1203-5696 |
November 1, 1999 |