Showing posts with label arrays in java. Show all posts
Showing posts with label arrays in java. Show all posts

Saturday, February 26, 2011

Chapter 62: Other Topics of Importance

So far, over the past chapters, we have covered a lot of topics that feature in the SCJP exam syllabus. Apart from this, there are a few other minor topics that you need to know which might feature in the exam questions.

Before we start, I have to tell you that this is going to be the penultimate chapter in this SCJP series and well, I am really glad that both of us have made it so far.

So without much delays, lets get started!!!

Compiling Java Programs

The javac command is used to invoke Java’s compiler and compile a Java source file.
A typical invocation of the javac command would look like below:

javac [options] [source files]

Both the [options] and the [source files] are optional parts of the command, and both allow multiple entries. The following are both legal javac commands:

javac -help
javac ClassName.java OneMoreClassName.java

The first invocation doesn’t compile any files, but prints a summary of valid options. The second invocation passes the compiler two .java files to compile (ClassName.java and OneMoreClassName.java). Whenever you specify multiple options and/or files they should be separated by spaces.

This command would create the .class files that would be require to run the java progam.

Compiling with -d

By default, the compiler puts a .class file in the same directory as the .java source file. This is fine for very small projects, but once you’re working on a project of any size at all, you’ll want to keep your .java files separated from your .class files. The -d option lets you tell the compiler in which directory to put the .class files it generates (d is for destination).

Lets take a look at two example commands:

javac -d classes source/MyTestClass.java
javac -d ../classes com/scjp/test/MyTestClass.java

Example 1 – Compile file named “MyTestClass.java” that is present inside the “source” sub-directory of the current directory and put the .class file in the “classes” sub-directory of the current directory

Example 2 – Compile the file named “MyTestClass.java” that is present in the following directory hierarchy “com/scjp/test/” from the current directory and put the .class file in the folder “classes” that is present one level above the current directory

One thing you must know about the -d option is that if the destination directory you specify doesn’t exist, you’ll get a compiler error. If, in the previous example, the classes directory did NOT exist, the compiler would say something like:

java:5: error while writing MyTestClass: classes/ MyTestClass.class (No such file or directory)

Running Java Programs

The java command is used to invoke the Java virtual machine. This command invokes the JVM and asks it to run the program that is specified in the argument.

java [options] className [args]

The [options] and [args] parts of the java command are optional, and they can both have multiple values. You must specify exactly one class file to execute, and the java command automatically assumes that you’re going to send only a .class file, so you don’t have to specify the .class extension on the command line. Here’s an example:

java MyTestClass 1 2 3

The above command invokes the .class file of our test class MyTestClass and passes 1, 2 and 3 as command line arguments.

For fun, just assume that the hypothetical code inside MyTestClass expects 3 command line arguments. Don't worry, am not going to bore you with the code of that class here…

Using System Properties

For the exam you need to know how to access the properties of the system in which you are running your programs.

Java has a class called java.util.Properties that can be used to access a system’s basic information like the current versions of the operating system, the Java compiler, and the Java virtual machine. In addition to providing such default information, you can also add and retrieve your own properties. Ex:

import java.util.*;
public class TestProperties {
public static void main(String[] args) {
Properties p = System.getProperties();
p.setProperty("props", "value");
p.list(System.out);
}
}

If this file is compiled and invoked as follows:
java -DcompileTimeProp=compileTimeVal TestProperties

You’ll get something like this:
...
os.name=Windows XP
props=value
...
java.specification.vendor=Sun Microsystems Inc.
user.language=en
java.version=1.6.0_05
...
compileTimeProp=compileTimeVal
...
There will be a lot more values printed on the console. To save space I just put out the information we are interested in…

Two name=value properties were added to the system’s properties: props=value was added via the setProperty method, and compileTimeProp=compileTimeVal was added via the -D option at the command line. When using the -D option, if your value contains white space the entire value should be placed in quotes like this:
java -DcompileTimeProp="compileTimeVal take 2" TestProperties

To repeat - when you use -D, the name=value pair must follow immediately, no spaces allowed.

The getProperty() method is used to retrieve a single property. It can be invoked with a single argument (a String that represents the name (or key)), or it can be invoked with two arguments, (a String that represents the name (or key), and a default String value to be used as the property if the property does not already exist). In both cases, getProperty() returns the property as a String.

Using Command-Line Arguments

You would probably know to handle or rather use command line arguments in your java program. But, just for the sake of completeness am putting out a simple example that handles command line arguments in the code. For the exam you need to know this (Why else would I bore you with such miniscule topics :-))

public class CommandLineArgExample {
public static void main(String[] args) {
int x = 0;
for(String s : args)
System.out.println(x++ + " element = " + s);
}
}

compiled and then invoked as follows

java CommandLineArgExample 1 A
the output will be
0 element = 1
1 element = A

Like all arrays, args index is zero based. Arguments on the command line directly follow the class name. The first argument is assigned to args[0], the second argument is assigned to args[1], and so on.

Exam Tip:
The main() method signature can be tweaked a little bit. So don't be confused or surprised if you see something you arent used to.
The following are all legal declarations for main():
static public void main(String[] args)
public static void main(String... x)
static public void main(String king_kong[])


Static Imports

Static imports is a new feature that was introduced as of Java 5. You already know that an import statement is required to include code from other java classes and APIs that are not part of the current class you are coding. These static imports were implemented to provide greater keystroke-reduction for programmers. Though, not many of us appreciate it, nonetheless, you may end up getting a question on this topic and hence it is my duty to cover this topic.

Without static imports:

public class RegularClassCode {
public static void main(String[] args) {
System.out.println(Integer.MAX_VALUE);
}
}

With static imports:

import static java.lang.System.out;
import static java.lang.Integer.*;
public class UseStaticImportsCode {
public static void main(String[] args) {
out.println(MAX_VALUE);
}
}

Both classes produce the same output:
2147483647

I guess, you already figured out whats happening here. By importing the System class, we were able to directly invoke its static methods. So instead of saying System.out.println() we just said out.println().

I personally am a little skeptical about the usefulness of this feature because, though we don't have to write System.out.println() everytime, if a new programmer who doesn't know what static imports is (cant expect everyone to know everything, isnt it?) opens up your code, he’ll be confused as to how in the hell did this guy print stuff on the console without using System.out.println() method.

There are a couple of rules for using static imports:

• You must say import static; you can’t say static import.
• Watch out for ambiguously named static members. For instance, if you do a static import for both the Integer class and the Long class, referring to MAX_VALUE will cause a compiler error, since both Integer and Long have a MAX_VALUE constant, and Java won’t know which MAX_VALUE you’re referring to.
• You can do a static import on static object references, constants (remember they’re static and final), and static methods.

Previous Chapter: Self Test - Chapters 55 to 61

Next Chapter: Some last words before you take the SCJP Certification

Wednesday, February 2, 2011

Chapter 18: Array Declaration, Construction, and Initialization

Arrays are objects in Java that store multiple variables of the same type. Arrays can hold either primitives or object references, but the array itself will always be an object on the heap, even if the array is declared to hold primitive elements. In other words, there is no such thing as a primitive array, but you can make an array of primitives. We are going to learn the following three things in this Chapter:

• How to make an array reference variable (declare)
• How to make an array object (construct)
• How to populate the array with elements (initialize)

There are several different ways to do each of those, and you need to know about all of them for the exam.

Tip:
Arrays are efficient, but most of the time you’ll want to use one of the Collection types from java.util (including HashMap, ArrayList, TreeSet). Collection classes offer more flexible ways to access an object (for insertion, deletion, and so on) and unlike arrays, can expand or contract dynamically as you add or remove elements (they’re really managed arrays, since they use arrays behind the scenes). There’s a Collection type for a wide range of needs. We will be covering Collections in greater detail in one of the forthcoming chapters.

Declaring an Array

Arrays are declared by stating the type of element the array will hold, which can be an object or a primitive, followed by square brackets to the left or right of the identifier.
Declaring an array of primitives:

int[] Values; // brackets before name (recommended)
int Values []; // brackets after name (legal but less readable)
// spaces between the name and [] legal, but bad

Declaring an array of object references:
Ferrari[] Ferraris; // Recommended
Ferrari Ferraris[]; // Legal but less readable

When declaring an array reference, you should always put the array brackets immediately after the declared type, rather than after the identifier (variable name). That way, anyone reading the code can easily tell that, for example, Values is a reference to an int array object, and not an int primitive.

We can also declare multidimensional arrays, which are in fact arrays of arrays. This can be done in the following manner:
String[][][] occupantName; // recommended
String[] ManagerName []; // Real bad coding practice, but legal

The first example is a three-dimensional array (an array of arrays of arrays) and the second is a two-dimensional array. Notice in the second example we have one square bracket before the variable name and one after. This is perfectly legal to the compiler, but if you write code like this, anyone who is going to manage your code in future is sure going to curse you badly.
It is never legal to include the size of the array in your declaration. Yes, before you ask me, let me admit that you can do that in some other languages, which is exactly why you might see a question or two that include code similar to the following:

int[5] races;

The preceding code won’t make it past the Java compiler. Remember, the JVM doesn’t allocate space until you actually instantiate the array object. That’s when size matters and not when you declare the array variable.

Constructing an Array

Constructing an array means creating the array object on the heap i.e., doing a new on the array type. To create an array object, Java must know how much space to allocate on the heap, so you must specify the size of the array at creation time. The size of the array is the number of elements the array will hold.

Constructing One-Dimensional Arrays

The most straightforward way to construct an array is to use the Keyword new followed by the array type, with a bracket specifying how many elements of that type the array will hold. The following is an example of constructing an array of type int:
int[] myArray; // Declares the array of ints
myArray = new int[4]; // constructs an array and assigns it
// to the myArray variable

The preceding code puts one new object on the heap—an array object holding four elements—with each element containing an int with a default value of 0. Think of this code as saying to the compiler, “Create an array object that will hold four int values, and assign it to the reference variable named myArray. Also, go ahead and set each int element to zero. Thanks.”
You can also declare and construct an array in one statement as follows:

int[] myArray = new int[4];

This single statement produces the same result as the two previous statements. Arrays of object types can be constructed in the same way:

Ferrari[] Ferraris = new Ferrari[5];

Remember that—despite how the code appears—the Ferrari constructor is not being invoked. We’re not creating a Ferrari instance, but rather a single Ferrari array object. After the preceding statement, there are still no actual Ferrari objects!

Exam Tip: Think carefully about how many objects are on the heap after a code statement or block executes. The exam will expect you to know, for example, that the preceding code produces just one object (the array assigned to the reference variable named Ferraris). The single object referenced by Ferraris holds five Ferrari reference variables, but no Ferrari objects have been created or assigned to those references.

Remember, arrays must always be given a size at the time they are constructed. The JVM needs the size to allocate the appropriate space on the heap for the new array object. It is never legal, for example, to do the following:

int[] carList = new int[]; // Will not compile; needs a size

Exam Tip: You may see the words “construct”, “create”, and “instantiate” used interchangeably. They all mean, “An object is built on the heap.” This also implies that the object’s constructor runs, as a result of the construct/create/instantiate code. You can say with certainty, for example, that any code that uses the Keyword new, will (if it runs successfully) cause the class constructor and all superclass constructors to run.

Constructing Multidimensional Arrays

Multidimensional arrays, remember, are simply arrays of arrays. So a two-dimensional array of type int is really an object of type int array (int []), with each element in that array holding a reference to another int array. The second dimension holds the actual int primitives. The following code declares and constructs a two-dimensional array of type int:

int[][] myArray = new int[3][];

Notice that only the first brackets are given a size. That’s acceptable in Java, since the JVM needs to know only the size of the object assigned to the variable myArray.

Initializing an Array

Initializing an array means putting things into it. The “things” in the array are the array’s elements, and they’re either primitive values, or objects referred to by the reference variables in the array. If you have an array of objects (as opposed to primitives), the array doesn’t actually hold the objects, just as any other nonprimitive variable never actually holds the object, but instead holds a reference to the object. But we talk about arrays as, for example, “an array of five strings,” even though what we really mean is, “an array of five references to String objects.” Then the big question becomes whether or not those references are actually referring to real String objects, or are simply null. Remember, a reference that has not had an object assigned to it is a null reference. And if you try to actually use that null reference by, say, applying the dot operator to invoke a method on it, you’ll get the most famous NullPointerException.

The individual elements in the array can be accessed with an index number. The index number always begins with zero, so for an array of ten objects the index numbers will run from 0 through 9. Suppose we create an array of three Ferraris as follows:
Ferrari [] raceCars = new Ferrari[3];

We have one array object on the heap, with three null references of type Ferrari, but we don’t have any Ferrari objects. The next step is to create some Ferrari objects and assign them to index positions in the array referenced by raceCars:
raceCars[0] = new Ferrari();
raceCars[1] = new Ferrari();
raceCars[2] = new Ferrari();

This code puts three new Ferrari objects on the heap and assigns them to the three index positions (elements) in the raceCars array.

Exam Tip: Look for code that tries to access an out-of-range array index. For example, if an array has three elements, trying to access the [3] element will raise an ArrayIndexOutOfBoundsException, because in an array of three elements, the legal index values are 0, 1, and 2. You also might see an attempt to use a negative number as an array index. The following are examples of legal and illegal array access attempts. Be sure to recognize that these cause runtime exceptions and not compiler errors!
Nearly all of the exam questions list both runtime exception and compiler error as possible answers.
int[] x = new int[5];
x[4] = 2; // OK, the last element is at index 4
x[5] = 3; // Runtime exception. There is no element at index 5!

int[] z = new int[2];
int y = -3;
z[y] = 4; // Runtime exception. y is a negative number

These can be hard to spot in a complex loop, but that’s where you’re most likely to see array index problems in exam questions.

A two-dimensional array (an array of arrays) can be initialized as follows:

int[][] races = new int[3][];
// Declare and create an array holding three references
// to int arrays

races[0] = new int[4];
// the first element in the races array is an int array
// of four int elements

races[1] = new int[6];
// the second element in the races array is an int array
// of six int elements

races[2] = new int[1];
// the third element in the races array is an int array
// of one int element

Initializing Elements in a Loop

Array objects have a single public variable, length that gives you the number of elements in the array. The last index value, then, is always one less than the length. For example, if the length of an array is 4, the index values are from 0 through 3. Often, you’ll see array elements initialized in a loop as follows:

Ferrari[] myFerraris = new Ferrari[6];
for(int x = 0; x < myFerraris.length; x++) {

myFerraris[x] = new Ferrari();

}


The above code creates a Ferrari array reference and then assigns a new Ferrari object into each position in the array using the length property of the array.


The length variable tells us how many elements the array holds, but it does not tell us whether those elements have been initialized.


Declaring, Constructing, and Initializing on One Line

You can use two different array-specific syntax shortcuts to both initialize and instantiate an array in a single statement. The first is used to declare, create, and initialize in one statement as follows:
int[] dots = {6,7,8};

The preceding code does four things:
• Declares an int array reference variable named dots.
• Creates an int array with a length of three (three elements).
• Populates the array’s elements with the values 6, 7, and 8.
• Assigns the new array object to the reference variable dots.

The size (length of the array) is determined by the number of comma-separated items between the curly braces. The code is functionally equivalent to the following longer code:
int[] dots;
dots = new int[3];
dots[0] = 6;
dots[1] = 7;
dots[2] = 8;

You may ask me now, “why use the longer way then?” The answer is simple my friend. Not always do we know how many elements we want to put in an array. For an example perspective I know how many int values I want in my array but during coding for an application, the array size might vary so, using the longer way is much more beneficial.

With object references rather than primitives, it works exactly the same way:

Ferrari[] myFerraris = {new Ferrari(“One”), new Ferrari("Two"), new Ferrari("Three")};

The preceding code creates one Ferrari array, referenced by the variable myFerraris, with a length of three elements. It also creates three new Ferrari objects (One, Two and Three), and adds them to the Ferrari reference variable elements in the myFerraris array.
You can also use the shortcut syntax with multidimensional arrays, as follows:
int[][] races = {{5,2,4,7}, {9,2}, {3,4}};

The preceding code creates a total of four objects on the heap. First, an array of int arrays is constructed (the object that will be assigned to the races reference variable). The races array has a length of three, derived from the number of items (comma-separated) between the outer curly braces. Each of the three elements in the races array is a reference variable to an int array, so the three int arrays are constructed and assigned to the three elements in the races array.

The size of each of the three int arrays is derived from the number of items within the corresponding inner curly braces. For example, the first array has a length of four, the second array has a length of two, and the third array has a length of two. So far, we have four objects: one array of int arrays (each element is a reference to an int array), and three int arrays (each element in the three int arrays is an int value). Finally, the three int arrays are initialized with the actual int values within the inner curly braces. Thus, the first int array contains the values 5, 2, 4, and 7. The following code shows the values of some of the elements in this two-dimensional array:

races[0] // an array of four ints
races[1] // an array of 2 ints
races[2] // an array of 2 ints
races[0][1] // the int value 2
races[2][1] // the int value 4

Constructing and Initializing an Anonymous Array

The second shortcut is called “anonymous array creation” and can be used to construct and initialize an array, and then assign the array to a previously declared array reference variable:
int[] myArray;
myArray = new int[] {4,7,2};

The preceding code creates a new int array with three elements, initializes the three elements with the values 4, 7, and 2, and then assigns the new array to the previously declared int array reference variable myArray. We call this anonymous array creation because with this syntax you don’t even need to assign the new array to anything.

Exam Tip: Remember that you do not specify a size when using anonymous array creation syntax. The size is derived from the number of items (comma-separated) between the curly braces. Pay very close attention to the array syntax used in exam questions (and there will be a lot of them). You might see syntax such as
new Object[3] {null, new Object(), new Object()};
// not legal;size must not be specified


Legal Array Element Assignments

What can you put in a particular array? For the exam, you need to know that arrays can have only one declared type (int [], Ferrari[], String [], and so on), but that doesn’t necessarily mean that only objects or primitives of the declared type can be assigned to the array elements. And what about the array reference itself? What kind of array object can be assigned to a particular array reference? For the exam, you’ll need to know the answers to all of these questions. And, that is exactly what we are going to see in the next few paragraphs.

Arrays of Primitives

Primitive arrays can accept any value that can be promoted implicitly to the declared type of the array. For example, an int array can hold any value that can fit into a 32-bit int variable. Thus, the following code is legal:

int[] list = new int[5];
byte b = 4;
char c = 'c';
short s = 7;
list[0] = b;
list[1] = c;
list[2] = s;

Arrays of Object References

If the declared array type is a class, you can put objects of any subclass of the declared type into the array. For example, if Subaru is a subclass of Car, you can put both Subaru objects and Car objects into an array of type Car as follows:

class Car {}
class Subaru extends Car {}
class Ferrari extends Car {}
...
Car [] myCars = {new Subaru(), new Car(), new Ferrari()};

It helps to remember that the elements in a Car array are nothing more than Car reference variables. So anything that can be assigned to a Car reference variable can be legally assigned to a Car array element.

If the array is declared as an interface type, the array elements can refer to any instance of any class that implements the declared interface. The following code demonstrates the use of an interface as an array type:
interface Retractable {
void retractRoof();
}

class Ferrari extends Car implements Retractable {
public void retractRoof() {
// implement cool Retractable method in a Ferrari-specific way
}
}

class Subaru extends StationWagon implements Retractable {
public void retractRoof() {
// implement cool Retractable method in a RacingShoe-specific way
}
}
class Volkswagen { }
class TestRetractableCars {
public static void main (String [] args) {
Retractable[] RetractableThings = new Retractable [3];
RetractableThings[0] = new Ferrari();
// OK because, Ferrari implements Retractable
RetractableThings[1] = new Subaru();
// OK because, Subaru implements Retractable
RetractableThings[2] = new Volkswagen();
// Not OK because, Volkswagen does not implement Retractable
}
}

The bottom line is this: any object that passes the “IS-A” test for the declared array type can be assigned to an element of that array.

Array Reference Assignments for One-Dimensional Arrays

For the exam, you need to recognize legal and illegal assignments for array reference variables. We’re not talking about references in the array (in other words, array elements), but rather references to the array object. For example, if you declare an int array, the reference variable you declared can be reassigned to any int array (of any size), but cannot be reassigned to anything that is not an int array, including an int value. Remember, all arrays are objects, so an int array reference cannot refer to an int primitive. The following code demonstrates legal and illegal assignments for primitive arrays:

int[] cats;
int[] dogs = new int[4];
char[] rats = new char[5];
cats = dogs; // OK, dogs refers to an int array
cats = rats; // NOT OK, rats refers to a char array

It’s tempting to assume that because a variable of type byte, short, or char can be explicitly promoted and assigned to an int, an array of any of those types could be assigned to an int array. You cannot do that in Java.

Arrays that hold object references, as opposed to primitives, aren’t as restrictive. Just as you can put a Ferrari object in a Car array (because Ferrari extends Car), you can assign an array of type Ferrari to a Car array reference variable as follows:

Car[] cars;

Ferrari[] myFerraris = new Ferrari[5];
cars = myFerraris; // OK because Ferrari is a type of Car
Truck[] trucks = new Truck [99];
cars = trucks; // NOT OK, Truck is not a type of Car

Apply the IS-A test to help sort the legal from the illegal. Ferrari IS-A Car, so a Ferrari array can be assigned to a Car array. Truck IS-A Car is not true; Truck does not extend Car.
Exam Tip: You cannot reverse the legal assignments. A Car array cannot be assigned to a Ferrari array. A Car is not necessarily a Ferrari, so if you’ve declared a Ferrari array, it might blow up if you assigned a Car array to the Ferrari reference variable. Think about it: a Car array could hold a reference to a Ferrari, so someone who thinks they have an array of Ferraris could suddenly find themselves with a Ferrari. Remember that the IS-A test can be checked in code using the instanceof operator.

The rules for array assignment apply to interfaces as well as classes. An array declared as an interface type can reference an array of any type that implements the interface. Remember, any object from a class implementing a particular interface will pass the IS-A (instanceof) test for that interface. For example, if Car implements Drivable, the following is legal:

Drivable[] drivableThings;
Car[] CarThings = new Car[3];
drivableThings = CarThings;
// OK, Car implements Drivable, so Car IS-A Drivable

Array Reference Assignments for Multidimensional Arrays

When you assign an array to a previously declared array reference, the array you’re assigning must be the same dimension as the reference you’re assigning it to. For example, a two-dimensional array of int arrays cannot be assigned to a regular int array reference, as follows:
int[] cats;
int[][] dogs = new int[3][];
cats = dogs; // NOT OK, dogs is a
// two-d array of int arrays
int[] rats = new int[6];
cats = rats; // OK, rats is an int array

Pay particular attention to array assignments using different dimensions. You might, for example, be asked if it’s legal to assign an int array to the first element in an array of int arrays, as follows:

int[][] books = new int[3][];
int[] numbers = new int[6];
int aNumber = 7;
books[0] = aNumber; // NO, expecting an int array not an int
books[0] = numbers; // OK, numbers is an int array


Initialization Blocks

We’ve talked about two places in a class where you can put code that performs operations: methods and constructors. Initialization blocks are the third place in a Java program where operations can be performed. Initialization blocks run when the class is first loaded (a static initialization block) or when an instance is created (an instance initialization block). Let’s look at an example:

class TestInitBlocks {
static int x;
int y;

static { x = 7 ; } // static init block
{ y = 8; } // instance init block
}

As you can see, the syntax for Initialization blocks is pretty straight-forward. They don’t have names, they can’t take arguments, and they don’t return anything. A static initialization block runs once, when the class is first loaded. An instance initialization block runs once every time a new instance is created. Remember when we talked about the order in which constructor code executed? Instance init block code runs right after the call to super() in a constructor, in other words, after all super-constructors have run.

You can have many Initialization blocks in a class. It is important to note that unlike methods or constructors, the order in which Initialization blocks appear in a class matters. When it’s time for Initialization blocks to run, if a class has more than one, they will run in the order in which they appear in the class file.

Finally, if you make a mistake in your static init block, the JVM can throw an ExceptionInInitializationError. Let’s look at an example,
class InitErrorExample {
static int [] x = new int[4];
static { x[4] = 5; } // bad array index!
public static void main(String [] args) { }
}

which produces something like:

Exception in class "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.ArrayIndexOutOfBoundsException: 4
at InitErrorExample.(InitErrorExample.java:3)

Exam Tip: By convention, init blocks usually appear near the top of the class file, somewhere around the constructors. However don’t be surprised if you find an init block tucked in between a couple of methods. Though it is perfectly legal to code your init blocks anywhere in the class you want, you may end up with compilation errors if you happen to take that risk

Previous Chapter: Chapter 17 - Passing Variables to Methods

Next Chapter: Chapter 19 - Wrapper Classes and Boxing

Saturday, January 1, 2011

Chapter 2: Declarations

Classes and Interfaces are the basis based on which the java programming universe revolves. Everything in Java is an object but an object is nothing but the runtime orientation of a class. In other words, an object is nothing but a class that is being executed.

Whenever you write any java code, it implicitly means that you are writing classes or interfaces. Within those classes, as you know, are variables and methods (plus a few other things). How you declare your classes, methods, and variables dramatically affects your code’s behavior

Source File Declaration Rules:

Before we dig into class declarations, let’s do a quick review of the rules associated with declaring classes, import statements, and package statements in a source file:
• There can be only one public class per source file.
• Comments can appear at the beginning or end of any line in the source code file; they are independent of any of the positioning rules discussed here.
• If there is a public class in a file, the name of the file must match the name of the public class. For example, a class declared as public class Rock { } must be in a source code file named Rock.java.
• If the class is part of a package, the package statement must be the first line in the source code file, before any import statements that may be present.
• If there are import statements, they must go between the package statement (if there is one) and the class declaration. If there isn’t a package statement, then the import statement(s) must be the first line(s) in the source code file. If there are no package or import statements, the class declaration must be the first line in the source code file.
• import and package statements apply to all classes within a source code file. In other words, there’s no way to declare multiple classes in a file and have them in different packages, or use different imports.
• A file can have more than one nonpublic class.
• Files with no public classes can have a name that does not match any of the classes in the file.

Now that we have taken a look at the rules for declaring a java source code file, let us get into the real thing about declaring classes.

Declaring Classes:

A Class can be declared with the following statement:

public class AnandsFirstclass {}

Irrespective of the fact that this class does not have any code, this piece of code when saved in a file called AnandsFirstclass.java compiles just fine. Here public is an access modifier (we will see access modifiers in greater detail in one of the subsequent chapters), class is the keyword that is used to specify that a class is being declared and AnandsFirstclass is the name of the class we are creating.

There are many different types of classes that you can create. Some of which are:
1. Final Classes – A class that cannot be inherited (Dont worry about inheritance just yet. We will look into it in full detail in one of the later chapters)
2. Normal Classes – The type of class that we declared a few lines back
3. Abstract Classes – A class that is similar to a normal class but that does not provide full functional behaviour by itself. It has to be subclassed/inherited in order to be used.

Abstract Classes in Detail:
An Abstract class is a special kind of class that cannot be instantiated. It has one or more methods which are not implemented in the class. These methods are declared abstract and they do not contain any code inside them.

Ex:
abstract class Parent {
public abstract String getSon();
public abstract String getDaughter();
....
....
//More methods that contain specific behaviour/code in them
}

The above is an abstract class “Parent” that has a lot of functionality but it has declared two abstract methods which have no code inside them. Any class that has one or more abstract methods has to be abstract. This abstract class cannot be instantiated.

i.e., the below piece of code will not work. The code will not even compile.

Parent object = new Parent();

Purpose of Abstract Classes:
Abstract classes are generally used where you want an amount of behaviour to be used by the class that extends the abstract class while at the same time giving options to the child class to provide a certain amount of behaviour itself.

A Child Class extending the Abstract Class:

public class Child extends Parent {
public String getSon() {
return “Sons Name”;
}

public String getDaughter(){
return “Daughters Name”;
}
...
... //Code specific to the Child class
}

Declaring Interfaces:

When you create an interface, you’re defining a contract for what a class can do, without saying anything about how the class will do it. Interfaces can be implemented by any class, from any inheritance tree. This lets you take radically different classes and give them a common characteristic.

Ex: You can create an interface Drivable which in effect means that it has the feature of being driven. Any class that implements this Drivable interface must provide an implementation of the drive() method can be driven. But how it will be driven is up to the classes to provide the implementation. Both a car and a bus can be driven but the how part is different. So the classes Car and Bus will implement this interface and provide their specific behavior about being driven.

Tip: An Interface is an 100% Abstract class

Comparison between an Abstract Class and an Interface:

While an abstract class can define both abstract and non-abstract methods, an interface can have only abstract methods. Another way interfaces differ from abstract classes is that interfaces have very little flexibility in how the methods and variables defined in the interface are declared. These rules are strict:

• All interface methods are implicitly public and abstract. In other words, you do not need to actually type the public or abstract modifiers in the method declaration, but the method is still always public and abstract. (You can use any kind of modifiers in the Abstract class)
• All variables defined in an interface must be public, static, and final—in other words, interfaces can declare only constants, not instance variables.
• Interface methods must not be static.
• Because interface methods are abstract, they cannot be marked final, strictfp, or native. (More on these modifiers later.)
• An interface can extend one or more other interfaces.
• An interface cannot extend anything but another interface.
• An interface cannot implement another interface or class.
• An interface must be declared with the keyword interface.

You must remember that all interface methods are public and abstract regardless of what you see in the interface definition.

Look out for questions where interface methods are declared with any combination of public, abstract, or no modifiers. For example, the following five method declarations, if declared within their own interfaces, are legal and identical!

void bbb();
public void bbb();
abstract void bbb();
public abstract void bbb();
abstract public void bbb();

whereas the below declarations wont compile:

The following interface method declarations won’t compile:
final void bbb(); // final and abstract can never be used
// together, and abstract is implied
static void bbb(); // interfaces define instance methods
private void bbb(); // interface methods are always public
protected void bbb(); // (same as above)

Declaring Variables in an Interface

We are allowed to declare variables in an interface. By default these variables would be constants because they would static and final. By placing the constants right in the interface, any class that implements the interface has direct access to the constants, just as if the class had inherited them.

You need to remember one key rule for interface constants. They must always be
public static final

Since the variables declared in an interface are by default public static and final, we need not mention them explicitly. But it is a good practice to do so to ensure that even novice programmers can understand the code you write.

Constructor Declarations:

In Java, objects are constructed. Every time you make a new object, at least one constructor is invoked. Every class has a constructor, although if you don’t create one explicitly, the compiler will build one for you.

Ex:
class Test {
public Test() { } // this is Test’s constructor

public void Test() { } // this is a badly named,
// but legal, method
}

If you see the example above, you would have realized that the constructor looks a lot like methods. Below are the main distinguishing factors between the constructor and normal methods:
1. The Constructor’s name is exactly the same as the name of the class
2. They do not have a return type (Please remember this. A Constructor cannot have a return type as part of the code)
3. Constructors cannot be static, abstract or final

Declaring Variables:

There are two types of variables in Java:
Primitives - A primitive variable can be one of eight types: char, boolean, byte, short, int, long, double, or float. Once a primitive has been declared, its primitive type can never change, although in most cases its value can change.
Reference variables - A reference variable is used to refer to (or access) an object. A reference variable is declared to be of a specific type and that type can never be changed.

We should remember that each of the primitive datatype has a particular range and by assigning values that are bigger than the size it can take would result in errors or loss of value and precision. Below are the data ranges of the primitive datatypes:

Primitive Data Type Ranges in Java
Data Type Bits Used Minimum Value Maximum Value
byte 8 -27 27 - 1
short 16 -215 215 -1
int 32 -231 231 -1
long 64 -263 263 -1
float 32 n/a n/a
double 64 n/a n/a
The range for these floating point numbers is difficult to determine and it is not required from the exam perspective as well. Booleans and char type variables do not have a range. Booleans can be either true or false and chars can be only one character in size Ex: “A” or “B” etc

Declaring Reference Variables:

Reference variables can be declared as static variables, instance variables, method parameters, or local variables. You can declare one or more reference variables, of the same type, in a single line

Variables can be declared in multiple places inside a class which determines what type of variable gets created. They are:

Instance Variables

Instance variables are defined inside the class, but outside of any method, and are only initialized when the class is instantiated. Instance variables are the fields that belong to each unique object.

Ex:
public class Test {
private String name = “Anand”;
private String country = “India”;
}

Here name and country are two instance variables where they would be a part of an object of the class Test. Since each variable is part of the class’s instance (object), they are called instance variables.
For the exam, you need to know that instance variables
• Can use any of the four access levels (which means they can be marked with any of the three access modifiers)
• Can be final
• Can be transient
• Cannot be abstract
• Cannot be synchronized
• Cannot be strictfp
• Cannot be native
• Cannot be static, because then they’d become class variables.

Static Variables or Class Variables:

The static modifier is used to create variables and methods that will exist independently of any instances created for the class. All static members exist before you ever make a new instance of a class, and there will be only one copy of a static member regardless of the number of instances of that class.

Things you can mark as static:
• Methods
• Variables
• A class nested within another class, but not within a method (more on this in Chapter 8).
• Initialization blocks

Things you can’t mark as static:
• Constructors (makes no sense; a constructor is used only to create instances)
• Classes (unless they are nested)
• Interfaces
• Method local inner classes
• Inner class methods and instance variables
• Local variables

Method Parameters:

These are variables that are declared as part of a methods declaration. These are arguments that will be used as part of the method.

Ex: public int add(int a, int b) {
return a + b;
}

Here a and be are the method parameters.

Local Variables:

These are variables that are declared inside a method and are used for processing inside the method.

Ex: public int add(int a, int b) {
private int c = 10;
return a + b + c;
}

Here c is the local variable.

Declaring Arrays:

In Java, arrays are objects that store multiple variables of the same type, or variables that are all subclasses of the same type. Arrays can hold either primitives or object references, but the array itself will always be an object on the heap, even if the array is declared to hold primitive elements. In other words, there is no such thing as a primitive array, but you can make an array of primitives.

The main thing you need to know about arrays in the exam perspective is how to create an array and how to assign values to the array elements.

Tip: Arrays are very useful and efficient but java has other utility classes like ArrayList or Vector that might be much better in performance than arrays. These collections give us easier access to its objects and also provide utility methods that might help us process these objects


Declaring an Array of Primitives

int[] keys; // Square brackets before name (recommended)
int keys []; // Square brackets after name (legal but less
// readable)

Declaring an Array of Object References

Thread[] processes; // Recommended
Thread processes []; // Legal but less readable

We can also declare multidimensional arrays, which are in fact arrays of arrays. This can be done in the following manner:

String[][] employeeNames;
String[] employeeNames[];

Above we have a 2 dimensional array which can be thought of as an array of arrays. Notice in the second example we have one square bracket before the variable name and one after. This is perfectly legal to the compiler, proving once again that just because it’s legal doesn’t mean it’s right.

Note: We will deal with assigning values to the array in a separate chapter.


Hope this chapter on Declarations was useful. I have intentionally left of declaration of Enumerations as part of this chapter because enums need to be taken up as a separate chapter because of the amount of details involved in enumerations.

Previous Chapter: Chapter 1 - Refreshing Java

Next Chapter: Chapter 3 - Declaring Enumerations (Enums)
© 2013 by www.inheritingjava.blogspot.com. All rights reserved. No part of this blog or its contents may be reproduced or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, or otherwise, without prior written permission of the Author.

ShareThis

Google+ Followers

Followers