A Crash Course in Programming

advertisement
A Crash Course in Programming
Note: The particular programming language I use here (as concrete examples of theory) is in Java,
but much of the syntax (i.e. the way the code is written) is very similar, and often identical, to how it
can be expressed in other languages such as C++, C#, etc.
Contents
Getting Started........................................................................................................................................ 3
Software you will probably find very helpful ...................................................................................... 3
A ‘Hello World’ Program ..................................................................................................................... 6
Running your Program ........................................................................................................................ 9
Part A - Primitive Types and Statements .............................................................................................. 10
Statements ........................................................................................................................................ 10
Primitive Types revisited ................................................................................................................... 11
Operations on primitive types .......................................................................................................... 12
More statements .............................................................................................................................. 13
If Statements ..................................................................................................................................... 13
While loops ....................................................................................................................................... 14
Turning this into a runnable program. .............................................................................................. 15
Rewriting the program using a ‘for’ loop .......................................................................................... 15
One Final Note: The ‘Scope’ of Variables.......................................................................................... 16
Section Review .................................................................................................................................. 17
Check your knowledge ...................................................................................................................... 18
Part B - Methods ................................................................................................................................... 19
Some basic pre-written methods you should know about ............................................................... 20
String ............................................................................................................................................. 20
Math .............................................................................................................................................. 21
How to find out the methods a class has in Eclipse .......................................................................... 21
Part C – Converting between types ...................................................................................................... 23
Casting............................................................................................................................................... 23
Part D – Arrays ...................................................................................................................................... 24
Some Quick Basics............................................................................................................................. 24
Cycling through an array’s values using a ‘for loop’ ......................................................................... 25
Example program: Finding the factors of a number ......................................................................... 25
Test Your Knowledge ........................................................................................................................ 27
1
Answers ............................................................................................................................................. 28
Another Example: Roman Numerals................................................................................................. 28
Object Orientation ................................................................................................................................ 32
Fraction Example............................................................................................................................... 32
toString methods .............................................................................................................................. 34
2
Getting Started
We’re going to start from absolute scratch! We’ll be introducing the basic concepts involved in
creating a basic program before working up to gradually complex stuff, as well as describing how we
can use some of the tools to write, test and ‘debug’ our programs. My philosophy to learning
programming is to learn by example, but that some basic ‘scaffolding’, i.e. programming theory, is
essential also to becoming an effective coder. Without the latter, there is a danger to ‘hack stuff
together’ in an undisciplined way.
Coding is a mixture of problem solving, engineering, creativity and scientific rigour. It involves
approaching some potentially high-level problem, perhaps found in maths or science (such as
generating a driving route based on a road map), and engineering a solution that translates that
problem to a workable program.
Software you will probably find very helpful
We recommend a program called Eclipse to write your programs. You can find it at
http://www.eclipse.org/downloads/. There’s lots of versions, but the one we’ll be using her is
“Eclipse IDE for Java Developers” (there’s a similar one called “...for Java EE Developers” – you
probably don’t need this one for the moment). There’s versions for Windows, Mac and Linux based
operating systems.
Eclipse is known as an IDE or Integrated Development Environment. This helps you in a number of
ways when coding:



For many languages, such as Java, it’ll let you know about incorrectly written code
immediately. While most ‘bugs’ in your code (i.e. unexpected behaviour) it won’t be able to
detect, it will underline code that has been written correctly according to the Java language,
just as a word processor might underline incorrectly spelled words.
It’ll ‘compile’ and run your code at the click of a button. Compiling is the process of taking
your code and converting it into a more basic form that the computer can directly read and
run.
It’ll make managing your code much easier, if for example if you want to rename variables,
move code about and other changes.
You can of course write your code in a basic text editor (e.g. Notepad!), and it’s useful knowing how
to compile and run code yourself without the assistance of an IDE. But if you insist on using a basic
text editor (which I did myself for many years before seeing the light!) you’ll miss all the advantages
that IDEs bring, and waste much more time on the less important parts of coding.
When you’ve downloaded Eclipse, double click on the icon of the main Eclipse program (probably
named eclipse.exe). You’ll be asked to select a workspace:
3
Your workspace is where you can create your various coding projects. Just name it anything you like,
put it somewhere on your hard drive you can easily find, then click OK.
This will take you to the main welcome screen, which will look different depending on what version
you downloaded. Click the arrow icon labelled ‘Workbench’ (pictured here on the top-right). This will
bring up the workbench that you’ll be working from. It may seem somewhat intimating at first, but
getting a basic program going is not too difficult.
4
From the File menu, select ‘New Project’, then ‘Java Project’ (since we’ll be coding in Java). If for
some reason Java Project doesn’t appear in the list, select ‘Project’, and then choose ‘Java Project’
from the list provided there. You should see a dialog something like this:
5
Enter an appropriate project name (e.g. “TestProject”), and then click Finish. Now, your should have
a new empty project to start coding in!
Hover your mouse over the tab named ‘Package Explorer’, i.e. where the ‘TestProject’ item is. You’ll
see a small arrow appear next to the label. Click it to expand the contents of the project, and you
should see something like this:
There’s two things here. The src folder is where all your ‘source code’ is going to go. Source code is
code that you write, whereas binaries are compiled code that the computer runs. The latter goes in
a directory called ‘bin’ which is hidden from view. Don’t worry about the ‘JRE System Library’ for
now. This contains various ‘libraries’ (i.e. prewritten code that you can refer to from your own) that
you might use.
A ‘Hello World’ Program
Many people who start learning a programming language start with a ‘Hello World’ program. This is
the simplest program you can imagine: just printing out the words “Hello World!” and then ending.
It’s obviously not a particularly useful program, but it’s quite useful to get over the initial program of
writing some code in the new unfamiliar language, and getting used to the start-to-finish process of
compiling and running the code.
Right click the src folder in TestProject, and select ‘New -> Class’ (see screenshot below).
6
We’ll be looking at ‘classes’ later, but for now, think of it as a place where we can store items and
behaviour associated with one thing in particular (e.g. computing a route on a map, or dealing with a
transaction from a customer). You’ll get this dialog:
There’s lots of options here, most of which won’t make sense yet. But there’s information you’ll
have to fill out to create the class.
1. In Name, put the name of your class. For the moment, put ‘MyTestProgram’.
7
2. Click the checkbox that says “public static void main” under ‘create method stubs’.
Definition: A ‘main method’ is where the computer looks for code when you ‘point’ it at a
particular class. So if you ran MyTestClass, the program would start at the main method, and run
whatever code is inside it.
Click ‘Finish’ and abracadabra! You’ll now have a workspace that looks something like this:
What have we got here? Towards the middle of the workspace we have a tab where we can modify
the code for our class. On the left in the Package Explorer, we can see our class listed under ‘default
package’. We won’t see ‘packages’ till later, but they allow us to group classes with similar behaviour
together. Since we didn’t specify a package name, it doesn’t have an assigned package, so appears as
‘default package’.
Let’s just concentrate on the code in our class now. We can see the ‘main method’ inside the class.
Most of the line starting “public static void” won’t make much sense at the moment. But the overall
effect of this line is to say we have some ‘method’ called ‘main’. Our code goes between the curly
braces, i.e. { }.
Starting a line using “//” indicates that the line of code is a comment. Comments allow us to explain
what our code is doing, and these lines will be ignored when the program is compiled/run.
Comments can span multiple lines, using “/* Your comment here */”. Here, the IDE has put a
comment starting ‘TODO’. This comment is just to say that the method has been automatically
generated, and we need to insert our code there, because it currently doesn’t do anything.
8
Remove the comment, and type the following into the code area:
And that’s all folks! We now have a fully-functioning program that we can immediately run.
Running your Program
We want to compile and run your program. Towards the top of the workspace, you’ll see an icon like
this:
. Click on it, and voila, the IDE will do the work for you. Towards the bottom of the
workspace, you’ll see the following very exciting message:
If you see this, it means you program has run successfully. So what is the ‘console’? It’s more or less
somewhere where you print text to. You may have heard of the ‘command line’ (known in Windows
as the ‘command prompt’), where you can type commands and navigate your file and directories for
example. If you were to run your program from the command line rather than in the IDE, you’d see
your ‘Hello world!’ message printed there. For the moment, think of it as somewhere were you can
show text you want to display. Otherwise, you might display your text in more advanced ways, such
as on a user interface, or transmitting it across a network to a display device somewhere else.
At this point, giving our salutary success in greeting the world, we’re going to give the practical side
of things a bit of a breather and get some basic programming theory that underpins many
programming languages (not just Java!). Once that’s done, we’ll be able to write some actual useful
programs!
9
Part A - Primitive Types and Statements
In computer programs, we can store values in placeholders, called ‘variables’, in exactly the same
way as we use variables in mathematics. In maths, these values can usually just be numerical figures.
In programming however, we have a number of different types. We say a variable has a particular
type, to mean that it holds particular types of values.
Here are the main ‘primitive types’:
Name
int
Explanation
An integer, i.e. holds a
round number.
A single ‘character’, i.e.
symbol.
A ‘boolean’, which is a
truth value.
Any decimal number
(i.e. not necessarily
whole)
char
bool
float
double
Again, any decimal
number, but we can
store double as many
digits.
Not used as often, but
allows us to store very
large integer numbers.
long
Example
-3
Length
4 bytes
‘e’, ‘!’ (notice the single
quotes)
true, false (and nothing
else)
1.42f, -6.0f (the ‘f’ at
the end is to
distinguish it from a
double type below)
5.3, 7.4
4 bytes
132458l (notice the ‘l’
at the end, to
distinguish it from an
integer)
8 bytes
4 bytes
4 bytes
8 bytes
We’ll see some examples of how we can use these in a short while, as well as what we mean by the
‘length’ column in the table.
Statements
A statement in programming simply represents some kind of ‘action’. Such actions might be
prompting some procedure to launch a missile, or much simpler things like assigning a value to a
variable. You may also have heard of ‘if’, ‘for’ and ‘while’ statements which we’ll get onto later,
along with all the other possible actions we might have.
The simplest action is an assignment. This is the process of assigning a variable a value. The ‘syntax’
is this:
type variableName = value;
Let’s dissect this.


The type is whatever type we want the variable to be. e.g int, bool.
The variable name can be anything. Convention however (at least for the moment) is that
the variable name starts with a lower case letter. A popular convention for naming variables
is camel case. This involves capitalising all but the first word in the name. e.g.
10


“stockPriceValue”. Make sure your variable name is descriptive of the value being stored in
it, so people reading you code know what it represents. Avoid using numbers, symbols, and
you’re not allowed a space.
The = in this case does not mean equality. It means whatever is on the right of the equals is
assigned to the variable on the left. We’ll see later how we can express equality in the
mathematical sense. In many programming languages, assignment is instead written as “:=”,
with a colon, so we might have “x:= 2”.
Finally we have the value we want to assign to the variable.
In many languages (including Java), we need to put a “;” at the end of the statement to say we’ve
finished the particular statement. In other languages (such as Python), the program reading your
code can work it out without the semicolon.
Some examples:



int x = 4;
bool isPresent = true;
float stockValue = 4756.35f;
Primitive Types revisited
When you assign a variable, the computer needs somewhere to store the value. We’ll see later that
there’s different types of places the computer might store the value.
All variables are assigned either 4 bytes or 8 bytes. 1 byte = 32 bits, where a bit is a 0 or 1 (these are
known as binary values). Therefore integers and floats for example are stored using 32 bits. A
‘double’ and ‘long’ variable however is stored using 64 bits, allowing us to store twice as much
information. You may wish to read up on what a ‘binary representation’ is to understand this more.
Definition: PRIMITIVE TYPE
A primitive type is one where the value is directly stored in the space assigned for it. This means
for example that an int, say 432, can be converted to binary (i.e. 0s and 1s), and this value is put in
the 4 byte slot allocated to it.
A ‘String’ is a type that is not primitive. A ‘string’ is simply a sequence of characters, e.g. “hello Bob”
to represent some textual value. Just like other variables, we assign 4 bytes to hold the value.
However, the string might be very long (e.g. an essay!), so it wouldn’t be possible to store it with just
32 bits. Instead therefore, we store a numerical address (which can think of for example as a house
number), which ‘points’ to where the value of the string is actually stored. This therefore is why a
String is not a primitive type, because we don’t actually store the value itself in the slot in memory
allotted to it.
You might at this point be thinking “Why do we restrict the value of the slots to 4 or 8 bytes? Why
not make the slots bit enough to hold the value depending on how long it is? We’ll see the reason
when we come on to arrays.
So where are these ‘slots’ to hold values? These are stored on the stack.
11
STACK
x (int): 4
b (bool)= false
str (String) = 253
253 is the ‘address’ for
some location in another
part of the memory.
4 bytes = 32 bits
253
“hello”
While this stuff might seem like very technical detail, there are reasons why it will be important
later, when for example we consider equality of non-primitive types.
Operations on primitive types
We can use a number of different ‘operators’ on primitive values. An ‘operator’ is just a symbol used
to represent function which takes two arguments. For example, + is obviously an operator which
takes two arguments and adds the values together. + is an infix operator because the operator
appears between the two arguments (i.e. 3 + 2, not + 3 2).
Some examples:






2 + 3: just addition on integers. Obviously also works on floats and doubles.
2 * 3 and 8 / 4: Multiplication and division. Important note: If you use / on integers, the
result is actually the whole number of times the divisor goes into the dividend. e.g. 7 / 3 will
give you 2.
7 % 3: The ‘modulus’ operator, which finds the remainder after the divison. In this case, the
result will be 1.
true && false: The && operator means ‘and’, and is usually applied to Boolean values. The
result is true if both the first and second argument is true, and false otherwise. We’ll see
how this can be used later.
true || false: As above, but represents ‘or’. Gives true if either the first or the second value
are true.
== This is equality! It takes the two arguments, and give the Boolean ‘true’ if they’re equal,
and false otherwise. So 3==4 evaluates (i.e. simplifies) to ‘false’. We’ll revisit equality later.
You might wonder if we can mix operands (i.e. the arguments of the operator) of different types.
What do you think happens if we evaluate this:
char myValue = ‘c’ + 2;
12
The answer, curiously, is that myValue now holds the value ‘e’. This is because primitive types are
ultimately just stored as a ‘number’ (represented in binary). ‘c’ happens to have the numerical value
99 (you will find the corresponding numbers for characters by looking up an ASCII table). 99 + 2 =
101. And since myValue has the specified type ‘char’, it will be interpreted as a character.
Conveniently, the numbers representing each of the letters of the alphabet are in order, so 101 gives
us ‘e’. So we can perform arithmetic using characters as well as numbers! We’ll see an example
program later where we want to print to the screen all the 26 letters of the alphabet using a loop
and character arithmetic.
There are some type combos that we are not allowed to combine. For example true + 5 is both
meaningless and will give us a code error. 2 * 4.03 though (where we’ve combined an integer and a
double) is meaningful, and gives us back 8.06 (a double).
More statements
We’ve previously only seen ‘assignment’ as a type of statement. What value does y store at the end
of this program?
int x = 3;
x = x + 1;
int y = x * 2;
The answer is 8. On the second line, the assignment first evaluates x+1 using the existing value of x,
then updates the value of x with the result of that expression. In this case, we’ve reassigned the
value of x. Notice we didn’t have to specify the type of x again on the second line, because we’ve
already declared it on the first. Technically speaking, the first line is a declaration (with assignment)
where we’re announcing the creation of x, whereas the second line is an assignment.
What other kinds of statements can we have then?
If Statements
Let’s see a few concrete examples first to see what ‘if’ means.
int x = 4;
if(x>2) {
x*=2;
x+=3;
}
We could describe in words the program as follows: “We first assign x the value 4. If this is greater
than 2 (which it is), we multiply x by 2, then add 3 to it”.
The *= and += are new types of statements we haven’t encountered yet. x*=2 is a quick way of the
assignment x = x*2. Similarly x+=3 means x = x+3.
Why the curly braces { }? This allows us to group these two statements involving reassigning x
together. You may have deduced the if statement consists of some condition (in normal brackets),
which we determine if it’s true, followed by a statement that we carry out if it is indeed true. The
curly braces allows us to say we do both x*=2 and x+=3 if we find that x>2 is true. If we have just one
statement, we don’t need to use curly braces:
13
if(x>2)x+=1;
The type of the condition should be bool, since it represents a ‘truth’ value. We could technically
write if(1), but it’s not very meaningful. There are cases however in some languages where it may be
useful to do something like this. In web-based languages such as Javascript or PHP, where the
variable ‘str’ holds some string value, if(str) asks whether the length of str is more than 0 characters
(i.e. is not the empty string). So it’s possible to have a non-boolean type for a condition, but let’s not
worry about this for the moment.
We can also specify some statements to run if the condition is false. For example:
if(x>=2)x = y;
else x = z;
Presuming that x, y and z already exist, this sets x to the value y if the existing value of x is greater or
equal than 2 (notice that we use >= rather than >), and set x to z otherwise.
While loops
It’s possible to keep repeating a statement (or statements) until some condition is met. We can
actually start to build something resembling a useful program now! For example, let’s say we
wanted to sum all integers from 1 to n.
int n = 20;
int total = 0;
int i = 1;
while(i<=n) {
total+= i;
i+=1;
}
Let’s try and dissect this, as it’s slightly more complicated! We have three variales. n in this case
represents the number we’re summing up to (i.e. 1 + 2 + … + (n-1) + n). ‘total’ represents our running
total, i.e. what we’ve counted so far. ‘i’ represents the current number we’re adding. So it’s starts
with 1 (since it’s the first number we’re adding to our running total), and has the value ‘n’ by the
time we’ve repeated the statements in the ‘while loop’ for the last time.
Let’s consider it step by step:







To start, n=20, total = 0, i = 1;
It is true that i<=n (since 1<=20), so we perform the statements inside the curly braces.
total+=i is the same as total = total + i. So the new value of total is 1,
representing the fact we’ve started by putting 1 in our running total.
We increment i by 1, so say that we now want to add 2 to our running total.
Since we’ve finished this two statements, we consider the condition of the while loop
again. Does i<=n? Yes, because 2<=20 evaluates to true.
Now, total = total + i gives total = 1 + 2. So the new running total is 3.
Again, we increment i on the next line, so i is now 3.
…
14


When i is finally 20, we find our condition 20<=20 still just about holds true. On the first
line of the while body (the ‘body’ refers to the statements we execute for an if/while/for
statement), we add 20 to the running total. i is incremented again, so is now 21.
We again evaluate the condition. Is i<=n. Now it’s false! 21<=20 is not true, and so the
‘while loop’ finally terminates. The program would now proceed to whatever comes after
the while statement if there was anything following it.
In general, the principle to coding is:
1. Thinking of some algorithm (perhaps in words, or thinking about it conceptually) that
achieves what we want. In this case, we’ve thought of a method on paper we can add the
numbers 1 to n (i.e. by adding 1, then 2, then 3, and keeping a running total).
2. We then translate this method/conceptualise to code.
Sometimes step 1 is the tricky part and step 2 is easy. And sometimes it’s the other way around!
Those with some mathematical knowledge will know that we could have found the sum of 1 to n
much easier using a summation formula. Our code could have been condensed to a simple:
int total = 0.5 * n * (n+1);
This illustrates nicely that there’s often multiple solutions to a given problem, and some solutions
are much more elegant, and require much less code, than others.
Turning this into a runnable program.
Let’s actually run this code!
public class MyTestClass {
public static void main(String[] args) {
int n = 20;
int total = 0;
int i = 1;
while(i<=n) {
total+= i;
i+=1;
}
System.out.println(total);
}
}
Press the ‘Run’ button again at the top of your workspace to run the code. Hopefully, you’ll see the
correct result of 1 + 2 + …. + 20.
Rewriting the program using a ‘for’ loop
There’s actually one more kind of construction besides ‘if’ and ‘while’ statements. These are known
as ‘for loops’. For loops basically allow you to vary some variable between some range. For example,
it might be useful to do something with all the numbers between 10 and 100. We’ll see particularly
when we come to arrays that for statements can be very useful!
15
Here’s a simple example:
for(int i=100; i<200; i++) {
System.out.println(i);
}
What do you think it does? Here’s what’s going on:



We’re creating some temporary variable, in this case ‘i’, which holds the value we’re varying.
We give it some initial value – this is the number at the start of the range (in this case 100).
The expression after the first semi-colon is some condition involving our variable that needs
to hold true for the code between the { … } to be executed. In this case, we’re saying that
our value of I must be less than 200.
The statement after the second semi-colon says what we do with our value of I each time.
We previously saw that i+=1 increases the value of a variable by 1. i++ is an alternative way
of writing this.
The result of the program therefore is to print out ‘i’ while I varies between 100 and 199. We don’t
see the 200 because the inequality is strict.
You may be thinking that when adding the numbers from 1 to n, the for loop might be useful
because we do indeed ‘do something’ with the numbers in a particular range. We rewrite our
program more simply like this:
int currentTotal = 0;
for(int i=1; i<=n; i++)currentTotal+= i;
Here we’re using the for loop to let ‘i’ vary between 1 and n, and add each of these numbers to our
running total. Notice that just like the while loop and if constructions, we don’t need the curly braces
if we only have one action to do (although the program would still run if we put them there).
One Final Note: The ‘Scope’ of Variables
I’ve said that in a ‘for’ loop, the variable ‘i’ we’ve declared is only temporary. What exactly do I mean
by this?
It means that ‘i’ can only be used inside the body of the for statement. For example, this would give
an error:
for(int i=0; i<10; i++) {
System.out.println(“Hello! “+i);
}
int b = i + 1;
The first 3 lines of code are fine, and in line 2 we’d print out “Hello 0”, then “Hello 1” and so on. This
works because ‘I’ is said to be scoped to the ‘for’ statement. That is, it ‘exists’ while we’re in the
body of the for statement (in this case, between the curly braces). However, the last line of code
uses ‘i’ outside of this scope, so will raise a compiler error.
A variable can only be declared once in the same scope. So this case for example is invalid:
16
int i = 3;
for(int i=0; i<10; i++) { … }
This is because the ‘i’ has already been declared on line 1, and we can ‘reassign’ to it after, rather
than create it again. However, interestingly, this is OK:
for(int i=0; i<10; i++) { … }
int i = 3;
This is because the scope of the first ‘i’ is only the ‘for loop’. It is discarded after, so we
recreate/redeclare it once more.
We’ll see in the next section when we look at methods/functions how variables might be scoped in
different contexts.
Section Review
Here’s a summary of what we’ve learnt so far:



Our program consists of a list of ‘statements’. There’s a number of statements we explored:
o We can declare/create a new variable using “type variableName = initialValue”, e.g.
“int x = 2” creates a variable, of type ‘integer’, that initially holds the value 2.
o We can reassign the value of a variable. E.g. “x = 3” updates the value of x to 3.
Obviously, a variable must already have been created if we want to modify its value.
o x+=2 is a shorthand for x = x+2, i.e. updating the value of x by increasing its value by
2. We can similarly do x-=2 or x*=2 or x/=2.
o x++ is a shorthand for x+=1.
o “If” constructions allow us to run some statements based on some condition
holding. E.g. if(x==2){ System.out.println(“It is 2!”); } else { System.out.println(“It
isn’t 2”) }
o “While” constructions allow us to run some statements ‘while’ the given condition
holds.
o “For” constructions allow us to execute some statements based on some temporary
variable varying between a range of values.
There are different ‘primitive types’ which store simple kinds of values, such as integers (int),
real numbers (float or double), Booleans (bool) and a single character (char). “String” is not a
primitive type (hence why the type name is not all lowercase letters).
We can combine values using various arithmetic operations. We could use “int x = y + z” for
example. “==” is used for equality, and the result of type bool. So “2==4” yields “false”, as
does “2>4” or “2>=4”. “true && false” (i.e. logical ‘and’) would give “false”, whereas “false
|| true” (i.e. logical ‘and’) would give “true”. “7%2” gives us the integer 1, because it’s the
remainder when we divide 7 by 2. Beware: 7/2 gives us 3 not 3.5. This is because an integer
divided by an integer gives an integer (where anything after the decimal point is discarded).
If we did 7 / 2.0, then the compiler sees the first number as a integer and the second as a
‘double’, so the result is a double, i.e. the correct result of 3.5.
17
Check your knowledge
What do the following programs print out? (without running the code) Answers below!
1
int x = 0;
while(x<100)x++;
System.out.println(x);
2
int x = 3;
if(x>3)x*= 2;
else x*=3;
System.out.println(x);
3
int y = 1;
for(int x=0; x<100; x++){
if(x%2==1)y*= x;
}
System.out.println(y);
Program 1 gives you 100! Each time the while loop runs its statement, we add 1 to x. When x=99,
the condition 99<100 still holds, so x gets incremented to 100. But then it’s not the case that
100<100, so the while loop terminates.
Program 2 gives you 9. In the ‘if’ statement, it’s not the case that 3>3 (because the inequality if strict,
so we run the ‘else’ statement rather than the ‘then’ statement. x*=3 updates the value of x by
multiplying by 3, so we get 9.
Program 3 is a bit harder. We have a ‘for construction’ where the value of x ranges between 0 and
99. For each of these numbers, we’re seeing if x%2==1. What does this mean? It says that if we
divide by 2, is the remainder 1? That’s equivalent to asking if x is odd! So for each odd value
between 0 and 99, we’re updating y so that we multiply by each of these values. Thus y ends up
being 1 x 3 x 5 x … x 99.
18
Part B - Methods
With our ‘add all the numbers up to n’ program, we had to specifically set the value of n. You might
think it useful however to be able to reuse this method for different values of n. In maths, this
concept is known as a function. Here’s an example function:
x
twice
2x
or f(x) = 2x. You may also sometimes see the domain and the range of the function specified. For
example f:R -> R indicates that the input of our ‘twice’ function can be any ‘real’ number, and the
output is similarly any ‘real’ number.
With methods/functions in programming, we similarly have to specify our inputs, what type they
are, and what the type of the output is. This is how we’d code our ‘twice’ function:
double twice(double x) {
return x*2;
}
Let’s dissect this. The first line specifies the various properties about the method. The first ‘double’
tells us the return type, i.e. the type of what the method returns (in this case some real number).
Next is the method name. In the brackets, we specify the arguments of the function, where each one
we specify the type. So in this case, we have one input x, which is also a real number.
If we want multiple arguments for the function, we can comma separate them:
double add(double num1, double num2) {
return num1 + num2;
}
Create a new class for these new methods within Eclipse. Unlike before, don’t tick the ‘main
method’ checkbox. Name it “MathsUtils”.
public class MathsUtils {
public static double add(double num1, double num2) {
Return num1 + num2;
}
public static int addToN(int n) {
int runningTotal = 0;
for(int i=1; i<=n; i++)runningTotal+= i;
return runningTotal;
}
}
Hmm, we seem to have used a few extra keywords here:

The public keyword means we can use the method in other classes. If it was private, we
could only use it in other methods in the same class. This is known as an access modifier. It
basically stops us making methods that we want only to be used within the class (e.g. to
calculate intermediate results) used elsewhere.
19

The static keyword is a bit more complicated. We’ll see in later sections the distinction
between a class and an object. But for the moment, consider it as allowing you to refer to
your method elsewhere as YourClass.myMethod(arguments).
Let’s use this elsewhere. In some other class that DOES have a main method:
public class TestClass {
public static void main(String[] args) {
System.out.println(MathsUtils.addToN(100));
}
}
Now run this code and voila, you should get the correct result printed to the console. Now that we
have moved our ‘addToN’ method to another class, we can keep reusing it for different values of n.
Before we move on, let’s look at the type signature of the ‘main method’:



It’s static. So when the program runs, it in essence calls TestClass.main(...).
The return type is void. This is a special type which just means “our method doesn’t return
anything”. Unlike mathematical functions, methods in programming need not actually give
you back a result. We might have a method “activeEjectorSeat” in a fighter plane – but we
might not be interested in the result this gives once the method has run!
It’s input is of type String[]. We’ll see in the very section that this is an ‘array of Strings’. If we
were running our program from the command line, we can actually pass information to the
program, which will be stored in args which we can use within the main method if we wish
(we haven’t so far). It’s possible to set these arguments in Eclipse too, but let’s not worry
about this for the moment.
Some basic pre-written methods you should know about
Most programming languages have large swathes of pre-written code for you to use. These are
known as libraries. Java has libraries for all sorts of things, whether it be accessing a database, doing
mathematical calculations, manipulating Strings, drawing stuff and even connecting with a digital
piano! (perhaps my favourite ever program I’ve written is to get the screen to flash up with “MERRY
CHRISTMAS!” if I played Jingle Bells on my piano – I probably had too much free time).
But here’s some initial libraries you should definitely know about.
String
I’ve mentioned before that a ‘string’ is not a primitive type. And that’s handy, because the String
class has all sorts of useful methods:
char charAt(int i): This gets the character at the ith position of a string. For example, the code:
String str = “Hello”;
System.out.println(str.charAt(1));
Will print out: ‘e’. Notice firstly that this didn’t give us ‘H’, which is the 1st letter. This is because in
programming, we tend to start counting from 0. Thus the argument of 1 actually gives us the 2nd
letter. Get used to this fact!
20
Notice also that we applied the method directly to the variable ‘str’, rather than say write
“String.charAt(...)” like we did in the previous section. This is because the charAt method is
not static, and thus it applies to a specific variable and its value. We’ll cement this later.
int length(): This gives us the length of a string, i.e. how many characters it has. So
“Hello”.length() will give us 5.
Math
This class contains a huge number of methods to do all sorts of mathematical calculations. Here’s
just a few:
static int round(double num): This rounds a number to the nearest integer. For example
Math.round(4.32) gives us 4.
static double sin(double angle): Unsurprisingly, this gives us the ‘sin’ function. But beware, this
takes the angle in radians, not in degrees. Older students will know that 180 degrees is the same as
pi radians. We could therefore find the sin of an angle in degrees as follows:
double angle = 45; // in degrees
System.out.println(Math.sin(angle * Math.PI / 180));
Here we’ve used the constant Math.PI. We can see the Math class doesn’t just have methods we can
use, but constants as well!
static double pow(double a, double b): This gives us ab. So Math.pow(2,3) gives us 8. Obviously
quite handy!
How to find out the methods a class has in Eclipse
You never actually have to ‘memorise’ the methods a class has. You tend to ‘discover’ them. Eclipse
has some nice tools to help you see the methods available in a class.
Just type in Math. Into Eclipse. As soon as you type the dot, you’ll get a popup showing you all the
possible methods and constants you can use. You can either double click on an option to then fill in
21
the code, or use the up and down arrays and press return to select. Here, we can see that Math
contains a lot of methods, as well as the constants PI and of course, E.
If this pop up doesn’t show up for any reason, put the text cursor after the dot, then press “Ctrl +
Space”. In general “Ctrl + Space” is a way of ‘auto-completing’ code. There’s all sorts of tricks you
can use to speed up coding. For example, just type “sysout” on a line, followed by “Ctrl + Space”.
Eclipse will expand this for you to System.out.println(...). Similarly, create a new class
with nothing inside it, and click within the curly braces. Type “main” there and press “Ctrl + Space”.
This will expand into a main method! Quite handy huh?
22
Part C – Converting between types
It’s often quite useful to convert between different types. For example, suppose someone typed in a
number into your program which you wish to do some calculations with. When they initially type it
in, it’s just text – i.e. it’s of type String. But we want it to be type int, or double/float, since we can’t
do mathematical operations on a String. This summary table indicates how we convert between
different types:
TO
int
FROM
int
char
float
String
(int) 'c'
(presuming you want to
character corresponding to
an ASCII number)
No conversion necessary
String.valueOf(63)
char
Character.digit('6', 10)
(the 10 just means the number is
base 10)
String.valueOf('c')
float
(int) 6.37f
(this ‘truncates’ the decimal, i.e.
discards everything after the
decimal point – it does not round)
Don’t do it!
String
Integer.parseInt(“693”)
"Hello".charAt(3)
(gets the 4th character)
String.valueOf(4.32f)
Float.parseFloat("3.23")
So for example, if we wanted to convert from an int to a String, then using the table, we’d do:
int exampleNumber = 24;
String numberAsAString = String.valueOf(exampleNumber);
We now have a new variable numberAsString which holds our number, except the type of it is now
String. We’ll see in a later program involving Roman Numerals why this might be helpful.
This example gets the 3rd digit (as an integer) of a number that was in String form:
String numAsStr = "59403";
char c = numAsStr.charAt(2);
int digitThird = Character.digit(c, 10);
This involves two conversion processes – firstly getting a char from within a String, and then
converting that char into an int. You’ll get used to these over time.
You might want to practice these conversions by starting with an int, converting to a char, then to an
String, and then back to an int again. Try writing this in one line of code.
Casting
You might wonder looking at this table why we have a primitive type in brackets when converting
from an int to a char or a float to an int. This is known as casting, and basically means we attempting
to directly change the type. So for int n = (int) 8.03, we’re taking the value 8.03 which is of
type double, changing the type to int using (int), and now we’re allowed to assign this resulting value
to a variable n which says the value must be of type int. When we convert to an int, we have to
discard any data after the decimal point. Why can’t we do a similar cast to and from String then? We
can’t cast between primitive types and non-primitive types. String is a class, not a primitive type.
23
Part D – Arrays
You might wonder how we might store a ‘collection’ of things in a single variable. One way to do this
is using arrays. An array contains a number of ‘slots’ in which we can put information. Arrays are
useful because it’s not always practical (or even possible) to have a separate variable for each bit of
information in a collection. Imagine for example we wanted to get all the words in a sentence, and
store each one separately. If we were to have a separate variable for each word, then (a) we would
have to have a huge number of variables for a long sentence and (b) if the sentence was the change
in length, we’d need a different number of variables. An array would solve this particular problem.
Some Quick Basics
Declaring: To declare/create an array (just as we would create a variable of a primitive type), use
something this:
int[] nums = new int[4];
In this case, we’ve created an array of integers, and allocated 4 slots. The syntax might seem a little
unusual at first, and we haven’t yet covered what the ‘new’ keyword means (we’ll encounter it later,
but we basically use it when we creating something that is not a primitive value). Currently these
slots don’t have anything in them. But we can assign a value to a particular slot:
nums[2] = 3;
This is what our array would look like after:
3
0
1
2
3
Indexing: Remember that in computing, we start counting from 0. So the slot with index 2 is actually
the third slot. We can also access the value of an array. This is known as indexing the array:
nums[2] = nums[2] + 1;
As you can see, the ‘index’ goes in square brackets, both when assigning to a lost and retrieving the
value in the slot.
Initialising/assigning: If we know in advance what values we’re going to put in the array, we can
combine the process of declaring the array variable and assigning it some values:
String[] colours = new String[]{ “green”, “blue”, “orange” }
Notice in this case we didn’t have to put the size of the array between the second square brackets.
This is because the compiler can work out the size from the number of items you’ve put in the curly
braces.
Getting the length: We can get the length of an array using myArray.length. So
colours.length would give us 3. Note that this includes empty slots! So nums.length would
give us 4, even though we’ve only put one item in it.
24
Cycling through an array’s values using a ‘for loop’
Perhaps the most common way of using a for loop is to go through the values of an array and do
something with each one. Recall that for loops are used when want to repeat some action using
some number in some range. We do have a range: the slot numbers in an array (of length n) go from
0 to n-1 (not including n, because we have 0 to n-1, not 1 to n, as we start slot numbers from 0).
Here’s a few examples:
String[] colours = new String[]{ “green”, “blue”, “orange” }
for(int i=0; i<colours.length; i++) {
System.out.println(“Colour: “+colours[i]);
}
This for loop does it statement for ‘i’ in the range 0 to colours.length-1 (because we used < not <=).
We then used this variable to index colours and print out the value.
Here’s another nice example of printing out the words in a sentence and its length:
String sentence = “This is a cool sentence.”;
String[] words = sentence.split(“ “);
For(int i=0; i<words.length; i++) {
System.out.println(“Word: “+words[i]);
}
System.out.println(“Length of sentence: “+words.length);
Here we’ve used a method of the String class we haven’t seen yet – split. This takes one argument,
the ‘delimiter’, or a string we use to split up a larger string. In this case, we’re saying to split the
sentence up by “ “, i.e. by spaces. The output is an array of Strings which contains the sentence split
up into words.
Warning: You might think we can print out the contents of an array with
System.out.println(myArray). Try it: you’ll see it gives you something fairly nonsensical. You have
to cycle through it values and print them one by one.
Example program: Finding the factors of a number
We’re going to create a method that finds all the factors of a number, and puts them in an array.
Add this method to your MathsUtils class:
public static int[] findFactors(int n) {
// …
}
How might we find the factors of the number n? Well, we could try candidate factors from 1 up to
half of n (there can’t be any factors above half its value, except for itself). And to tell a number is a
factor, we have to see if there’s a remainder of 0 when we divide n by the candidate factor.
We’ll create an array ‘factors’ which holds these factors we’ve found. One problem however (and
why for this particular program I wouldn’t usually use an array) is that we don’t know in advance
how many factors we’ll find so we don’t know how big to make the array so have exactly the right
number of slots. Our strategy here therefore is to have a temporary array which will have definitely
25
have enough slots to put our factors in (although with some slots likely to be empty), and then clean
up at the end by returning an array of the right size and with no empty space.
Let’s get started!
public static int[] findFactors(int n) {
int[] factors = new int[n];
int c = 0;
for(int i=2; i<=n/2; i++) {
if(n%i==0) {
factors[c] = i;
c+=1;
}
}
return factors;
}
Here’s what’s going on:






On the first line of the method, we’re creating our array. We’ve got n slots, because that’s
definitely going to be enough for all our factors.
We’ve created a variable c. The point of this is to act as a counter for how many factors
we’ve found so far. This is so we know the correct slot number to put a factor into the
factors array once we’ve found a new one.
Our for loop goes from 2 to half of n. You might wonder what happens if n is an odd number.
Recall that an integer divided by an integer gives us a integer, discarding any decimals. So if
n is 15, we’d look for factors up to 7. That seems fine. And even if n/2 gave us a decimal
number (e.g. a double), then it wouldn’t be a problem because if n=7, we’d execute the body
of the for loop with i=3 (since it satisfies the for loop’s range condition of 3<=3.5), and once
we do i++, I will be 4, and 4<=3.5 is not true, so the for body wouldn’t run again.
Inside the for loop (i.e. in the body), we’re checking whether our candidate factor i is indeed
a factor. We’re once again using the % operator to find the remainder.
If it is a factor, we add it to our factors array in the correct slot. c effectively points at the
correct slot number to put our factor in. Since we’ve added a factor to our array, we now
need to move c along to the next slot number for when we find the next factor.
We’re returning factors at the end. But we have a lot of empty slots, which is not somewhat
messy (because if another method using findFactors tries to get the length of the array so
for example we can look through the factors we’ve got with a for loop, the .length value is
going to be the size including empty slots, not the number of factors there actually are).
There’s two ways we can fix this last problem.
Method 1: We could create a second array which has the correct number of slots, say factorsNew,
and copy the factors from the factors array to factorsNew. Recall that c is a counter which counted
the number of factors we’ve found. We can now use that to know the size of the array we need.
int factorsNew = new int[c];
for(int i=0; i<c; i++)factorsNew[i] = factors[i];
return factorsNew;
26
We’ve used a for loop here to copy each element of factors into factorsNew. Here’s a diagram which
might help visualise what we’re doing here:
n = 20 (and c ends up being 4 after finding the factors)
int[] factors
2
4
5
10
int[] factorsNew
2
4
5
10
Method 2: If there’s a common operation you want to do, there’s almost certainly a utility method
for it! Googling “Java array copy” brought up a utility class System.arraycopy. Here’s how we’d use it:
int factorsNew[] = new int[c];
System.arraycopy(factors, 0, factorsNew, 0, c);
return factorsNew;
The arguments are as follows:





The first is the array we’re copying from (factors).
The second is the index of the source array which we start copying from (i.e. slot 0).
The third is the destination array, where we’re copying to (factorsNew).
The fourth is the index of the destination array we start copying to (again slot 0, so we copy
to the start of the array).
The fifth is the number of items we’re copying over. We’re copying c items in this case,
because we found c factors.
In general, you never need to explicitly remember these library functions because they’re so easy to
look up. But some are so common, that it’s worthwhile to remember how to use them to save you
time in future.
The System class has a number of useful methods. We’ve already seen println, and now we’ve seen
arraycopy. Remember, in Eclipse you can find out what methods are available by typing System. ,
and hopefully you’ll get a popup listing the various methods.
Test Your Knowledge
Write programs using arrays to do the following:

Generate an array with the numbers 1 to 100 in them (and then print out the items of the
array).
27


Generate an array of the first 100 square numbers. Then subsequently update the array so
each value is doubled.
Slightly more difficult: Generate an array with the letters of the alphabet (without explicitly
writing out all the letters). Hint – you character arithmetic.
Answers
Program 1: (note that our for loop varies i from 0 to 99, so we have to add one to get the numbers 1
to 100)
int[] nums = new int[100];
for(int i=0; i<100; i++)nums[i] = i+1;
for(int i=0; i<100; i++)System.out.println(nums[i]);
Program 2:
int[] squares = new int[100];
for(int i=0; i<100; i++)squares[i] = Math.pow(i+1, 2);
for(int i=0; i<100; i++)squares[i] = squares[i]*2;
Program 3:
char[] alphabet = new char[26];
for(int i=0; i<26; i++)alphabet[i] = ‘a’ + i;
Another Example: Roman Numerals
You’ve been asked to write a program that converts the current year (or any number) into roman
numerals. Roman numerals have symbols for units, tens and hundreds. So for example, to get the
roman numeral representation of 654, we get the representation of 600 (“DC”), the representation
of 50 (“L”) and the representation of 4 (“IV”) and just stick them together giving “DCLIV”.
Create a new class called “RomanFun” and copy this code. We’ll then dissect it to find out what’s
going on:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class RomanFun {
public static String convert(int n) {
String[] units = new String[] { "", "I", "II", "III", "IV", "V", "VI",
"VII", "VIII", "IX" };
String[] tens = new String[] { "", "X", "XX", "XXX", "XL", "L", "LX",
"LXX", "LXXX", "XC" };
String[] hundreds = new String[] { "", "C", "CC", "CCC", "CD", "D",
"DC", "DCC", "DCCC", "CM" };
String nAsStr = String.valueOf(n);
int u = Character.digit(nAsStr.charAt(nAsStr.length() - 1), 10);
int t = Character.digit(nAsStr.charAt(nAsStr.length() - 2), 10);
int h = Character.digit(nAsStr.charAt(nAsStr.length() - 3), 10);
return hundreds[h] + tens[t] + units[u];
}
public static void main(String[] args) {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
28
while (true) {
try {
System.out.print("> ");
String input = br.readLine();
System.out.println(RomanFun.convert(Integer.parseInt(input)));
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Here’s an explanation of the convert method:






As we’ve done before, we’ve created a (static) method that does the conversion process,
then written a separate main method so we can test it out. Remember that by putting the
code to convert a number to roman numerals in a separate method, it makes it easier to
execute the code multiple times for different numbers as inputs, and makes it easier to
reuse elsewhere.
The method signature tells us we’re taking an integer as the input (as a variable n), and
returning a String at the end which is the roman numeral representation.
In a String array, we’ve put the various roman numeral representations of each number for
units, tens and hundreds. Notice that the roman numeral for 4, i.e. “IV”, is in ‘slot 4’ of the
array (remembering slot 0 is the first slot because we count from 0). That means if we were
to use units[4], we would get the roman numeral for 4. So we just need to establish the
‘units’ digit of the input, say u, and then use units[u] to find the digit as a roman
numeral.
The first element of each array is the empty string because 0 has representation in roman
numerals. If we had the number 103 for example, we’d have CIII, without using any letters
for the number of 10s.
If say our input is n=541, and we’ve found some way (which we’ve yet to discuss) of getting
the hundreds digit h=5, the tens digit t=4 and the units digit u=1, then hundreds[h] + tens[t]
+ units[u] will give us the final result we want. Here, the + operator is being used on strings,
so it has the effect of joining the strings together.
So the remaining question is how we find h, t and u? One way is to convert the number to a
String, so 541 becomes “541”. If we do, we can use the String class’ .charAt method to get
each of the characters that make up the string, and thus each digit.
o We can use String.valueOf(n) to convert our integer n to a String. We’ve
assigned this to a variable nAsStr.
o We can get the length of the String (and thus the number of digits in the numbers)
by using nAsStr.length(). For our 541 example, this will obviously be 3.
o The units digit appears at the end of the number. What index is this at? Remember
that .charAt(0) will get the first digit of the String, .charAt(1) the second, and so on.
Because we start counting from 0, we actually want the character at position in the
String nAsStr.length()-1. So we can get the character (of type char) of the
last digit using nAsStr.charAt(nAsStr.length()-1). This gives us ‘1’.
o But we want this character as an integer. We can use the method
Character.digit to do this. Its first argument is the character we want to
29
o
convert. The second argument is the ‘base’. Use 10, because the English number
system (or more historically accurate, the Hindu number system!) is base 10.
Similarly, we can get the tens and hundreds digit by looking at the second from last
and third from last digit respectively.
That’s the convert method sorted. The main method in the code shows how we can actually take
input from the console! Previously, our programs have printed out to the console using System.out
(appearing at the bottom of the screen if using Eclipse). But we can use System.in to actually type
into the console as well and use the input.
Let’s break it down line by line:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
Don’t worry about the exact syntax yet, since we haven’t really discussed the creation of objects. But
in our variable br, we’re essentially getting a connection to the console so we can read from it one
line at a time.
while (true) {
A while loop that takes ‘true’ as its condition will loop forever, because the condition of the while
loop always holds (because it is literally ‘true’!). This is good, because it means our ‘Roman Numeral
Service’ will always ask for more numbers to convert without stopping.
try {
Later on we’ll be covering ‘exceptions’. But for now this is all you need to know: Some methods of
classes require has to have some backup behaviour if something goes wrong. Suppose for example
there was a method to read from a file. What if the file didn’t exist? Or what if for some other
reason we couldn’t read from it? We need to be able to have a contingency strategy in such cases.
The basic syntax of this is:
try { ..Do some code which might go wrong.. } catch(..potential
problem..) { ..Backup strategy.. }
System.out.print("> ");
The prints out a “>” symbol onto the console. Notice that this method is print not println. The
difference is that in the former, what is printed doesn’t get a line to itself. Anything printed after (or
anything we type into the console) will come after it on the same line, rather than the next.
String input = br.readLine();
We’re using the readLine() method of the class BufferedReader (because the variable br
we created is of type BufferedReader). This will wait until we’ve typed something into the console
and pressed return (because we earlier told the BufferedReader to ‘listen’ to System.in), and then
return a String. We’ve put the output of the method into a variable input.
System.out.println(RomanFun.convert(Integer.parseInt(input)));
This does multiple things in one go. Firstly, the number we typed into the console is currently in
String form. We need to convert it to an integer, because the RomanFun.convert method expects an
integer as its input. Integer.parseInt converts from a String to an integer. Roman.convert
then uses this integer and gives back a String containing the Roman numeral form. Then finally,
System.out.println prints it out to the console.
} catch (IOException e) {
This line says we want to deal with any problems that arose in the block of code following ‘try’. In
this particular case, the .readLine method could of had a problem in terms of reading from the
30
source (e.g. for some reason, we couldn’t get what was typed into the console). ‘IO’ here stands for
‘Input Output’. So this line code says we’re dealing with any problems to do with input/output.
e.printStackTrace();
This is our ‘backup strategy’. Here we’re just printing out the details of the error that occurred (when
it does occur). The variable ‘e’ represents the error that occurred. And it has a method called
printStackTrace() which prints details of the error. Don’t worry about this now, we’ll be covering it
later.
Things you might want to try to extend this program:
1. Why not try and extend the code above to deal with thousands in roman numerals? The
roman numerals for 1000, 2000 and 3000 are M, MM and MMM respectively.
2. The maximum number you can hand in Roman Numerals is 3999. Make sure your program
returns something sensible (e.g. the string “INVALID”) if the number inputted to your
convert method is outside this range.
3. Your program will currently give an error message if you try to enter a two digit number,
because when trying to get the hundreds digit using .charAt, you’ll find that
nAsStr.length()-3 will give you a negative number (and you can’t get the -1th
character of a String!). Make use of ‘if’ statements to make sure you handle different length
numbers.
31
Object Orientation
There’s been a few instances in our programs where we’ve used the ‘new’ keyword when assigning a
value to a variable. We did this for example when creating an array, and some of the example
programs, we saw something like:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
This was different to when we say assigned ‘primitive’ values to a variable, e.g:
int x = 3;
The ‘new’ keyword is creating a new ‘object’ for us. But let’s take a step back first and consider what
an ‘object’ is. With primitive types, we saw that we can only hold a simple value, like an integer or
character. But there’s certain things that we might like to use or assign to a variable that aren’t quite
as simple. Take a fraction for example. We might want to assign the fractions ½ and ¼ to variables x
and y, and then say manipulate them to find x + y to yield a new fraction. Primitive types won’t let us
do that (unless we convert the fractions into decimal form). A fraction is an example of an ‘object’ –
it has multiple constituent values, i.e. the numerator and denominator, and behaviour associated
with it, such as multiplying the fraction by a constant or another fraction, or adding/subtracting
another fraction it.
An object therefore can have two things:
1. Associated properties. We could call this the ‘state’ of the object, to mean the data
currently associated with it. We’ll see this term being used particularly often.
2. Associated behaviour.
Let’s roll right into a concrete example, sticking with our fraction theme.
Fraction Example
Create a new class ‘Fraction’, and then copy this code. I’ll then explain it bit by bit:
public class Fraction {
int numerator;
int denominator;
public Fraction(int n, int d) {
numerator = n;
denominator = d;
}
public Fraction add(Fraction other) {
int numeratorNew = numerator*other.denominator + denominator*other.numerator;
int denominatorNew = denominator*other.denominator;
return new Fraction(numeratorNew, denominatorNew);
}
public Fraction multiply(int k) {
return new Fraction(numerator*k, denominator);
}
public Fraction multiply(Fraction other) {
return new Fraction(numerator*other.numerator, denominator*other.denominator);
}
public static void main(String[] args) {
// Let's test our class out!
Fraction half = new Fraction(1, 2);
Fraction quarter = new Fraction(1, 4);
Fraction result = half.add(quarter);
32
System.out.println("1/2 + 1/4 = "+result.numerator+"/"+result.denominator);
}
}
Run it, and you should see on the console: “1/2 + 1/4 = 6/8”. Now let’s work out what’s going
on:
int numerator;
int denominator;
Previously, when we’ve declared new variables, they’ve always been inside the body of a method.
These were known as ‘local variables’, because they only existed while running the code inside our
method (see the subsection on ‘Scoping’ for a reminder).
When the variables are inside the class, but not in any method, they’re known as attributes. This is
data associated with a particular fraction, in this case, the numerator and denominator. When we
create a new fraction, we expect these attributes to hold these values.
Class vs object: Before I go any further, let’s establish the difference between a class and an object.
The code you see above is a class. It represents some specification about what a fraction is and how
it behaves. But it doesn’t actually represent a specific fraction. When we create a specific ‘Fraction’
using the Fraction class by supplying a numerator and denominator, then we have an object. Our
class therefore embodies the concept of a generic ‘fraction’, whereas an object is a specific fraction
like ½ or ¼. We say that ½ is an instance of the Fraction class, and you will sometimes see the term
instantiation to mean we’ve taken a class a created a concrete object from it.
public Fraction(int n, int d) {
numerator = n;
denominator = d;
}
Constructors are methods which allow an object to be created. We want to be able to create the
fraction ½ for example by using:
Fraction half = new Fraction(1,2);
A constructor is just like any method we’ve seen before, except for the method name is the name of
the class (Fraction), and it has no return type. It takes arguments just like a normal method, and this
is the data concerning the fraction we need to build it, in this case the numerator and denominator.
Good so far, but what’s happening inside this method?
Recall from before that parameters of a method only exist while the method is running, before
they’re destroyed. So the variables n and d won’t last for very long. We need to be able to preserve
this data inside the object. The solution is to set our attributes to these values. That way, we’ve
passed on the data we’ve passed into the constructor to the storage location of the object.
public Fraction add(Fraction other) {
int numeratorNew = numerator*other.denominator + denominator*other.numerator;
int denominatorNew = denominator*other.denominator;
return new Fraction(numeratorNew, denominatorNew);
}
We can also define behaviour associated with the fraction. We’ve seen previously that objects can
have associated methods. So for example, we could do:
String x = “Hello”;
char c = x.charAt(1);
33
Similarly, if we have a fraction which we’ve stored in the variable half, and want to add a fraction
stored in a variable quarter, we might want to do half.add(quarter), which we might expect
to return a new fraction with these fractions added together.
Our ‘add’ method in the code presented takes the other fraction passed in as an argument (the
variable other), and then combines. When we do numerator*other.denominator for example, we’re
using a combination of the state of the current fraction with the state of the ‘other’ fraction. When
the method runs, it’s in the context of the object we’re applying the method to. So for
half.add(quarter), the attribute numerator (and any other attributes) holds the value
associated with the half fraction, because the method is being applied to this object.
Similarly, when we run x.charAt(1)in the example above, the charAt method (however it is
implemented) has access to the attributes of the String value that the variable x holds, presumably
being able to access its individual characters and give back the right one according to the number we
passed in as the argument of the method.
public Fraction multiply(int k) {
return new Fraction(numerator*k, denominator);
}
Now we’re defining another method, which allows us to take the fraction we’re applying the method
to, multiply it by a number, and then return a suitable new fraction.
public Fraction multiply(Fraction other) {
return new Fraction(numerator*other.numerator, denominator*other.denominator);
}
Wait, we already have a multiply method don’t we? Java (along with most other Object-Oriented
languages) allow us to have multiple different methods with the same name, provided that the
argument types are different. This is known as overloading the method. By having two different
multiply methods, we allow a fraction to be multiplied by either a constant or another fraction.
public static void main(String[] args) {
// Let's test our class out!
Fraction half = new Fraction(1, 2);
Fraction quarter = new Fraction(1, 4);
Fraction result = half.add(quarter);
System.out.println("1/2 + 1/4 = "+result.numerator+"/"+result.denominator);
}
Our main method, as ever, allows us to test out our code (and could have been put elsewhere
outside of the Fraction class – we’ve just left it in there for convenience). Because we defined a
constructor of the Fraction class, we can create concrete instantiations of our class representing
actual fractions. We’re creating new fractions here and putting the values in the variables half and
quarter. We’re then adding these two fractions to get a new fraction result.
We’re then printing out the fraction to the console by accessing its attributes.
toString methods
You might be wondering what would happen if we tried to print out the fraction directly:
System.out.println(result);
The answer is this:
Fraction@119298d
34
What on Earth? The problem is, we haven’t told our program how to put our Fraction in a suitable
String form. Therefore, its just gone with its default behaviour of printing the class name of the
object and a fairly unhelpful number indicating its identity. But we can add a new method to our
Fraction class so that our program knows what to do:
public String toString() {
return numerator+"/"+denominator;
}
The toString method takes no arguments and needs to return a String. Its role is to take the state of
our object, and convert it into a suitable string format so it can say be printed to the console. We
usually expect it to use the attributes of the class, because the attributes represent the state of the
object, and we want to express the state of the object when we put it in string form. If you replace
your main method with this, you’ll then get the same output as in the older version of the program:
public static void main(String[] args) {
// Let's test our class out!
Fraction half = new Fraction(1, 2);
Fraction quarter = new Fraction(1, 4);
Fraction result = half.add(quarter);
System.out.println(half+" + "+quarter+" = "+result);
}
Run it, and hey presto! Recall that when we use the + operator and one of the arguments to the left
or right is a String, then all the arguments get converted to Strings so that + can append them
together into one String. When Java does so, it looks at the type of your class (in this case Fraction),
and then uses your toString method if you supplied one.
35
Download