Java 4
Java 4
Before going further let us know the difference between constructor and a
method.
A constructor cannot be static but a method can be. When the following
code is compiled. the compiler complains "modifier static not allowed
here".
Extends Implements::
We know earlier that Java does not support multiple inheritance but
supports partially through interfaces.
After extends there must be only one class of either concrete (non-
abstract) or abstract. After implements there must be interfaces only and
can be of any number. But if a class would like to extend a number of
concrete classes then, how it can? The following program illustrates.
class A { }
class B extends A { }
interface C { }
interface D { }
Even though Java does not support multiple inheritance directly, it can
achieve all the benefits using extends and implements as in the above
program
Let us list some rules which are already stated in "Extends Implements"
topic. Take some classes and interfaces.
1. After extends there must be only one class either concrete (non-
abstract) or abstract.
class A { }
class B { }
interface C { }
interface D { }
interface E { }
interface C extends D
interface C extends D, E
interface C extends D, E
class A implements C
interface C extends D, E
class A extends B implements C
Even though the keywords "extends" and "implements" are used with
inheritance, they differ a lot in their usage.
class CheckDemo
{
private int date;
public void validate(int d1)
{
if( d1 > 0 && d1 < 32)
{
date = d1;
System.out.println("Yes, your birth date is " + date + " and
is valid");
}
else
{
System.out.println("Sorry, your birth date is " + d1 + " and
is invalid");
}
}
}
public class BirthDate
{
public static void main(String args[])
{
CheckDemo cd1 = new CheckDemo();
cd1.validate(15);
cd1.validate(35);
}
}
CheckDemo class includes one private variable date and one public method
validate(). The validate() method validates the date send by the other
class BirthDate. If it is within the range of 1 to 31, it assigns the
value to the private variable date, else gives a message.
The other class BirthDate, can not assign to date directly as it is
private. So, the BirthDate class accesses the private variable through
public method, validate().
This is a very basic question asked in every interview and should known
to each programmer also.
Everyone says "no" as Java does not support pointers. No one actually see
the address of the object in Java. No one can dream of call by reference
without pointers with their experience of C/C++.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class CallByValue
{
public void display(int y)
{
y = 20;
}
public static void main(String args[])
{
CallByValue cbv = new CallByValue();
int x = 10;
cbv.display(x);
System.out.println(x); // prints 10 and not 20
}
}
class Test
{
public void display() { System.out.println("Hello 1"); }
}
class Demo
{
public static void main(String args[])
{
Test t1 = new Test();
t1.display();
}
}
We say, class Demo has the object t1 of Test class. Or say, Demo "has-a"
object of Test. This is known as "has-a" relationship and is known as
composition in Java. This, we know earlier in detail in "Composition –
“has-a” Relationship". Other name of composition is aggregation.
Suppose take another example, say car. A car HAS-A engine, which states
in car object we will define engine object.
Observe the code where properties for a Student object is given using a
constructor at the time of object creation.
Let us repeat the same code with methods, say setter methods (in Spring,
it is known as setter injection; injecting the properties to an object
through setter methods).
All methods of an interface must be public and abstract (by default takes
also if not mentioned). As static methods should have a body, the
interface methods cannot be static.
Put the same question for an interface. Everyone says anonymously, "no"
because there is no implementation (body) of methods as all are abstract.
Coming to an abstract class, the question arises as one case variation of
abstract class is that it can contain all abstract methods. I mean, an
abstract class with all concrete (non-abstract) methods. People ask (of
course it is a good question for interviews also for freshers) why we
cannot create an instance of an abstract class when all methods are non-
abstract.
Can you force an abstract class to contain only abstract methods? No,
designers did not provide a way. In general, you cannot create an
instance of an abstract class. The same rule applies for all the three
variations of abstract class – a) containing all concrete methods b)
containing all abstract methods and c) containing a mixture of abstract
and concrete methods.
interface Test
{
void greet();
}
public class Demo
{
public static void main(String[] args)
{
Test t = new Test()
{
public void greet()
{
System.out.print("\nHi, Best wishes to way2java.com\n");
}
};
t.greet();
}
}
Let us answer one more question.
Can we create an object of abstract class where all methods are non-
abstract (concrete)? Answer for this is also "no". The answer for this is
already discussed in Can we instantiate an abstract class?
In Java, the execution starts from main() method. But for compilation,
main() is not required. Java's main() method syntax is quiet different
from C/C++.
Every word in the above statement has got a meaning to the JVM.
1. public: It is a keyword and denotes that any other class (JVM) can
call the main() method without any restrictions.
2. static: It is a keyword and denotes that any other class (JVM) can
call the main() method without the help of an object. More about static
is available at static Keyword – Philosophy.
3. void: It is a keyword and denotes that the main() method does not
return a value.
The Java program under execution takes some context area (execution area)
in the RAM. JVM is in another context area. To call the main(), the JVM
requires an object. When the JVM has not entered into the program, how it
can create an object or get an object. To overcome this, allow the JVM to
access the main() without object just by declaring static. Once the JVM
enters, it can create hundreds of objects later.
Whether you pass right now command-line arguments or not, you must have
the string array as parameter as it is the part of syntax.
Any word is missed in the above statement, the program compiles, but does
not execute.
A program using main() is discussed in "Basic Class Structure,
Compilation and Execution".
Static Constructor::
Java does not permit to declare a constructor as static. Following are
the reasons.
1. Static means for the same class. For example, static methods cannot be
inherited.
Observe, the compiler error message. It says, static is not allowed with
constructor.
Private Constructor::
Declaring a private constructor is a very rare usage. First of all can we
do it?
class Test
{
private Test()
{
System.out.println("I am default private constructor");
}
}
public class Demo
{
public static void main(String args[])
{
Test t1 = new Test();
}
}
The Demo class cannot create an object of Test in its main() method.
Observe the screenshot about the compiler message. If the constructor is
not private, the Demo can do it within no time as usual.
Overload Main::
Method overloading is nothing but using the same method in the same class
a number of times with different parameters. Just like any other method,
the main() method also can be overloaded. Following program llustrates.
The JVM does not find ambiguity to call which main() method is to be
called. It knows clearly, it requires such main() that includes the
parameter String args[]. Other main() methods are treated as user-
defined. As all the main() methods are static in the above code, they are
called without the help of an object.
The question is can you have a main() method in the abstract class. Yes,
definitely, because main() is a concrete method and abstract class allows
concrete methods. But what you can you do with the main() when you are
not allowed to create objects of abstract classes. But, you can create
objects of another class and use other class methods by composition.
class Test
{
int x = 10;
public void display()
{
System.out.println("Hello 1");
}
}
public abstract class Demo
{
public static void main(String args[])
{
Test t1 = new Test();
System.out.println("From abstract class main(): " + t1.x);
t1.display();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Snake // this program does not
compile
{
void swim()
{
System.out.println("Swims with the whole body");
}
}
class Duck extends Snake
{
void swim()
{
System.out.println("Swims with legs");
}
}
class Fish extends Snake
{
void swim()
{
System.out.println("Swims with fins");
}
}
// once class extending two classes
public class Animal extends Duck, Fish
{
public static void main(String args[])
{
Animal a1 = new Animal();
a1.swim();
}
}
diagramm
interface Snake
{
public abstract void swim();
}
interface Duck extends Snake // between two interfaces, it is
extends and not implements
{
public abstract void swim();
}
interface Fish extends Snake
{
public abstract void swim();
}
public class Animal implements Duck, Fish
{
public void swim()
{
System.out.println("Swim with legs and hands");
}
public static void main(String args[])
{
Animal a1 = new Animal();
a1.swim();
}
}
How the ambiguity diamond problem solved now through interfaces (an idea
taken from Objective C)? Interface methods being abstract do not carry
any body of implementation. So, Animal is inheriting the same three
swim() methods (can I call dummy methods, fancily) from its three parents
without implementation. As the method is the same, the subclass Animal
gives the body as it likes. Compiler thinks all the three swim methods
are overridden.
class Snake
{
void swim()
{
System.out.println("Swims with the whole body");
}
}
class Duck extends Snake
{
void swim()
{
System.out.println("Swims with legs");
}
}
class Fish extends Duck
{
void swim()
{
System.out.println("Swims with fins");
}
}
public class Animal extends Fish
{
public static void main(String args[])
{
Animal a1 = new Animal();
a1.swim();
}
}
diagram
The above swim() method prints "Swims with fins". Then how the Animal
uses Duck or Snake’s swim() methods. Simply use composition as follows.
Duck d1 = new Duck();
d1.swim();
or
Snake s1 = new Snake();
s1.swim();
Another reason for avoidance is Java would like to discard the problems
of object casting between super classes and subclasses, ambiguity in
constructor chaining etc.
Java is relatively a very simple language to use compared C/C++ with the
non-support of complex and confusing features like pointers, multiple
inheritance and operator overloading. These features are rarely used in
practice and at the same time poorly understood by the language
beginners.
It is a good design move, the Java designers adapted. Java also proved
that a language can exist happily without the support of operator
overloading.
Java designers keep only two things in their mind while language is being
developed – a) to make programming simple to practice and 2) to increase
performance.
1. The first and very important reason is the security. The concept of
Pointers in C-lang is often misused and is probably the biggest reason
for people considering C-lang a complicated programming language.
The creators of Java did not like to introduce this complexity into their
programming language and intentionally excluded the concept of pointers.
This was an intentional decision by the creators of Java, because most
people would agree that having pointers creates a lot of potential for
bugs in the code – pointers can be quite confusing, especially to new
programmers. Because arrays and strings are given the status of classes
with methods of manipulating the elements, there is no need for pointers
to those constructs.
For example, pointers allow the other function values to change which the
function may not like. For example, some function would like the $ value
as Rs.61.5. The other function may change the value of $ with pointer
support. Then the original function looses its value integrity.
With the introduction of the JVM, the use of GC has eliminated the need
to explicitly de-allocate memory like in C/C++. The explicit means of de-
allocating memory from an object in Java is handled implicitly by the GC
daemon thread, which means that an object that reaches out of scope in
memory is automatically sent to the GC for garbage collection. This
feature of Java coupled with the original intent of the creators made it
a necessity to eliminate complexity and thus introduced a more managed
approach to dynamic memory.
In Java we have references which are close to pointers but not same.
References store the address of the object in memory. Pointers can be
manipulated (like arithmetic operations of addition etc.) but references
cannot be manipulated.
Many think that abstract methods are waste and interfaces are still more
waste. If you understand correctly, you find their immense usage. Let us
see one.
Interface is like a blue print for a house to construct. Using the blue
print we construct the house. Blue print (paper) is not itself a house.
Similarly, interface gives a blue print (template) of methods from which
new classes can be developed easily.
Java Class vs Interface::
Class
Interface
Supports only multilevel and hierarchical inheritances but not multiple
inheritance Supports all types of inheritance – multilevel, hierarchical
and multiple
"extends" keyword should be used to inherit "implements" keyword should
be used to inherit
Should contain only concrete methods (methods with body) Should contain
only abstract methods (methods without body)
The methods can be of any access specifier (all the four types) The
access specifier must be public only
Methods can be final and static Methods should not be final and static
Variables can be private Variables should be public only
Can have constructors Cannot have constructors
Can have main() method Cannot have main() method as main() is a concrete
method
Know also the differences between abstract class vs interface.
After learning "what is class in Java", let us go to see how many types
of classes exist in Java.
1. Classes
Java comes with classes and abstract classes. What we call, generally a
class in Java, is known as concrete class. Other way, to say, a Java
class which is not abstract, is a concrete class. A concrete class can be
final also.
After going though the above link, follow the following links in an order
to know about other classes.
2. Abstract Classes
3. Interfaces
class Employee
{ // starting brace of the class
(delimiter)
int empid; // variables
String name; // three are given here
double salary;
Employee() // constructor
{
// some code here that assigns
values to the above 3 variables
}
Java supports two types of castings – primitive data type casting and
reference type casting. Reference type casting is nothing but assigning
one Java object to another object. It comes with very strict rules and is
explained clearly in Object Casting. Now let us go for data type casting.
Implicit casting
Explicit casting
Boolean casting.
Examples:
double x = 10.5;
int y = (int) x;
The double x is explicitly converted to int y. The thumb rule is, on both
sides, the same data type should exist.
3. Boolean casting
boolean x = true;
int y = x; // error
boolean x = true;
int y = (int) x; // error
byte –> short –> int –> long –> float –> double
double d2 = 66.0;
char ch2 = (char) d2;
System.out.println(ch2); // prints B
}
}
Object casting (reference casting) discusses casting between objects of
different classes involved in inheritance.
After knowing the Java rules of Data Type Casting (Type Conversion), let
us cast byte to short. The byte takes 1 byte of memory and short takes
two bytes of memory. Assignment 1 byte value to 2 bytes is done
implicitly by the JVM.
byte –> short –> int –> long –> float –> double
The left-side value can be assigned to any right-side value and is done
implicitly. The reverse requires explicit casting.
Examples:
short x = 10;
int y = x;
byte x = 10;
short y = x;
Following program explains.
After knowing primitive data types and Java rules of Data Type Casting
(Type Conversion), let us cast short to byte. The byte takes 1 byte of
memory and short takes 2 bytes of memory. Assigning 2 bytes of memory to
1 byte of memory requires explicit casting.
byte –> short –> int –> long –> float –> double
The left-side value can be assigned to any right-side value and is done
implicitly. The reverse like short to byte requires explicit casting.
Examples of implicit casting
short x = 10;
int y = x;
byte x = 10;
short y = x;
The short s1 is explicitly type casted to byte b1. Observe, the syntax of
explicit casting. On both sides, it should be byte.
•
Java int to long:
After knowing primitive data types and Java rules of Data Type Casting
(Type Conversion), let us cast int to long. The int takes 4 byte of
memory and long takes 8 bytes of memory. Assignment 4 bytes of memory to
8 byte of memory is done implicitly (automatic conversion).
byte –> short –> int –> long –> float –> double
The left-side value can be assigned to any right-side value and is done
implicitly. The reverse like long to int requires explicit casting.
int x = 10;
longt y = x;
byte x = 10;
short y = x;
long l1 = i1;
Advantages of Packages
With a single import statement, all the classes and interfaces can be
obtained into our program.
Unlike a header file, Java permits to import even a single class also.
Avoids namespace problems. Two classes of the same name cannot be put in
the same package but can be placed in two different packages.
Access between the classes can be controlled. Using packages,
restrictions can be imposed on the access of other package classes.
Access specifiers work on package boundaries (between the classes of
other packages).
We can find all the related classes and interfaces in a single space.
Searching and identification will be easier.
Packages and sub-packages are the easiest way to organize the classes.
Importing All/Single Class
By placing the same class in two different packages, which Java permits,
namespace problems can be solved. Namespace is the area of execution of a
program in RAM. The Date class exists in two packages – java.util and
java.sql. Importing these two packages in a program gives ambiguity
problem to the compiler. In the following program compiler gets ambiguity
problem and is solved with fully-qualified name.
import java.util.*;
import java.sql.*;
Note: When fully qualified name is included, importing the package is not
necessary.
Like identifiers have conventions, the packages come with their own
naming conventions. Like keywords and protocols, packages are also of
lowercase letters. In a single project, a number of programmers may be
involved assigned with different modules and tasks. To avoid namespace
problems in storing their work, naming conventions are followed. While
creating packages, they may follow company name, project name or personal
name etc. to precede their package. Following are a few examples.
All the classes and interfaces that come with the installation of JDK are
put together are known as Java API (Application Programming Interface).
All the Java API packages are prefixed with java or javax. Following
table gives some important packages, a few prominent classes and their
functionality.
Java is a friendly language and permits to create our own packages and
use in programming. We know earlier, Java allows us to create our
exceptions. Creating packages are indispensable in project development
where number of developers are involved doing different modules and
tasks. We know packages avoid name collision problems. Package naming
conventions are very helpful to locate the applications developed by a
single individual or team.
1
2
3
4
5
6
7
8
9
10
package forest;
import java.util.*;
public class Tiger
{
public void getDetails(String nickName, int weight)
{
System.out.println("Tiger nick name is " + nickName);
System.out.println("Tiger weight is " + weight);
}
}
Order of Package Statement
The above program codingwise is very simple but is important to know the
steps of package creation.
package forest;
import java.util.*;
public class Tiger
Package statement
Import statement
Class declaration
If exists, the package statement must be first one in the program. If
exists, the import statement must be the second one. Our class
declaration is the third. Any order changes, it is a compilation error.
When the code is ready, the next job is compilation. We must compile with
package notation. Package notation uses –d compiler option as follows.
3rd Step: Now finally, write a program from the target directory
D:/sumathi and access the package.
import forest.Tiger;
public class Animal
{
public static void main(String args[])
{
Tiger t1 = new Tiger ();
t1.getDetails("Everest", 50);
}
}
The compilation and execution is as usual as follows.
import forest.*;
To work with the above statement, remove the source file Tiger.java file
from C:\snr directory; else use as import forest.Tiger.
1. With a simple import statement, all the classes and interfaces can
be imported.
2. Java includes a provision to import only one class from a package.
3. It avoids namespace problems (name conflicts). Two classes with the
same name cannot be put in the same package but can be put in two
different packages because a package creates its own namespace (folder).
4. Access for the classes can be controlled.
5. Classes and interfaces of same functionality can be grouped
together.
6. Because functionally all the classes are related, later their
identification and determining the location become easier.
7. Java packages are used to group and organize the classes.
Java permits to import all the classes or only one class from a package.
C-lang does not have this facility of including only one function from a
header file.
import java.util.Stack; //
imports only Stack class
import java.awt.event.ActionEvent; // imports only
ActionEvent class
// observe, no asterisk, *
Importing Classes – Different Approaches
Fully qualified name includes writing the names of the packages along
with the class name as follows.
java.awt.event.ActionListener
java.util.Stack
This way of using may not look nice when we use the same class a number
of times in the code as readability becomes boredom. This will be a nice
approach and justified when the class is used only once.
import java.awt.event.ActionListener;
import java.util.Stack;
This type of approach is the best and beneficial when only one class is
required from the same package. Importing one class (when other classes
are not required) saves a lot of RAM space usage on the client’s machine.
import java.awt.event.*;
import java.util.*;
The asterisk (*) mark indicates all the classes and interfaces of the
package. After importing, the objects of the cl
asses can be created straightaway.
This type of approach is beneficial when many classes and interfaces are
required from a package.
Access specifiers, as the name indicates, specify the access to our code
for other classes – whether other classes can access or not and if
permitted, to what extent they can access. Java includes access modifiers
also which are quiet different from access specifiers.
public
protected
default
private
All the Access specifiers are keywords and thereby should be written in
lowercase letters only. Java does not have the confusing combinations of
public protected etc. which C++ does. All specifiers are straight to
their meaning. To understand the specifiers easily, let us take a small
scenario where two packages exist – animal and bird. Let us imagine two
classes Lion and Tiger exist in animal package and Parrot and Peacock
exist in bird package. It is illustrated in the following figure.
Let us think that there exists a method called void eat() in the Tiger
class of animal package. Now the question is who can access this eat()
method; Lion of same package or Peacock of different package. The access
specifiers, in Java, act on package boundaries.
1. public
1. It can be accessed by the classes of the same package. That is, Lion
of the same package can access it.
2. It can also be accessed by the classes of other packages also. That
is, Peacock of other package also can access.
2. protected
3. default
Let us assume that the eat() method is default. Default means we do not
specify any specifier at all; that is we write simply void eat() without
any specifier.
The specifiers, public, protected and default does not make any
difference for the classes of the same package, but makes to the classes
of other packages only. We can say that access specifiers act on package
boundaries.
Note: Actually there exist a default keyword in Java, but used with
switch statement. Do not get confused here with the default specifier.
4. private
When we look into "/java/awt>" with dir command, the OS shows the files
and subdirectories of awt. It shows clearly that event subdirectory
exists; but it is not opened. To see the files of event directory, we
must go to "/java/awt/event>" and give the dir command.
That is, with java.awt, the event subpackage is imported but it classes
are not opened and thereby not available to the program. To use the
classes of event sub package, it is necessary to import explicitly
java.awt.event package; else compiler raises error saying "cannot resolve
symbol".
Every version adds new packages and classes. JDK 1.5 version started its
work under the codename Project Tiger and the version was released on
September, 2004. JDK 1.5 version adds the following features to Java
language. These features are programmatically very important.
Autoboxing
Generics
Enhanced for loop
Varargs
Enums
Static imports
C-lang printf()
StringBuilder
Metadata
Autoboxing – Automatic Conversion
Upto JDK 1.4, all the data structures of Java stores only objects and
when retrieved returns objects. The problem is, even simple data types
are to be converted into objects (using wrapper classes) and stored. The
retrieved objects are to be converted back to data types to use in
arithmetic operations in coding. This is a big nuisance to the
programmer. This is overcome in JDK 1.5 with the introduction of
autoboxing concept. Autoboxing permits to store data types directly in DS
and retrieve back data types. Autoboxing is discussed clearly in data
structures topic.
Generally to print the values, we take a for loop. The for loop includes
initialization, test condition and incrementing/decrementing. These are
avoided in enhanced for loop and this loop works in arrays and DS only.
enhanced for loop is illustrated in data structures topic.
The Varargs concept permits the user to pass any number of arguments to a
method depending on the requirement at runtime. The arguments are stored
as an array internally. Following program illustrates.
Enums
switch(es)
{
case HIGH:
System.out.println("High salary"); break;
case MEDIUM:
System.out.println("Medium salary"); break;
case LOW:
System.out.println("Low salary"); break;
case POOR:
System.out.println("Poor salary");
}
}
}
switch(es)
Static Imports
Many methods of classes like Math and Character are static. If the
variables and methods of these classes are used very often, all are must
be prefixed with Math or Character which is tedious. To overcome this,
the JDK 1.5 comes with static imports. With static imports, the static
keyword need not be used in coding as in the following program.
ceil(), floor(), pow are the static methods of Math class and PI is a
static variable. All these are used without using prefix Math name.
nf1.setMinimumFractionDigits(2);
nf1.setMaximumFractionDigits(5);
The first statement gives two minimum decimal points and the second
statement gives five maximum decimal points. They are given if required
only.
High-performance StringBuilder
Observe.
There are two display() methods with public and private. These two words
give permissions to other classes to access display() method. public
means any class from anywhere can access (like a public park; any one can
enter or leave without ticket). private means not accessible to other
classes; the method can be used by the same class (in which it is
declared, like a private property used by the same family for which it
belongs). Now I think it is clear. The public and private are known as
access specifiers because they specify the access.
1
2
3
4
5
6
7
8
class Test
{
public void display() { }
}
class Demo extends Test
{
public void display() { }
}
In the above code, the display() method of Test class is overridden by
Demo class. Infact, Demo class is at liberty to override or not. Now let
us apply a small modifier to display() method of Test class. See the
following code.
1
2
3
4
5
6
7
8
class Test
{
public final void display() { }
}
class Demo extends Test
{
public void display() { }
}
In the super class Test, observe, the display() method is added with
final keyword. In the super class, if a method is declared as final, it
cannot be overridden by subclass. That is, super class by declaring
method as final does not allow the subclass to override. This is the
modification given to the method in super class with final. final is
known as access modifier.
Now let us see one more modifier to have better understanding. Observe
the following code.
class Demo
{
int marks = 50;
static int price = 70;
public static void main(String args[])
{
Demo d1 = new Demo();
System.out.println(d1.marks); // marks called with object d1
System.out.println(price); // price called without object d1
}
}
In Demo class, marks is a non-static variable and price is static
variable. marks (non-static variable) requires object to call from main()
method where as static variable price does not require object. So, now
what is the modification static gave. static modifies the access and
gives the facility to call without the help of an object.
I am sure, you are very clear with the difference between specifier and
modifier.