Core Java Notes: Chapter-1, 2,3 Features of JAVA Environment
Core Java Notes: Chapter-1, 2,3 Features of JAVA Environment
Chapter- 1 , 2,3
Java is not just a programming language; it’s a revolutionary new technology that is being
deployed wherever advanced processing power is required. It is also a leading programming
language for wireless technology and real-time systems. Sun Microsystems officially describes Java
as a programming language with the following attributes:
Compiled and Interpreted: - Java is both a compiled and interpreted language. Java translates
source code into byte code instructions. As byte codes are not machine instructions, Java
interpreter generates machine code that can directly be executed by the particular machine that is
running the Java program.
Platform Independent and Portable: - A central issue for the Java designers was that of code
longevity and portability. Operating system upgrades, processor upgrades and changes in core
system resources can all combine to make a program dysfunctional. With a language like Java,
programs once written can be run anywhere, anytime.
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 on a
clean state. One outcome of this was a clean, usable, pragmatic approach to object orientation.
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 and Secure: - The multiplatform environment of the web places extraordinary demands
on a program, because the program must execute reliably on a variety of system. Accordingly, the
ability to create robust programs was given a high priority in the design of Java. 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. Further, it
checks your code at runtime.
For a language that is widely used for programming on the Internet, security becomes a
crucial issue. Java systems safeguard the memory by ensuring that no viruses are communicated
with an applet.
Distributed: - Java is distributed language, i.e. it can be used for creating applications that run on
networks. It can share both data and programs and Java applications can easily access remote
objects on Internet.
A single threaded application has one thread of execution running at all times and such
programs can execute only one task at a time.
Java language, being similar to C++, provides the programmer with a familiar
environment to program. It diverges from C++ in areas that create most of the problems
in programming with C++. Some of these features that are different in Java are:
In Java, the class subsumes the role of the structure and union; so they are not needed
separately. Any functions you need must be encapsulated in a class. The interface replaces the
problems with “fragile super classes”—a term used to refer to the unstable way in which
multiple inherited classes are used in C++. By getting rid of structures and encapsulating
arrays as objects, Java attempts to eliminate the original logic behind pointers. Use of objects
made sure that writing for Java will produce robust, efficient code, much less prone to bugs
memory leaks and corruption.
The Java technology is actually a group of technologies. It not only provides the language
part for developing applications, but also supports architecture for running these applications.
It concurrently provides necessary tools to develop, compile and run the Java applications.
Being derived from C++, Java is comprehensible, and the task of programmer is further
simplified by the advance features it provides, such as automatic garbage collection and
thread synchronization.
The Byte code: - The first step in the Java application life cycle is the compilation of code. The
Java compiler acts just as any other compiler. It creates the machine code for execution from a
higher level language. The Java compiler compiles the code for a machine that physically dose
not e3xists. This compiled code is known as byte code, and hypothetical machine is called Java
Virtual Machine.
Byte
Source compiler code
Javac
Process of compilation
Java Virtual Machine: The JVM is invoked differently depending on the type of Java program.
JVM performs the following functions.
1. When a class is executed, JVM loads all required classes automatically from the local disk
or from across the network. This is the function of class loader utility of JVM.
2. After loading the required classes, JVM verifies to make sure that the classes do not violate
any of the basic rules of Java language. This is the function of the byte code verifier.
3. Then JVM keeps track of all memory usage. It takes care of memory allocation and also
performs the release of memory after the object is no longer needed. This process which
manages dereferenced objects is called Garbage Collection.
Just-In-Time (JIT)Compilers:- Within JVM, Just-In-Time (JIT) compilers are used to improve
performance. JIT compiler translates byte codes only the first time. If repe3ated execution of the
code is required, it is automatically mapped to the corresponding native machine code. This
especially effective in repetitive code, such as loops or recursive functions.
Byte Interpreter
Class
loader code
verifier
JIT compiler
Though Java was created by James Gosling for developing small, platform-independent
and robust programs that were used in consumer electronics, it can be used to develop more
dynamic programs. It is the leading programming language for wireless technology, web services,
and real-time embedded programming for cell phones. Broadly we can categorize Java programs
into the following two main groups:
Applets
Applications
Applets: - A Java applet is a small program embedded in a web page and is run when that page is
browsed using a web browser. Applets are downloaded over the network and can make network
connections only to the host they are issued from. Applets are inherently graphical in nature and
tend to contain such as buttons, labels, text fields, etc., to accept user inputs.
Applications: - Applications are stand-alone program written in Java. They are invoked by using
a JVM which resides within a local operating system. An application must contain a static method
‘main()’ from where its execution begins. Java applications can also execute on the server
machine. The multitier model of internet computing uses these types of server-side Java
applications.
Chapter - 4
Java tokens:
A token is the smallest element in a program that is meaningful to the compiler. These tokens
define the structure of the language. The Java token set can be divided in to five categories:
Identifiers, Keywords, Literals, Operators and separators.
Identifiers: - Identifiers are names provided by the programmer. These names can be assigned to
variables, methods, functions, classes, etc., to uniquely identify them to the compiler. Identifiers
must be composed of letters, numbers, the underscore and the dollar sign ($). They cannot
contain white spaces, and can only begin with a letter, the underscore or a dollar sign. You cannot
begin a variable name with a number. Java keywords cannot be used as an identifier.
Keywords: - Java keywords are reserved words and have special meaning for the Java compiler.
They cannot be used as identifiers in a program. Java has a rich set of keywords. There are 48
reserved keywords currently defined in the Java language
The keywords const and goto are reserved but not used. In the early days of Java, several other
keywords were reserved for possible future use. However, the current specification for Java only
defines the keywords shown in Table.
Literals
A constant value in Java is created by using a literal representation of it. For example, here are
some literals:
100 98.6 'X' "This is a test"
Left to right, the first literal specifies an integer, the next is a floating-point value, the third is a
character constant, and the last is a string.
Operators:- Java provides a rich operator environment. Most of its operators can be divided into
the following four groups: arithmetic, bitwise, relational, and logical. Java also defines some
additional operators that handle certain special situations.
Arithmetic Operators
Arithmetic operators are used in mathematical expressions in the same way that they are used in
algebra. The following table lists the arithmetic operators:
Relational Operators
The relational operators determine the relationship that one operand has to the other.
Specifically, they determine equality and ordering. The relational operators are shown here:
Prof. Rushabh Shah Mobile: 9426519009
Assistant Professor
Nirma University Page 7
Core Java Notes
Separators :-In Java, there are a few characters that are used as separators. The most commonly
used separator in Java is the semicolon. As you have seen, it is used to terminate statements. The
separators are shown in the following table:
A programming language uses control statements to cause the flow of execution to advance and
branch based on changes to the state of a program.
Java's program control statements can be put into the following categories:
i. Selection
ii. Iteration
iii. Jump.
i. Selection statements allow your program to choose different paths of execution based
upon the outcome of an expression or the state of a variable.
ii. Iteration statements enable program execution to repeat one or more statements (that
is, iteration statements form loops).
iii. Jump statements allow your program to execute in a nonlinear fashion. All of Java's
control statements are examined here.
Java supports two selection statements: if and switch. These statements allow you to control the
flow of your program's execution based upon conditions known only during run time.
if
The if statement is Java's conditional branch statement. It can be used to route program
execution through two different paths. Here is the general form of the if statement:
if (condition) statement1;
else statement2;
The if works like this: If the condition is true, then statement1 is executed. Otherwise, statement2
(if it exists) is executed. In no case will both statements be executed.
Nested ifs
A nested if is an if statement that is the target of another if or else. Nested ifs are very common in
programming. When you nest ifs, the main thing to remember is that an else statement always
refers to the nearest if statement that is within the same block as the else and that is not already
associated with an else.
if(condition)
statement;
else if(condition)
statement;
else if(condition)
statement;
.
.
.
else
statement;
The if statements are executed from the top down. As soon as one of the conditions controlling
the if is true, the statement associated with that if is executed, and the rest of the ladder is
bypassed. If none of the conditions is true, then the final else statement will be executed.
switch
The switch statement is Java's multiway branch statement. It provides an easy way to dispatch
execution to different parts of your code based on the value of an expression. As such, it often
provides a better alternative than a large series of if-else-if statements. Here is the general form
of a switch statement:
switch (expression) {
case value1:
// statement sequence
break;
case value2:
// statement sequence
break;
.
.
.
case valueN:
// statement sequence
break;
Prof. Rushabh Shah Mobile: 9426519009
Assistant Professor
Nirma University Page 11
Core Java Notes
default:
// default statement sequence
}
Nested switch Statements
You can use a switch as part of the statement sequence of an outer switch. This is called a nested
switch. Since a switch statement defines its own block, no conflicts arise between the case
constants in the inner switch and those in the outer switch.
Iteration Statements
Java's iteration statements are for, while, and do-while. These statements create what we
commonly call loops.
while
The while loop is Java's most fundamental looping statement. It repeats a statement or block
while its controlling expression is true. Here is its general form:
while(condition) {
// body of loop
}
do-while
As you just saw, if the conditional expression controlling a while loop is initially false, then the
body of the loop will not be executed at all. However, sometimes it is desirable to execute the
body of a while loop at least once, even if the conditional expression is false to begin with. In
other words, there are times when you would like to test the termination expression at the end of
the loop rather than at the beginning. Fortunately, Java supplies a loop that does just that: the do-
while. The do-while loop always executes its body at least once, because its conditional
expression is at the bottom of the loop. Its general form is
do {
// body of loop
} while (condition);
for
Here is the general form of the for statement:
for(initialization; condition; iteration) {
// body
}
The for loop operates as follows. When the loop first starts, the initialization portion of the loop is
executed. Generally, this is an expression that sets the value of the loop control variable, which
acts as a counter that controls the loop. It is important to understand that the initialization
expression is only executed once. Next, condition is evaluated. This must be a Boolean expression.
It usually tests the loop control variable against a target value. If this expression is true, then the
body of the loop is executed. If it is false, the loop terminates. Next, the iteration portion of the
loop is executed. This is usually an expression that increments or decrements the loop control
variable. The loop then iterates, first evaluating the conditional expression, then executing the
body of the loop, and then executing the iteration expression with each pass. This process repeats
until the controlling expression is false.
Jump Statements
Java supports three jump statements: break, continue, and return. These statements transfer
control to another part of your program.
Using break
In Java, the break statement has three uses. First, as you have seen, it terminates a statement
sequence in a switch statement. Second, it can be used to exit a loop. Third, it can be used as a
"civilized" form of goto. The last two uses are explained here.
Using continue
Sometimes it is useful to force an early iteration of a loop. That is, you might want to continue
running the loop, but stop processing the remainder of the code in its body for this particular
iteration. This is, in effect, a goto just past the body of the loop, to the loop's end. The continue
statement performs such an action.
In while and do-while loops, a continue statement causes control to be transferred directly to
the conditional expression that controls the loop. In a for loop, control goes first to the iteration
portion of the for statement and then to the conditional expression. For all three loops, any
intermediate code is bypassed.
Here is an example program that uses continue to cause two numbers to be printed on each line:
// Demonstrate continue.
class Continue {
public static void main(String args[]) {
for(int i=0; i<10; i++) {
System.out.print(i + " ");
if (i%2 == 0) continue;
System.out.println("");
}
}
}
return
The last control statement is return. The return statement is used to explicitly return from a
method. That is, it causes program control to transfer back to the caller of the method.
class BoxDemo {
public static void main(String args[]) {
Box mybox = new Box();
double vol;
// assign values to mybox's instance variables
mybox.width = 10;
mybox.height = 20;
mybox.depth = 15;
// compute volume of box
vol = mybox.width * mybox.height * mybox.depth;
System.out.println("Volume is " + vol);
}
}
As just explained, the new operator dynamically allocates memory for an object. It has this
general form:
It is important to understand that new allocates memory for an object during run time. The
advantage of this approach is that your program can create as many or as few objects as it needs
during the execution of your program. However, since memory is finite, it is possible that new
will not be able to allocate memory for an object because insufficient memory exists. If this
happens, a run-time exception will occur.
Introducing Methods
Constructors
It can be tedious to initialize all of the variables in a class each time an instance is created.
Java allows objects to initialize themselves when they are created.
This automatic initialization is performed through the use of a constructor. A constructor
initializes an object immediately upon creation. It has the same name as the class in which it
resides and is syntactically similar to a method.
Once defined, the constructor is automatically called immediately after the object is
created, before the new operator completes. Constructors look a little strange because they have
no return type, not even void. This is because the implicit return type of a class' constructor is the
class type itself.
It is the constructor's job to initialize the internal state of an object so that the code
creating an instance will have a fully initialized, usable object immediately.
/* Here, Box uses a constructor to initialize the dimensions of a box.*/
class Box {
double width;
double height;
double depth;
// This is the constructor for Box.
Box() {
System.out.println("Constructing Box");
width = 10;
height = 10;
depth = 10;
}
// compute and return volume
double volume() {
return width * height * depth;
}
}
class BoxDemo6 {
public static void main(String args[]) {
// declare, allocate, and initialize Box objects
Box mybox1 = new Box();
Box mybox2 = new Box();
double vol;
// get volume of first box
vol = mybox1.volume();
System.out.println("Volume is " + vol);
// get volume of second box
vol = mybox2.volume();
System.out.println("Volume is " + vol);
}}
Parameterized Constructors
While the Box( ) constructor in the preceding example does initialize a Box object, it is
not very useful—all boxes have the same dimensions. What is needed is a way to construct Box
objects of various dimensions. The easy solution is to add parameters to the constructor.
class Box {
double width;
double height;
double depth;
// This is the constructor for Box.
Box(double w, double h, double d) {
width = w;
height = h;
depth = d;
}
// compute and return volume
double volume() {
return width * height * depth;
}
}
class BoxDemo7 {
public static void main(String args[]) {
// declare, allocate, and initialize Box objects
Box mybox1 = new Box(10, 20, 15);
Box mybox2 = new Box(3, 6, 9);
double vol;
// get volume of first box
vol = mybox1.volume();
System.out.println("Volume is " + vol);
// get volume of second box
vol = mybox2.volume();
System.out.println("Volume is " + vol);
}
}
Sometimes a method will need to refer to the object that invoked it. To allow this, Java defines the
this keyword. this can be used inside any method to refer to the current object. That is, this is
always a reference to the object on which the method was invoked. You can use this anywhere a
reference to an object of the current class' type is permitted.
To better understand what this refers to, consider the following version of Box( ):
// A redundant use of this.
Box(double w, double h, double d) {
this.width = w;
this.height = h;
this.depth = d;
}
Garbage Collection
Since objects are dynamically allocated by using the new operator, you might be wondering how
such objects are destroyed and their memory released for later reallocation. In some languages,
such as C++, dynamically allocated objects must be manually released by use of a delete operator.
Java takes a different approach; it handles deallocation for you automatically. The technique that
accomplishes this is called garbage collection. It works like this: when no references to an object
exist, that object is assumed to be no longer needed, and the memory occupied by the object can
be reclaimed. There is no explicit need to destroy objects as in C++. Garbage collection only
occurs sporadically (if at all) during the execution of your program.
Sometimes an object will need to perform some action when it is destroyed. For example, if an
object is holding some non-Java resource such as a file handle or window character font, then you
might want to make sure these resources are freed before an object is destroyed. To handle such
situations, Java provides a mechanism called finalization. By using finalization, you can define
specific actions that will occur when an object is just about to be reclaimed by the garbage
collector.
To add a finalizer to a class, you simply define the finalize( ) method. The Java run time calls that
method whenever it is about to recycle an object of that class. Inside the finalize( ) method you
will specify those actions that must be performed before an object is destroyed. The garbage
collector runs periodically, checking for objects that are no longer referenced by any running state
or indirectly through other referenced objects. Right before an asset is freed, the Java run time
calls the finalize( ) method on the
object.
It is important to understand that finalize( ) is only called just prior to garbage collection. It is not
called when an object goes out-of-scope, for example. This means that you cannot know when—
or even if—finalize( ) will be executed. Therefore, your program should provide other means of
releasing system resources, etc., used by the object. It must not rely on finalize( ) for normal
program operation.
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.
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. 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. Java will employ its automatic type conversions
only if no exact match is found.
}
}
Overloading Constructors
In addition to overloading normal methods, you can also overload constructor methods.
that receives it will refer to the same object as that referred to by the argument. This effectively
means that objects are passed to methods by use of call-by-reference. Changes to the object inside
the method do affect the object used as an argument. For example, consider the following
program:
Recursion
Java supports recursion. Recursion is the process of defining something in terms of itself. As it
relates to Java programming, recursion is the attribute that allows a method to call itself. A
method that calls itself is said to be recursive.
if(n==1) return 1;
result = fact(n-1) * n;
return result;
}
class Recursion {
public static void main(String args[]) {
Factorial f = new Factorial();
System.out.println("Factorial of 3 is " + f.fact(3));
System.out.println("Factorial of 4 is " + f.fact(4));
System.out.println("Factorial of 5 is " + f.fact(5));
}
}
As you know, encapsulation links data with the code that manipulates it. However,
encapsulation provides another important attribute: access control. Through encapsulation, you
can control what parts of a program can access the members of a class. By controlling access, you
can prevent misuse.
How a member can be accessed is determined by the access specifier that modifies its
declaration. Java supplies a rich set of access specifiers. Some aspects of access control are related
mostly to inheritance or packages. (A package is, essentially, a grouping of classes.)
Here, let's begin by examining access control as it applies to a single class. Once you
understand the fundamentals of access control, the rest will be easy. Java's access specifiers are
public, private, and protected. Java also defines a default access level. protected applies only when
inheritance is involved.
When a member of a class is modified by the public specifier, then that member can be
accessed by any other code in your program. When a member of a class is specified as private,
then that member can only be accessed by other members of its class. Now you can understand
why main( ) has always been preceded by the public specifier.
In the classes developed so far, all members of a class have used the default access mode,
which is essentially public. To understand the effects of public and private access, consider the
following program:
// methods to access c
void setc(int i) { // set c's value
c = i;
}
int getc() { // get c's value
return c;
}
}
class AccessTest {
public static void main(String args[]) {
Test ob = new Test();
// These are OK, a and b may be accessed directly
ob.a = 10;
ob.b = 20;
// This is not OK and will cause an error
// ob.c = 100; // Error!
// You must access c through its methods
ob.setc(100); // OK
System.out.println("a, b, and c: " + ob.a + " " +
ob.b + " " + ob.getc());
}
}
Understanding static
There will be times when you will want to define a class member that will be used
independently of any object of that class. Normally a class member must be accessed only in
conjunction with an object of its class. However, it is possible to create a member that can be used
by itself, without reference to a specific instance. To create such a member, precede its
declaration with the keyword static. When a member is declared static, it can be accessed before
any objects of its class are created, and without reference to any object. You can declare both
methods and variables to be static. The most common example of a static member is main( ).
main( ) is declared as static because it must be called before any objects exist.
Instance variables declared as static are, essentially, global variables. When objects of its
class are declared, no copy of a static variable is made. Instead, all instances of the class share the
same static variable.
If you need to do computation in order to initialize your static variables, you can declare a static
block which gets executed exactly once, when the class is first loaded.
static {
System.out.println("Static block initialized.");
b = a * 4;
}
If you wish to call a static method from outside its class, you can do so using the following general
form:
classname.method( )
Introducing final
A variable can be declared as final. Doing so prevents its contents from being modified. This means that
you must initialize a final variable when it is declared. For Example
It is a common coding convention to choose all uppercase identifiers for final variables. Variables
declared as final do not occupy memory on a per-instance basis. Thus, a final variable is
essentially a constant.
A static nested class is one which has the static modifier applied. Because it is static, it
must access the members of its enclosing class through an object. That is, it cannot refer to
members of its enclosing class directly. Because of this restriction, static nested classes are seldom
used.
The most important type of nested class is the inner class. An inner class is a non-static
nested class. It has access to all of the variables and methods of its outer class and may refer to
them directly in the same way that other non-static members of the outer class do. Thus, an inner
class is fully within the scope of its enclosing class.
The following program illustrates how to define and use an inner class. The class named Outer
has one instance variable named outer_x, one instance method named test( ), and defines one
inner class called Inner.
outer.test();
}
}
Strings can be constructed a variety of ways. The easiest is to use a statement like this:
String myString = "this is a test";
Once you have created a String object, you can use it anywhere that a string is allowed.
For example, this statement displays myString:
System.out.println(myString);
Java defines one operator for String objects: +. It is used to concatenate two strings. For
example, this statement
String myString = "I" + " like " + "Java.";
results in myString containing "I like Java."
The String class contains several methods that you can use. Here are a few. You can test two
strings for equality by using equals( ). You can obtain the length of a string by calling the length( )
method. You can obtain the character at a specified index within a string by calling charAt( ).
// Demonstrating some String methods.
class StringDemo2 {
public static void main(String args[]) {
String strOb1 = "First String";
String strOb2 = "Second String";
String strOb3 = strOb1;
System.out.println("Length of strOb1: " +
strOb1.length());
System.out.println("Char at index 3 in strOb1: " +
strOb1.charAt(3));
if(strOb1.equals(strOb2))
System.out.println("strOb1 == strOb2");
else
System.out.println("strOb1 != strOb2");
if(strOb1.equals(strOb3))
System.out.println("strOb1 == strOb3");
else
System.out.println("strOb1 != strOb3");
}}
Sometimes you will want to pass information into a program when you run it. This is
accomplished by passing command-line arguments to main( ). A command-line argument is the
information that directly follows the program's name on the command line when it is executed.
To access the command-line arguments inside a Java program is quite easy—they are stored as
strings in the String array passed to main( ). For example, the following program displays all of
the command-line arguments that it is
called with: