Learning Java the Right Way

Introduction

It’s been long that I read the Java® Language Specification Java SE 6 Edition but never thought of writing any post on that. Recently I started reading the Java® Language Specification Java SE 7 Edition and here I present my learning. This series is an effort for learning java the right way. directly from the source.

It is the best practice, to learn a language from its specification. But most of the time when someone starts with the JLS, they get repelled by the first three chapters of the JLS, which is mostly about the Grammar and Lexical Structure of the Language. It mostly introduces us with the productions(rules) of the Grammar.

We will discuss about few properties of Java point by point and will try to understand each of them in detail. In coming posts, we may discover more of Java and by the end of the series we will be able to answer almost all the questions asked in interviews now a days and would be able to impress our colleagues and interviewers. 🙂

What does Java offer?

We must understand that Java is a relatively high level language. Java provides lot of features out of the box, which makes it easy to learn for today’s developers and focus on the real business implementation rather than worrying about the system level infrastructure management. Few of them are listed below:

  • Automatic Storage Management : This is done using a garbage collector, which avoids the safety problems of explicit de-allocations. When an object is no longer referenced, it may be reclaimed by the garbage collector. If an object declares a finalizer, the finalizer is executed before the object is reclaimed to give the object a last chance to clean up resources that would not otherwise be released. Also, when a class is no longer needed, it may be unloaded.
  • Avoids Unsafe Constructs : Arrays are accessed after explicitly doing an index check and throws an ArrayIndexOutOfBound exception. This helps in running the program correctly, else imagine a scenario where the language does not check the array index and returns a value which is stored in the memory location, but the memory location is not within the boundaries of the array. This could pose a big question on the correctness of your program.
  • No explicit declaration order required : It does not require types or their members to be declared before they are used. It only becomes significant when we declare local variables, local classes and the order of initializers of fields in a class or interface. While all other variables are automatically initialized to a default value, the Java programming language does not automatically initialize local variables.

The Java Programming Language is statically and strongly typed

Statically Typed :

This means that every variable and expression in the language has a Type and it is known at compile time.

Strongly Typed

This means that it limits the values which can be assigned to a variable of a given Type and it also limits the values which can be returned by an expression upon evaluation.

This helps in clearly distinguishing between the error which can be detected at compile time and the ones that can only be detected at run time.

What happens at the compile time?

Compile time activities include the following:

  • The program is translated into machine independent byte code representation.
  • Overloaded methods and constructors are resolved by picking the most specific method or constructor from those which are applicable.
What happens at the run time?

The Run-time activities include the following:

  • Loading and linking of the classes which are needed to execute a program.
  • Optional machine code generation and dynamic optimization of the program.
  • Actual program execution

What is Type?

In the above section we mentioned Type a lot, so before we move further, lets complete our discussion on Type. Java defines the below category of Types.

The Primitive Type

The primitive types are of boolean and numeric type. The numeric type can be of integral(byte, short, char, int, long) or floating point(float, double) types.

The values which can be assigned to the primitive types are called primitive values. The primitive values do not share state with other primitive values.

The boolean type can only have either of the two literals true or false.

The integral type byte can store 8 bit or 1 byte signed two’s complement integers.
The integral type short can store 16 bit or 2 byte signed two’s complement integers.
The integral type int can store 32 bit or 4 byte signed two’s complement integers.
The integral type long can store 64 bit or 8 byte signed two’s complement integers.
The type char can store 16 bit or 2 byte unsigned integers.

The floating point float can store a 32 bit or 4 byte IEEE 754 floating point numbers.
The floating point double can store a 64 bit or 8 byte IEEE 754 floating point numbers.

Classes exist for wrapping primitive values inside of objects. In many cases, wrapping and unwrapping is performed automatically by the compiler (in which case, wrapping is called boxing, and unwrapping is called unboxing).

The primitive types are defined to be the same on all machines and in all implementations

The Reference Type

The reference types are class types, interface types and array types. The values which can be assigned to a reference type are references to objects. An object is a dynamically created instance of a class type or a dynamically created array.

Casts on reference types are checked at run time to ensure type safety.
More about Reference type in the coming posts.

The Null Type

It just has one value that is null. It has no name and hence we cannot define a variable of type Null. The value can be assigned to any Reference Type.

Variables and Methods

Class Variables and Class Methods

Class variables exist one per class, this means that no matter how many instances of a class we spawn, there is only one value referenced by a class variable.

Class methods operate without reference to a specific object, this means that no matter how many instances of a class we spawn, we can always invoke the class methods with the class name.

Instance Variables and Instance Methods

Instance variables are dynamically created in objects that are instances of classes. Instance methods are invoked on instance of classes and such instances become the current object this during the method execution.

A Typical Program Execution in Java

  • A program is normally stored as binary files representing compiled classes and interfaces.
  • These binary files can be loaded into a Java Virtual Machine, linked to other classes and interfaces, and initialized.
  • Objects that are class instances also contain an instance of each super class of the class, and object creation involves recursive creation of these super class instances.

There are many more things which happen during the course of the execution of a program, which will be discussed in detail in the coming posts.

Exception Handling In Java

Exceptions are behavior of a program which should not occur in a happy path execution. We always wish that a program must not fall into any exception and run smoothly. But exceptions are inevitable, because our programs interact with multiple components and systems and we cannot guarantee that these systems are running smoothly.

Below are the categories of exceptions broadly defined in Java.

Checked Exceptions

These are such exceptions whose possibility of occurrence can be detected at compile time. They are detected by the compiler and it ensures that checked exceptions are properly handled by requiring that a method or constructor can result in a checked exception only if the method or constructor declares it. This provides compile-time checking that exception handlers exist.

Most user-defined exceptions should be checked exceptions.

Un-checked Exceptions

These exceptions can only be detected at the run time. They occur due to invalid operations in the program and are detected by the Java Virtual Machine. Few examples are ArrayIndexOutOfBound and NullPointerException.

Errors

Errors result from failures detected by the Java Virtual Machine, such as OutOfMemoryError.

Conclusion

We just scratched the surface of the JLS, and tried to understand Java from a different perspective. Learning Java definitely is a bigger task and I will try to make it much more simpler in the coming posts.

Java definitely is a wonderful language and I am writing these posts from the reference of Java 1.7, we might be discovering many new features of Java 1.7 which is not known to the old programmers.

Don’t forget to subscribe to TechieMe to get updates on latest posts.