Java was developed by James Gosling, Patrick Naughton, Chris Warth, Ed Frank, and Mike Sheridan at Sun Microsystems, Inc. in 1991. It took 18 months to develop the first working version. This language was initially called “Oak,” but was renamed “Java” in 1995. Primary motivation was the need for a platformindependent (that is, architectureneutral) language that could be used to create software to be embedded in various consumer electronic devices, such as microwave ovens and remote controls.
Create a Source File
Using notepad
First, start your editor. You can launch the Notepad editor from the Start menu by selecting Programs > Accessories > Notepad. In a new document, type in the following code:
/** * The HelloWorldApp class implements an application that
* simply prints "Hello World!" to standard output. */
class HelloWorldApp
{
string.
}
public static void main(String[] args)
{
System.out.println("Hello World!"); // Display the
}
Save the Java Source Code
Save the code in a file with the name HelloWorldApp.java. To do this in Notepad, first choose the File > Save As menu item. Then, in the Save As dialog box:
1. Using the Save in combo box, specify the folder (directory) where you'll save your file. In this example, the directory is java on the C drive.
Now click Save, and exit Notepad.
Compile the Source File into a .class File
Bring up a shell, or "command," window. The shell window should look similar to the following figure.
The prompt shows your current directory. When you bring up the prompt, your current directory is usually your home directory.
To compile your source file, change your current directory to the directory where your file is located. For example, if your source directory is java on the D drive, type the following command at the prompt and press Enter:
cd D:\java
Now the prompt should change to D:\java>.
Now you are ready to compile. At the prompt, type the following command and press Enter.
javac HelloWorldApp.java
The compiler has generated a bytecode file, HelloWorldApp.class. At the prompt, type dir to see the new file that was generated, as shown in the following figure.
Run the Program
In the same directory, enter the following command at the prompt:
java HelloWorldApp
Create a Source File
Using Eclipse
1. First, start eclipse. Create a new project by choosing File > New > Java Project. Type the name of project in text box corresponding to project name and click on Finish. Creation of new project creates at location given in dialog box. For example c:\eclipse\Sample.
Create a new class file in just created project. Type name of new file. Click finish.
1. Type source code in Example class file.
2. Run the program by clicking over Run icon.
JAVA program execution process
In the Java programming language, all source code is first written in plain text files ending with the .java extension.
Those source files are then compiled into .class files by the javac compiler.
A .class file does not contain code that is native to your processor.
It instead contains bytecodes — the machine language of the Java Virtual Machine (Java VM).
The java launcher tool then runs your application with an instance of the Java Virtual Machine.
Execution Process
Java Virtual Machine
Because the Java VM is available on many different operating systems, the same .class files are capable of running on Microsoft Windows, the Solaris TM Operating System (Solaris OS), Linux, or Mac OS.
Java Virtual Machine
Bytecode/Java Class File
A Java class file is a file containing Java bytecode and having .class extension that can be executed by JVM. A Java class file is created by a Java compiler from .java files as a result of successful compilation. As we know that a single Java programming language source file (or we can say .java file) may contain one class or more than one class. So if a .java file has more than one class then each class will compile into a separate class files. Translating a Java program into bytecode makes it much easier to run a program in a wide variety of environments because only the JVM needs to be implemented for each platform. Although the details of the JVM will differ from platform to platform, all understand the same Java bytecode.
Benefit of JVM
The fact that a Java program is executed by the JVM also helps to make it secure. Because the JVM is in control, it can contain the program and prevent it from generating side effects outside of the system. The safety is also enhanced by certain restrictions that exist in the Java language.
Disadvantage of JVM:
In general, when a program is compiled to an intermediate form and then interpreted by a virtual machine, it runs slower than it would run if compiled to executable code. However, with Java, the differential between the two is not so great. Because bytecode has been highly optimized, the use of bytecode enables the JVM to execute programs much faster than you might expect.
Just-In-Time (JIT) compiler
It converts selected portions of bytecode into executable code in real time, on a piece-by-piece, demand basis. It is important to understand that it is not practical to compile an entire Java program into executable code all at once, because Java performs various runtime checks that can be done only at run time. Furthermore, not all sequences of bytecode are compiled—only those that will benefit from compilation. The remaining code is simply interpreted.
Java Features
Simple
Secure
Portable
Objectoriented
Robust
Multithreaded
Architectureneutral
Interpreted
High performance
Distributed
Dynamic
A First Simple Program
/* Example.java */ class Example
{
System is a predefined class
out is the output stream instance
println( ) is a method
// Your program begins with a call to main(). public static void main(String args[])
{
System.out.println("This is a simple Java
program.");
}
}
class Example2
{
public static void main(String args [])
{
int num; // this declares a variable called num num = 100; // this assigns num the value 100 System.out.println("This is num: " + num); num = num * 2;
Comments
Comments are ignored by the Java compiler. Java supports three types of comments.
1. Single-line comment
2. Multiline Comment
i. It begins with the characters /* and continues, over any number of lines, until the characters */.
ii. Any text between the /* and the */ is ignored by javac.
iii. This type of comment cannot be nested (i.e., one /* */ comment cannot appear within another).
3. DOC Comment
If a comment begins with /** and ends with*/ , it is regarded as a special doc comment. Like regular multiline comments doc comments cannot be nested.
/**
* Upload a file to a web server.
* *
@param file The file to upload.
* @return <tt>true</tt> on success,
* <tt>false</tt> on failure.
* @author David Flanagan
*/
javadoc extracts these comments and processes them to create
online documentation for your class. A doc comment can contain HTML tags and can use additional syntax understood by javadoc.
Note
Comments may appear between any tokens of a Java program, but may not appear within a token.
int /*hello */ num;
Comments may not appear within doublequoted string literals. A comment within a string literal simply becomes a literal part of that string.
Reserved Words
They are part of the syntax of the language and may not be used to name variables, classes, and so forth
The character sequence consisting of a single underscore, _, is also disallowed as an identifier.
Identifier naming conventions
Camel Casing: The usual Java convention is to name variables using camel case. This means that the first letter of a variable should be lowerase, but that the first letter of any other words in the identifier should be uppercase.
Literals
Literals are sequences of source characters that directly represent constant values. They include integer and floatingpoint numbers, single characters within single quotes, strings of characters within double quotes, and the reserved words true, false, and null.
Punctuation
Java uses a number of punctuation characters as tokens. The punctuation characters into two categories, separators and operators.
1. Separators(12 in number)
Primitive Data Types
Java supports eight basic data types (byte, short, int, long, char, float, double) known as primitive types.
Boolean type
Character type
Integer types (byte, short, int, and long)
Floating point types (float and double)
Java’s all data types have a strictly defined range. For example, an
int is always 32 bits, regardless of the particular platform.
Note: Languages such as C and C++ allow the size of an integer to vary based upon the dictates of the execution environment.
Java Is a Strongly Typed Language
Java is a strongly typed language. First, every variable has a type, every expression has a type, and every type is strictly defined. Second, all assignments, whether explicit or via parameter passing in method calls, are checked for type compatibility. There are no automatic coercions or conversions of conflicting types as in some languages. The Java compiler checks all expressions and parameters to ensure that the types are compatible. Any type mismatches are errors that must be corrected before the compiler will finish compiling the class.
Integers
Java defines four signed integer types: byte, short, int, and long. Java does not support unsigned, positiveonly integers. Many other computer languages support both signed and unsigned integers.
Name Width Range
long 64 –9,223,372,036,854,775,808 to9,223,372,036,854,775,807
int 32 –2,147,483,648 to 2,147,483,647
short 16 –32,768 to 32,767
byte 8 –128 to 127
Floating-Point Types
There are two kinds of floatingpoint types, float and double, which represent single and double precision numbers, respectively.
Name Width in Bits Approximate Range
double 64 4.9e–324 to 1.8e+308
float 32 1.4e–045 to 3.4e+038
Characters
In Java, the data type used to store characters is char. Java char is a 16bit type. The range of a char is 0 to 65,536. There are no negative chars. Java uses Unicode to represent characters. Unicode defines a fully international character set that can represent all of the characters found in all human languages.
In the formal specification for Java, char is referred to as an
integral type, which means that it is in the same general category as int, short, long, and byte. However, because its principal use is for representing Unicode characters, char is commonly considered to be in a category of its own.
Booleans
Java has a primitive type, called boolean, for logical values. It can have only one of two possible values, true or false. This is the type returned by all relational operators, as in the case of a < b.
Literals
Integer Literals
Any whole number value is an integer literal.
Decimal – 12, 3465,9223372036854775807L
Octal : o1, 0234
Hexadecimal : 0x2A6, 0x2aa6, 0X23EF, 0x7ffffffffffffffL Binary: 0b or 0B. // JDK 7 onwards
int x = 0b1101_0101_0001_1010;
int x = 123_456_789;
Underscores can only be used to separate digits. They cannot come at the beginning or the end of a literal. It is, however, permissible for more than one underscore to be used between two digits.
Integer literals create an int value, which in Java is a 32bit integer value. Since Java is strongly typed, you might be wondering how it is possible to assign an integer literal to one of Java’s other integer types, such as byte or long, without causing a type mismatch error. Fortunately, such situations are easily handled. When a literal value is assigned to a byte or short variable, no error is generated if the literal value is within the range of the target type.
Floating-Point Literals
Floatingpoint numbers represent decimal values with a fractional component.
Standard notation 2.0, 3.14159, and 0.6667, 9_423.1_0_9
Scientific notation : 6.022E23, 314159E–05, and 2e+100.
Floatingpoint literals in Java default to double precision. To specify a float literal, you must append an F or f to the constant. You can also explicitly specify a double literal by appending a D or d.
Hexadecimal floatingpoint literals : 0x12.2P2 (72.5)
P, called the binary exponent, indicates the poweroftwo by which the number is multiplied.
Boolean Literals
A boolean value can have, true and false. The values of true
and false do not convert into any numerical representation.
Character Literals
Characters in Java are indices into the Unicode character set. They are 16bit values that can be converted into integers and manipulated with the integer operators, such as the addition and subtraction operators. such as '\'' for the singlequote character itself and '\n' for the newline character. There is also a mechanism for directly entering the value of a character in octal or hexadecimal. For octal notation, use the backslash followed by the threedigit number. For example, '\141' is the letter 'a'. For hexadecimal, you enter a backslashu ( \u), then exactly four hexadecimal digits. For example,'\u0063' is the ‘c'.
Escape Sequence
String Literals
String literals are a sequence of characters between a pair of double quotes.
Examples:
"Hello World" "two\nlines"
"\"This is in quotes\""
The escape sequences and octal/hexadecimal notations can be part of the string literals. Strings must begin and end on the same line.
Identifiers
An identifier is simply a name given to some part of a Java program, such as a class, a method within a class, or a variable declared within a method.
1. Identifiers may be of any length
2. It may contain letters and digits.
3. An identifier may not begin with a digit.
4. identifiers may not contain punctuation characters except dollar sign($) as well as other Unicode currency symbols such as £ and
¥.
Note:
The underscore character can still appear in a Java identifier, but it is no longer legal as a complete identifier by itself.
Declaring a Variable
In Java, all variables must be declared before they can be used. For example:
type identifier [ = value ][, identifier [= value ] …]; int a, b, c;
int d = 3, e, f = 5;
byte z = 22; // initializes z. double pi = 3.14159; . char x = 'x';
Dynamic Initialization
A variable can be initialized dynamically using any expression. For example:
double r;
r=23.45 // assignment
double pi=3.142; // initialization
double area=pi*r*r; // dynamic initialization
Type Conversion and Casting
Conversion of one type to another is called type conversion.
i. Implicit (Automatic) Conversion
ii. Explicit Conversion
If the two types are compatible, then Java will perform the conversion automatically. For example, it is always possible to assign an int value to a long variable. However, not all types are compatible, and thus, not all type conversions are implicitly allowed.
Automatic Conversions
When one type of data is assigned to another type of variable, an automatic type conversion will take place if the following two conditions are met:
i. The two types are compatible.
ii. The destination type is larger than the source type.
When these two conditions are met, a widening conversion takes place. For widening conversions, the numeric types ( integer and floatingpoint ) are compatible with each other.
Note: Java also performs an automatic type conversion when storing a literal integer constant into variables of type byte, short, long, or char.
Explicit Casting (narrowing conversion)
Java does not do automatic conversion between incompatible types. To create a conversion between two incompatible types, you must use a cast. A cast is simply an explicit type conversion. It has this general form:
(targettype) value
int a=325 byte b;
b = (byte) a;
If the integer’s value is larger than the range of a byte, it will be reduced modulo byte’s range.
class Conversion {
public static void main(String args[])
{
byte b;
int i = 257;
double d = 323.142; System.out.println("\nConversion of int to byte."); b = (byte) i;
System.out.println("i and b " + i + " " + b); System.out.println("\nConversion of double to int."); i = (int) d;
System.out.println("d and i " + d + " " + i); System.out.println("\nConversion of double to byte."); b = (byte) d;
System.out.println("d and b " + d + " " + b);
}
}
Type Promotion Rules
Java defines several type promotion rules that apply to expressions.
All byte, short, and char values are promoted to int.
If one operand is a long, the whole expression is promoted to long.
If one operand is a float, the entire expression is promoted to float.
If any of the operands are double, the result is double.
class Promote {
public static void main(String args[])
{
byte b = 42; char c = 'a'; short s = 1024; int i = 50000; float f = 5.67f;
double d = .1234;
double result = (f * b) + (i / c) (d * s); System.out.println((f * b) + " + " + (i / c) + " " + (d * s)); System.out.println("result = " + result);
}
}
OpERATOrs
Arithmetic Operators
Oper ator Result
+ Addition (also unary plus)
– Subtraction (also unary minus)
* Multiplication
/ Division
% Modulus
++ Increment
+= Addition assignment
– = Subtraction assignment
*= Multiplication assignment
/= Division assignment
%= Modulus assignment
– – Decrement
Basic Arithmetic Operators
The basic arithmetic operations—
Modulus Operator
The modulus operator, %, returns the remainder of a division operation. It can be applied to floatingpoint types as well as integer types.
class Modulus {
public static void main(String args[]) { int x = 42;
double y = 42.25;
System.out.println("x mod 10 = " + x % 10); System.out.println("y mod 10 = " + y % 10);
}
}
Modulus Operator
public class modulus {
public static void main(String args[]) { int b = 42;
int a=10; System.out.println(b%a); //2
System.out.println(b%a); //42% 10 =2
System.out.println(b%a); //42 % 10 =2 System.out.println(b/a); // 42/10=4
}
}
Arithmetic Compound Assignment Operators
+=
*=
-=
/=
class OpEquals {
public static void main(String args[]) { int a = 1;
int b = 2; int c = 3; a += 5;
b *= 4;
Increment and Decrement
class IncDec {
public static void main(String args[]) { int a = 1;
int b = 2; int c;
int d;
c = ++b; d = a++; c++;
System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("c = " + c); System.out.println("d = " + d);
}
}
Bitwise Operators:
Bitwise Operators:
Java defines several bitwise operators that can be applied to the integer types: long, int, short, char, and byte.
Left Shift
The left shift operator, <<, shifts all of the bits in a value to the left a specified number of times. It has this general form:
value << num
Here, num specifies the number of positions to leftshift the value in value. That is, the << moves all of the bits in the specified value to the left by the number of bit positions specified by num. For each shift left, the highorder bit is shifted out (and lost), and a zero is brought in on the right. This means that when a left shift is applied to an int operand, bits are lost once they are shifted past bit position 31. If the operand is a long, then bits are lost after bit position 63.
Right Shift
The right shift operator, >>, shifts all of the bits in a value to the right a specified number of times.
value >> num
Here, num specifies the number of positions to rightshift the value in value. That is, the >> moves all of the bits in the specified value to the right the number of bit positions specified by num.
When you are shifting right, the top (leftmost) bits exposed by the right shift are filled in with the previous contents of the top bit. This is called sign extension and serves to preserve the sign of negative numbers when you shift them right.
For example:
–8 >> 1 is –4, which, in binary, is 11111000
–8>> 1
11111100 –4
It is interesting to note that if you shift –1 right, the result always remains –1, since sign extension keeps bringing in more ones in the highorder bits.
Unsigned Right Shift
Unsigned Right Shift inserts zero into the highorder bit no matter what its initial value was. This is known as an unsigned shift.
int a = 1;
a = a >>> 24;
11111111 11111111 11111111 11111111 –1 in binary as an int
>>>24
00000000 00000000 00000000 11111111 255 in binary as an
int
Remember, smaller values are automatically promoted to int in expressions. This means that signextension occurs and that the shift will take place on a 32bit rather than on an 8 or 16bit value. That is, one might expect an unsigned right shift on a byte value to zerofill beginning at bit 7. But this is not the case, since it is a 32bit value that is actually being shifted.
Bitwise Operator Compound Assignments
class OpBitEquals {
public static void main(String args[])
{
int a = 1; int b = 2; int c = 3; a |= 4;
b >>= 1;
c <<= 1;
a ^= c;
System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("c = " + c);
}
}
Relational Operators
Operator Result
== Equal to
!= Not equal to
> Greater than
< Less than
>= Greater than or equal to
<= Less than or equal to
Examples:
a>=0 n%2==0
b*b4*a*c>=0
Example: Relational Operator
public class RelationalOperatoR1
{
public static void main(String args[])
{
int a=12,B=15,YEAR=2020,age=15,num=23; System.out.println(a>b); System.out.println(year%4==0); System.out.println(age<18); System.out.println(num%2==0);
}
}
Boolean Logical Operators
The Boolean logical operators shown here operate only on boolean operands.
Short-Circuit Logical Operators
Java provides two interesting Boolean operators not found in some other computer languages. These are secondary versions of the Boolean AND and OR operators, and are commonly known as short-circuit logical operators. As you can see from the preceding table, the OR operator results in true when A is true, no matter what B is. Similarly, the AND operator results in false when A is false, no matter what B is. If you use the || and && forms, rather than the | and & forms of these operators, Java will not bother to evaluate the righth and operand when the outcome of the expression can be determined by the left operand alone.
Difference between boolean logical & and &&
public class BooleanLogiCAL1 {
public static void main(String[] args) { int a,b,c,d;
a=B=10;
System.out.println(a++>=11 & b++<20); System.out.println("a= "+ a); System.out.println("b= "+ b);
c=d=10;
System.out.println(c++>=11 && d++<20); System.out.println("c= "+ c); System.out.println("d= "+ d);
}
}
Difference between boolean logical | and ||
public class BooleanLogiCAL1
{
public static void main(String[] args) { int a,b,c,d;
a=B=10;
System.out.println(a++>=10 | b++<20); System.out.println("a= "+ a); System.out.println("b= "+ b);
c=d=10;
System.out.println(c++>=10 || d++<20); System.out.println("c= "+ c); System.out.println("d= "+ d);
}
}
Example (Short-circuited And)
if (denom != 0 && num / denom > 10)
Since the shortcircuit form of AND (&&) is used, there is no risk of causing a runtime exception when denom is zero. If this line of code were written using the single & version of AND, both sides would be evaluated, causing a runtime exception when denom is zero.
if(c==1 & e++ < 100) d = 100;
Here, using a single & ensures that the increment operation will be applied to e whether c is equal to 1 or not.
Assignment Operator
The assignment operator is the single equal sign, =.
var = expression;
int x, y, z;
x = y = z = 100; // set x, y, and z to 100
This fragment sets the variables x, y, and z to 100 using a single statement.
The ? Operator [ternary (three-way) operator ]
expression1 ? expression2 : expression3
Here, expression1 can be any expression that evaluates to a
boolean value.
Example: Ternary Operator
public class BooleanLogical4
{
public static void main(String[] args)
{
int a=13;
String s= A%2==1? "Odd":"Even"; System.out.println(s);
}
}
Example: ^ and ^=
import java.util.Scanner; public class BooleanLogical5
{
public static void main(String[] args)
{
int a,b,c;
boolean winner=false,result;
Scanner in= new Scanner(System.in); a=in.nextInt();
b=in.nextInt();
result = a<100 ^ B>100; winner^=result;
System.out.println(winner?"Winner":"looser ");
}
}Dr. Ashok Kumar 79
May 9, 2020
Example: ! and !=
public class BooleanLogical3 {
public static void main(String[] args) { int a,b;
a=B=10;
System.out.println(!(A<10)); System.out.println((a>=10)!=(b>=10));
}
}
Operator Precedence
Highest
++ (postfix) – – (postfix)
++ (prefix) – – (prefix) ~ ! + (unary) – (unary) (type-cast)
* / %
+ –
>> >>> <<
> >= < <= instanceof
== !=
&
^
|
&&
||
?:
->
= op=
Lowest
Using Parentheses
Parentheses raise the precedence of the operations that are inside them.
a >> b + 3 or a >> (b + 3)
Arrays
An array is a collection of homogeneous data elements. Arrays of any type can be created and may have one or more dimensions. A specific element in an array is accessed by its index.
One-Dimensional Arrays
To create an array, you first must create an array variable of the desired type. The general form of a onedimensional array declaration is
type var-name[ ];
Allocating Memory
array-var = new type [size]; e.g.
days = new int[12]
Declaration and Memory Allocation
It is possible to combine the declaration of the array variable with the allocation of the array itself, as shown here:
int month_days[] = new int[12];
Array Initialization
// Average of five numbers class Average
{
public static void main(String args[])
{
double nums[] = {10.1, 11.2, 12.3, 13.4, 14.5};
double result = 0; int i;
for(i=0; i<5; i++)
result = result + nums[i]; System.out.println("Average is " + result / 5);
}
}
Note: The Java runtime system will check to be sure that all array indexes are in the correct range.
Two Dimension Array
In Java, two dimensional (multidimensional) arrays
are actually arrays of arrays.
For example, the following declares a two dimensional array variable called twoD:
When you allocate memory for a multidimensional array, you need only specify the memory for the first (leftmost) dimension. You can allocate the remaining dimensions separately. For example, this following code allocates memory for the first dimension of twoD when it is declared. It allocates the second dimension manually.
int twoD[][] = new int[4][]; twoD[0] = new int[5]; twoD[1] = new int[5]; twoD[2] = new int[5]; twoD[3] = new int[5];
Triangular Matrix
Since multidimensional arrays are actually arrays of arrays, the length of each array is under your control.
int twoD[][] = new int[4][]; twoD[0] = new int[1]; twoD[1] = new int[2]; twoD[2] = new int[3]; twoD[3] = new int[4];
Array Initialization
double m[][] = {
{ 0*0, 1*0, 2*0, 3*0 },
{ 0*1, 1*1, 2*1, 3*1 },
{ 0*2, 1*2, 2*2, 3*2 },
{ 0*3, 1*3, 2*3, 3*3 }
};
Alternative Array Declaration Syntax
There is a second form that may be used to declare an array:
type[ ] var-name;
For example, the following two declarations are equivalent: int al[] = new int[3];
int[] A2 = new int[3];
The following declarations are also equivalent: char twOD1[][] = new char[3][4];
char[][] twOD2 = new char[3][4];
This alternative declaration form offers convenience when declaring several arrays at the same time.
Java supports two selection statements:
i. if
ii. switch
These statements allow you to control the flow of your program’s execution based upon conditions known only during run time.
Simple if statement
It can be used to route program execution through two different paths.
if (condition)
{
statement;
if else statement
It can be used to route program execution through two different paths.
if (condition)
{
statement1;
Example: if else statement
import java.util.Scanner; public class larger {
public static void main(String[] args)
{
int a,b;
Scanner in =new Scanner(System.in); try
{
System.out.println("Input two numbers");
Nested ifs
A nested if is an if statement that is the target of another if or else.
if(i == 10)
{
if(j < 20)
a = b; if(k > 100)
c = d;
}
else
else
a = d;
a = c;
Largest of three
numbers if(a>b)
{
if(a>c)
System.out.println(a);
else
System.out.println(c);
}
Program to find largest of three
import java.util.Sncaunnmer;bers public class Largest {
public static void main(String[] args) { int a,b,c;
Scanner in =new Scanner(System.in);
try
{
System.out.println("Input three numbers"); a=in.nextInt(); b=in.nextInt(); c=in.nextInt(); if(a>b)
{
if(a>c)
System.out.println(a);
else
The if-else-if Ladder
if(condition)
statement; else if(condition)
statement; else if(condition)
statement;
.
.
.
else
statement;
class IfElse {
public static void main(String args[]) { int month = 4; // April
String season;
if(month == 12 || month == 1 || month == 2) season = "Winter";
else if(month == 3 || month == 4 || month == 5) season = "Spring";
else if(month == 6 || month == 7 || month == 8) season = "Summer";
else if(month == 9 || month == 10 || month == 11) season = "Autumn";
else
season = "Bogus Month"; System.out.println("April is in the " + season + ".");
}
}
Switch
The switch statement is Java’s multiway branch statement. It often provides a better alternative than a large series of if elseif
switch (expression) {
case value1:
// statement sequence break;
case value2:
expression must be of type byte, short, int, char, String or an enumeration.
// A simple example of the switch.
class SampleSwitch {
public static void main(String args[]) { for(int i=0; i<6; i++)
switch(i) { case 0:
System.out.println("i is zero."); break;
case 1:
System.out.println("i is one."); break;
case 2:
System.out.println("i is two."); break;
case 3:
System.out.println("i is three."); break;
default:
System.out.println("i is greater than 3.");
}
}
}
What will be the output of this program?
class MissingBreak {
public static void main(String args[]) { for(int i=0; i<12; i++)
switch(i) { case 0:
case 1:
case 2:
case 3:
case 4:
System.out.println("i is less than 5"); break;
case 5:
case 6:
case 7:
case 8:
case 9:
System.out.println("i is less than 10"); break;
default:
System.out.println("i is 10 or more");
}}}
Using a string to control a switch statement.
class StringSwitch {
public static void main(String args[]) { String str = "two";
switch(str) { case "one":
System.out.println("one"); break;
case "two": System.out.println("two"); break;
case "three": System.out.println("three"); break;
default:
System.out.println("no match"); break;
} Note:
}
} Switch can be nested as if-else statement.
Iteration Statements
Java’s iteration statements are for, while, and do-while. These statements create what we commonly call loops. A loop repeatedly executes the same set of
instructions until a termination condition is met.
While
It repeats a statement or block while its controlling expression is true. Here is its general form:
while(condition) {
// body of loop
}
The condition can be any Boolean expression.
The curly braces are unnecessary if only a single statement is being repeated.
The body of the while (or any other of Java’s loops) can be empty. This is because a null statement (one that consists only of a semicolon) is syntactically valid in Java.
// Demonstrate the while loop.
class While {
public static void main(String args[]) { int n = 10;
while(n > 0) { System.out.println("tick " + n); n--;
}
}
}
What will be the output of this program?
// The target of a loop can be empty. class NoBody {
public static void main(String args[])
{
int i, j;
i = 100;
j = 200;
// find midpoint between i and j while(++i < --j); // no body in this loop System.out.println("Midpoint is " + i);
}
}
do-while
The do-while loop always executes its body at least once, because its conditional expression is at the bottom of the loop.
do {
// body of loop
} while (condition);
// Demonstrate the do-while loop. class DoWhile {
public static void main(String args[]) { int n = 10;
do {
System.out.println("tick " + n); n--;
} while(n > 0);
}
}
// Using a do-while to process a menu selection
class Menu {
public static void main(String args[]) throws java.io.IOException {
char choice; do {
System.out.println("Help on: "); System.out.println(" 1. if");
System.out.println(" 2. switch");
System.out.println(" 3. while");
System.out.println(" 4. do-while");
System.out.println(" 5. for\n"); System.out.println("Choose one:"); choice = (char) System.in.read();
} while( choice < '1' || choice > '5'); System.out.println("\n"); switch(choice) {
case '1': System.out.println("The if:\n"); System.out.println("if(condition) statement;"); System.out.println("else statement;");
break;
case '2':
System.out.println("The switch:\n"); System.out.println("switch(expressi on) {");
System.out.println(" case constant:"); System.out.println(" statement sequence"); System.out.println(" break;"); System.out.println(" //...");
System.out.println("}"); break;
case '3':
System.out.println("The while:\n"); System.out.println("while(condition) statement;");
break; case '4':
System.out.println("The do- while:\n"); System.out.println("do {");
System.out.println(" statement;"); System.out.println("} while (condition);");
break;
Dr. Ashok Kumar 115case '5': May 9, 2020
for
for(initialization; condition; iteration) {
// body
}
If only one statement is being repeated, there is no need for the curly braces.
Declaring Loop Control Variables Inside the for Loop
class ForTick {
public static void main(String args[]) {
// here, n is declared inside of the for loop for(int N=10; n>0; n) System.out.println("tick " + n);
}
}
the scope of that variable ends when the for statement does. Outside the
for loop, the variable will cease to exist.
Using the Comma
class Comma {
public static void main(String args[]) { int a, b;
FOR(A=1, b=4; a<b; a++, b) { System.out.println("a = " + a); System.out.println("b = " + b);
}
}
}
You can intentionally create an infinite loop (a loop that never terminates) if you leave all three parts of the for empty.
For example: for( ; ; )
{
// ...
}
// Demonstrate the for loop. class ForTick {
public static void main(String args[]) { int n;
for(n=10; n>0; n--) System.out.println("tick " + n);
}
}
We can also use the comma in the for loop.
program to check the prime numbers class Prime {
public static void main( String args[]) {
int num , i;
//boolean isprime = true;
for (num=3; num <= 15; num++){ boolean isprime = true;
for( i=2; i <= num/i ; i++) { if(num % i == 0){
isprime = false; break;} }
if (isprime)
System.out.println(" entered number " +num + " is prime"); else
System.out.println(" number "+num+ " is not prime");
}
}}
// program to check the prime numbers class PrIME1 {
public static void main( String args[]) {
int num , i, count =0;
//boolean isprime = true;
//for (num=3; num <= 15; num++){ for (num=3; ; num++){
boolean isprime = true; for( i=2; i <= num/i ; i++) { if(num % i == 0){
isprime = false; break;} }
if (isprime){
System.out.println(" entered number "
+num + " is prime"); count++; }
if ( count ==10) break;
//else
//System.out.println(" number "+num+ " is not prime");
}}
// program to find sum of digits using for loop
import java.util.Scanner; class Sum_digits {
public static void main( String args[]) { int number, sum=0;
Scanner s = new Scanner( System.in); System.out.println( "enter a number"); number = s.nextInt();
for( int i=0; number >0; i++)
{
sum = sum + nUMBER%10; number/=10;
}
System.out.println( " sum of digits is " + sum);
}}
For-Each
A for-each style loop is designed to cycle through a collection of objects, such as an array, in strictly sequential fashion, from start to finish.
The general form of the for-each: for(type itr-var : collection)
statement-block
// Use a for-each style for loop
class ForEach
{
public static void main(String args[ ])
{
int nums[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int sum = 0; for(int x : nums)
{
System.out.println("Value is: " + x); sum += x;
}
System.out.println("Summation: " + sum);
}
}
// Use break with a for-each style for
class ForEACH2
{
public static void main(String args[])
{
int sum = 0;
int nums[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for(int x : nums)
{
System.out.println("Value is: " + x); sum += x;
if(x == 5) break; // stop the loop when 5 is obtained
}
System.out.println("Summation of first 5 elements: " + sum);
} Note: Iteration variable is read only.
}
Iterating Over Multidimensional Arrays
class ForEach3
{
public static void main(String args[])
{
int sum = 0;
int nums[][] = new int[3][5]; for(int i = 0; i < 3; i++)
for(int j = 0; j < 5; j++) nums[i][j] = (i+1)*(j+1);
for(int x[] : nums)
{
for(int y : x) {
System.out.println("Value is: " + y); sum += y;
}
System.out.println("Summation: " + sum);
}
}
// Search an array using for-each style for.
class Search
{
public static void main(String args[])
{
int nums[] = { 6, 8, 3, 7, 5, 6, 1, 4 };
int val = 5;
boolean found = false; for(int x : nums)
{
if(x == val)
{
found = true; break;
}
}
if(found)
System.out.println("Value found!");
}
}
Nested Loops
class Nested {
public static void main(String args[])
{
int i, j;
for(i=0; i<10; i++)
{
Output:
..........
.........
........
.......
......
.....
Break statement
class BreakLooP2
{
public static void main(String args[]) { int i = 0;
while(i < 100)
{
if(i == 10)
break; // terminates loop if i is 10 System.out.println("i: " + i);
i++;
}
System.out.println("Loop complete.");
}
}
Labeled break
Syntax:
break label;
class Break {
public static void main(String args[])
{
boolean t = true; first: {
second: {
third: {
}
System.out.println("Before the break.");
if(t) break second; // break out of second block System.out.println("This won't execute");
System.out.println("This won't execute");
}
System.out.println("This is after second block.");
}
}
}
Using 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("");
}
}
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.
Labelled continue
class ContinueLabel
{
public static void main(String args[])
{
outer: for (int i=0; i<10; i++) { for(int j=0; j<10; j++)
{
if(j > i)
{
System.out.println(); continue outer;
}
System.out.print(" " + (i * j));
}
}
System.out.println();
Dr. A}s}hok Kumar 133
May 9, 2020
class definition
A class is defines a new data type. Once defined, this new type can be used to create objects of that type. Thus, a class is a template for an object, and an object is an instance of a class.
A simplified general form of a class definition: class classname
{
type instancevariable1; type instancevariable2;
// ...
type instancevariableN;
type methodname1(PARAMETErlist)
{
// body of method
}
// ...
type methodnameN(parameterlist)
{
// body of method
}
}
The data, or variables, defined within a class are called instance variables. The code is contained within methods. Collectively, the methods and variables defined within a class are called members of the class. The methods that determine how a class’ data can be used. Variables defined within a class are called instance variables because each instance of the class (that is, each object of the class) contains its own copy of these variables. Thus, the data for one object is separate and unique from the data for another.
A Simple Class
class Box
{
double width; double height; double depth;
}
A class declaration only creates a template; it does not create an actual object. Thus, the preceding code does not cause any objects of type Box to come into existence.
Create a Box object:
Box mybox = new Box(); or
Box mybox; // declare reference to object mybox = new Box(); // allocate a Box object
Accessing instance variables Use the dot (.) operator. mybox.width = 100;
Example
class Box
{
double width; double height; double depth;
}
class BoxDemo
{
public static void main(String args[])
{
Box mybox = new Box(); double vol; mybox.width = 10;
mybox.height = 20;
mybox.depth = 15;
vol = mybox.width * mybox.height * mybox.depth; System.out.println("Volume is " + vol);
}
}
Assigning Object Reference Variables
Box B1 = new Box(); Box B2 = B1;
b1 and b2 will both refer to the same object. The changes made to the object through b2 will affect the object to which b1 is referring, since they are the same object.
Box B1 = new Box(); Box B2 = B1;
// ...
B1 = null;
Methods
This is the general form of a method:
type name(parameterlist)
{
// body of method
}
Here, type specifies the type of data returned by the method.
The name of the method can be any legal identifier.
The parameterlist is a sequence of type and identifier pairs separated by commas. Parameters are essentially variables that receive the value of the arguments passed to the method when it is called.
Adding a Method to the Box Class
class Box
{
double width; double height; double depth;
// display volume of a box void volume()
{
System.out.print("Volume is ");
System.out.println(width * height * depth);
}
}
class BoxDemo3
{
public static void main(String args[])
{
Box MYBOX1 = new Box(); Box MYBOX2 = new Box(); MYBOX1.WIDTH = 10;
MYBOX1.HEIGHT = 20;
MYBOX1.DEPTH = 15; instance variables */ MYBOX2.width = 3;
MYBOX2.height = 6;
MYBOX2.depth = 9;
// display volume of first box MYBOX1.VOLUME();
// display volume of second box
MYBOX2.volume();
}
}
Method returning a Value
class BoxDemo4
{
class Box
{
double width; double height; double depth;
// compute and return volume
double volume()
{
return width * height * depth;
}
}
public static void main(String args[])
{
Box mybox1 = new Box(); Box mybox2 = new Box(); double vol;
mybox1.width = 10;
mybox1.height = 20;
mybox1.depth = 15; instance variables */ mybox2.width = 3;
mybox2.height = 6;
mybox2.depth = 9;
vol = mybox1.volume();
System.out.println("Volume is " + vol);
// get volume of second box
vol = mybox2.volume();
System.out.println("Volume is " + vol);
}
}
Adding a Method That Takes Parameters
int square()
{
return 10 * 10;
}
Without Parameters
int square(int i)
{
return i * i;
}
With Parameters
parameterized method
class Box
{
double width; double height; double depth; double volume()
{
return width * height * depth;
}
// sets dimensions of box
void setDim(double w, double h, double d)
{
width = w; height = h; depth = d;
}
}
class BoxDemo5
{
public static void main(String args[])
{
Box mybox1 = new Box(); Box mybox2 = new Box(); double vol; mybox1.setDim(10, 20, 15);
mybox2.setDim(3, 6, 9); vol = mybox1.volume();
System.out.println("Volume is " + vol); vol = mybox2.volume(); System.out.println("Volume is " + vol);
}
}
Methods can return Arrays
static int [] sum1()
{
int x[] ={10, 20,30};
for(int i1=0;i1<x.length;i1++) x[i1]=x[i1]+1;
return x;
}
How to call in a main Function
public static void main(String[] args)
{
int B[]={10, 20, 30};
int a[];
for(int i=0;i<b.length;i++) System.out.println("B is " + b[i]); a=sum1();
for(int i=0;i<a.length;i++) System.out.println("B is " + a[i]);
}
static int [] sum1() { int x[] ={10, 20,30};
for(int i1=0;i1<x.length;i1++) x[i1]=x[i1]+1;
return x; }
Methods can take array as an Argument and Can return Array
public class FirstApp
{
public static void main(String[] args)
{
int b[]={10, 20, 30};
int a[]; a=sum1(b);
for(int i=0;i<a.length;i++)
System.out.println( a[i]);
}
static int [] sum1(int x[])
{
for(int i1=0;i1<x.length;i1++) x[i1]=x[i1]+1;
return x;
}
}
Constructors
• Constructor in java is a special type of method that is used to initialize the object.
• Java constructor is invoked at the time of object creation.
• It constructs the values i.e. provides data for the object that is why it is known as constructor.
• It has the same name as the class in which it resides and is syntactically similar to a method.
Example: Constructors
class Box
{
double width; double height; double depth;
// 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[])
{
Box MYBOX1 = new Box(); Box mybox2 = new Box(); double vol;
vol = MYBOX1.volume(); System.out.println("Volume is " + vol); vol = MYBOX2.volume(); System.out.println("Volume is " + vol);
}
}
}
class Box
{
Parameterized Constructors
double width; double height; double depth;
Box(double w, double h, double d)
{
width = w; height = h; depth = d;
}
// compute and return volume double volume()
{
class BoxDemo7
{
public static void main(String args[])
{
Box MYBOX1 = new BOX(10, 20, 15); Box mybox2 = new Box(3, 6, 9); double vol;
vol = MYBOX1.volume(); System.out.println("Volume is " + vol); vol = MYBOX2.volume(); System.out.println("Volume is " + vol);
}
}
return width * height * depth;
}
}
this Keyword
this can be used inside any method to refer to the current object.
// A redundant use of this. Box(double w, double h, double d)
{
this.width = w; this.height = h; this.depth = d;
}
// Use this to resolve namespace collisions. Box(double width, double height, double depth)
{
this.width = width; this.height = height; this.depth = depth;
}
Garbage Collection
Java 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.
// This class defines an integer stack that can hold 10 values class Stack
{
int stck[] = new int[10]; int tos;
// Initialize top-of-stack Stack()
{
tos = -1;
}
// Push an item onto the stack
void push(int item)
{
if(tos==9)
System.out.println("Stack is full.");
else
}
stck[++tos] = item;
// Pop an item from the stack
int pop()
{
if(tos < 0)
{
}
else
}
}
System.out.println("Stack underflow."); return 0;
return stck[tos--];
class TestStack
{
public static void main(String args[])
{
Stack mystack1 = new Stack(); Stack mystack2 = new Stack();
// push some numbers onto the stack for(int i=0; i<10; i++)
mystack1.push(i); for(int i=10; i<20; i++) mystack2.push(i);
// pop those numbers off the stack System.out.println("Stack in mystack1:"); for(int i=0; i<10; i++)
System.out.println(mystack1.pop()); System.out.println("Stack in mystack2:"); for(int i=0; i<10; i++)
System.out.println(mystack2.pop());
}
}
Overloading Methods
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.
Note: Java uses the type and/or number of arguments as its guide to determine which version of the overloaded method to actually call.
class OverloadDemo
{
void test()
{
System.out.println("No parameters");
}
void test(int a)
{
System.out.println( a);
}
void test(int a, int b)
{
System.out.println( a + " " + b)
}
double test(double a)
{
System.out.println(+ a); return a*a;
} }
} Dr. Ashok Kumar
163
May 9, 2020
// Automatic type conversions apply to overloading. class OverloadDemo {
void test() {
System.out.println("No parameters");
}
// Overload test for two integer parameters. void test(int a, int b) { System.out.println("a and b: " + a + " " + b);
}
// Overload test for a double parameter void test(double a) {
System.out.println(" a: " + a); class Overload {
} public static void main(String args[]) {
} OverloadDemo ob = new OverloadDemo(); int i = 88;
ob.test();
ob.test(10, 20);
ob.test(i); // this will invoke test(double) ob.test(123.2); // this will invoke test(double)
}
}
Overloading Constructors
/* Here, Box defines three constructors to initialize the dimensions of a box various ways.*/ class Box {
double width; double height; double depth;
// constructor used when all dimensions specified Box(double w, double h, double d) {
width = w; height = h; depth = d;
}
Box() { // constructor used when no dimensions specified width = 1; // use 1 to indicate
height = 1; // an uninitialized depth = 1; // box
}
Box(double len) {// constructor used when cube is created width = height = depth = len;
}
// compute and return volume double volume() {
return width * height * depth;
}}
class OverloadCons {
public static void main(String args[]) {
// create boxes using the various constructors Box mybox1 = new Box(10, 20, 15);
Box mybox2 = new Box(); Box mycube = new Box(7); double vol;
// get volume of first box vol = mybox1.volume();
System.out.println("Volume of mybox1 is " + vol);
// get volume of second box vol = mybox2.volume();
System.out.println("Volume of mybox2 is " + vol);
// get volume of cube vol = mycube.volume();
System.out.println("Volume of mycube is " + vol);
}
}
Using Objects as Parameters
// Objects may be passed to methods. class Test
{
int a, b; Test(int i, int j)
{
a = i; b = j;
}
boolean equalTo(Test o)
{
if(o.a == a && o.b == b) return true;
else
return false;
class PassOb
{
public static void main(String args[])
{
Test ob1 = new Test(100, 22); Test ob2 = new Test(100, 22); Test ob3 = new Test(-1, -1);
System.out.println("ob1 == ob2: " + ob1.equalTo(ob2));
System.out.println("ob1 == ob3: " + ob1.equalTo(ob3));
}
}
}
}
// Here, Box allows one object to initialize another. class Box {
double width; double height; double depth;
// Notice this constructor. It takes an object of type Box.
Box(Box ob) { // pass object to constructor width = ob.width;
height = ob.height; depth = ob.depth;
}
// constructor used when all dimensions specified Box(double w, double h, double d) {
width = w; height = h; depth = d;
}
// constructor used when no dimensions specified Box() {
width = 1; // use 1 to indicate height = 1; // an uninitialized depth = 1; // box
}
// constructor used when cube is created Box(double len) {
width = height = depth = len;
}
// compute and return volume double volume() {
return width * height * depth;
}
}
class OverloadCons2 {
public static void main(String args[]) {
// create boxes using the various constructors Box mybox1 = new Box(10, 20, 15);
Box mybox2 = new Box(); Box mycube = new Box(7);
Box myclone = new Box(mybox1); // create copy of mybox1 double vol;
// get volume of first box vol = mybox1.volume();
System.out.println("Volume of mybox1 is " + vol);
// get volume of second box vol = mybox2.volume();
System.out.println("Volume of mybox2 is " + vol);
// get volume of cube vol = mycube.volume();
System.out.println("Volume of cube is " + vol);
// get volume of clone vol = myclone.volume();
System.out.println("Volume of clone is " + vol);
}
}
class Test
{
Argument Passing ( Call by Value and Call by Reference)
class CallByValue
void meth(int i, int j)
{
i *= 2;
j /= 2;
}
}
{
public static void main(String args[]) { Test ob = new Test();
int a = 15, b = 20;
System.out.println("a and b before call: " + a + " " + b);
ob.meth(a, b);
System.out.println("a and b after call: " + a + " " + b);
}
}
Argument Passing ( Call by Value and Call by Reference)
class PassObjRef
class Test { int a, b;
Test(int i, int j)
{
a = i; b = j;
}
// pass an object void meth(Test o)
{
*= 2;
/= 2;
}
}
{
public static void main(String args[])
{
Test ob = new Test(15, 20); System.out.println("ob.a and ob.b before call: " +
ob.a + " " + ob.b); ob.meth(ob);
System.out.println("ob.a and ob.b after call: "
+
ob.a + " " + ob.b);
}
}
Returning Objects
// Returning an object. class Test {
int a; Test(int i) { a = i;
}
Test incrByTen() { Test temp = new Test(a+10);
return temp;
}
}
class RetOb
{
public static void main(String args[])
{
Test ob1 = new Test(2); Test ob2;
ob2 = ob1.incrByTen(); System.out.println("ob1.a: " + ob1.a); System.out.println("ob2.a: " + ob2.a); ob2 = ob2.incrByTen(); System.out.println("ob2.a after second increase: "
+ ob2.a);
}
}
Recursion
class Factorial
{
int fact(int n)
{
int result; if(n==1) return 1;
class Recursion
{
public static void main(String args[])
{
Factorial f = new Factorial(); System.out.println("Factorial of 3 = " +
result = fact(n1) * n; f.fact(3));
return result;
}
}
System.out.println("Factorial of 4 = " + f.fact(4)); System.out.println("Factorial of 5 = " + f.fact(5));
}
}
Access Control (private and public)
When a member of a class is modified by public, then that member can be accessed by any other code. When a member of a class is specified as private, then that member can only be accessed by other members of its class. When no access modifier is used, then by default the member of a class is public within its own package, but cannot be accessed outside of its
/* Difference between public and private */
class Test
{
int a; // default access public int b; // public access
private int c; // private access
// 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());
}
}
Example: Stack class
class Stack
{
private int stck[] = new int[10]; private int tos;
// Initialize topofstack Stack() {
tos = 1;
}
// Push an item onto the stack void push(int item) { if(tos==9)
System.out.println("Stack is full."); else
stck[++tos] = item;
}
// Pop an item from the stack int pop() {
if(tos < 0) { System.out.println("Stack underflow.");
return 0;
}
else
return stck[tos];
}
}
class TestStack
{
public static void main(String args[])
{
Stack mystack1 = new Stack(); Stack mystack2 = new Stack();
// push some numbers onto the stack for(int i=0; i<10; i++) MYSTACK1.Push(i); for(int i=10; i<20; i++) MYSTACK2.push(i);
// pop those numbers off the stack System.out.println("Stack in mystack1:"); for(int i=0; i<10; i++) System.out.println(mystACK1.Pop()); System.out.println("Stack in mystack2:"); for(int i=0; i<10; i++) System.out.println(mystACK2.pop());
// mystack1.TOS = 2; // illegal statements
// mystack2.Stck[3] = 100;
}
}
Static keyword
The static keyword can be applied with variables, methods, blocks and nested class.
When a member is declared static, it can be accessed before any objects of its class are created, and without reference to any object.
Methods declared as static have several restrictions:
They can only directly call other static methods.
They can only directly access static data.
They cannot refer to this or super in any way.
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.
// Demonstrate static variables, methods, and blocks.
class UseStatic
{
static int a = 3; static int b;
static void meth(int x) { System.out.println("x = " + x); System.out.println("a = " + a); System.out.println("b = " + b);
}
static {
System.out.println("Static block initialized."); b = a * 4;
}
public static void main(String args[])
{
meth(42);
}
}
/* Program when main() is not reached */
public class ProgramWithoutMainMethod
{
static
{
System.out.println("Look at me ! I am running without
Main method"); System.exit(0);
}
public static void main(String args[])
{
System.out.println("Am I here ?");
}
}
Example: static variable
class Student{ int rollno; String name;
static String college ="ITS"; Student(int r,String n){ rollno = r;
name = n;
}
void display ()
{System.out.println(rollno+" "+name+" “
+college);} }
public static void main(String args[]){ System.out.println(Student .college); Student s1 = new Student(111,"Karan"); Student s2 = new Student(222,"Aryan"); s1.display();
s2.display();
}
public class Area
{
static void triangleArea(double l1, double l2, double l3)
{
double s = (l1 + l2 + l3) / 2;
double areaDouble = s*(s l1)*(s l2)*(s l3); double area = Math.sqrt(areaDouble); System.out.println("Triangle area = " + area);
}
public static void main(String[] args)
{
double l1 = 2.23, l2= 2.1, l3 = 2.3; triangleArea(l1, l2, l3);
}
}
class StaticDemo
{
static int a = 42; static int b = 99; static void callme() {
Here inside main( ), the static method callme( ) and the static variable b are accessed through their class name StaticDemo.
System.out.println("a = " + a);
}
}
class StaticByName {
public static void main(String args[])
{
StaticDemo.callme(); System.out.println("b = " + StaticDemo.b);
}
}
// Improved Stack class that uses the length array member.
class Stack { private int stck[]; private int tos;
// allocate and initialize stack Stack(int size) {
stck = new int[size]; tos = 1;
}
// Push an item onto the stack void push(int item) { if(tos==stck.length1)
System.out.println("Stack is full."); else
stck[++tos] = item;
}
// Pop an item from the stack int pop() {
if(tos < 0) {
System.out.println("Stack underflow."); return 0;
} else
return stck[tos];
}}
class TestStack2
{
public static void main(String args[]) { Stack mystack1 = new Stack(5);
Stack mystack2 = new Stack(8);
// push some numbers onto the stack for(int i=0; i<5; i++) mystack1.push(i); for(int i=0; i<8; i++) mystack2.push(i);
// pop those numbers off the stack System.out.println("Stack in mystack1:"); for(int i=0; i<5; i++) System.out.println(mystack1.pop()); System.out.println("Stack in mystack2:"); for(int i=0; i<8; i++) System.out.println(mystack2.pop());
}
}
Nested and Inner Classes
There are two types of nested classes: static and non-static. The scope of a nested class is bounded by the scope of its enclosing class. A nested class has access to the members, including private members, of the class in which it is nested. However, the enclosing class does not have access to the members of the nested class. A static nested class is one that has the static modifier applied. Because it is static, it must access the non-static members of its enclosing class through an object. 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.
// Demonstrate an inner class. class Outer
{
int outer_x = 100; void test() {
Inner inner = new Inner(); inner.display();
}
// this is an inner class class Inner {
void display() { System.out.println("display: outer_x = " + outer_x);
}
}
}
class InnerClassDemo
{
public static void main(String args[])
{
Outer outer = new Outer(); outer.test();
}
}
// Guess the output class Outer {
int outer_x = 100; void test() {
Inner inner = new Inner(); inner.display();
}
// this is an inner class class Inner {
int y = 10; // y is local to Inner void display() {
System.out.println("display: outer_x = " + outer_x);
}
}
void showy() { System.out.println(y);
}}
class InnerClassDemo
{
public static void main(String args[])
{
Outer outer = new Outer(); outer.test();
}
}
// Define an inner class within a for class InnerClassDemo
loop. {
class Outer { public static void main(String args[])
int outer_x = 100; {
void test() { Outer outer = new Outer();
for(int i=0; i<10; i++) { outer.test();
class Inner { }
void display() { }
System.out.println("display: outer_x =
" + outer_x);
}
}
Inner inner = new Inner();
inner.display();
}
}
}
Command-Line Arguments
To access the commandline arguments inside a Java program is quite easy—they are stored as strings in a String array passed to the args parameter of main( ). The first commandline argument is stored at args[0], the second at args[1], and so on.
// Display all commandline arguments. class CommandLine
{
public static void main(String args[])
{
for(int i=0; i<args.length; i++) System.out.println("args[" + i + "]: " + args[i]);
}
}
java CommandLine this is a test 100 1
Variable-Length Arguments
A method that takes a variable number of arguments is called a variable-arity method, or simply a varargs, short for variable-length arguments, method. A variablelength argument is specified by three periods (…).
For example,
static void vaTest(int ... v)
{
}
This syntax tells the compiler that vaTest( ) can be called with zero or more arguments. As a result, v is implicitly declared as an array of type int[ ].
A method can have “normal” parameters along with a variablelength parameter. However, the variablelength parameter must be the last parameter declared by the method. There must be only one varargs parameter.
class VarArgs {
// vaTest() now uses a vararg. static void vaTest(int ... v) {
System.out.print("Number of args: " + v.length +" Contents: "); for(int x : v)
System.out.print(x + " "); System.out.println();
}
public static void main(String args[])
{
// Notice how vaTest() can be called with a
// variable number of arguments. vaTest(10); // 1 arg
vaTest(1, 2, 3); // 3 args vaTest(); // no args
}
}
// Use varargs with standard arguments.
class VarArgs2 {
// msg a normal parameter and v a varargs parameter. static void vaTest(String msg, int ... v)
{
System.out.print(msg + v.length + " Contents: "); for(int x : v)
System.out.print(x + " "); System.out.println();
}
public static void main(String args[])
{
vaTest("One vararg: ", 10); vaTest("Three varargs: ", 1, 2, 3); vaTest("No varargs: ");
}}
Overloading Vararg Methods
// Varargs and overloading. class VarArgs3 {
static void vaTest(int ... v) { System.out.print("vaTest(int ...): " + "Number of args: " + v.length +
" Contents: "); for(int x : v)
System.out.print(x + " "); System.out.println();
}
static void vaTest(boolean ... v) { System.out.print("vaTest(boolean ...) "
+
"Number of args: " + v.length + " Contents: ");
for(boolean x : v) System.out.print(x + " "); System.out.println();
}
static void vaTest(String msg, int ... v) { System.out.print("vaTest(String, int ...): "
+
msg + v.length + " Contents: "); for(int x : v)
System.out.print(x + " "); System.out.println();
}
public static void main(String args[])
{
vaTest(1, 2, 3);
vaTest("Testing: ", 10, 20); vaTest(true, false, false);
}
}
Inheritance
Inheritance
Using inheritance, you can create a general class that defines traits common to a set of related items. This class can then be inherited by other, more specific classes, each adding those things that are unique to it. A class that is inherited is called a superclass. The class that does the inheriting is called a subclass. You can only specify one superclass for any subclass that you create. Java does not support the inheritance of multiple superclasses into a single subclass. We can create a hierarchy of inheritance in which a subclass becomes a superclass of another subclass. However, no class can be a superclass of itself.
// Example: Inheritance. // extending class A.
// Create a superclass. class B extends A
class A {
{ int k;
int i, j; void showk()
void showij() {
{ System.out.println("k: " + k);
System.out.println("i and j: " + i }
+ " " + j); void sum()
} {
} System.out.println("i+j+k: " +
(i+j+k));
}
}
class SimpleInheritance {
public static void main(String args []) { A superOb = new A();
B subOb = new B();
// The superclass may be used by itself. superOb.i = 10;
superOb.j = 20; System.out.println("Contents of superOb: "); superOb.showij();
System.out.println();
/* The subclass has access to all public members of its superclass. */ subOb.i = 7;
subOb.j = 8;
subOb.k = 9;
System.out.println("Contents of subOb: "); subOb.showij();
subOb.showk(); System.out.println();
System.out.println("Sum of i, j and k in subOb:"); subOb.sum();
}
}
Member Access and Inheritance
/*This program contains an error and will not compile.
*/
// Create a superclass. class A {
int i; // public by default private int j; // private to A void setij(int x, int y) {
i = x; j = y;
}
}
// A's j is not accessible here. class B extends A {
int total; void sum() {
total = i + j; // ERROR, j is not accessible here
}
}
Although a subclass includes
all of the members of its superclass, it cannot access those members of the superclass that have been declared as private.
class Access {
public static void main(String args[]) { B subOb = new B();
subOb.setij(10, 12); subOb.sum();
System.out.println("Total is " + subOb.total);
}
}
// This program uses inheritance to extend // constructor used when no dimensions
Box. specified
class Box { Box() {
double width; width = 1; // use 1 to indicate
double height; height = 1; // an uninitialized
double depth; depth = 1; // box
// construct clone of an object }
Box(Box ob) { // pass object to constructor // constructor used when
width = ob.width; //cube is created
height = ob.height; Box(double len) {
depth = ob.depth; width = height = depth = len;
} }
// constructor used when all dimensions // compute and return volume
specified double volume() {
Box(double w, double h, double d) { return width * height * depth;
width = w; }
height = h; }
depth = d;
}
// Here, Box is extended to include weight.
class BoxWeight extends Box { double weight; // weight of box
// constructor for BoxWeight BoxWeight(double w, double h, double d, double m) {
width = w; height = h; depth = d; weight = m;
}
} class DemoBoxWeight {
public static void main(String args[]) { BoxWeight mybox1 = new BoxWeight(10, 20, 15, 34.3);
BoxWeight mybox2 = new BoxWeight(2, 3, 4, 0.076); double vol;
vol = mybox1.volume(); System.out.println("Volume of mybox1 is " + vol);
System.out.println("Weight of mybox1 is " + mybox1.weight); System.out.println();
vol = mybox2.volume(); System.out.println("Volume of mybox2 is " + vol);
System.out.println("Weight of mybox2 is " + mybox2.weight);
}
}
Dr. Ashok Kumar 20 3 May 9, 2020
A Superclass Variable Can Reference a Subclass Object
class RefDemo {
public static void main(String args[]) {
BoxWeight weightbox = new BoxWeight(3, 5, 7, 8.37); Box plainbox = new Box();
double vol;
vol = weightbox.volume(); System.out.println("Volume of weightbox is " + vol);
System.out.println("Weight of weightbox is " + weightbox.weight); System.out.println();
// assign BoxWeight reference to Box reference plainbox = weightbox;
vol = plainbox.volume(); // OK, volume() defined in Box System.out.println("Volume of plainbox is " + vol);
/* The following statement is invalid because plainbox does not define a weight member. */
// System.out.println("Weight of plainbox is " + plainbox.weight);
}
}
super
Whenever a subclass needs to refer to its immediate superclass, it can do so by use of the keyword super. super has two general forms. The first calls the superclass’ constructor. The second is used to access a member of the superclass that has been hidden by a member of a subclass.
// BoxWeight now uses super to initialize its Box attributes. class BoxWeight extends Box
{
double weight; // weight of box
// initialize width, height, and depth using super() BoxWeight(double w, double h, double d, double m) { super(w, h, d); // call superclass constructor
weight = m;
}
}
// A complete implementation of // constructor used when no dimensions
BoxWeight. specified
class Box { Box() {
private double width; width = 1; // use 1 to indicate
private double height; height = 1; // an uninitialized
private double depth; depth = 1; // box
// construct clone of an object }
Box(Box ob) { // pass object to // constructor used when
constructor //cube is created
width = ob.width; Box(double len) {
height = ob.height; width = height = depth = len;
depth = ob.depth; }
} // compute and return volume
// constructor used when all dimensions double volume() {
specified return width * height * depth;
Box(double w, double h, double d) { }
width = w; }
height = h;
depth = d;
}
Dr. Ashok Kumar 20 6 May 9, 2020
// BoxWeight now fully implements all constructors. class BoxWeight extends Box {
double weight; // weight of box
// construct clone of an object
BoxWeight(BoxWeight ob) { // pass object to constructor super(ob);
weight = ob.weight;
}
// constructor when all parameters are specified BoxWeight(double w, double h, double d, double m) { super(w, h, d); // call superclass constructor
weight = m;
}
// default constructor BoxWeight() { super();
weight = 1;}
// constructor used when cube is created BoxWeight(double len, double m) { super(len);
weight = m;
}}
class DemoSuper {
public static void main(String args[]) {
BoxWeight mybox1 = new BoxWeight(10, 20, 15, 34.3);
BoxWeight mybox2 = new BoxWeight(2, 3, 4, 0.076); BoxWeight mybox3 = new BoxWeight(); // default BoxWeight mycube = new BoxWeight(3, 2); BoxWeight myclone = new BoxWeight(mybox1); double vol;
vol = mybox1.volume(); System.out.println("Volume of mybox1 is " + vol);
System.out.println("Weight of mybox1 is " + mybox1.weight); System.out.println();
vol = mybox2.volume(); System.out.println("Volume of mybox2 is " + vol);
System.out.println("Weight of mybox2 is " + mybox2.weight); System.out.println();
vol = mybox3.volume(); System.out.println("Volume of mybox3 is " + vol);
System.out.println("Weight of mybox3 is " + mybox3.weight); System.out.println();
vol = myclone.volume(); System.out.println("Volume of myclone is " + vol);
System.out.println("Weight of myclone is " + myclone.weight); System.out.println();
vol = mycube.volume(); System.out.println("Volume of mycube is " + vol);
System.out.println("Weight of mycube is " + mycube.weight); System.out.println();}}
A Second Use for super
The second form of super acts somewhat like this, except that it always refers to the superclass of the subclass in which it is used. This usage has the following general form:
super.member
Here, member can be either a method or an instance variable.
This second form of super is most applicable to situations in which member names of a subclass hide members by the same name in the superclass
// Using super to overcome name hiding.
class A { int i;
}
// Create a subclass by extending class A. class B extends A {
int i; // this i hides the i in A B(int a, int b) {
super.i = a; // i in A i = b; // i in B
}
void show() {
System.out.println("i in superclass: " + super.i); System.out.println("i in subclass: " + i);
}
}
class UseSuper {
public static void main(String args[]) { B subOb = new B(1, 2); subOb.show();
}
}
Creating a Multilevel Hierarchy
You can build hierarchies that contain as many layers of inheritance as you like. As mentioned, it is perfectly acceptable to use a subclass as a superclass of another.
// Extend BoxWeight to include shipping // constructor used when no dimensions
costs. specified
// Start with Box. Box() {
class Box { width = 1; // use 1 to indicate
private double width; height = 1; // an uninitialized
private double height; depth = 1; // box
private double depth; }
// construct clone of an object // constructor used when cube is created
Box(Box ob) Box(double len) {
{ // pass object to constructor width = height = depth = len;
width = ob.width; }
height = ob.height; // compute and return volume
depth = ob.depth; double volume() {
} return width * height * depth;
}
Box(double w, double h, double d) { }
width = w;
height = h;
depth = d;
}
// Add weight.
class BoxWeight extends Box { double weight; // weight of box
// construct clone of an object
BoxWeight(BoxWeight ob) { // pass object to constructor super(ob);
weight = ob.weight;
}
// constructor when all parameters are specified BoxWeight(double w, double h, double d, double m) { super(w, h, d); // call superclass constructor
weight = m;
}
// default constructor BoxWeight() { super();
weight = 1;
}
// constructor used when cube is created BoxWeight(double len, double m) { super(len);
weight = m;
}}
// Add shipping costs.
class Shipment extends BoxWeight { double cost;
// construct clone of an object
Shipment(Shipment ob) { // pass object to constructor super(ob);
cost = ob.cost;
}
// constructor when all parameters are specified Shipment(double w, double h, double d,double m, double c) { super(w, h, d, m); // call superclass constructor
cost = c;
}
// default constructor Shipment() { super();
cost = 1;
}
// constructor used when cube is created Shipment(double len, double m, double c) { super(len, m);
cost = c;
}}
class DemoShipment {
public static void main(String args[]) {
Shipment shipment1 = new Shipment(10, 20, 15, 10, 3.41);
Shipment shipment2 = new Shipment(2, 3, 4, 0.76, 1.28); double vol;
vol = shipment1.volume(); System.out.println("Volume of shipment1 is " + vol);
System.out.println("Weight of shipment1 is “ + shipment1.weight); System.out.println("Shipping cost: $" + shipment1.cost); System.out.println();
vol = shipment2.volume(); System.out.println("Volume of shipment2 is " + vol);
System.out.println("Weight of shipment2 is “ + shipment2.weight); System.out.println("Shipping cost: $" + shipment2.cost);
}
}
// Demonstrate when constructors are executed.
// Create a super class. class A {
A() { System.out.println("Inside A's constructor."); }
}
// Create a subclass by extending class A. class B extends A {
B() { System.out.println("Inside B's constructor."); }
}
// Create another subclass by extending B. class C extends B {
C() { System.out.println("Inside C's constructor."); }
}
class CallingCons {
public static void main(String args[]) { C c = new C();}}
Method Overriding
In a class hierarchy, when a method in a subclass has the same name and type signature as a method in its superclass, then the method in the subclass is said to override the method in the superclass.
// Method overriding. class A {
int i, j;
A(int a, int b) { i = a;
j = b;
}
// display i and j void show() {
System.out.println("i and j: " + i + " " + j);
}}
class B extends A
{
int k;
B(int a, int b, int c) { super(a, b);
k = c;
}
// display k – this overrides show() in A void show() {
System.out.println("k: " + k);
}
}
class Override
{
public static void main(String args[])
{
B subOb = new B(1, 2, 3); subOb.show(); // this calls show() in B
}
}
If you wish to access the superclass version of an overridden method, you can do so by using super.
class B extends A { int k;
B(int a, int b, int c) { super(a, b);
k = c;
}
void show() {
super.show(); // this calls A's show() System.out.println("k: " + k);
}
}
Note: Method overriding occurs only when the names and the type signatures of the two methods are identical. If they are not, then the two methods are simply overloaded.
// Methods with differing type signatures are overloaded–not overridden.
class A { // Create a subclass by extending
int i, j; class A.
A(int a, int b) { class B extends A {
i = a; int k;
j = b; B(int a, int b, int c) {
} super(a, b);
// display i and j k = c;
void show() }
{ // overload show()
System.out.println("i and j: " + i void show(String msg)
+ " " + j); {
} System.out.println(msg + k);
} }}
class Override
{
public static void main(String args[])
{
B subOb = new B(1, 2, 3);
subOb.show("This is k: "); // this calls show() in B subOb.show(); // this calls show() in A
}
}
Dynamic Method Dispatch
Dynamic method dispatch is the mechanism by which a call to an overridden method is resolved at run time, rather than compile time. Dynamic method dispatch is important because this is how Java implements runtime polymorphism.
// Dynamic Method Dispatch class B extends A
class A {
{ // override callme()
void callme() void callme()
{ {
System.out.println("Inside A's System.out.println("Inside B's
callme method"); callme method");
} }
} }
class C extends A {
// override callme() void callme() {
System.out.println("Inside C's callme method");
}}
class Dispatch {
public static void main(String args[]) { A a = new A(); // object of type A
B b = new B(); // object of type B C c = new C(); // object of type C A r; // obtain a reference of type A r = a; // r refers to an A object
r.callme(); // calls A's version of callme r = b; // r refers to a B object r.callme(); // calls B's version of callme r = c; // r refers to a C object
r.callme(); // calls C's version of callme
}
}
// Using runtime polymorphism. class Figure {
double dim1; double dim2;
Figure(double a, double b) { dim1 = a;
dim2 = b;
}
double area() { System.out.println("Area for Figure is undefined.");
return 0;
}
}
class Rectangle extends Figure class Triangle extends Figure
{ {
Rectangle(double a, double b) Triangle(double a, double b)
{ {
super(a, b); super(a, b);
} }
// override area for rectangle // override area for right triangle
double area() double area()
{ {
System.out.println("Inside Area System.out.println("Inside Area
for Rectangle."); for Triangle.");
return dim1 * dim2; return dim1 * dim2 / 2;
} }
} }
class FindAreas
{
public static void main(String args[])
{
Figure f = new Figure(10, 10); Rectangle r = new Rectangle(9, 5); Triangle t = new Triangle(10, 8); Figure figref;
figref = r;
System.out.println("Area is " + figref.area()); figref = t;
System.out.println("Area is " + figref.area()); figref = f;
System.out.println("Area is " + figref.area());
}
}
Abstract Classes
There are situations in which you will want to define a superclass that declares the structure of a given abstraction without providing a complete implementation of every method. That is, sometimes you will want to create a superclass that only defines a generalized form that will be shared by all of its subclasses, leaving it to each subclass to fill in the details. Such a class determines the nature of the methods that the subclasses must implement.
// A Simple demonstration of abstract. abstract class A {
abstract void callme();
// concrete methods are still allowed in abstract classes void callmetoo() {
System.out.println("This is a concrete method.");
}
}
class B extends A { void callme() {
System.out.println("B's implementation of callme.");
}
}
class AbstractDemo {
public static void main(String args[]) { B b = new B();
b.callme(); b.callmetoo();
}
}
Final Keyword
An instance variable can be declared as final. Doing so prevents its contents from being modified, making it, essentially, a constant. This means that you must initialize a final field when it is declared. You can do this in one of two ways: First, you can give it a value when it is declared.
Second, you can assign it a value within a constructor. final int FILE_NEW = 1; final int FILE_OPEN = 2;;
In addition to fields, both method parameters and local variables can be declared final. Declaring a parameter final prevents it from being changed within the method. Declaring a local variable final prevents it from being assigned a value more than once.
The keyword final can also be applied to methods, but its meaning is substantially different than when it is applied to variables.
Examples: Final Variables
//Final instance variable class Bike9{
final int speedlimit=90;//final variable
void run(){ speedlimit=400; // error
}
public static void main(String args[]){
Bike9 obj=new Bike9(); obj.run();
}
}
// Final Parameter class Bike11{
int cube(final int n){ n=n+2;//can't be changed as n
is final
return n*n*n;
}
public static void main(String args[]){
Bike11 b=new Bike11(); b.cube(5);
}
}
About Static blank final variable
class A
{
static final int data;//static blank final variable static{ data=50;}
public static void main(String args[])
{
System.out.println(A.data);
}
}
Blank final variable
class Bike10
{
final int speedlimit;//blank final variable
Bike10(){ speedlimit=70;
System.out.println(speedlimit);
}
public static void main(String args[])
{
new Bike10();
}
}
Final to Prevent Overriding in Methods
class A
{
final void meth()
{
System.out.println("This is a final method.");
}
}
Final to Prevent Inheritance
Sometimes you will want to prevent a class from being inherited. To do this, precede the class declaration with final. Declaring a class as final implicitly declares all of its methods as final, too. As you might expect, it is illegal to declare a class as both abstract and final since an abstract class is incomplete by itself and relies upon its subclasses to provide complete
implementations
final class A
{
//...
}
// The following class is illegal.
Object Class
All other classes are subclasses of Object. This means that a reference variable of type Object can refer to an object of any other class.
Method Purpose
Object clone( ) Creates a new object that is the same as the object being cloned.
boolean equals(Object object) Determines whether one object is equal to another.
void finalize( ) Called before an unused object is recycled.
final Class<?> getClass( ) Obtains the class of an object at run time.
int hashCode( ) Returns the hash code associated with the invoking object.
final void notify( ) Resumes execution of a thread waiting on the invoking object.
final void notifyAll( ) Resumes execution of all threads waiting on the invoking object.
String toString( ) Returns a string that describes the object.
void wait( )
void wait(long milliseconds) void wait(long milliseconds, int nanoseconds)
Waits on another thread of execution
Packages
Packages
Packages are containers for classes. They are used to keep the class name space compartmentalized.
A package allows you to create a class named List, which you can store in your own package without concern that it will collide with some other class named List stored elsewhere.
Defining a Package
This is the general form of the package statement: package pkg; // pkg is the name of the package For example:
package MyPackage;
Multilevel package statement:
package pkg1[.pkg2[.pkg3]];
Here pkg2 will be sub-directory of pkg1 and pkg3 is sub- directory of.pkg2
Java uses file system directories to store packages. For example, the .class files for any classes you declare to be part of MyPackage must be stored in a directory called MyPackage. Remember that case is significant, and the directory name must match the package name exactly.
Java provides many levels of protection to allow fine- grained control over the visibility of variables and methods within classes, subclasses, and packages. Java addresses four categories of visibility for class members:
Subclasses in the same package
Non-subclasses in the same package
Subclasses in different packages
Classes that are neither in the same package nor subclasses
The three access modifiers, private, public, and protected, provide a variety of ways to produce the many levels of access required by these categories.
Private No Modifier Protected Public
Same class Yes Yes Yes Yes
Same package subclass No Yes Yes Yes
Same package non subclass No Yes Yes Yes
Different package subclass No No Yes Yes
Different package non subclass No No No Yes
// A simple package package MyPack; class Balance
{
String name;
Balance(String n, double b)
{
name = n; bal = b;
}
void show()
{
if(bal<0) System.out.print(">> ");
System.out.println(name + ": $" + bal);
}
class AccountBalance
{
public static void main(String args[])
{
Balance current[] = new Balance[3]; current[0] = new Balance("K. J.
Fielding", 123.23);
current[1] = new Balance("Will Tell", 157.02);
current[2] = new Balance("Tom Jackson", 12.33);
i=0; i<3; i++) current[i].show();
}}
}
package p1;
public class Protection { int n = 1;
private int n_pri = 2; protected int n_pro = 3; public int n_pub = 4; public Protection() {
System.out.println("base constructor"); System.out.println("n = " + n); System.out.println("n_pri = " + n_pri); System.out.println("n_pro = " + n_pro); System.out.println("n_pub = " + n_pub);
}
}
package p1;
class Derived extends Protection
{
Derived()
{
System.out.println("derived constructor"); System.out.println("n = " + n);
// class only
// System.out.println("n_pri = "+ n_pri); System.out.println("n_pro = " + n_pro); System.out.println("n_pub = " + n_pub);
}
}
package p1;
class SamePackage
{
SamePackage()
{
Protection p = new Protection(); System.out.println("same package constructor"); System.out.println("n = " + p.n);
// class only
// System.out.println("n_pri = " + p.n_pri); System.out.println("n_pro = " + p.n_pro); System.out.println("n_pub = " + p.n_pub);
}
}
package p1; // Instantiate the various classes in p1.
public class Demo
{
public static void main(String args[])
{
Protection ob1 = new Protection(); Derived ob2 = new Derived(); SamePackage ob3 = new SamePackage();
}
}
package p2;
class Protection2 extends p1.Protection
{
Protection2()
{
System.out.println("derived other package constructor");
// class or package only
// System.out.println("n = " + n);
Package p2;
class OtherPackage
{
OtherPackage()
{
p1.Protection p = new p1.Protection();
// class or package only
//package p2;
// Instantiate the various classes in p2. public class Demo1
{
public static void main(String args[])
{
Protection2 ob1 = new Protection2(); OtherPackage ob2 = new OtherPackage();
}
}
Importing Packages
This is the general form of the import statement:
import pkg1 [.pkg2].(classname | *);
Here, pkg1 is the name of a toplevel package, and pkg2 is the name of a subordinate package inside the outer package separated by a dot (.). There is no practical limit on the depth of a package hierarchy, except that imposed by the file system. Finally, you specify either an explicit classname or a star (*), which indicates that the Java compiler should import the entire package. This code fragment shows both forms in use:
import java.util.Date; import java.io.*;
java.lang.* is implicitly imported by the compiler for all programs.
package MyPack;
This means that they can be used by nonsubclass code outside their package.
*/
public class Balance { String name;
double bal;
import MyPack.*;
class TestBalance
{
public static void main(String args[])
{
Interfaces
Interfaces are syntactically similar to classes, but they lack instance variables, and, as a general rule, their methods are declared without any body. Any number of classes can implement an interface. One class can implement any number of interfaces. To implement an interface, a class must provide the complete set of methods required by the interface. However, each class is free to determine the details of its own implementation. By providing the interface keyword, Java allows you to fully utilize the “one interface, methods” aspect of polymorphism.
Defining an Interface
This is a simplified general form of an interface:
access interface name {
return-type method-name1(parameter-list); return-type method-name2(parameter-list); type final-varname1 = value;
type final-varname2 = value;
//...
return-type method-nameN(parameter-list); type final-varnameN = value;
}
The methods that are declared have no bodies. They end with a semicolon after the parameter list. They are, essentially, abstract methods. Variables are implicitly final and static, meaning they cannot be changed by the implementing class. They must also be initialized. All methods and variables are implicitly public. Each class that includes such an interface must implement all of the methods.
Implementing Interfaces
Once an interface has been defined, one or more classes can implement that interface. To implement an interface, include the implements clause in a class definition, and then create the methods required by the interface. The general form of a class that includes the implements clause looks like this:
class classname [extends superclass] [implements interface [,interface...]]
{
// classbody
}
If a class implements more than one interface, the interfaces are separated with a comma. If a class implements two interfaces that declare the same method, then the same method will be used by clients of either interface. The methods that implement an interface must be declared public. Also, the type signature of the implementing method must match exactly the type signature specified in the interface definition.
interface Callback
{
void callback(int param);
} class Client implements Callback {
// Implement Callback's interface public void callback(int p) {
System.out.println("callback called with " + p);
}
}
class TestIface {
public static void main(String args[]) { Callback c = new Client(); c.callback(42);
}
}
It is both permissible and common for classes that implement interfaces to define additional members of their own. For example, the following version of Client implements callback( ) and adds the method nonIfaceMeth( ):
class Client implements Callback {
// Implement Callback's interface public void callback(int p) {
System.out.println("callback called with " + p);
}
void nonIfaceMeth() {
System.out.println("Classes that implement interfaces " +
"may also define other members, too.");
}
}
class TestIface {
public static void main(String args[]) { Callback c = new Client(); c.callback(42);
}
}
Although c can be used to access the callback( ) method, it cannot access any other members of the Client class. An interface reference variable has knowledge only of the methods declared by its interface declaration
interface Callback {
void callback(int param);
}
class Client implements Callback {
// Implement Callback's interface public void callback(int p) { System.out.println("callback called with " + p);
} }
// Another implementation of Callback. class AnotherClient implements Callback {
// Implement Callback's interface public void callback(int p) { System.out.println("Another version of callback");
System.out.println("p squared is " + (p*p));
}}
class TestIface2
{
public static void main(String args[])
{
Callback c = new Client(); AnotherClient ob = new AnotherClient(); c.callback(42);
c = ob; // c now refers to AnotherClient object
allback(42);
}
}
Partial Implementations
If a class includes an interface but does not fully implement the methods required by that interface, then that class must be declared as abstract.
abstract class Incomplete implements Callback
{
int a, b; void show()
{
System.out.println(a + " " + b);
}
//...
}
Nested Interfaces
An interface can be declared a member of a class or another interface. Such an interface is called a member interface or a nested interface. A nested interface can be declared as public, private, or protected. This differs from a toplevel interface, which must either be declared as public or use the default access level. When a nested interface is used outside of its enclosing scope, it must be qualified by the name of the class or interface of which it is a member. Thus, outside of the class or interface in which a nested interface is declared, its name must be fully qualified.
// A nested interface example. class NestedIFDemo {
// This class contains a member public static void main(String args[]) {
interface. // use a nested interface reference
class A { A.NestedIF nif = new B();
// this is a nested interface if(nif.isNotNegative(10))
public interface NestedIF { System.out.println("10 is not
boolean isNotNegative(int x); negative");
} if(nif.isNotNegative(12))
} System.out.println("this won't be
// B implements the nested interface. displayed");
class B implements A.NestedIF { }
public boolean isNotNegative(int x) { }
return x < 0 ? false: true;
}
}
class Test implements Showable.Message
{
public void msg(){System.out.println("Hello nested interface");} public static void main(String args[])
{
Showable.Message message=new Test();//upcasting here message.msg();
}}
Variables in Interfaces
import java.util.Random; interface SharedConstants
{
int NO = 0; int YES = 1;
int MAYBE = 2; int LATER = 3; int SOON = 4; int NEVER = 5;
}
class Question implements SharedConstants
{
Random rand = new Random(); int ask() {
int prob = (int) (100 * rand.nextDouble()); if (prob < 30)
return NO; // 30% else if (prob < 60) return YES; // 30% else if (prob < 75) return LATER; // 15% else if (prob < 98) return SOON; // 13% else
return NEVER; // 2%
}
}
class AskMe implements SharedConstants {
static void answer(int result) { switch(result) {
case NO: System.out.println("No"); break;
case YES: System.out.println("Yes"); break;
case MAYBE: System.out.println("Maybe"); break;
case LATER: System.out.println("Later"); break;
case SOON: System.out.println("Soon"); break;
case NEVER: System.out.println("Never"); Break;}}
public static void main(String args[]) {
Question q = new Question(); answer(q.ask());
answer(q.ask());
answer(q.ask());
answer(q.ask());
}
}
Interfaces Can Be Extended
One interface can inherit another by use of the keyword extends. The syntax is the same as for inheriting classes.
// This class must implement all of A and B class MyClass implements B {
public void meth1() { System.out.println("Implement meth1().");
}
public void meth2() { System.out.println("Implement meth2().");
}
public void meth3() { System.out.println("Implement meth3().");
}
}
class IFExtend {
public static void main(String arg[]) { MyClass ob = new MyClass(); ob.meth1();
ob.meth2();
ob.meth3();
}}
Default Interface Methods
Prior to JDK 8, an interface could not define any implementation whatsoever. This meant that for all previous versions of Java, the methods specified by an interface were abstract, containing no body. This is the traditional form of an interface and is the type of interface that the preceding discussions have used. The release of JDK 8 has changed this by adding a new capability to interface called the default method. A default method lets you define a default implementation for an interface method. In other words, by use of a default method, it is now possible for an interface method to provide a body, rather than being abstract. It is important to point out that the addition of default methods does not change a key aspect of interface: its inability to maintain state information. An interface still cannot have instance variables.
Default Method ( JDK 8)
An interface default method is defined similar to the way a method is defined by a class. The primary difference is that the declaration is preceded by the keyword default.
// Implement MyIF.
class MyIFImp implements MyIF {
// Only getNumber() defined by MyIF needs to be implemented.
// getString() can be allowed to default. public int getNumber() {
return 100;
}
} // Use the default method. class DefaultMethodDemo
{
public static void main(String args[]) { MyIFImp obj = new MyIFImp();
// Can call getNumber(), because it is explicitly
// implemented by MyIFImp: System.out.println(obj.getNumber());
// Can also call getString(), because of default
// implementation: System.out.println(obj.getString());
}
}
It is both possible and common for an implementing class to define its own implementation of a default method.
For example, MyIFImp2 overrides getString( ):
class MyIFImp2 implements MyIF
{
// Here, implementations for both getNumber( ) and getString( ) are provided. public int getNumber() {
return 100;
}
public String getString() {
return "This is a different string.";
}
}
Now, when getString( ) is called, a different string is returned
Multiple Inheritance Issue
Java does not support the multiple inheritance of classes.
Now that an interface can include default methods, you might be wondering if an interface can provide a way around this restriction.
The answer is, essentially, NO.
As there is still a key difference between a class and an interface: a class can maintain state information (especially through the use of instance variables), but an interface cannot. default methods do offer a bit of what one would normally associate with the concept of multiple inheritance. For example, you might have a class that implements two interfaces. If each of these interfaces provides default methods, then some behavior is inherited from both. Thus, to a limited extent, default methods do support multiple inheritance of behavior.
*What if name conflict will occur.
More Points on Inheritance
IS-A Relationship
class C1
{
…
}
class C2 extends C1
{
…..
}
Has-A relationship
class C1
{
…
}
Uses-A relationship
class C1
{
…
}
Example on aggregation Has-A type
class Operation{ int square(int n){ return n*n;
}
}
class Circle{
Operation op;//aggregation double pi=3.14;
Dr. Ashok Kumar 279
May 9, 2020
Exception Handling
An exception is an abnormal condition that arises in a code sequence at run time. In other words, an exception is a runtime error.
In computer languages that do not support exception handling, errors must be checked and handled manually—typically through the use of error codes, and so on.
In Java, exception is an object (either of inbuilt class or of user defined class) that describes an exceptional (that is, error) condition that has occurred in a piece of code. When an exceptional condition arises, an object representing that exception is created and thrown in the method that caused the error.
Java exception handling is managed via five keywords: try, catch, throw, throws, and finally.
This is the general form of an exceptionhandling block:
try {
// block of code to monitor for errors
}
catch (ExceptionType1 exOb)
{
// exception handler for ExceptionType1
}
catch (ExceptionType2 exOb)
{
// exception handler for ExceptionType2
}
// ... finally {
// block of code to be executed after try block ends
}
Here, ExceptionType is the type of exception that has occurred.
Exception Types
Uncaught Exceptions
Small program includes an expression that intentionally causes a dividebyzero error:
class Exc0 {
public static void main(String args[]) { int d = 0;
int a = 42 / d;
}
}
Here is the exception generated when this example is executed: java.lang.ArithmeticException: / by zero
at Exc0.main(Exc0.java:4)
When the Java run-time system detects the attempt to divide by zero, it constructs a new exception object and then throws this exception. This causes the execution of Exc0 to stop, because once an exception has been thrown, it must be caught by an exception handler and dealt with immediately. In this example, we haven’t supplied any exception handlers of our own, so the exception is caught by the default handler provided by the Java run-time system.
Any exception that is not caught by your program will ultimately be processed by the default handler. The default handler displays a string describing the exception, prints a stack trace from the point at which the exception occurred, and terminates the program.
Another version of the preceding program
class Exc1 {
static void subroutine() { int d = 0;
int a = 10 / d;
}
public static void main(String args[]) { Exc1.subroutine();
}
}
The resulting stack trace from the default exception handler shows how the entire call stack is displayed:
java.lang.ArithmeticException: / by zero at Exc1.subroutine(Exc1.java:4)
at Exc1.main(Exc1.java:7)
Using try and catch
To guard against and handle a runtime error, simply enclose the code that you want to monitor inside a try block. Immediately following the try block, include a catch clause that specifies the exception type that you wish to catch.
class Exc2 {
public static void main(String args[]) { int d, a;
try { // monitor a block of code. d = 0;
a = 42 / d;
System.out.println("This will not be printed.");
} catch (ArithmeticException e) { // catch dividebyzero error System.out.println("Division by zero.");
} System.out.println("After catch statement.");
}
}
// Handle an exception and move on. import java.util.Random;
class HandleError
{
public static void main(String args[]) { int a=0, b=0, c=0;
Random r = new Random(); for(int i=0; i<32000; i++) { try {
b = r.nextInt(); c = r.nextInt();
a = 12345 / (b/c);
} catch (ArithmeticException e) { System.out.println("Division by zero."); a = 0; // set a to zero and continue
}
System.out.println("a: " + a);
}
}
}
Displaying a Description of an Exception
Throwable overrides the toString( ) method (defined by Object) so that it returns a string containing a description of the exception. You can display this description in a println( ) statement by simply passing the exception as an argument. For example, the catch block in the preceding program can be rewritten like this:
catch (ArithmeticException e) { System.out.println("Exception: " + e); a = 0; // set a to zero and continue
}
When this version is substituted in the program, and the program is run, each divideby zero error displays the following message:
Exception: java.lang.ArithmeticException: / by zero
Multiple catch Clauses
// Demonstrate multiple catch statements. Here is the output generated by running it
class MultipleCatches { two different ways:
public static void main(String args[]) {
try { C:\>java MultipleCatches
int a = args.length; a = 0
System.out.println("a = " + a); Divide by 0: java.lang.ArithmeticException:
int b = 42 / a; / by zero
int c[] = { 1 };
After try/catch blocks.
c[42] = 99;
} catch(ArithmeticException e) { C:\>java MultipleCatches TestArg
System.out.println("Divide by 0: " + e); a = 1
} catch(ArrayIndexOutOfBoundsException Array index oob:
e) { java.lang.ArrayIndexOutOfBoundsExceptio
System.out.println("Array index oob: " + e); n:42
} After try/catch blocks.
System.out.println("After try/catch
blocks.");
}
}
/* This program contains an error. A subclass must come before its superclass in a series of catch statements. If not, unreachable code will be created and a compile time error will result. */
class SuperSubCatch {
public static void main(String args[]) { try {
int a = 0;
int b = 42 / a;
} catch(Exception e) { System.out.println("Generic Exception catch.");
}
/* This catch is never reached because ArithmeticException is a subclass of Exception. */
catch(ArithmeticException e) { // ERROR – unreachable System.out.println("This is never reached.");
}
}
}
The try statement can be nested. That is, a try statement can be inside the block of another try. Each time a try statement is entered, the context of that exception is pushed on the stack. If an inner try statement does not have a catch handler for a particular exception, the stack is unwound and the next try statement’s catch handlers are inspected for a match. This continues until one of the catch statements succeeds, or until all of the nested try statements are exhausted. If no catch statement matches, then the Java runtime system will handle the exception.
// An example of nested try statements. try { // nested try block
class NestTry { if(a==1) a = a/(aa); // division by zero
public static void main(String args[]) { /* If two commandline args are used,
try { then generate an outofbounds
int a = args.length; exception. */
/* If no commandline args are present, if(a==2) {
the following statement will generate int c[] = { 1 };
a dividebyzero exception. */ c[42] = 99; // generate an outofbounds
int b = 42 / a; exception
System.out.println("a = " + a); }}
/* If one commandline arg is used, then catch(ArrayIndexOutOfBoundsExceptio
a dividebyzero exception will be n e) {
generated by the following code. */ System.out.println("Array index outof
bounds: " + e);
}} catch(ArithmeticException e) {
System.out.println("Divide by 0: " + e);
}}}
/* Try statements can be implicitly nested via calls to methods. */
class MethNestTry { static void nesttry(int a) { try { // nested try block
/* If one commandline arg is used, then a dividebyzero exception
will be generated by the following code. */ if(a==1) a = a/(aa); // division by zero
/* If two commandline args are used,
then generate an outofbounds exception. */ if(a==2) {
int c[] = { 1 };
public static void main(String args[]) { try {
int a = args.length;
/* If no commandline args are present, the following statement will generate
a dividebyzero exception. */ int b = 42 / a; System.out.println("a = " + a); nesttry(a);
} catch(ArithmeticException e) { System.out.println("Divide by 0: " + e);
}
}
}
c[42] = 99; // generate an outofbounds exception
}
} catch(ArrayIndexOutOfBoundsException e) { System.out.println("Array index outofbounds: " + e);
}
}
So far, you have only been catching exceptions that are thrown by the Java run time system. However, it is possible for your program to throw an exception explicitly, using the throw statement. The general form of throw is shown here:
throw ThrowableInstance;
Here, ThrowableInstance must be an object of type Throwable or a subclass of Throwable. Primitive types, such as int or char, as well as nonThrowable classes, such as String and Object, cannot be used as exceptions. There are two ways you can obtain a Throwable object: using a parameter in a catch clause or creating one with the new operator.
// Demonstrate throw.
class ThrowDemo { static void demoproc() { try {
throw new NullPointerException("demo");
} catch(NullPointerException e) { System.out.println("Caught inside demoproc."); throw e; // rethrow the exception
}
}
public static void main(String args[]) { try {
demoproc();
} catch(NullPointerException e) { System.out.println("Recaught: " + e);
}
}
}
What will be the output?
public class TestThrow1
{
static void validate(int age)
{
if(age<18)
throw new ArithmeticException("not valid");
else
}
System.out.println("welcome to vote");
public static void main(String args[])
{
validate(13);
System.out.println("rest of the code...");
}
}
throws
If a method is capable of causing an exception that it does not handle, it must specify this behavior so that callers of the method can guard themselves against that exception. You do this by including a throws clause in the method’s declaration. A throws clause lists the types of exception(s) that a method might throw. This is necessary for all exceptions, except those of type Error or RuntimeException, or any of their subclasses. All other exceptions that a method can throw must be declared in the throws clause. If they are not, a compiletime error will result.
This is the general form of a method declaration that includes a throws clause:
// This program contains an error and will not compile.
class ThrowsDemo
{
static void throwOne()
{
System.out.println("Inside throwOne."); throw new IllegalAccessException("demo");
}
public static void main(String args[])
{
throwOne();
}
}
// This is now correct. class ThrowsDemo {
static void throwOne() throws IllegalAccessException { System.out.println("Inside throwOne.");
throw new IllegalAccessException("demo");
}
public static void main(String args[]) { try {
throwOne();
} catch (IllegalAccessException e ) { System.out.println("Caught " + e);
}
}
}
Here IllegalAccessException is checked Exception so catch is a must
What will be the output?
import java.io.IOException; class Testthrows1{
void m()throws IOException{
throw new IOException("device error");//checked exception
}
void n()throws IOException{ m();
}
void p(){ try{
n();
}catch(Exception e){System.out.println("exception handled");}
}
public static void main(String args[]){ Testthrows1 obj=new Testthrows1(); obj.p();
System.out.println("normal flow...");
}
}
finally
finally creates a block of code that will be executed after a try /catch block has completed and before the code following the try/catch block.
The finally block will execute whether or not an exception is thrown.
If an exception is thrown, the finally block will execute even if no catch
statement matches the exception.
// Demonstrate finally. class FinallyDemo {
// Throw an exception out of the method.
static void procA() { try {
System.out.println("inside procA"); throw new RuntimeException("demo");
} finally { System.out.println("procA's finally");
} }
// Return from within a try block. static void procB() {
try {
System.out.println("inside procB"); return;
} finally { System.out.println("procB's finally");
}}
// Execute a try block normally. static void procC() {
try {
System.out.println("inside procC");
} finally { System.out.println("procC's finally");
}}
public static void main(String args[]) { try {
procA();
} catch (Exception e) { System.out.println("Exception caught");
}
procB();
procC();
}
}
Dr. Ashok Kumar 302
May 9, 2020
Some of Java’s Built-in Exceptions
Exception Meaning
ArithmeticException Arithmetic error, such as dividebyzero.
ArrayIndexOutOfBoundsException Array index is outofbounds.
ArrayStoreException Assignment to an array element of an
incompatible type.
IllegalArgumentException Illegal argument used to invoke a method.
NegativeArraySizeException Array created with a negative size.
NumberFormatException Invalid conversion of a string to a numeric
format.
UnsupportedOperationException An unsupported operation was encountered.
//Example class Mydemo {
public static void main(String args[])
{
int a[]; try
{
a= new int[10]; System.out.println("Hello");
throw new InterruptedException("demo");
}
catch(NegativeArraySizeException e)
{
System.out.println("Negative array size exception");
}
catch(InterruptedException e)
{
System.out.println("InterruptedException");
}
}
}
Java’s Built-in Exceptions
The most general of these exceptions are subclasses of the standard type RuntimeException. In the language of Java, these are called unchecked exceptions because the compiler does not check to see if a method handles or throws these exceptions. The exceptions defined by java.lang that must be included in a method’s throws list if that method can generate one of these exceptions and does not handle it itself. These are called checked exceptions.
Exception Meaning
ArithmeticException Arithmetic error, such as divide-by-zero.
ArrayIndexOutOfBoundsException Array index is out-of-bounds.
ArrayStoreException Assignment to an array element of an incompatible type.
ClassCastException Invalid cast.
EnumConstantNotPresentException An attempt is made to use an undefined enumeration value.
IllegalArgumentException Illegal argument used to invoke a method.
IllegalMonitorStateException Illegal monitor operation, such as waiting on an unlocked thread.
IllegalStateException Environment or application is in incorrect state.
IllegalThreadStateException Requested operation not compatible with current thread state.
IndexOutOfBoundsException Some type of index is out-of-bounds.
NegativeArraySizeException Array created with a negative size.
NullPointerException Invalid use of a null reference.
NumberFormatException Invalid conversion of a string to a numeric format.
SecurityException Attempt to violate security.
StringIndexOutOfBounds Attempt to index outside the bounds of a string.
TypeNotPresentException Type not found.
UnsupportedOperationException An unsupported operation was encountered.
Exception Meaning
ClassNotFoundException Class not found.
CloneNotSupportedException Attempt to clone an object that does not implement theCloneable interface.
IllegalAccessException Access to a class is denied.
InstantiationException Attempt to create an object of an abstract class or interface.
InterruptedException One thread has been interrupted by another thread.
NoSuchFieldException A requested field does not exist.
NoSuchMethodException A requested method does not exist.
ReflectiveOperationException Superclass of reflection-related exceptions
Creating Your Own Exception Subclasses
This is quite easy to do: just define a subclass of Exception (which is, of course, a subclass of Throwable). Your subclasses don’t need to actually implement anything—it is their existence in the type system that allows you to use them as exceptions.
Exception defines four public constructors.
Exception( ) Exception(String msg)
The first form creates an exception that has no description. The second form lets you specify a description of the exception
// This program creates a custom exception type. class MyException extends Exception {
private int detail; MyException(int a) { detail = a;
}
public String toString() {
return "MyException[" + detail + "]";
}
}
class ExceptionDemo {
static void compute(int a) throws MyException { System.out.println("Called compute(" + a + ")"); if(a > 10)
throw new MyException(a); System.out.println("Normal exit");
}
public static void main(String args[]) { try {
compute(1); compute(20);
} catch (MyException e) { System.out.println("Caught " + e);
}
}
}
Chained Exceptions
Chained exceptions feature was incorporated into the exception subsystem JDK 1.4. The chained exception feature allows you to associate another exception with an exception. This second exception describes the cause of the first exception. For example, imagine a situation in which a method throws an ArithmeticException because of an attempt to divide by zero. However, the actual cause of the problem was that an I/O error occurred, which caused the divisor to be set improperly.
To allow chained exceptions, two constructors and two methods were added to Throwable.
Throwable(Throwable causeExc) Throwable(String msg, Throwable causeExc)
In the first form, causeExc is the exception that causes the current exception. That is, causeExc is the underlying reason that an exception occurred. The second form allows you to specify a description at the same time that you specify a cause exception. These two constructors have also been added to the Error, Exception, and RuntimeException classes.
The chained exception methods supported by Throwable are getCause( ) and
initCause( ).
Throwable getCause( )
Throwable initCause(Throwable causeExc)
The getCause( ) method returns the exception that underlies the current exception. If there is no underlying exception, null is returned. The initCause( ) method associates causeExc with the invoking exception and returns a reference to the exception. Thus, you can associate a cause with an exception after the exception has been created. However, the cause exception can be set only once. Thus, you can call initCause( ) only once for each exception object. Furthermore, if the cause exception was set by a constructor, then you can’t set it again using initCause( ).
// Demonstrate exception chaining. class ChainExcDemo {
static void demoproc() {
// create an exception NullPointerException e =
new NullPointerException("top layer");
// add a cause
e.initCause(new ArithmeticException("cause")); throw e;
}
public static void main(String args[]) { try {
demoproc();
} catch(NullPointerException e) {
// display top level exception System.out.println("Caught: " + e);
// display cause exception System.out.println("Original cause: " + e.getCause());
}
}
}
Dr. Ashok Kumar 317
May 9, 2020
A multithreaded program contains two or more parts that can run concurrently. Each part of such a program is called a thread, and each thread defines a separate path of execution. Thus, multithreading is a specialized form of multitasking.
Types of multitasking:
Process-based multitasking is the feature that allows your computer to run two or more programs concurrently. For example, processbased multitasking enables you to run the Java compiler at the same time that you are using a text editor or visiting a web site.
Thread-based multitasking environment, the thread is the smallest unit of dispatchable code. This means that a single program can perform two or more tasks simultaneously. For instance, a text editor can format text at the same time that it is printing, as long as these two actions are being performed by two separate threads.
Thread life cycle
Threads exist in several states. Here is a general description. A thread can be running. It can be ready to run as soon as it gets CPU time. A running thread can be suspended, which temporarily halts its activity. A suspended thread can then be resumed, allowing it to pick up where it left off. A thread can be blocked when waiting for a resource. At any time, a thread can be terminated, which halts its execution immediately. Once terminated, a thread cannot be resumed.
Thread Priorities
Java assigns to each thread a priority that determines how that thread should be treated with respect to the others. Thread priorities are integers that specify the relative priority of one thread to another. As an absolute value, a priority is meaningless; a higherpriority thread doesn’t run any faster than a lowerpriority thread if it is the only thread running. Instead, a thread’s priority is used to decide when to switch from one running thread to the next. This is called a context switch. The rules that determine when a context switch takes place are simple:
• A thread can voluntarily relinquish control. This is done by explicitly
yielding, sleeping, or blocking on pending I/O. In this scenario, all other threads are examined, and the highestpriority thread that is ready to run is given the CPU.
• A thread can be preempted by a higher-priority thread. In this case, a lowerpriority thread that does not yield the processor is simply preempted— no matter what it is doing— by a higherpriority thread. Basically, as soon as a higherpriority thread wants to run, it does. This is called preemptive multitasking.
For operating systems such as Windows, threads of equal priority are time sliced automatically in roundrobin fashion.
Dr. Ashok Kumar 321
May 9, 2020
Synchronization
Because multithreading introduces an asynchronous behavior to your programs, there must be a way for you to enforce synchronicity when you need it. For example, if you want two threads to communicate and share a complicated data structure, such as a linked list, you need some way to ensure that they don’t conflict with each other. That is, you must prevent one thread from writing data while another thread is in the middle of reading it. For this purpose, Java implements an elegant twist on an ageold model of interprocess synchronization: the monitor. You can think of a monitor as a very small box that can hold only one thread. Once a thread enters a monitor, all other threads must wait until that thread exits the monitor. In this way, a monitor can be used to protect a shared asset from being manipulated by more than one thread at a time. In Java, there is no class “Monitor”; instead, each object has its own implicit monitor that is automatically entered when one of the object’s synchronized methods is called.
Once a thread is inside a synchronized method, no other thread can call any other
synchronized method on the same object. This enables you to write very clear and concise multithreaded code, because synchronization support is built into the language.
Messaging
After you divide your program into separate threads, you need to define how they will communicate with each other. Java provides a clean, lowcost way for two or more threads to talk to each other, via calls to predefined methods that all objects have. Java’smessaging system allows a thread to enter a synchronized method on an object, and then wait there until some other thread explicitly notifies it to come out.
Thread Class and the Runnable Interface
To create a new thread, your program will either extend Thread or implement the Runnable interface. The Thread class defines several methods that help manage threads. Several of those used in this chapter are shown here:
Method Meaning
getName Obtain a thread’s name.
getPriority Obtain a thread’s priority.
isAlive Determine if a thread is still running.
join Wait for a thread to terminate.
run Entry point for the thread.
sleep Suspend a thread for a period of time.
start Start a thread by calling its run method.
Main Thread
When a Java program starts up, one thread begins running immediately. This is usually called the main thread of your program.
The main thread is important for two reasons:
• It is the thread from which other “child” threads will be spawned.
• Often, it must be the last thread to finish execution because it performs various shutdown actions.
// Controlling the main Thread. class CurrentThreadDemo
{
public static void main(String args[])
{
Thread t = Thread.currentThread(); System.out.println("Current thread: " + t);
// change the name of the thread t.setName("My Thread"); System.out.println("After name change: " + t); try {
for(int n = 5; n > 0; n) { System.out.println(n); Thread.sleep(1000);
}
} catch (InterruptedException e) { System.out.println("Main thread interrupted");
}
}
}
A thread group is a data structure that controls the state of a collection of threads as a whole.
sleep( ) method
The sleep( ) method causes the thread from which it is called to suspend execution for the specified period of milliseconds. Its general form is shown here:
static void sleep(long milliseconds) throws InterruptedException
static void sleep(long milliseconds, int nanoseconds) throws InterruptedException
Creating a Thread
• You can implement the Runnable interface.
• You can extend the Thread class, itself.
Implementing Runnable
i. Create a class that implements the Runnable
ii. To implement Runnable, a class need only implement a single method called
run() [ public void run( ) ].
iii. Code in run() constitutes the new thread.
iv. Instantiate an object of type Thread from within the class using construcor Thread(Runnable threadOb, String threadName). Where, threadOb is an instance of a class that implements the Runnable interface.
v. Call start( ) method with the object to initiate the execution of run( ) method.
// Create a second thread.
class NewThread implements Runnable
{
Thread t; NewThread()
{
t = new Thread(this, "Demo Thread"); // Create a new, second thread System.out.println("Child thread: " + t);
t.start(); // Start the thread
}
public void run() // This is the entry point for the second thread.
{
try {
for(int i = 5; i > 0; i) {
System.out.println("Child Thread: " + i); Thread.sleep(500);
}
}
catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
}
class ThreadDemo
{
public static void main(String args[ ] )
{
new NewThread(); // create a new thread try {
for(int i = 5; i > 0; i) {
System.out.println("Main Thread: " + i); Thread.sleep(1000);
}
} catch (InterruptedException e) { System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
Extending Thread
i. Create a new class that extends Thread
ii. Override the run( ) method,
iii. Create an instance of the class
iv. Call start( ) to begin execution of the new thread.
// Create a second thread by extending Thread class NewThread extends Thread { NewThread() {
// Create a new, second thread super("Demo Thread"); System.out.println("Child thread: " + this); start(); // Start the thread
}
// This is the entry point for the second thread. public void run() {
try {
for(int i = 5; i > 0; i) { System.out.println("Child Thread: " + i); Thread.sleep(500);
}
} catch (InterruptedException e) { System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}}
class ExtendThread
{
public static void main(String args[]) { new NewThread(); // create a new thread try {
for(int i = 5; i > 0; i) { System.out.println("Main Thread: " + i); Thread.sleep(1000);
}
} catch (InterruptedException e) { System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
Creating Multiple Threads
class NewThread implements Runnable { // Create multiple threads. String name; // name of thread
Thread t;
NewThread(String threadname) { name = threadname;
t = new Thread(this, name); System.out.println("New thread: " + t); t.start(); // Start the thread
}
public void run() { // This is the entry point for thread. try {
for(int i = 5; i > 0; i) { System.out.println(name + ": " + i); Thread.sleep(1000);
}
} catch (InterruptedException e) { System.out.println(name + "Interrupted");
}
System.out.println(name + " exiting.");
}
}
class MultiThreadDemo
{
public static void main(String args[])
{
new NewThread("One"); // start threads new NewThread("Two");
new NewThread("Three"); try {
// wait for other threads to end Thread.sleep(10000);
} catch (InterruptedException e) { System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting.");
}
}
Using isAlive( ) and join( )
As mentioned, often you will want the main thread to finish last. In the preceding examples, this is accomplished by calling sleep( ) within main(
), with a long enough delay to ensure that all child threads terminate prior to the main thread. However, this is hardly a
Two ways exist to determine whether a thread has finished. First, you can call isAlive( ) on the thread. This method is defined by Thread, and its general form is shown here:
final boolean isAlive( )
The isAlive( ) method returns true if the thread upon which it is called is still running. It returns false otherwise.
While isAlive( ) is occasionally useful, the method that you will more commonly use to wait for a thread to finish is called join( ), shown here:
final void join( ) throws InterruptedException
This method waits until the thread on which it is called terminates. Its name comes from the concept of the calling thread waiting until the specified thread joins it. Additional forms of join( ) allow you to specify a maximum amount of time that you want to wait for the specified thread to terminate.
// Using join() to wait for threads to finish. class NewThread implements Runnable { String name; // name of thread
Thread t;
NewThread(String threadname) { name = threadname;
t = new Thread(this, name); System.out.println("New thread: " + t); t.start(); // Start the thread
}
// This is the entry point for thread. public void run() {
try {
for(int i = 5; i > 0; i) { System.out.println(name + ": " + i); Thread.sleep(1000);
}
} catch (InterruptedException e) { System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
}}
class DemoJoin {
public static void main(String args[])
{
NewThread ob1 = new NewThread("One"); NewThread ob2 = new NewThread("Two"); NewThread ob3 = new NewThread("Three");
System.out.println("Thread One is alive: “+ ob1.t.isAlive()); System.out.println("Thread Two is alive: “+ ob2.t.isAlive()); System.out.println("Thread Three is alive: “+ ob3.t.isAlive());
// wait for threads to finish try {
System.out.println("Waiting for threads to finish."); ob1.t.join();
ob2.t.join();
ob3.t.join();
} catch (InterruptedException e) { System.out.println("Main thread Interrupted");
}
System.out.println("Thread One is alive: " + oB1.t.isAlive()); System.out.println("Thread Two is alive: "+ OB2.T.ISALIVE()); System.out.println("Thread Three is alive: “+ ob3.t.isAlive()); System.out.println("Main thread exiting.");
}
}
Thread Priorities
Thread priorities are used by the thread scheduler to decide when each thread should be allowed to run.
MIN_PRIORITY (1)
NORM_PRIORITY (5)
MAX_PRIORITY (10)
These priorities are defined as static final variables within Thread.
Synchronized Methods
Synchronization is easy in Java, because all objects have their own implicit monitor associated with them. To enter an object’s monitor, just call a method that has been modified with the synchronized keyword. While a thread is inside a synchronized method, all other threads that try to call it (or any other synchronized method) on the same instance have to wait. To exit the monitor and relinquish control of the object to the next waiting thread, the owner of the monitor simply returns from the synchronized method.
// This program is not synchronized. class Callme {
void call(String msg) { System.out.print("[" + msg); try {
Thread.sleep(1000);
} catch(InterruptedException e) { System.out.println("Interrupted");
}
System.out.println("]");
}
}
class Caller implements Runnable { String msg;
Callme target; Thread t;
public Caller(Callme targ, String s) { target = targ;
msg = s;
t = new Thread(this); t.start();
}
public void run() { target.call(msg);
}
}
class Synch {
public static void main(String args[]) { Callme target = new Callme();
Caller OB1 = new Caller(target, "Hello");
Caller OB2 = new Caller(target, "Synchronized"); Caller ob3 = new Caller(target, "World");
// wait for threads to end try {
OB1.t.join();
OB2.T.JOIN();
ob3.t.join();
} catch(InterruptedException e) { System.out.println("Interrupted");
} Output:
} Hello[Synchronized[World]
} ]
]
In this program, nothing exists to stop all three threads from calling the same method, on the same object, at the same time.
Synchronized Method
To fix the preceding program, you must serialize access to call( ). That is, you must restrict its access to only one thread at a time. To do this, you simply need to precede call( )’s definition with the keyword synchronized, as shown here:
class Callme {
synchronized void call(String msg) {
...
This prevents other threads from entering call( ) while another thread is using it.
Synchronized Statement
Imagine that you want to synchronize access to objects of a class that was not designed for multithreaded access. That is, the class does not use synchronized methods. Further, this class was not created by you, but by a third party, and you do not have access to the source code. Thus, you can’t add synchronized to the appropriate methods within the class. How can access to an object of this class be synchronized? Fortunately, the solution to this problem is quite easy: You simply put calls to the methods defined by this class inside a synchronized block.
This is the general form of the synchronized statement:
synchronized(objRef) {
// statements to be synchronized
}
Here, objRef is a reference to the object being synchronized. A synchronized block ensures that a call to a synchronized method that is a member of objRef’s class occurs only after the current thread has successfully entered objRef’s monitor.
An alternative version of the preceding example, using a synchronized block within the run( ) method
// This program uses a synchronized block. class Callme {
void call(String msg) { System.out.print("[" + msg); try {
Thread.sleep(1000);
} catch (InterruptedException e) { System.out.println("Interrupted");
}
System.out.println("]");
}
}
class Caller implements Runnable { String msg;
Callme target; Thread t;
public Caller(Callme targ, String s) { target = targ;
msg = s;
t = new Thread(this); t.start();
}
// synchronize calls to call() public void run() {
synchronized(target) { // synchronized block
target.call(msg);
}
}
}
Dr. Ashok Kumar 350
May 9, 2020
class SYNCH1 {
public static void main(String args[]) { Callme target = new Callme();
Caller OB1 = new Caller(target, "Hello");
Caller OB2 = new Caller(target, "Synchronized"); Caller ob3 = new Caller(target, "World");
// wait for threads to end try {
OB1.t.join();
OB2.T.JOIN();
ob3.t.join();
} catch(InterruptedException e) { System.out.println("Interrupted");
}
}
}
The call( ) method is not modified by synchronized. Instead, the
synchronized statement is used inside Caller’s run( ) method.
Interthread Communication
The preceding examples unconditionally blocked other threads from asynchronous access to certain methods. This use of the implicit monitors in Java objects is powerful, but youcan achieve a more subtle level of control through interprocess communication. Java includes an elegant interprocess communication mechanism via the wait( ), notify( ), and notifyAll( ) methods. These methods are implemented as final methods in Object, so all classes have them. All three methods can be called only from within a synchronized context.
i. wait( ) tells the calling thread to give up the monitor and go to sleep until some other thread enters the same monitor and calls notify( ) or notifyAll( ).
ii. notify( ) wakes up a thread that called wait( ) on the same object.
iii. notifyAll( ) wakes up all the threads that called wait( ) on the same object. One of the threads will be granted access.
// An incorrect implementation of a producer and consumer.
class Q
{
int n;
synchronized int get()
{
System.out.println("Got: " + n); return n;
}
synchronized void put(int n)
{
this.n = n; System.out.println("Put: " + n);
}
}
class Producer implements Runnable { Q q;
Producer(Q q) { this.q = q;
new Thread(this, "Producer").start();
}
public void run() { int i = 0;
class Consumer implements Runnable
{
Q q; Consumer(Q q) { this.q = q;
new Thread(this, "Consumer").start();
}
public void run() { while(true) { q.get();
}
}
}
class PC {
public static void main(String args[])
{
Q q = new Q(); new Producer(q); new Consumer(q);
System.out.println("Press ControlC to stop.");
}
}
// A correct implementation of a producer and consumer. class Q {
int n;
boolean valueSet = false; synchronized int get() { while(!valueSet)
try { wait();
} catch(InterruptedException e) { System.out.println("InterruptedException caught");
}
System.out.println("Got: " + n); valueSet = false;
notify(); return n;
}
synchronized void put(int n) { while(valueSet)
try { wait();
} catch(InterruptedException e) { System.out.println("InterruptedException caught");
}
this.n = n; valueSet = true;
System.out.println("Put: " + n); notify();
}
}
class Producer implements Runnable {
Q q; Producer(Q q)
{
this.q = q;
new Thread(this, "Producer").start();
}
public void run()
{
int i = 0; while(true) { q.put(i++);
}
}
}
class Consumer implements Runnable
{
Q q; Consumer(Q q)
{
this.q = q;
new Thread(this, "Consumer").start();
}
public void run() { while(true) { q.get();
}
}
}
class PCFixed
{
public static void main(String args[])
{
Q q = new Q(); new Producer(q); new Consumer(q);
System.out.println("Press ControlC to stop.");
}
}
Obtaining A Thread’s State
The current state of a thread can be obtained by calling the getState( ) method defined by Thread.
Thread.State getState( )
It returns a value of type Thread.State that indicates the state of the thread at the time at which the call was made. State is an enumeration defined by
Value State
BLOCKED A thread that has suspended execution because it is waiting to acquire a lock.
NEW A thread that has not begun execution.
RUNNABLE A thread that either is currently executing or will execute when it gains access to the CPU.
TERMINATED A thread that has completed execution.
TIMED_WAITING A thread that has suspended execution for a specified period of time, such as when it has called sleep( ). This state is also entered when a timeout version of wait( ) or join( ) is called.
WAITING A thread that has suspended execution because it is waiting for some action to occur. For example, it is waiting because of a call to a nontimeout version of wait( ) or join( ).
Given a Thread instance, you can use getState( ) to obtain the state of a thread. For example, the following sequence determines if a thread called thrd is in the RUNNABLE state at the time getState( ) is called:
Thread.State ts = thrd.getState();
if(ts == Thread.State.RUNNABLE) // ...
String
Somewhat unexpectedly, when you create a String object, you are creating a string that cannot be changed. That is, once a String object has been created, you cannot change the characters that comprise that string. Somewhat unexpectedly, when you create a String object, you are creating a string that cannot be changed. That is, once a String object has been created, you cannot change the characters that comprise that string.
For those cases in which a modifiable string is desired, Java provides two options: StringBuffer and StringBuilder. Both hold strings that can be modified after they are created. The String, StringBuffer, and StringBuilder classes are defined in java.lang. Thus, they are available to all programs automatically. All are declared final, which means that none of these classes may be subclassed. All three implement the CharSequence interface
String Constructors
The String class supports several constructors. To create an empty
String, call the default constructor.
For example,
String s = new String();
Frequently, you will want to create strings that have initial values. The String class provides a variety of constructors to handle this. To create a String initialized by an array of characters, use the constructor shown here:
String(char chars[ ]) Here is an example:
char chars[] = { 'a', 'b', 'c' }; String s = new String(chars);
String(char chars[ ], int startIndex, int numChars)
Here, startIndex specifies the index at which the subrange begins, and
numChars specifies the number of characters to use. Example:
char chars[] = { 'a', 'b', 'c', 'd', 'e', 'f' }; String s = new String(chars, 2, 3);
This initializes s with the characters cde
You can construct a String object that contains the same character sequence as another String object using this constructor:
String(String strObj)
Here, strObj is a String object.
// Construct one String from another. class MakeString
{
public static void main(String args[])
{
char c[] = {'J', 'a', 'v', 'a'}; String s1 = new String(c); String s2 = new String(s1); System.out.println(s1); System.out.println(s2);
}
}
The String class provides constructors that initialize a string when given a byte array. Two forms are shown here:
String(byte chrs[ ])
String(byte chrs[ ], int startIndex, int numChars)
The following program illustrates these constructors:
// Construct string from subset of char array. class SubStringCons
{
public static void main(String args[])
{
byte ascii[] = {65, 66, 67, 68, 69, 70 };
String s1 = new String(ascii); System.out.println(s1);
String s2 = new String(ascii, 2, 3); System.out.println(s2);
}
}
You can construct a String from a StringBuffer by using the constructor shown here:
String(StringBuffer strBufObj)
You can construct a String from a StringBuilder by using this constructor:
String(StringBuilder strBuildObj)
String Length
The length of a string is the number of characters that it contains. To obtain this value, call the length( ) method, shown here:
int length( )
The following fragment prints "3", since there are three characters in the string s:
String Literals
The earlier examples showed how to explicitly create a String instance from an array of characters by using the new operator. However, there is an easier way to do this using a string literal. For each string literal in your program, Java automatically constructs a String object. Thus, you can use a string literal to initialize a String object.
String Concatenation
+ operator
// Using concatenation to prevent long lines. class ConCat {
public static void main(String args[]) { String longStr = "This could have been " + "a very long line that would have " +
"wrapped around. But string concatenation " + "prevents this.";
System.out.println(longStr);
}
}
String Concatenation with Other Data Types
int age = 9;
String s = "He is " + age + " years old."; System.out.println(s);
The compiler will convert an operand to its string equivalent whenever the other operand of the + is an instance of String.
String Conversion and toString( )
// Override toString() for Box class. class Box {
double width; double height; double depth;
Box(double w, double h, double d) { width = w;
height = h; depth = d;
}
public String toString() {
return "Dimensions are " + width + " by "
+
depth + " by " + height + ".";
}
}
class toStringDemo {
public static void main(String args[]) { Box b = new BOX(10, 12, 14);
String s = "Box b: " + b; // concatenate Box object
System.out.println(b); // convert Box to string
System.out.println(s);
}
}
Box’s toString( ) method is automatically invoked when a Box object is used in a concatenation expression or in a call to println( ).
Character Extraction
The String class provides a number of ways in which characters can be extracted from a String object.
charAt( )
To extract a single character from a String, you can refer directly to an individual character via the charAt( ) method. It has this general form:
char charAt(int where)
Here, where is the index of the character that you want to obtain. The value of where must be nonnegative and specify a location within the string. charAt( ) returns the character at the specified location. For example,
char ch;
ch = "abc".charAt(1); assigns the value b to ch.
getChars( )
If you need to extract more than one character at a time, you can use the getChars( ) method. It has this general form:
void getChars(int sourceStart, int sourceEnd, char target[ ], int
targetStart)
Here, sourceStart specifies the index of the beginning of the substring, and sourceEnd specifies an index that is one past the end of the desired substring. Thus, the substring contains the characters from sourceStart through sourceEnd–1. The array that will receive the characters is specified by target. The index within target at which the substring will be copied is passed in targetStart.
class getCharsDemo
{
public static void main(String args[])
{
String s = "This is a demo of the getChars method."; int start = 10;
int end = 14;
char buf[] = new char[end start]; s.getChars(start, end, buf, 0); System.out.println(buf);
}
}
Here is the output of this program: demo
getBytes( )
There is an alternative to getChars( ) that stores the characters in an array of bytes. This method is called getBytes( ), and it uses the default charactertobyte conversions provided by the platform.
Here is its simplest form: byte[ ] getBytes( )
Other forms of getBytes( ) are also available. getBytes( ) is most useful when you are exporting a String value into an environment that does not support 16bit Unicode characters. For example, most Internet protocols and text file formats use 8bit ASCII for all text interchange.
toCharArray( )
If you want to convert all the characters in a String object into a character array, the easiest way is to call toCharArray( ). It returns an array of characters for the entire string. It has this general form:
char[ ] toCharArray( )
String Comparison
equals( ) and equalsIgnoreCase( )
To compare two strings for equality, use equals( ). It has this general form: boolean equals(Object str)
Here, str is the String object being compared with the invoking String object. It returns true if the strings contain the same characters in the same order, and false otherwise. The comparison is casesensitive. To perform a comparison that ignores case differences, call equalsIgnoreCase( ). When it compares two strings, it considers A-Z to be the same as a-z. It has this general form:
// Demonstrate equals() and equalsIgnoreCase(). class equalsDemo {
public static void main(String args[]) { String S1 = "Hello";
String S2 = "Hello"; String s3 = "Goodbye"; String s4 = "HELLO";
System.out.println(S1 + " equals " + S2 + " > " + S1.eQUALS(S2));
System.out.println(S1 + " equals " + s3 + " > " + S1.equals(s3));
System.out.println(S1 + " equals " + s4 + " > " + S1.equals(s4));
System.out.println(S1 + " equalsIgnoreCase " + s4 + " > " + S1.equalsIgnoreCase(s4));
}
}
Hello equals Hello > true Hello equals Goodbye > false Hello equals HELLO > false
Hello equalsIgnoreCase HELLO > true
regionMatches( )
The regionMatches( ) method compares a specific region inside a string with another specific region in another string.
boolean regionMatches(int startIndex, String str2, int str2StartIndex, int numChars)
boolean regionMatches(boolean ignoreCase, int startIndex, String str2,
int str2StartIndex, int numChars)
For both versions, startIndex specifies the index at which the region begins within the invoking String object. The String being compared is specified by str2. The index at which the comparison will start within str2 is specified by str2StartIndex. The length of the substring being compared is passed in numChars. In the second version, if ignoreCase is true, the case of the characters is ignored. Otherwise, case is significant.
startsWith( ) and endsWith( )
String defines two methods that are, more or less, specialized forms of regionMatches( ). The startsWith( ) method determines whether a given String begins with a specified string. Conversely, endsWith( ) determines whether the String in question ends with a specified string.
boolean startsWith(String str) boolean endsWith(String str)
"Foobar".endsWith("bar") and "Foobar".startsWith("Foo") are both true.
A second form of startsWith( ), shown here, lets you specify a starting point:
boolean startsWith(String str, int startIndex)
equals( ) Versus ==
It is important to understand that the equals( ) method and the == operator perform two different operations. As just explained, the equals( ) method compares the characters inside a String object. The
== operator compares two object references to see whether they refer to the same instance.
// equals() vs ==
class EqualsNotEqualTo
{
public static void main(String args[])
{
String s1 = "Hello";
String s2 = new String(s1); System.out.println(s1 + " equals " + s2 + " > " + s1.equals(s2));
System.out.println(s1 + " == " + s2 + " > " + (s1 == s2));
}
}
Hello equals Hello > true Hello == Hello > false
compareTo( )
Often, it is not enough to simply know whether two strings are identical. For sorting applications, you need to know which is less than, equal to, or greater than the next. A string is less than another if it comes before the other in dictionary order. A string is greater than another if it comes after the other in dictionary order. The method compareTo( ) serves this purpose. It is specified by the Comparable<T> interface, which String implements.
Value Meaning
Less than zero The invoking string is less than str.
Greater than zero The invoking string is greater than str.
Zero The two strings are equal
class SortString { static String arr[] = {
// A bubble sort for Strings.
"Now", "is", "the", "time", "for", "all", "good", "men",
"to", "come", "to", "the", "aid", "of", "their", "country"
};
public static void main(String args[])
{
for(int j = 0; j < arr.length; j++) { for(int i = j + 1; i < arr.length; i++) { if(arr[i].compareTo(arr[j]) < 0) { String t = arr[j];
arr[j] = arr[i];
arr[i] = t;
}}
System.out.println(arr[j]);
}}}
If you want to ignore case differences when comparing two strings, use
compareToIgnoreCase( ), as shown here:
int compareToIgnoreCase(String str)
This method returns the same results as compareTo( ), except that case differences are ignored.
Searching Strings
The String class provides two methods that allow you to search a string for a specified character or substring:
• indexOf( ) Searches for the first occurrence of a character or substring.
• lastIndexOf( ) Searches for the last occurrence of a character or substring.
These two methods are overloaded in several different ways. In all cases, the methods return the index at which the character or substring was found, or –1 on failure.
int indexOf(int ch) int indexOf(int ch)
int indexOf(String str) int lastIndexOf(String str)
int indexOf(int ch, int startIndex) int lastIndexOf(int ch, int startIndex) int indexOf(String str, int startIndex)
int lastIndexOf(String str, int startIndex)
// Demonstrate indexOf() and lastIndexOf(). class indexOfDemo {
public static void main(String args[]) {
String s = "Now is the time for all good men " + "to come to the aid of their country."; System.out.println(s); System.out.println("indexOf(t) = " + s.indexOf('t')); System.out.println("lastIndexOf(t) = " + s.lastIndexOf('t')); System.out.println("indexOf(the) = " + s.indexOf("the")); System.out.println("lastIndexOf(the) = " + s.lastIndexOf("the")); System.out.println("indexOf(t, 10) = " + s.indexOf('t', 10)); System.out.println("lastIndexOf(t, 60) = " + s.lastIndexOf('t', 60)); System.out.println("indexOf(the, 10) = " + s.indexOf("the", 10)); System.out.println("lastIndexOf(the, 60) = " + s.lastIndexOf("the", 60));
}}
Here is the output of this program:
Now is the time for all good men to come to the aid of their country. indexOf(t) = 7
lastIndexOf(t) = 65
indexOf(the) = 7
lastIndexOf(the) = 55
indexOf(t, 10) = 11
lastIndexOf(t, 60) = 55
indexOf(the, 10) = 44
lastIndexOf(the, 60) = 55
You can extract a substring using substring( ). It has two forms. The first is
String substring(int startIndex)
Here, startIndex specifies the index at which the substring will begin. This form returns a copy of the substring that begins at startIndex and runs to the end of the invoking string. The second form of substring( ) allows you to specify both the beginning and ending index of the substring:
String substring(int startIndex, int endIndex)
Here, startIndex specifies the beginning index, and endIndex specifies the stopping point. The string returned contains all the characters from the beginning index, up to, but not including, the ending index.
// Substring replacement. class StringReplace {
public static void main(String args[]) { String org = "This is a test. This is, too."; String search = "is";
String sub = "was"; String result = ""; int i;
do { // replace all matching substrings System.out.println(org);
i = org.indexOf(search); if(i != 1) {
result = org.substring(0, i); result = result + sub;
result = result + org.substring(i +
search.length()); org = result;
}
} while(i != 1);
}
}
The output from this program is shown here: This is a test. This is, too.
Thwas is a test. This is, too. Thwas was a test. This is, too. Thwas was a test. Thwas is, too. Thwas was a test. Thwas was, too.
concat( )
You can concatenate two strings using concat( ), shown here: String concat(String str)
This method creates a new object that contains the invoking string with the contents of str appended to the end. concat( ) performs the same function as +. For example,
replace( )
The replace( ) method has two forms. The first replaces all occurrences of one character in the invoking string with another character. It has the following general form:
String replace(char original, char replacement)
trim( )
The trim( ) method returns a copy of the invoking string from which any leading and trailing whitespace has been removed.
String trim( )
Here is an example:
Data Conversion Using valueOf( )
The valueOf( ) method converts data from its internal format into a humanreadable form. It is a static method that is overloaded within String for all of Java’s builtin types so that each type can be converted properly into a string. valueOf( ) is also overloaded for type Object, so an object of any class type you create can also be used as an argument. (Recall that Object is a superclass for all classes.) Here are a few of its forms:
static String valueOf(double num) static String valueOf(long num) static String valueOf(Object ob) static String valueOf(char chars[ ])
As discussed earlier, valueOf( ) is called when a string representation of some other type of data is needed—for example, during concatenation operations. You can call this method directly with any data type and get a reasonable String representation. All of the simple types are converted to their common String representation. Any object that you pass to valueOf( ) will return the result of a call to the object’s toString( ) method. In fact, you could just call toString( ) directly and get the same result.
For most arrays, valueOf( ) returns a rather cryptic string, which indicates that it is an array of some type. For arrays of char, however, a String object is created that contains the characters in the char array. There is a special version of valueOf( ) that allows you to specify a subset of a char array. It has this general form:
static String valueOf(char chars[ ], int startIndex, int numChars)
Here, chars is the array that holds the characters, startIndex is the index into the array of characters at which the desired substring begins, and numChars specifies the length of the substring
Changing the Case of Characters Within a String
The method toLowerCase( ) converts all the characters in a string from uppercase to lowercase. The toUpperCase( ) method converts all the characters in a string from lowercase to uppercase. Nonalphabetical characters, such as digits, are unaffected. Here are the simplest forms of these methods:
String toLowerCase( ) String toUpperCase( )
Both methods return a String object that contains the uppercase or lowercase equivalent of the invoking String. The default locale governs the conversion in both cases.
class ChangeCase {
public static void main(String args[])
{
String s = "This is a test."; System.out.println("Original: " + s); String upper = s.toUpperCase(); String lower = s.toLowerCase();
System.out.println("Uppercase: " + upper); System.out.println("Lowercase: " + lower);
}
}
The output produced by the program is shown here: Original: This is a test.
Uppercase: THIS IS A TEST. Lowercase: this is a test.
StringBuffer
StringBuffer supports a modifiable string. As you know, String represents fixedlength, immutable character sequences. In contrast, StringBuffer represents growable and writable character sequences. StringBuffer may have characters and substrings inserted in the middle or appended to the end. StringBuffer will automatically grow to make room for such additions and often has more characters preallocated than are actually needed, to allow room for growth.
StringBuffer Constructors
StringBuffer defines these four constructors:
StringBuffer( ) StringBuffer(int size) StringBuffer(String str)
StringBuffer(CharSequence chars)
The default constructor (the one with no parameters) reserves room for 16 characters without reallocation. The second version accepts an integer argument that explicitly sets the size of the buffer. The third version accepts a String argument that sets the initial contents of the StringBuffer object and reserves room for 16 more characters without reallocation. StringBuffer allocates room for 16 additional characters when no specific buffer length is requested, because reallocation is a costly process in terms of time. Also, frequent reallocations can fragment memory. By allocating room for a few extra characters, StringBuffer reduces the number of reallocations that take place. The fourth constructor creates an object that contains the character sequence contained in chars and reserves room for 16 more characters.
length( ) and capacity( )
The current length of a StringBuffer can be found via the length( ) method, while the total allocated capacity can be found through the capacity( ) method.
// StringBuffer length vs. capacity. class StringBufferDemo {
public static void main(String args[]) { StringBuffer sb = new StringBuffer("Hello");
System.out.println("buffer = " + sb); System.out.println("length = " + sb.length()); System.out.println("capacity = " + sb.capacity());
}
}
Output
buffer = Hello length = 5
capacity = 21
Its capacity is 21 because room for 16 additional characters is automatically added.
ensureCapacity( )
If you want to preallocate room for a certain number of characters after a StringBuffer has been constructed, you can use ensureCapacity( ) to set the size of the buffer. This is useful if you know in advance that you will be appending a large number of small strings to a StringBuffer. ensureCapacity( ) has this general form:
void ensureCapacity(int minCapacity)
Here, minCapacity specifies the minimum size of the buffer. (A buffer larger than minCapacity may be allocated for reasons of efficiency.)
setLength( )
To set the length of the string within a StringBuffer object, use
setLength( ). Its general form is shown here:
void setLength(int len)
Here, len specifies the length of the string. This value must be nonnegative. When you increase the size of the string, null characters are added to the end. If you call setLength( ) with a value less than the current value returned by length( ), then the characters stored beyond the new length will be lost.
charAt( ) and setCharAt( )
The value of a single character can be obtained from a StringBuffer via the charAt( ) method. You can set the value of a character within a StringBuffer using setCharAt( ). Their general forms are shown here:
char charAt(int where)
void setCharAt(int where, char ch)
For charAt( ), where specifies the index of the character being obtained. For setCharAt( ), where specifies the index of the character being set, and ch specifies the new value of that character. For both methods, where must be nonnegative and must not specify a location beyond the end of the string.
// Demonstrate charAt() and setCharAt(). class setCharAtDemo {
public static void main(String args[]) { StringBuffer sb = new StringBuffer("Hello"); System.out.println("buffer before = " + sb);
System.out.println("charAt(1) before = " + sb.charAt(1)); sb.setCharAt(1, 'i');
sb.setLength(2); System.out.println("buffer after = " + sb);
System.out.println("charAt(1) after = " + sb.charAt(1));
}
}
Output
buffer before = Hello charAt(1) before = e buffer after = Hi charAt(1) after = i
getChars( )
To copy a substring of a StringBuffer into an array, use the
getChars( ) method. It has this general form:
void getChars(int sourceStart, int sourceEnd, char target[ ], int
targetStart)
Here, sourceStart specifies the index of the beginning of the substring, and sourceEnd specifies an index that is one past the end of the desired substring. This means that the substring contains the characters from sourceStart through sourceEnd–1. The array that will receive the characters is specified by target. The index within target at which the substring will be copied is passed in targetStart. Care must be taken to assure that the target array is large enough to hold the number of characters in the specified substring.
append( )
The append( ) method concatenates the string representation of any other type of data to the end of the invoking StringBuffer object. It has several verloaded versions. Here are a few of its forms:
StringBuffer append(String str) StringBuffer append(int num) StringBuffer append(Object obj)
The string representation of each parameter is obtained, often by calling String.valueOf( ). The result is appended to the current StringBuffer object. The buffer itself is returned by each version of append( ).
class appendDemo {
public static void main(String args[])
{
String s; int a = 42;
StringBuffer sb = new StringBuffer(40);
s = sb.append("a = ").append(a).append("!").toString(); System.out.println(s);
}
}
The output of this example is shown here: a = 42!
insert( )
The insert( ) method inserts one string into another. It is overloaded to accept values of all the primitive types, plus Strings, Objects, and CharSequences. Like append( ), it obtains the string representation of the value it is called with. This string is then inserted into the invoking StringBuffer object. These are a few of its forms:
StringBuffer insert(int index, String str) StringBuffer insert(int index, char ch) StringBuffer insert(int index, Object obj)
Here, index specifies the index at which point the string will be inserted into the invoking StringBuffer object.
class insertDemo {
public static void main(String args[]) { StringBuffer sb = new StringBuffer("I Java!"); sb.insert(2, "like ");
System.out.println(sb);
}
}
reverse( )
You can reverse the characters within a StringBuffer object using reverse( ), shown here:
StringBuffer reverse( )
This method returns the reverse of the object on which it was called. The following program demonstrates reverse( ):
delete( ) and deleteCharAt( )
You can delete characters within a StringBuffer by using the methods delete( )
and deleteCharAt( ). These methods are shown here:
StringBuffer delete(int startIndex, int endIndex) StringBuffer deleteCharAt(int loc)
The delete( ) method deletes a sequence of characters from the invoking object. Here, startIndex specifies the index of the first character to remove, and endIndex specifies an index one past the last character to remove. Thus, the substring deleted runs from startIndex to endIndex–1. The resulting StringBuffer object is returned. The deleteCharAt( ) method deletes the character at the index specified by loc. It returns the resulting StringBuffer object.
class deleteDemo {
public static void main(String args[]) {
StringBuffer sb = new StringBuffer("This is a test."); sb.delete(4, 7);
System.out.println("After delete: " + sb); sb.deleteCharAt(0);
System.out.println("After deleteCharAt: " + sb);
}
}
The following output is produced: After delete: This a test.
After deleteCharAt: his a test.
replace( )
You can replace one set of characters with another set inside a StringBuffer object by calling replace( ). Its signature is shown here:
StringBuffer replace(int startIndex, int endIndex, String str)
The substring being replaced is specified by the indexes startIndex and endIndex. Thus, the substring at startIndex through endIndex–1 is replaced. The replacement string is passed in str. The resulting StringBuffer object is returned. The following program demonstrates replace( ):
// Demonstrate replace() class replaceDemo {
public static void main(String args[]) {
StringBuffer sb = new StringBuffer("This is a test."); sb.replace(5, 7, "was");
System.out.println("After replace: " + sb);
}
}
Here is the output:
After replace: This was a test.
substring( )
You can obtain a portion of a StringBuffer by calling substring(
). It has the following two forms:
String substring(int startIndex)
String substring(int startIndex, int endIndex)
The first form returns the substring that starts at startIndex and runs to the end of the invoking StringBuffer object. The second form returns the substring that starts at startIndex and runs through endIndex–1.
Method Description
StringBuffer appendCodePoint(int ch) Appends a Unicode code point to the end of the invoking object. A reference to the object is returned.
int codePointAt(int i) Returns the Unicode code point at the location specified by i.
int codePointBefore(int i) Returns the Unicode code point at the location that precedes that specified by i.
int codePointCount(int start, int end) Returns the number of code points in the portion of the invoking String that are between start and end–1.
int indexOf(String str) Searches the invoking StringBuffer for the first occurrence of str. Returns the index of the match, or –1 if no match is found.
int indexOf(String str, int startIndex) Searches the invoking StringBuffer for the first occurrence of str, beginning at startIndex. Returns the index of the match, or –1 if no match is found.
int lastIndexOf(String str) Searches the invoking StringBuffer for the last occurrence of str. Returns the index of the match, or –1 if no match is found.
int lastIndexOf(String str, int startIndex) Searches the invoking StringBuffer for the last occurrence of str, beginning at startIndex. Returns the index of the match, or –1 if no match is found.
int offsetByCodePoints(int start, int num) Returns the index within the invoking string that is num
code points beyond the starting index specified by start.
CharSequence subSequence(int startIndex, int stopIndex) Returns a substring of the invoking string, beginning at startIndex and stopping at stopIndex. This method is required by the CharSequence interface, which is implemented by StringBuffer.
void trimToSize( ) Requests that the size of the character buffer for the invoking object be reduced to better fit the current contents.
class IndexOfDemo {
public static void main(String args[]) {
StringBuffer sb = new StringBuffer("one two one"); int i;
i = sb.indexOf("one"); System.out.println("First index: " + i); i = sb.lastIndexOf("one"); System.out.println("Last index: " + i);
}
}
The output is shown here: First index: 0
Last index: 8
Enumerations
Enumerations
In its simplest form, an enumeration is a list of named constants.
// An enumeration of apple varieties. enum Apple {
Jonathan, GoldenDel, RedDel, Winesap, Cortland
}
The identifiers Jonathan, GoldenDel, and so on, are called enumeration constants. Each is implicitly declared as a public, static final member of Apple. Furthermore, their type is the type of the enumeration in which they are declared, which is Apple in this case. Thus, in the language of Java, these constants are called self-typed, in which “self” refers to the enclosing enumeration
Declares variable of enumeration type Apple ap;
Because ap is of type Apple, the only values that it can be assigned (or can contain) are those defined by the enumeration. For example, this assigns ap the value RedDel:
ap = Apple.RedDel;
Two enumeration constants can be compared for equality by using the = = relational operator.
For example
if(ap == Apple.GoldenDel) // ...
An enumeration value can also be used to control a switch statement. Of course, all of the case statements must use constants from the same enum as that used by the switch expression.
For example:
// Use an enum to control a switch statement. switch(ap) {
case Jonathan:
// ...
case Winesap:
// ...
The names of the enumeration constants are used without being qualified by their enumeration type name. This is because the type of the enumeration in the switch expression has already implicitly specified the enum type of the case constants. There is no need to qualify the constants in the case statements with their enum type name. In fact, attempting to do so will cause a compilation error.
When an enumeration constant is displayed, such as in a println( )
statement, its name is output.
For example, given this statement: System.out.println(Apple.Winesap);
// An enumeration of apple varieties. enum Apple {
Jonathan, GoldenDel, RedDel, Winesap, Cortland
}
class EnumDemo {
public static void main(String args[])
{
Apple ap;
ap = Apple.RedDel;
// Output an enum value. System.out.println("Value of ap: " + ap); System.out.println();
ap = Apple.GoldenDel;
// Compare two enum values. if(ap == Apple.GoldenDel)
System.out.println("ap contains GoldenDel.\n");
switch(ap) { case Jonathan:
System.out.println("Jonathan is red."); break;
case GoldenDel:
System.out.println("Golden Delicious is yellow."); break;
case RedDel:
System.out.println("Red Delicious is red."); break;
case Winesap: System.out.println("Winesap is red."); break;
case Cortland: System.out.println("Cortland is red."); break;}}}
The values( ) and valueOf( ) Methods
All enumerations automatically contain two predefined methods: values( ) and valueOf( ).
public static enum-type [ ] values( ) public static enum-type
valueOf(String str )
The values( ) method returns an array that contains a list of the enumeration constants. The valueOf( ) method returns the enumeration constant whose value corresponds to the string passed in str. In both cases, enum-type is the type of the enumeration.
The return type of Apple.valueOf("Winesap") is Winesap.
Wrapper Classes
Despite the performance benefit offered by the primitive types, there are times when you will need an object representation. For example, you can’t pass a primitive type by reference to a method. The type wrappers are Double, Float, Long, Integer, Short, Byte, Character, and Boolean. These classes offer a wide array of methods that allow you to fully integrate the primitive types into Java’s object hierarchy.
Character
Character is a wrapper around a char. The constructor for Character isCharacter(char ch). Here, ch specifies the character that will be wrapped by the Character object being created. To obtain the char value contained in a Character object, call charValue( ), shown here:
Boolean
Boolean is a wrapper around boolean values. It defines these constructors:
Boolean(boolean boolValue) Boolean(String boolString)
In the first version, boolValue must be either true or false. In the second version, if boolString contains the string "true" (in uppercase or lowercase), then the new Boolean object will be true. Otherwise, it will be false. To obtain a boolean value from a Boolean object, use booleanValue( ), shown here:
boolean booleanValue( )
It returns the boolean equivalent of the invoking object.
The Numeric Type Wrappers
By far, the most commonly used type wrappers are those that represent numeric values. These are Byte, Short, Integer, Long, Float, and Double. All of the numeric type wrappers inherit the abstract class Number. Number declares methods that return the value of an object in each of the different number formats. These methods are shown here:
All of the numeric type wrappers define constructors that allow an object to be constructed from a given value, or a string representation of that value.
For example, here are the constructors defined for Integer:
Integer(int num) Integer(String str)
If str does not contain a valid numeric value, then a NumberFormatException is thrown. All of the type wrappers override toString( ). It returns the humanreadable form of the value contained within the wrapper.
// Demonstrate a type wrapper. class Wrap
{
public static void main(String args[])
{
Integer iOb = new Integer(100); //boxing
int i = iOb.intValue(); //unboxing System.out.println(i + " " + iOb); // displays 100 100
}
}
The process of encapsulating a value within an object is called boxing. The process of extracting a value from a type wrapper is called unboxing.
Autoboxing
Beginning with JDK 5, Java added two important features: autoboxing and auto-unboxing. Autoboxing is the process by which a primitive type is automatically encapsulated (boxed) into its equivalent type wrapper whenever an object of that type is needed. There is no need to explicitly construct an object. Autounboxing is the process by which the value of a boxed object is automatically extracted (unboxed) from a type wrapper when its value is needed. There is no need to call a method such as intValue( ) or doubleValue( ). With autoboxing, it is no longer necessary to manually construct an object in order to wrap a primitive type. You need only assign that value to a typewrapper reference. Java automatically constructs the object for you.
For example
Integer iOb = 100; // autobox an int
// Demonstrate autoboxing/unboxing. class AutoBox
{
public static void main(String args[])
{
Integer iOb = 100; // autobox an int int i = iOb; // autounbox
System.out.println(i + " " + iOb); // displays 100 100
}
}
// Autoboxing/unboxing takes place with
// method parameters and return values. class AutoBox2 {
// Take an Integer parameter and return
// an int value;
static int m(Integer v) { return v ; // autounbox to int
}
public static void main(String args[]) {
// Pass an int to m() and assign the return value
// to an Integer. Here, the argument 100 is autoboxed
// into an Integer. The return value is also autoboxed
// into an Integer. Integer iOb = m(100); System.out.println(iOb);
}}
// Autoboxing/unboxing occurs inside expressions. class AutoBox3 {
public static void main(String args[]) { Integer iOb, IOB2;
int i;
iOb = 100;
System.out.println("Original value of iOb: " + iOb);
// The following automatically unboxes iOb,
// performs the increment, and then reboxes
// the result back into iOb.
++iOb;
System.out.println("After ++iOb: " + iOb);
// Here, iOb is unboxed, the expression is
// evaluated, and the result is reboxed and
// assigned to IOB2. IOB2 = iOb + (iOb / 3);
The output is shown here: Original value of iOb: 100 After ++iOb: 101
IOB2 after expression: 134 i after expression: 134
System.out.println("IOB2 after expression: " + IOB2);
// The same expression is evaluated, but the
// result is not reboxed. i = iOb + (iOb / 3);
System.out.println("i after expression: " + i);
}
}
Dr. Ashok Kumar
441
May 9, 2020
class AutoBox4 {
public static void main(String args[])
{
Integer iOb = 100; Double dOb = 98.6; dOb = dOb + iOb;
System.out.println("dOb after expression: " + dOb);
}
}
Autounboxing also allows you to mix different types of numeric objects in an expression. Once the values are unboxed, the standard type promotions and conversions are applied.
Integer iOb = 2; switch(iOb) {
case 1: System.out.println("one"); break;
case 2: System.out.println("two"); break;
default: System.out.println("error");
}
When the switch expression is evaluated, iOb is unboxed and its
int value is obtained.
class AutoBox5 {
public static void main(String args[])
{
// Autobox/unbox a boolean. Boolean b = true;
// Below, b is autounboxed when used in
// a conditional expression, such as an if. if(b) System.out.println("b is true");
// Autobox/unbox a char. Character ch = 'x'; // box a char char ch2 = ch; // unbox a char
System.out.println("ch2 is " + ch2);
}
}
No comments:
Post a Comment