Getting Started with Java

Sunday, 21 October 2018

How is Java platform independent?

The platform independent means that the java source code can run on all operating systems.
A program is written in a language which is a human readable language. It may contain words, phrases etc which the machine does not understand. For the source code to be understood by the machine, it needs to be in a language understood by machines, typically a machine-level language. So, here comes the role of a compiler. The compiler converts the high-level language (human language) into a format understood by the machines. Therefore, a compiler is a program that translates the source code for another program from a programming language into executable code.
This executable code may be a sequence of machine instructions that can be executed by the CPU directly, or it may be an intermediate representation that is interpreted by a virtual machine. This intermediate representation in Java is the Java Byte Code.
Step by step Execution of Java Program:
  • Whenever, a program is written in JAVA, the javac compiles it.
  • The result of the JAVA compiler is the .class file or the bytecode and not the machine native code (unlike C compiler).
  • The bytecode generated is a non-executable code and needs an interpreter to execute on a machine. This interpreter is the JVM and thus the Bytecode is executed by the JVM.
  • And finally program runs to give the desired output.
.

In case of C or C++ (language that are not platform independent), the compiler generates an .exe file which is OS dependent. When we try to run this .exe file on another OS it does not run, since it is OS dependent and hence is not compatible with the other OS.
Java is platform independent but JVM is platform dependent
In Java, the main point here is that the JVM depends on the operating system – so if you are running Mac OS X you will have a different JVM than if you are running Windows or some other operating system. This fact can be verified by trying to download the JVM for your particular machine – when trying to download it, you will given a list of JVM’s corresponding to different operating systems, and you will obviously pick whichever JVM is targeted for the operating system that you are running. So we can conclude that JVM is platform dependent and it is the reason why Java is able to become “Platform Independent”.
Important Points:
  • In the case of Java, it is the magic of Bytecode that makes it platform independent.
  • This adds to an important feature in the JAVA language termed as portability. Every system has its own JVM which gets installed automatically when the jdk software is installed. For every operating system separate JVM is available which is capable to read the .class file or byte code.
  • An important point to be noted is that while JAVA is platform-independent language, the JVM is platform-dependent. Different JVM is designed for different OS and byte code is able to run on different OS.

How is Java platform-independent when it needs a JVM to run?

Typically, the compiled code is the exact set of instructions the CPU requires to "execute" the program. In Java, the compiled code is an exact set of instructions for a "virtual CPU" which is required to work the same on every physical machine.
So, in a sense, the designers of the Java language decided that the language and the compiled code was going to be platform independent, but since the code eventually has to run on a physical platform, they opted to put all the platform dependent code in the JVM.
This requirement for a JVM is in contrast to your Turbo C example. With Turbo C, the compiler will produce platform dependent code, and there is no need for a JVM work-alike because the compiled Turbo C program can be executed by the CPU directly.
With Java, the CPU executes the JVM, which is platform dependent. This running JVM then executes the Java bytecode which is platform independent, provided that you have a JVM available for it to execute upon. You might say that writing Java code, you don't program for the code to be executed on the physical machine, you write the code to be executed on the Java Virtual Machine.
The only way that all this Java bytecode works on all Java virtual machines is that a rather strict standard has been written for how Java virtual machines work. This means that no matter what physical platform you are using, the part where the Java bytecode interfaces with the JVM is guaranteed to work only one way. Since all the JVMs work exactly the same, the same code works exactly the same everywhere without recompiling. If you can't pass the tests to make sure it's the same, you're not allowed to call your virtual machine a "Java virtual machine".
Of course, there are ways that you can break the portability of a Java program. You could write a program that looks for files only found on one operating system (cmd.exe for example). You could use JNI, which effectively allows you to put compiled C or C++ code into a class. You could use conventions that only work for a certain operating system (like assuming ":" separates directories). But you are guaranteed to never have to recompile your program for a different machine unless you're doing something really special (like JNI).

Final Keyword in Java

It is used to make a variable as a constant, Restrict method overriding, Restrict inheritance. It is used at variable level, method level and class level. In java language final keyword can be used in following way.
  • Final Keyword at Variable Level
  • Final Keyword at Method Level
  • Final Keyword at Class Level
final keyword in java

Final at variable level

Final keyword is used to make a variable as a constant. This is similar to const in other language. A variable declared with the final keyword cannot be modified by the program after initialization. This is useful to universal constants, such as "PI".

Final Keyword in java Example

public class Circle
{
public  static final double PI=3.14159;

public static void main(String[] args) 
{
System.out.println(PI);
}
}

Final Keyword at method level

It makes a method final, meaning that sub classes can not override this method. The compiler checks and gives an error if you try to override the method.
When we want to restrict overriding, then make a method as a final.

Example

public class A
{
public void fun1()
{
.......
}
public final void fun2()
{
.......
}

}
class B extends A
{
public void fun1()
{
.......
}
public void fun2()
{
 // it gives an error because we can not override final method
}
}

Example of final keyword at method level

Example

class Employee
{
final void disp()
{
System.out.println("Hello Good Morning");  
}
}
class Developer extends Employee
{
void disp()
{
System.out.println("How are you ?");  
}
}
class FinalDemo
{
public static void main(String args[])
{
Developer obj=new Developer();
obj.disp();
}  
} 

Output

It gives an error

Final Keyword at Class Level

It makes a class final, meaning that the class can not be inheriting by other classes. When we want to restrict inheritance then make class as a final.

Example

public final class A
{
......
......
}
public class B extends  A
{
// it gives an error, because we can not inherit final class
}

Example of final keyword at class level

Example

final class Employee
{
int salary=10000;
}
class Developer extends Employee
{
void show()
{
System.out.println("Hello Good Morning");  
}
}
class FinalDemo
{
public static void main(String args[])
{
Developer obj=new Developer();
Developer obj=new Developer();
obj.show();
}  
} 

Output

Output:
It gives an error

Why Java is not a purely Object Oriented Language?

Pure Object Oriented Language or Complete Object Oriented Language are Fully Object Oriented Language which supports or have features which treats everything inside program as objects. It doesn’t support primitive datatype(like int, char, float, bool, etc.). There are seven qualities to be satisfied for a programming language to be pure Object Oriented. They are:
  1. Encapsulation/Data Hiding
  2. Inheritance
  3. Polymorphism
  4. Abstraction
  5. All predefined types are objects
  6. All user defined types are objects
  7. All operations performed on objects must be only through methods exposed at the objects.
Example: Smalltalk
Why Java is not a Pure Object Oriented Language?
Java supports property 1, 2, 3, 4 and 6 but fails to support property 5 and 7 given above. Java language is not a Pure Object Oriented Language as it contain these properties:
  • Primitive Data Type ex. int, long, bool, float, char, etc as Objects: Smalltalk is a “pure” object-oriented programming language unlike Java and C++ as there is no difference between values which are objects and values which are primitive types. In Smalltalk, primitive values such as integers, booleans and characters are also objects.
    In Java, we have predefined types as non-objects (primitive types).


    int a = 5; 
    System.out.print(a);
    
  • The static keyword:  When we declares a class as static then it can be used without the use of an object in Java. If we are using static function or static variable then we can’t call that function or variable by using dot(.) or class object defying object oriented feature.
  • Wrapper Class: Wrapper class provides the mechanism to convert primitive into object and object into primitive. In Java, you can use Integer, Float etc. instead of int, float etc. We can communicate with objects without calling their methods. ex. using arithmetic operators.
    String s1 = "ABC" + "A" ;
    
    Even using Wrapper classes does not make Java a pure OOP language, as internally it will use the operations like Unboxing and Autoboxing. So if you create instead of int Integer and do any mathematical operation on it, under the hoods Java is going to use primitive type int only.
    public class BoxingExample 
    {
        public static void main(String[] args) 
        {
                Integer i = new Integer(10);
                Integer j = new Integer(20);
                Integer k = new Integer(i.intValue() + j.intValue());
                System.out.println("Output: "+ k);
        }
    }
    In the above code, there are 2 problems where Java fails to work as pure OOP:
    1. While creating Integer class you are using primitive type “int” i.e. numbers 10, 20.
    2. While doing addition Java is using primitive type “int”.

Wrapper Classes in Java

1. Overview 

As the name suggests, wrapper classes are objects encapsulating primitive Java types.
Each Java primitive has a corresponding wrapper:
  • boolean, byte, short, char, int, long, float, double 
  • Boolean, Byte, Short, Character, Integer, Long, Float, Double
These are all defined in the java.lang package, hence we don’t need to import them manually.

2. Wrapper Classes

“What’s the purpose of a wrapper class?”. It’s one of the most common Java interview questions.
Basically, generic classes only work with objects and don’t support primitives. As a result, if we want to work with them, we have to convert primitive values into wrapper objects.
For example, the Java Collection Framework works with objects exclusively. Long back when (prior to Java 5, almost 15 years back) there was no autoboxing and we, for example, couldn’t simply call add(5) on a collection of Integers.
At that time, those primitive values needed to be manually converted to corresponding wrapper classes and stored in collections.
Today, with autoboxing, we can easily do ArrayList.add(101) but internally Java converts the primitive value to an Integer before storing it in the ArrayList using the valueOf() method.

3. Primitive to Wrapper Class Conversion

Now the big question is: how do we convert a primitive value to a corresponding wrapper class e.g. an int to Integer or a char to Character?
Well, we can either use constructor or static factory methods to convert a primitive value to an object of a wrapper class.
Let’s see an example of converting an int value to an Integer object in Java:
1
2
3
Integer object = new Integer(1);
 
Integer anotherObject = Integer.valueOf(1);
The valueOf() method returns an instance representing the specified int value.
It returns cached values which makes it efficient. It always caches values between -128 to 127 but can also cache other values outside this range.
Similarly, we can also convert boolean to Boolean, byte to Byte, char to Character, long to Long, float to Float, and double to Double. Though if we have to convert String to Integerthen we need to use parseInt() method because String isn’t a wrapper class.
On the other hand, to convert from a wrapper object to a primitive value, we can use the corresponding method such as intValue(), doubleValue() etc:
1
int val = object.intValue();
A comprehensive reference can be found here.

4. Autoboxing and Unboxing

In the previous section, we showed how to manually convert a primitive value to an object.
After Java 5, this conversion can be done automatically by using features called autoboxing and unboxing.
“Boxing” refers to converting a primitive value into a corresponding wrapper object.Because this can happen automatically, it’s known as autoboxing.
Similarly, when a wrapper object is unwrapped into a primitive value then this is known as unboxing.
What this means in practice is that we can pass a primitive value to a method which expects a wrapper object or assign a primitive to a variable which expects an object:
1
2
3
4
List<Integer> list = new ArrayList<>();
list.add(1); // autoboxing
 
Integer val = 2; // autoboxing
In this example, Java will automatically convert the primitive int value to the wrapper.
Internally, it uses the valueOf() method to facilitate the conversion. For example, the following lines are equivalent:
1
2
3
Integer value = 3;
 
Integer value = Integer.valueOf(3);
Though this makes conversion easy and codes more readable, there are some cases where we shouldn’t use autoboxing e.g. inside a loop.
Similar to autoboxing, unboxing is done automatically when passing an object to a method that expects a primitive or when assigning it to a primitive variable:
1
2
3
4
5
6
7
Integer object = new Integer(1);
int val1 = getSquareValue(object); //unboxing
int val2 = object; //unboxing
 
public static int getSquareValue(int i) {
    return i*i;
}
Basically, if we write a method that accepts a primitive value or wrapper object, we can still pass both values to them. Java will take care of passing the right type e.g. primitive or wrapper depending upon context.

5. Conclusion

In this quick tutorial, we talked about wrapper classes in Java, as well as the mechanism of autoboxing and unboxing.

How is Java platform independent?

The platform independent means that the java source code can run on all operating systems. A program is written in a language which is a h...