Java Classes and Objects
In general, the source code in Java is kept in separate files. A file (with the file extension of .java) usually contains one class definition and is compiled into a machine-readable class file (with the file extension .class). Remember from Part 1 that Java is an object-oriented language, that is, it is built around objects. Objects can be representations of physical objects, like a mug, or more abstract objects, like a product delivery process in e-commerce.
A class defines the properties of an object and how it behaves or works. In this way, a class is like the blueprint of an object. Classes define things such as its member variables of the class. The abilities (or behavior) of the object are defined as methods.
Let’s look at a sample class definition:
public class Car { // Member variables (properties about the object) private String mColor; // Methods (abilities of the object) public void setColor(String color) { mColor = color; } public void accelerate() { // Code to accelerate a car goes here } }
It is important to note that this file should be called “Car.java”. The class and file name should always match, exactly.
In this example, we have one member variable “mColor” which represents the Color that this object should show. Note: The lower-case “m” prefix is a naming convention indicating it is a member variable.
Access Modifiers
For classes, member variables, and methods, we usually want to specify who can access them. In some cases, we want things to be publicly available, meaning that anyone can see and modify or delete them. In other cases, we may want to keep things private in order to protect data from purposeful or accidental changes. The keywords public, private, and protected are access modifiers that control who can access the class, variable, or method.
Packages
Classes are often grouped together along by some kind of criteria, into packages. A package is simply a collection of related classes and is usually named in a format that follows reverse domain notation, taking the URL for your website or project and reversing it, e.g. oracle.com → com.oracle.
Type Casting
Type casting is treating a value (block of memory) referenced by a variable as being of a different type than the type the variable is declared as.
For example, here was cast a string into a number, telling the compiler it is an int:
double doub = 32.7; int num = (int) doub; |
TaskRun the above code, and consider and answer the following questions:
|
Conditionals
In Java the ‘if’ conditional, checks if a condition that is evaluated is true or false.
if (awesomeness.equals("Great")) { language = “Java”; } |
We begin with the keyword ‘if’, and the condition to be tested is surrounded by parentheses. If the condition is found to be “true”, then the code inside the curly braces is executed. If the condition is not “true”, nothing happens. If we want to take some further action if the condition is not met or “false”, then we can use the ‘else’ keyword to specify what code should run instead, as in the following example:
if (awesomeness.equals(“Great”)) { language = “Java”; } else { language = “Some Other language”; } |
We can chain as many conditions together as we want using ‘else if’, like this:
if (awesomeness.equals("Great")) { language = “Java”; } else if (awesomeness.equals("Interpreted")) { language = “Python”; } else { language = “Some Other language”; }
Arrays in Java
As we discussed earlier, variables are small “containers” of data which can contain just a single packet of information. However, arrays can contain multiple packets of this data. Consider an array like:
The first thing to notice is the array index starts at 0, not 1. We can program the array into code:
int[] myArray = {12, 5, 17, 11, 51}; String[] myStringArray = {"Hello", "Hi", "What", “Why”, “Where”}; //print first element of myArray System.out.length(myArray[0]); //Arrays have length System.out.length(myArray.length) //prints 5 |
In the above example, it was not difficult to program the array since it only contained five elements. However, programming a large array, containing say, 200 elements, would be difficult and unnecessarily time-consuming. For such large arrays, we will use loops.
Repeating with Loops
Looping through an array of data is another basic concept in programming. For example, let’s say we want to loop through the list of Strings from the Arrays section above and output them. If we do it one at a time, the code would look like this:
System.out.println(“String 1 is ” + myStringArray[0]); System.out.println(“String 2 is ” + myStringArray[1]); System.out.println(“String 3 is ” + myStringArray[2]); System.out.println(“String 4 is ” + myStringArray[3]); System.out.println(“String 5 is ” + myStringArray[4]); |
What if we have hundreds of Strings? Or what if we’re dealing with millions of records from a database? What if we have to run 10 lines of code for each record in the database? That’s a lot of code to write, and most of it would be repetitive, which violates the “Don’t Repeat Yourself (DRY)” principle.
Instead, we will loop through an array to run code for each item in the collection. In what follows, we will rewrite the snippet above as using a few different loops.
The “for” Loop
for (int i = 0; i < appTitle.length; i++) { System.out.println(“i’th title is ” + appTitle[i]); } |
The basic idea of the syntax is: “for (some conditions) do the code inside these curly braces”. The conditions given in the parentheses take on this form:
(initialize statement; terminate statement; step statement) |
This type of ‘for’ loop often uses a counter variable (often named “i” for “index”, as in our example above) that keeps track of the position in the collection.
- initialize statement: The first statement inside the parentheses sets up the counter variable or whatever logic will be used to keep track of our position in the loop. In our example, the variable “i” is set to 0, the first index of the appTitle array.
- terminate statement: The next statement inside the parentheses (separated by a semicolon) tells us when this loop should stop processing and exit to the next line of code after the closing curly brace. In our example, we want the code inside the curly braces to continue executing for each “i” value, as long as “i” is less than the number of total number of items in the array. Since there are 5 items in the array, the last item is at index 4 (because the indexing starts at 0). Thus, we want to stop once “i” surpasses 4. Otherwise, we will get an ArrayIndexOutOfBoundsException.
- step statement: This last statement (again separated by a semicolon) defines how our counter will change after each step is executed. In our example, we are using a special “increment” shortcut that adds one to an integer value. ‘++’ can be used to increment a variable by one, and ‘–’ can be used to decrement a variable by one.
We must be careful when defining these conditions. What if we decrement our counter instead of incrementing it, and our terminate condition is never met? In such cases, our program or app will get caught in what is known as an “infinite loop”. The loop will never exit and our program will use up resources indefinitely, which will lead to a crash, freeze, or “Application Not Responding (ANR)” in Android.
Task
for (int i = 0; i < 100; i+=2) { System.out.println( “i : ” + i); }
int a = 5; System.out.println( a++); System.out.println( a--); System.out.println(++a); System.out.println(--a); System.out.println(,++(a++)); System.out.println(++((a++)--));
int a = 5; System.out.println( a**); //The multiplication operator
|
The “while” Loop
Another loop logic is a “while” loop, which executes code as long as a given condition is met. The biggest difference between a “while” loop and and “if” loops is that, for a “while” loop, we need to initialize our index “i” outside of the loop, as well as define how the loop steps through the the code, inside of the curly braces, instead of being a statement inside the parentheses where the “if” loop conditions were placed.
int i = 0; while (i < appTitle.length) { Log.d(TAG, appTitle[i]); i++; }
Line 1 is the initialize statement, line 2 contains the terminate statement, and line 4 is the step statement. The general syntax is as follows:
while (condition) { // code to execute } |
The “if” loop and “while” loop can often be rewritten as the other, so we can choose whichever makes the most sense for how we want to loop in the context of a given problem. Sometimes it’s easier to write one or the other based on the data with which we are working.
The do-while Loop
Similar to the “while” loop, the “do-while” loop is different, in that it checks the condition at the bottom of the loop instead of the top. This guarantees that the code inside the loop will execute at least one time. If the condition is not met in the first pass of a loop, the “while” loop will skip the code inside the curly braces, but the “do-while” loop will process the code once and then move on.
int i = 111; do { System.out.println( "Just looking at app names"); } while (i < appTitle.length); |
The for-each Loop
Sometimes iterators and conditions can start to appear complicated. Fortunately, Java contains yet another way of writing a loop when you want to iterate over a collection of items. The idea behind a “for-each” loop is that the program will run some code for each item in a collection.
for (String title : appTitle) { System.out.println( title); } |
The “for-each” loop replaces the three conditions of the “for” loop with a simplified declaration. The right side of the colon is the array or collection to be looped through, and the left side is a temporary variable used to hold the item in the current iteration of the loop. In the above example, we get a String from each item in the appTitle array and the String is stored in a temporary variable named “title”. We can read this as “for each name in appTitle, do the code in the curly braces”.
Task
* *** ***** *******
for ( int j = 0; j < 5; j++ ) { System.out.print( j + " " ); }
for ( int j = 5; ________ ; j++ ) { System.out.print( j + " " ); } |
Error Handling: try-ing Code and catch-ing Exceptions
Remember that ArrayIndexOutOfBoundsException briefly mentioned before? Java provides us with a framework for gently handling all sorts of errors in our programs. The basic idea is that if something wrong happens in our program or app, the Java runtime system will raise a little flag that says something is wrong. If we are on the lookout for these flags we can handle them appropriately and save our users from a crash or bad experience.
The act of raising that little flag is called throwing an exception, and we must catch them in code in our app. Let’s use an example to illustrate:
String url = "http://google.com"; try { URL blogUrl = new URL(url); } catch (MalformedURLException e) { Log.e(TAG, "Error creating a URL object with " + url); } |
Until this example, we’ve seen code that executes normally in the main thread of the program. If any exceptions are thrown in that type of code, then they are typically very serious and will likely cause the app to crash. However, there are often methods that throw less serious exceptions, but that we nonetheless cannot (and should not) ignore. In such cases, we need to put that code inside a “try” block, like lines 2-4 above. In this example, the URL constructor throws a MalformedURLException if a bad URL is given as the input parameter. If we don’t catch that exception (or some superclass of it, like Exception) then our code will not compile.
The “catch” block requires the type of exception to be caught to be declared as a variable inside the parentheses after the catch keyword. Then, as usual, the code to be executed in case of that exception is written between the curly braces.
If we need to check for multiple exceptions, like if we tried to open an HTTP connection using blogUrl, which throws an IOException, then we can chain “catch” statements one after another, like this:
try { // some code } catch (MalformedURLException e) { Log.e(TAG, "There was an error creating a URL object."; } catch (IOException e) { Toast.makeText(this, "Error connecting to site.", Toast.LENGTH_LONG).show(); } |
Note: No other code can go between the ending curly brace of one “catch” statement and the catch keyword of the next.
There is one more block of code that can be chained to this sequence: the “finally” block. This is where we put code that we want to execute even if an exception is thrown. In the example below, we open a connection to a file for writing and want to make sure we close it no matter what happens so that the connection is not open indefinitely:
Writer writer; try { writer = new OutputStreamWriter(new FileOutputStream("out.txt")); writer.write("Liran was here."); } catch (IOException e) { Log.e(TAG, "Error writing to file."); } finally { if (writer != null) { writer.close(); } } |
Note: The writer variable will be null if an exception was thrown trying to initialize it. Hence we need to check if it’s null or not, closing it only if it was initialized.
Phew… again we have covered a lot on this post. Let’s pick it up next time.
Happy coding.