Introduction To Java
Introduction To Java
INTRODUCTION TO JAVA
Importance of JAVA
Java enables users to develop applications on the internet for servers, desktops
computers and small hand-held devices.
The future of computing is being influenced by the internet, and Java promises to
remain a pig part of the future.
Java is developed to be simple, object-oriented, distributed, interpreted, robust, secure,
architecture-natural, portable, high-performance, multi-threaded and dynamic.
Java is a full-featured, general purpose programming language that is capable of
developing robust applications.
Principles of OOPS
Abstraction
Abstraction is a way to remove the association of the behavior of an object with the actual details behind
the scenes which implement that object's behavior.
This 'abstraction' is usually accomplished through the use of base classes with virtual functions; each
derived function provides the details that implement the behavior behind that abstraction.
A simple example is using a base class "Animal", with a virtual function "Walk". In the case two-legged
versus four-legged animals, both of them walk, but the actual mechanics are different. The "Walk"
method abstracts the actual mechanics behind the walking that each "Animal" does.
Polymorphism
This ability of different objects to respond each in its own way to identical messages is called
polymorphism.
Polymorphism results from the fact that every class lives in its own name space. The names assigned
within a class definition won't conflict with names assigned anywhere outside it. This is true both of the
instance variables in an object's data structure and of the object's methods:
Just as the fields of a C structure are in a protected name space so are an object's instance variables.
Method names are also protected. Unlike the names of C functions method names aren't global symbols.
The name of a method in one class can't conflict with method names in other classes; two very different
classes could implement identically named methods.
Method names are part of an object's interface. When a message is sent requesting an object to do
something the message names the method the object should perform. Because different objects can have
different methods with the same name the meaning of a message must be understood relative to the
particular object that receives the message. The same message sent to two different objects could invoke
two different methods.
The main benefit of polymorphism is that it simplifies the programming interface. It permits conventions
to be established that can be reused in class after class. Instead of inventing a new name for each new
function you add to a program the same names can be reused. The programming interface can be
described as a set of abstract behaviors quite apart from the classes that implement them.
Inheritance
The easiest way to explain something new is to start with something old. If you want to describe what a
``schooner'' is it helps if your listeners already know what ``sailboat'' means. If you want to explain how a
harpsichord works it's best if you can assume your audience has already looked inside a piano or has seen
a guitar played or at least is familiar with the idea of a ``musical instrument.''
The same is true if want to define a new kind of object; the description is simpler if it can start from the
definition of an existing object.
With this in mind object-oriented programming languages permit you to base a new class definition on a
class already defined. The base class is called a superclass; the new class is its subclass. The subclass
definition specifies only how it differs from the superclass; everything else is taken to be the same.
Nothing is copied from superclass to subclass. Instead the two classes are connected so that the subclass
inherits all the methods and instance variables of its superclass much as you want your listener's
understanding of ``schooner'' to inherit what they already know about sailboats. If the subclass definition
were empty (if it didn't define any instance variables or methods of its own) the two classes would be
identical (except for their names) and share the same definition. It would be like explaining what a
``fiddle'' is by saying that it's exactly the same as a ``violin.'' However the reason for declaring a subclass
isn't to generate synonyms but to create something at least a little different from its superclass. You'd
want to let the fiddle play bluegrass in addition to classical music.
Encapsulation
To design effectively at any level of abstraction you need to be able to leave details of implementation
behind and think in terms of units that group those details under a common interface. For a programming
unit to be truly effective the barrier between interface and implementation must be absolute. The interface
must encapsulate the implementation--hide it from other parts of the program. Encapsulation protects an
implementation from unintended actions and inadvertent access.
In C a function is clearly encapsulated; its implementation is inaccessible to other parts of the program
and protected from whatever actions might be taken outside the body of the function. Method
implementations are similarly encapsulated but more importantly so are an object's instance variables.
They're hidden inside the object and invisible outside it. The encapsulation of instance variables is
sometimes also called information hiding.
It might seem at first that hiding the information in instance variables would constrain your freedom as a
programmer. Actually it gives you more room to act and frees you from constraints that might otherwise
be imposed. If any part of an object's implementation could leak out and become accessible or a concern
to other parts of the program it would tie the hands both of the object's implementor and of those who
would use the object. Neither could make modifications without first checking with the other.
Suppose for example that you're interested in the Faucet object being developed for the program that
models water use and you want to incorporate it in another program you're writing. Once the interface to
the object is decided you don't have to be concerned as others work on it fix bugs and find better ways to
implement it. You'll get the benefit of these improvements but none of them will affect what you do in
your program. Because you're depending solely on the interface nothing they do can break your code.
Your program is insulated from the object's implementation.
Moreover although those implementing the Faucet object would be interested in how you're using the
class and might try to make sure that it meet your needs they don't have to be concerned with the way
you're writing your code. Nothing you do can touch the implementation of the object or limit their
freedom to make changes in future releases. The implementation is insulated from anything that you or
other users of the object might do.
* Identity
* Classification
* Polymorphism
* Inheritance
Identity:
The term Object Oriented means that we organize the software as a collection of
discrete objects. An object is a software package that contains the related data and the
procedures. Although objects can be used for any purpose, they are most frequently
used to represent real-world objects such as products, customers and sales orders. The
basic idea is to define software objects that can interact with each other just as their real
world counterparts do, modeling the way a system works and providing a natural
foundation for building systems to manage that business.
Classification:
In principle, packaging data and procedures together makes perfect sense. In practice,
it raises an awkward problem. Suppose we have many objects of the same general
type- for example a thousand product objects, each of which could report its current
price. Any data these objects contained could easily be unique for each object. Stock
number, price, storage dimensions, stock on hand, reorder quantity, and any other
values would differ from one product to the next. But the methods for dealing with these
data might well be the same. Do we have to copy these methods and duplicate them in
every object?
No, this would be ridiculously inefficient. All object-oriented languages provide a simple
way of capturing these commonalties in a single place. That place is called a class. The
class acts as a kind of template for objects of similar nature.
Polymorphism:
Polymorphism is a Greek word meaning ¡§many forms¡¨. It is used to express the fact
that the same message can be sent to many different objects and interpreted in different
ways by each object. For example, we could send the message "move" to many
different kinds of objects. They would all respond to the same message, but they might
do so in very different ways. The move operation will behave differently for a window
and differently for a chess piece.
Inheritance:
Objects and classes are a fundamental part of object-orientated programming, and therefore
Java. A class contains both data (referred to as attributes), and executable code (referred to as
methods). In the previous tutorial, we created a class that contained a single method ' main '.
When the class was executed, the main method was called, and the application ran as a normal
program. While it is possible to use only a single class in a Java project, this is not good practice
for large applications. The power object-orientation lies in breaking tasks down into simpler
components that perform logically related tasks. Even a moderately complex program should
be composed of many classes, which interact with each other.
A Java method is a set of Java statements which can be included inside a Java class.
Here is the main() method from a Java program which prints "Hello World":
23736839
Classes
A class is a structure that defines the data and the methods to work on that data. When you write
programs in the Java language, all program data is wrapped in a class, whether it is a class you
write or a class you use from the Java platform API libraries.
The ExampleProgram class from the simple program in the first lesson of Part 1 is a
programmer-written class that uses the java.lang.System class from the Java platform API
libraries to print a character string to the command line.
class ExampleProgram {
public static void main(String[] args){
System.out.println("I'm a simple Program");
}
}
Classes in the Java platform API libraries define a set of objects that share a common structure
and behavior. The java.lang.System class used in the example defines such things as standard
input, output, and error streams, and access to system properties. In contrast, the
java.lang.String class defines character strings.
In the example, you do not see an explicit use of the String class, but in the Java language, a
character string can be used anywhere a method expects to receive a String object. During
execution, the Java platform creates a String object from the character string passed to the
System.out.println call, but your program cannot call any of the String class methods
because it did not instantiate the String object.
If you want access to the String methods, you can rewrite the example program to create a
String object as follows. This way, you can call a method such as the String.concat method
that adds text to the original string.
class ExampleProgram {
public static void main(String[] args){
String text = new String("I'm a simple Program ");
System.out.println(text);
String text2 = text.concat(
"that uses classes and objects");
System.out.println(text2);
}
}
Objects
An instance is an executable copy of a class. Another name for instance is object. There can be
any number of objects of a given class in memory at any one time.
In the last example, four different String objects are created for the concatenation operation,
text object, text2 object, and a String object created behind the scenes from the " that uses
classes and objects" character string passed to the String.concat method.
Besides the String object, there is an instance of the ExampleProgram.java class in memory as
well.
The System class is never instantiated by the ExampleProgram class because it contains only
static variables and methods, and therefore, cannot be instantiated by a program, but it is
instantiated behind the scenes by the Java virtual machine1 (VM).
MethodBinding
Calling a non-virtual method, decided at a compile time is known as early binding or static
binding.
Calling a virtual method (Pure Polymorphism), decided at a runtime is known as late binding or
dynamic binding
Static Method Binding —
If the compiler can resolve the binding at the compile time only then such a binding is called
Static Binding or Early Binding. All the instance method calls are always resolved at runtime,
but all the static method calls are resolved at compile time itself and hence we have static
binding for static method calls. Because static methods are class methods and hence they can
be accessed using the class name itself (in fact they are encourgaed to be used using their
corresponding class names only and not by using the object references) and therefore access
to them is required to be resolved during compile time only using the compile time type
information. That's the reason why static methods can not actually be overriden. Read more -
Can you override static methods in Java?
Similarly, access to all the member variables in Java follows static binding as Java doesn't
support (in fact, it discourages) polymorphic behavior of member variables. For example:-
class SuperClass{
...
public String someVariable = "Some Variable in SuperClass";
...
}
System.out.println(superClass1.someVariable);
System.out.println(superClass2.someVariable);
...
Output:-
Some Variable in SuperClass
Some Variable in SuperClass
Dynamic Binding refers to the case where compiler is not able to resolve the call and the
binding is done at runtime only. Let's try to understand this. Suppose we have a class named
'SuperClass' and another class named 'SubClass' extends it. Now a 'SuperClass'
reference can be assigned to an object of the type 'SubClass' as well. If we have a method
(say 'someMethod()') in the 'SuperClass' which we override in the 'SubClass' then a call
of that method on a 'SuperClass' reference can only be resolved at runtime as the compiler
can't be sure of what type of object this reference would be pointing to at runtime.
...
SuperClass superClass1 = new SuperClass();
SuperClass superClass2 = new SubClass();
...
Here, we see that even though both the object references superClass1 and superClass2
are of type 'SuperClass' only, but at run time they refer to the objects of types
'SuperClass' and 'SubClass' respectively.
Hence, at compile time the compiler can't be sure if the call to the method 'someMethod()'
on these references actually refer to which version of the method - the super class version or
the sub class version.
Thus, we see that dynamic binding in Java simply binds the method calls (inherited methods
only as they can be overriden in a sub class and hence compiler may not be sure of which
version of the method to call) based on the actual object type and not on the declared type
of the object reference.
Method Overloading
In Java it is possible to define two or more methods within the same class that share the same
name, as long as their parameter declarations are different. When this is the case, the methods are
said to be overloaded, and the process is referred to as method overloading. Method overloading
is one of the ways that Java implements polymorphism.
If you have never used a language that allows the overloading of methods, then the concept may
seem strange at first. But as you will see, method overloading is one of Java's most exciting and
useful features. When an overloaded method is invoked, Java uses the type and/or number of
arguments as its guide to determine which version of the overloaded method to actually call.
Thus,
overloaded methods must differ in the type and/or number of their parameters. While overloaded
methods may have different return types, the return type alone is insufficient to distinguish two
versions of a method. When Java encounters a call to an overloaded method, it simply executes
the version of the method whose parameters match the arguments used in the call. Here is a
simple example that illustrates method overloading:
No parameters
a: 10
a and b: 10 20
double a: 123.2
Result of ob.test(123.2): 15178.24
Exceptions
An exception is an event that occurs during the execution of a program that disrupts the normal
flow of instructions.
Java exception classes are organised into a hierarchy. There is a basic exception class called
Exception as you might expect. But in fact, the base of the hierarchy starts not with Exception
but with a class called Throwable, which is then subclassed into Exception and Error
Exception subclasses represent errors that a program can reasonably recover from. Except
for RuntimeException and its subclasses (see below), they generally represent errors that
a program will expect to occur in the normal course of duty: for example, network
connection errors and filing system errors.
Error subclasses represent "serious" errors that a program generally shouldn't expect to
catch and recover from. These include conditions such as an expected class file being
missing, or an OutOfMemoryError.
RuntimeException is a further subclass of Exception. RuntimeException and its
subclasses are slightly different: they represent exceptions that a program shouldn't
generally expect to occur, but could potentially recover from. They represent what are
likely to be programming errors rather than errors due to invalid user input or a badly
configured environment.
The first step in constructing an exception handler is to enclose the code that might throw an
exception within a try block. In general, a try block looks like the following.
try {
code
}
catch and finally blocks . . .
The segment in the example labeled code contains one or more legal lines of code that could
throw an exception. (The catch and finally blocks are explained in the next two subsections.)
To construct an exception handler for the writeList method from the ListOfNumbers class,
enclose the exception-throwing statements of the writeList method within a try block. There
is more than one way to do this. You can put each line of code that might throw an exception
within its own try block and provide separate exception handlers for each. Or, you can put all
the writeList code within a single try block and associate multiple handlers with it. The
following listing uses one try block for the entire method because the code in question is very
short.
try {
System.out.println("Entered try statement");
out = new PrintWriter(new FileWriter("OutFile.txt"));
for (int i = 0; i < SIZE; i++) {
out.println("Value at: " + i + " = "
+ vector.elementAt(i));
}
}
catch and finally statements . . .
If an exception occurs within the try block, that exception is handled by an exception handler
associated with it. To associate an exception handler with a try block
}
Each catch block is an exception handler and handles the type of exception indicated by its
argument. The argument type, ExceptionType, declares the type of exception that the handler
can handle and must be the name of a class that inherits from the Throwable class. The handler
can refer to the exception with name.
The catch block contains code that is executed if and when the exception handler is invoked.
The runtime system invokes the exception handler when the handler is the first one in the call
stack whose ExceptionType matches the type of the exception thrown. The system considers it a
match if the thrown object can legally be assigned to the exception handler's argument.
The following are two exception handlers for the writeList method — one for two types of
checked exceptions that can be thrown within the try statement.
try {
} catch (FileNotFoundException e) {
System.err.println("FileNotFoundException: "
+ e.getMessage());
throw new SampleException(e);
} catch (IOException e) {
System.err.println("Caught IOException: "
+ e.getMessage());
}
Both handlers print an error message. The second handler does nothing else. By catching any
IOException that's not caught by the first handler, it allows the program to continue executing.
The finally Block
The finally block always executes when the try block exits. This ensures that the finally
block is executed even if an unexpected exception occurs. But finally is useful for more than
just exception handling — it allows the programmer to avoid having cleanup code accidentally
bypassed by a return, continue, or break. Putting cleanup code in a finally block is always a
good practice, even when no exceptions are anticipated.
Note: If the JVM exits while the try or catch code is being executed, then the finally block
may not execute. Likewise, if the thread executing the try or catch code is interrupted or killed,
the finally block may not execute even though the application as a whole continues.
The try block of the writeList method that you've been working with here opens a
PrintWriter. The program should close that stream before exiting the writeList method. This
poses a somewhat complicated problem because writeList's try block can exit in one of three
ways.
The runtime system always executes the statements within the finally block regardless of what
happens within the try block. So it's the perfect place to perform cleanup.
The following finally block for the writeList method cleans up and then closes the
PrintWriter.
finally {
if (out != null) {
System.out.println("Closing PrintWriter");
out.close();
} else {
System.out.println("PrintWriter not open");
}
}
In the writeList example, you could provide for cleanup without the intervention of a finally
block. For example, you could put the code to close the PrintWriter at the end of the try block
and again within the exception handler for ArrayIndexOutOfBoundsException, as follows.
try {
} catch (FileNotFoundException e) {
out.close(); //Don't do this; it duplicates code.
System.err.println("Caught: FileNotFoundException: "
+ e.getMessage());
throw new RuntimeException(e);
} catch (IOException e) {
System.err.println("Caught IOException: "
+ e.getMessage());
}
However, this duplicates code, thus making the code difficult to read and error-prone should you
modify it later. For example, if you add code that can throw a new type of exception to the try
block, you have to remember to close the PrintWriter within the new exception handler
UNIT-2
A member of a class has an identifier as its name. For now, we will require all such names to be
unique within a class. We will slightly relax this restriction when we discuss overloading in
Section Each member name must conform to the syntactic rules given for variables.
Java objects are a generalization of Scheme structs, because the collection of operations
(methods) that operate on the instances of a class is determined by the class definition. In
Scheme, the set of operations for manipulating a struct is fixed (a constructor, a recognizer, field-
accessors, and field-modifiers).
The following Java program text defines a class Entry suitable for representing entries in the
class Entry {
/* fields */
String name;
String address;
String phone;
/* constructor */
Entry(String n, String a, String p) {
this.name = n;
this.address = a;
this.phone = p;
}
/* accessors */
String getName() { return this.name; }
String getAddress() { return this.address; }
String getPhone() { return this.phone; }
}
This class is the Java analog of the Scheme structure definition
where the name, address and phone fields are always bound to strings.
Java Buzzwords
· Simple
· Secure
· Portable
· Object-oriented
· Robust
· Multithreaded
· Architecture-neutral
· Interpreted
· High performance
· Distributed
· Dynamic
Simple
Java was designed to be easy for the professional programmer to learn and use effectively.
Assuming that you have some programming experience, you have some programming
experience, you will not find java hard to master. If you already understand the basic concepts of
object-oriented programming, learning java will be even easier. Best of all, if you are an
experienced C++ programmer, moving to java will require very little effort. Because java
inherits the C/C++ syntax and many of the object-oriented features of C++, most programmers
have little trouble learning java. Also, some of the more confusing concepts from C++ are either
left out of java or implemented in a cleaner, more approachable manner.
Secure
Java's robustness features help to make it secure, as do the limitations on the access that Java
applets have the local machine on which they are running.
Java's portability derives (once again) largely from its platform-independent byte code format.
But portablility is also supported by the fact that the language has, in general, no system-
dependent features. For example, all primitive data types are required to have the same sizes on
all platforms.
Object-Oriented
Although influenced by its predecessors, java was not designed to be source-code compatible
with any other language. This allowed the java team the freedom to design with a blank slate.
One outcome of this was a clean, usable, pragmatic approach to objects. Borrowing liberally
from many seminal object-software environments of the last few decades, java manages to strike
a balance between the purist’s “everything is an object” paradigm and the pragmatist’s “stay out
of my way” model. The object model in java is simple and easy to extend, while simple types,
such as integers, are kept as high-performance non-objects.
Robust
The multi plat formed environment of the Web places extraordinary demands on a program,
because the program must execute reliably in a variety of systems. Thus, the ability to create
robust programs was given a high priority in the design of java. To gain reliability, java restricts
you in a few key areas, to force you to find your mistakes early in program development. At the
same time, java frees you from having to worry about many of the most common causes of
programming errors. Because java is a strictly typed language, it checks your code at compile
time. However, it also checks your code at run time. In fact, many hard-to-track-down bugs that
often turn up in hard-to-reproduce run-time situations are simply impossible to create in Java.
Knowing that what you have written will behave in a predictable way under diverse conditions is
key feature of java.
Multithreaded
Java has built-in classes that support multithreading (also called "concurrency").