This post summarises technical learnings from the free Java Programming course on Udacity, which is recommended to gain the required programming foundations before starting the OU’s post-grad Software Development module, M813. These notes are in addition to those I’ve been making while studying the Udemy Java Developer course: see my posts here and here.
How Long is This Course?
According to Question 4 of Homework 0, this Udacity course takes 180 hours over 10 weeks = 18 hours per week. Really? I just knocked out Lesson 1 (of 7) in a couple of hours – and that included ‘blogging’ time as well as ‘doing’ time.
Here’s the Syllabus:
Lesson 1: Intro to Java
- what is programming
- intro to Java programming
- algorithms
- pseudo-code
Lesson 2: Intro to Classes and Objects
- working with variables
- different variable types
- arguments
- return values
- method declarations
- string methods
- pitfalls
- shared objects
Lesson 3: Graphics
- drawing pictures, rectangles
- draw a simple object (a crate)
- intro to colour
Lesson 4: Fundamental Data Types
- working with numbers
- arithmetic operations
- mathematical functions
- ‘Sunset Effect’
- reading input
- formatting output
- calculating circular fields
Lesson 5: Decisions
- if statement
- relational operators (eg equalities, inequalities)
- using Booleans
- practice exercises
Lesson 6: Iterations
- loops
- infinite loop
- dealing with loop errors
- asymmetric bounds
Lesson 7: Arrays, ArrayLists, and Simple Array Algorithms
- ArrayLists & how they work
- modifying an ArrayList
- separators
Evaluating the Udacity Course:
This is billed as a complete beginners’ course, with no required knowledge of programming, so it does start from absolute basics (similar to the intro material covered in Tim Buchalka’s Java class on Udemy). Doing a quick comparison of the syllabi for both courses, the one on Udemy does appear to go into a lot more depth, both in terms of the background theory and covering more advanced aspects.
It’s interesting to note that the OU’s qualification lead for the MSc Computing programme recommends this Udacity course for people needing to get up to speed with programming in general, and Java in particular, in advance of the M813 Software Development module. I was worried the object-oriented and coding skills needed for the module would be more advanced than this. It would be OK anyway, I’ve got plenty of free time to dedicate to extra-curricular activities to make sure I’m at the required skill and knowledge levels. But reviewing this syllabus – and going through the first lesson – suggests to me the coding elements of M813 will be pretty basic. They should certainly be easy enough for me to handle at my current programming skill levels. That makes me feel a lot happier.
Next Steps:
Having reviewed the module study guide for M813, I can see that the Java coding unit doesn’t kick in until around week 7 (c. 9th June) so I’ve got plenty of time to get more Java experience under my belt before then. My plan is to complete this Udacity course (since it’s the recommended one). I’m not expected that to take too long, I can probably buzz through it in the next week or so. Good. I feel more comfortable about my lead into M813 now.
Then that leaves me several weeks to the end of April to go through the rest of Tim Buchalka’s course (now renamed the Complete Java Masterclass) and I should be able to cover that in the last weeks of April (and on into early May if need be). There’s about 60 hours of videos left to study on that course. It will be more advanced so a bit harder, but will be going deeper in than I’ll need for M813 anyway. I still feel it’s an important course to complete because the syllabus includes Object-Oriented Programming and I suspect that will give me a good pre-flight grounding in OO. I think that’s going to be vital before I start hitting the UML design exercises in Unit 1 (starting 1st May).
Cracking on with This Udacity Course:
The course recommends the free BlueJ developer environment as it’s good for learning with. I already have IntelliJ IDE running, but it wasn’t a problem for me to install BlueJ as well (I already had Java installed as a JDK so didn’t need to complete that step) and it’s runnig perfectly for me. The course itself does also provide an online environment so downloading software is not strictly required, but I definitely recommend it as an easy and intuitive environment in which to learn.
Objects and Methods:
In a simple Hello World program, within the print command (as below) System.out is an object, which is a fancy way of representing, in the programming language, things that do some kind of work. In this case the object is the terminal window (on which we will want the string “Hello World!” to be outputted).
System.out.println("Hello World!");
In the same command, println is a method, which is basically an instruction to be executed. So here the method is to execute the command to print out the string on the terminal window, with ln indicating the ‘carriage return’, or new line, to be added after the string is printed. Logically, there is another print method (simply, print), which prints the designated output but without the addition of a new line.
Errors:
A compile-time error (also called a syntax error) refers to an error when the code or program is compiled into machine code in order to be run. Here something is missing from the command, is spelt incorrectly, or an unidentified variable named used, etc.
A run-time error (also called a logic error) refers to one where the code is syntactically correct and so runs without a problem, but the wrong answer is outputted. The code worked but you didn’t get the expected/desired result. This indicates something wrong in the algorithm being used, or could even be as simple as a typo in a string to be outputted (eg “Hello worl” instead of “Hello world”).
Exception errors within run-time are also possible (eg trying to output the result of arithmetic expression 1/0). The code will compile without error but, on execution, an error message is returned and the program ceases to run at the point at which the error occurred.
Algorithms:
These can be thought of as recipes (or sequences of instructions) to get the computer to do something more complex than just a simple one-liner of code. In technical terms, algorithms fulfil three criteria:
- unambiguous – the sequence of instructions can only be interpreted (and therefore executed) in one way
- executable – the computer can actually compile and run that sequence without errors
- terminating – the sequence of steps comes to and end (eg is not stuck in an infinite loop)
An important thing to remember about algorithms is that, in order to work (from a human point of view) is that there needs to be sufficient information as input. For example, you cannot decide which of two cars will be the most economical to buy without knowing your expected mileage and also the average per litre petrol cost.
Pseudo-code:
When preparing a complex algorithm (the correct sequence of steps), it if often advisable to create some pseudo-code in terms of the recipe of steps which needs to be followed, generally consisting of a mix of natural language and mathematical instructions. In software development terms, this is the modelling and design stage of the early life-cycle. Only once we’re happy with the design will we proceed to turn that into Java code (or whatever other programming language is being used).
Elements within pseudo-code can include:
- mathematical computations (eg total cost = purchase cost + petrol cost in year 1, where petrol cost = expected annual mileage / car’s mileage)
- decisions (eg if total cost of car 1 > total cost of 2, choose car 2)
- repetition (eg while {criteria} is met, do {action}) (eg repeat {step} n times)
- logical statements (eg if {condition 1} and {condition 2} are met, do {action})
Algorithms (and hence pseudo-code) don’t just have to deal with numerical calculations. For example, they can be used for sequencing, sorting, categorising text or objects. An example would be sorting building blocks into sequence by colour. The pseudo-code algorithm will look like:
while {criteria: building block colours are out of sequence},
do {action: find first wrong-sequence pair of blocks and swap them}
Objects, Classes & Object-Oriented Programming (OOP):
Modern programming is based on objects (hence OOP) rather than on actions. The objects can be associated with some data (attributes), equivalent to the data contained in a database’s data fields. Code or procedures (methods) can be applied to the objects. As a result, the methods can access and even modify the object’s data fields. In OOP, the objects can be made to interact with one another giving great versatility in programming. This is in contrast to earlier programming forms which simply took some data as inputs and applied a method on them to get some transformed data outputs.
While there are many different object-oriented programming languages, the most popular ones (including Java) are class-based. Here, all objects are instances of a class. A class can be thought of as a generic category of a thing (eg ‘cups of coffee’ is a class). There can be many specific instances of the class (eg the picture above is one instance of the ‘cups of coffee’ class), and in class-based OO programming languages, all objects are instances of their class. The key thing to remember about objects as instances of a class is that they all behave the same way, ie they all have the same underlying attributes.
This idea of objects’ behaviour is related to the ideas of types (introduced in a previous post here). For example, the data types string, integer, float, and so we saw previously are all variable types. But they can also be thought of as different classes. When we set up a variable and denote it as a string type, we are defining that variable as an instance of the string class. The fact that all instances of a class have common behaviour means that they can all do the same thing, or rather, can all have the same methods or procedures applied to them. In programming terms, we say the method is called on the class.
The benefits of OOP are that, due to their popularity, there are many pre-made objects which one can make use of in their programming. These are like pre-made building blocks or components with some useful functionality built-in. Building a program this way can be thought of as being like building a house from pre-fabricated modules rather than building from scratch, which obviously saves time (and money) as well as making the process a lot easier.
The program code you write asks the objects to do some work (perform something according to their functionality). There’s no need to know how they do it, it’s enough to know what they will do. The form it takes is familiar from previous Python programming:
object.method()
or
object.method(argument1, argument2)
Remember that in each case, the object is an instance of the given class. We name the object with a particular variable name as an identifier. This variable name allows the program to identify which specific object, or instance, is to be manipulated by the method being called upon it. The value stored in the variable will then be manipulated or transformed as required by the called method.
When we assign a value to a variable name in Java, we use the construct
type variableName = initialValue;
for example
string aName = "Jennifer";
Don’t forget when declaring a new variable to assign a value (even if nil or empty) to avoid the program returning an error.
When a new class has been defined and we wish to establish a new object as an instance of that class, we need to specify the variable name, what class it is, and also we specify a new instance of that class together with its initial value. In Java it looks like this:
className variableName = new className(initialValue);
Simple algorithms with classes:
Assume we’ve established a new class called Day, then we can write a simple algorithm to do calculations as follows (taken from Lesson 2 in the course):
Day birthDay = new Day(1951,5,26);
Day lastDay = new Day(2012,7,23);
int daysAlive = lastDay.daysFrom(birthDay);
System.out.println(daysAlive);
Here we declare two new instances of the Day class and assign initial values them. We then call the daysFrom method on the lastDay instance, passing argument birthDay to it, and assign the resulting value (i.e. number of days between birthDay and lastDay) to the variable daysAlive (a variable of type int), then print it out.
Methods and documentation:
The kinds of methods we are able to call on an object (an instance of a class) and the argument(s) we need to pass to it are determined when we first establish the class itself. This is referred to as the Public Interface of the class. An analogy would be the Owner’s Manual for a car which tells you what each button on the dashboard is for.
The equivalent of the owner’s manual in Java development terms is the javadoc. To find this is BlueJ – for classes or projects set up and available with this course – when the class or project folder is open, select Tools\Project Documentation. This brings up a new window with the class/project documentation as an HTML file (opens in browser). This includes summary and details of all methods applicable to that class. The method details include the parameters which need to be input as arguments. Where a project has more than one class defined, the documentation includes all classes, with hyperlinks in the left-hand menu for each one.
Java JDK 8 documentation is available here. For standard variable classes and their methods, documentation is here. – the format is the same as before, a summary of methods is given with hyperlinks to more detailed descriptions about each method and its parameters.
More on methods – arguments and returned values:
We saw a simple example above of calling a method on an object, passing some arguments to it, and returning the value to another variable (in that case a variable of int type):
int daysAlive = lastDay.daysFrom(birthDay);
Here are two more examples:
int methodName1();
void methodName2(double arg1, double arg2);
In the first example, methodName1 takes no arguments and does return a value, which is of type int – ie it returns an integer number. The second example does not return anything (indicated by the use of void) but takes two arguments (arg1 and arg2). Note that these arguments’ types have been specified as double – this is a special case of making two variable declarations within the method call (they’re the parameter variables for that method).
Constructing objects:
In BlueJ – after opening a folder to load a new class definition, and compiling – we can easily construct new objects of the class. By right-clicking on the class and either selecting new className(), which constructs a new object of the class with no initial value, or selecting new className(arg1, arg2, …), which requires us to enter the initial value for the object, the new object is created. (In the latter case, the number and type of arguments will be dependent on how className has been defined.)
This is equivalent to the code we saw above where a new instance of a class is declared using:
className variableName = new className(arg1, arg2, ...);
The new object is displayed as a red box in the lower pane. We can right-click and choose Inspect to see a dialogue box which shows the value of parameter(s) in the object. Right-clicking also shows the available methods callable on the object. Note that this red box is an object which is a placeholder for some values and upon which certain methods can be called (or functions can be implemented).
To call the method on the object just constructed, use:
variableName.methodName();
Using the Code Pad in BlueJ:
Select View\Show Code Pad – the code pane appears in bottom right-hand corner (the panes can be resized as in a normal windows-style application). Here you can type code and execute it without need for opening up the Editor or right-clicking the class or object boxes and selecting the required command. Examples using the code pad:
String varName = “Something”; \\ declares new string variable and stores initial value (a semi-colon is required because it’s a statement, to be run as part of an execution)
System.out.println(varName); \\ prints the value of varName in a new output pane which opens up separately (semi-colon required, as above)
varName.length() \\ prints out in the Code Pad the length of the string value stored in varName (a semi-colon is NOT required if you want the Code Pad to execute the command immediately and print out the output in the Code Pad)
varName \\ prints the value of varName out in the Code Pad (again, a semi-colon is NOT required to get an immediate output)
With this final example, when the value of the varName object is printed in the Code Pad, beside it will be a small red box. Click on this and a dialogue box opens up requesting you to name the object, then the object will be constructed and placed in the objects pane at bottom left. (Alternatively, you can click and drag it into the objects pane then name the object.) This object (red box) can be manipulated as we did before, by right-clicking and choosing the required method to call on it. Eg for a string object, call one of the many methods executable on that type of object, such as length(), and so on.
The Code Pad (along with manipulating the red objects) is great for quick trial and experimentation as well as for getting to know what certain methods do. I can see this would prove an excellent tool to help me learn Java coding to help with my M813 assignments.
Writing a new Java class with a main method:
Defining a new Java class is simple in BlueJ. Simply create a new project then in the empty top right pane, right click and select New Class, name the class (eg StringDemo; note the convention for class names is to capitalise all words, whereas the convention for object variable names is to capitalise any second and subsequent words only). Language and Type will default to Java and Class respectively – then click OK.
This creates a new class box in the top pane. Right-click this and select Open Editor. In the Code Editor, after the comment line, type in the required code to define the new class and your program, eg:
public class StringDemo
{
____public static void main(String[] args)
____{
________// type in your program code here
________String river = "Thames";
________int numberOfLetters = river.length();
________System.out.println(numberOfLetters);
____}
}
Compile, then close the editor. Right-click the class box and select main(String[] args) to run the program. This will open up a dialogue box requesting arguments to pass to the method. In this case our method takes no arguments, so just hit OK and it will execute and the output is given in a new pop-up window.
Exploring a few String methods:
The Java documentation details the method calls for all classes and variable types. The main Java 8 documentation homepage is here: Java 8.0, while documentation for the String class is here: String Class.
Here are some examples:
river.replace("a","o");
replaces the first given character (or sequence of characters) with the second, hence returns the output “Thomes” when printed.
Another useful method is trim()
which trims any whitespace from the start and/or end of a string, for example:
String messyString = " Hello, world! ";
String neatString = messyString.trim();
Printing out neatString gives “Hello, world!”
Changing a string to all upper case or all lower case can be achieved using toUpperCase()
and toLowerCase()
respectively. Alternatively, an argument can be specified in the method call to determine the location from which characters in the string are to be changed.
Accessors and mutators:
The above methods are all known as accessor methods, since they access the contents of the object and return a value based on the method call. They do not change or transform the underlying object itself (unless we specifically included that transformation in our method call). For example, messyString
will still read ” Hello, world! ” even though we called the trim()
method on it. messyString
would only be transformed if we executed the revised statement messyString = messyString.trim();
This contrasts with mutator methods which do change the object upon which they are called, eg pic.translate(10, 15)
which will translate a variable pic to a new location (refer earlier examples).
Shared objects:
Since we know mutator methods transform the variable they’re called on, we should also be careful to note that any variable we create based on the original variable (which is then subsequently mutated), will itself also be mutated. This happens when the second variable is referencing the first variable. An example (using an earlier project, Rectangles) is:
Rectangle box = new Rectangle(5, 10, 60, 90);
Rectangle box2 = box;
Here, the variable box2
is referencing the variable box
, so anything which happens to variable box will shared with box2
. This happens because the variable names are not themselves instances or objects, but rather are labels or references – places held in working memory where the program uses to refer to specific objects or instances. Hence, in the above example, box2
points to the same label or reference as box
.
This is the basis of object-oriented programming and what makes it so powerful. But, it does mean we have to be careful when creating new variables which reference existing ones. If we call a method which transforms the object contained in the original variable, the second variable (which references the first) will also be transformed. Now, if we call another mutator method, this time on the second variable, the object referenced by both the first and second variables will be transformed. This is because it is just one shared object, with two variables referencing it.
Even when we call accessor methods on the first and second variables, this will still be true, since – as before – both variables are still pointing to the same reference, ie pointing to the same object (or instance of the respective variables). The only way this may change is if we assign a new reference or label to one of the variables, which causes it to now point to an entirely new object.
This shared object effect will occur for both the string class and any class we might define (such as Rectangles, etc), since they are both object-based classes. Integers (int type) differ though, as they are not objects.
Testing Java programs in BlueJ:
Testing forms a fundamental part of software development; the M813 module will cover Unit Testing in particular (refer future post: LINK-tbc) but this section just gives a quick into and shows how testing of programs can be set up in the BlueJ environment.
The simplest form of testing is to test the class itself, by creating a separate test class (using a naming convention of ClassNameTest, or ClassNameTester). Here we replicate the same code in the original class we are testing, but to it we add print statements to verify both the expected result and actual result of calling a particular method on an object in that class. This testing regime can apply to both the class constructor method itself, and to other methods callable on the class.
For example, say we defined a new class to create instances of a Rectangle object, which also includes methods to draw the rectangle, to translate it, and to return its various parameters (x- and y- coordinates, width and length). The original class has a main()
method which looks like this (note here we are passing integer values directly to the class constructor in the form of (x, y, width, length); the constructor was defined elsewhere, code not given):
public class Rectangle
{
____public static void main(String[] args)
____{
________Rectangle box = new Rectangle(5, 10, 35, 65);
________box.draw();
________box.translate(20, 10);
____}
}
Then the test class would have a main method like this (note, here we’re only testing the callable methods translate()
, getX()
and getWidth()
, we have not tested the class constructor method itself, although a complete Unit Test would do so):
public class RectangleTest
{
____public static void main(String[] args)
____{
________Rectangle box = new Rectangle(5, 10, 35, 65);
________box.translate(20, 10);
________System.out.println(box.getX());
________System.out.println("Expected: 25");
________System.out.println(box.getWidth());
________System.out.println(("Expected: 35");
____}
}
The test class includes the result we expect to see, if the translate()
method has worked correctly, along with the actual result. By comparing these two we can verify whether the class and method has worked as we expected it to.
Getting graphical:
Java includes a standard graphics library, documentation available online here: Graphics Class, which enables an application to draw and colour graphics objects such as rectangles, lines, circles and text. The construct the graphics object, call the constructor method, passing the arguments as necessary, then to create it, call the draw() method.
Line: requires parameters (x1, y1, x2, y2) where (x1, y1) is the starting coordinate and (x2, y2) is the ending coordinate, its constructor is Line varName = new Line(x1, y1, x2, y2);
and it is drawn using varName.draw();
Rectangle: requires parameters (x, y, w, l) where (x, y) is the starting coordinate (top-left corner), w is the width (increasing along the x-axis) and l is the length (or depth, decreasing down the y-axis). Its constructor is Rectangle varName = new Rectangle(x, y, w, l);
and it is also drawn using varName.draw();
Ellipse: requires parameters (x, y, w, l) which relate to the rectangle which encloses the circle, where (x, y) is the starting coordinate (top-left corner) of the enclosing rectangle, w is that rectangle’s width (increasing along the x-axis, as before) and l is its length (decreasing down the y-axis, as before). Its constructor is Ellipse varName = new Ellipse(x, y, w, l);
and it is drawn using varName.draw();
Circle: is a special case of an ellipse which is enclosed by a square, rather than a circle, but is constructed in the same way as for an ellipse using Ellipse varName = new Ellipse(x, y, w, l);
Text: requires parameters (x, y, text) where (x, y) is the starting coordinate (at top-left corner) and text is the String object (given either as a referencing variable, or directly in quotes, eg “Java is cool!”). Its constructor is Text varName = new Text(x, y, text);
and it is drawn using varName.draw();
Colour:
Shapes are default to unfilled and drawn in black, but we can change this using the following methods. Here R, G and B indicate the integer values (from 0 to 255) in the RGB colour scheme. So for example (255, 0, 0) indicates pure red, (0, 255, 0) is pure green, (0, 0, 255) is pure blue, and so on:
Drawing in colour: varName.setColor(new Color(R, G, B));
then drawing as before using varName.draw();
resulting in an unfilled coloured shape
Filling with colour: varName.setColor(new Color(R, G, B));
then draeing with varName.fill();
resulting in a filled coloured shape
Don’t forget the methods and constructors use American spelling. You can find the relevant Java docs here: Color Class.
To determine the correct RGB code for the required colour, just use a suitable colour picker like the one available in MS Paint or search online (eg www.rgbcolorcode.com). Some common colours are:
- Black: 0,0,0
- White: 255,255,255
- Grey: 128,128,128
- Red: 255,0,0
- Orange: 255,128,0
- Yellow: 255,255,0
- Chartreuse green: 128,255,0
- Green: 0,255,0
- Green-blue: 0,255,128
- Cyan: 0,255,255
- Azure blue: 0,128,255
- Blue: 0,0,255
- Violet: 128,0,255
- Magenta: 255,0,255
- Bright pink: 255,0,128
Java also has colour constants, such as Color.RED (RGB:255,0,0) or Color.BLUE (RGB:0,0,255) which can be used instead of specifying the RGB values in the setColor() method, eg varName.setColor(Color.RED));
which gives the same result as varName.setColor(new Color(255, 0, 0));
. Some common Java colour constants are:
- Color.BLACK
- Color.WHITE
- Color.GRAY
- Color.RED
- Color.ORANGE
- Color.YELLOW
- Color.GREEN
- Color.CYAN
- Color.BLUE
- Color.MAGENTA
The Intro to Java Programming series continues in Part II.
References:
Introduction to Java Programming, San Jose State University available on Udacity