Unit-1 : Object Oriented Programming And Introduction To Java, Data Types, Operators, Statements And Defining Classes In Java

• Features of the Java Language, Object-oriented Programming
• Creating an Application in Java, Compiling and executing Applications in Java
• Program comments
• Primitive data types, Integer Data Types, Floating Point Data Types
• Reference Data types
• Arrays, single and multi-dimensional arrays
• Other reference types, classes, interfaces, enums and annotations
• Unicode escapes in Java source code
• Understanding super types and subtypes.
• Operators - Arithmetic, String concatenation, Relational, Logical, Bitwise, increment-decrement,
conditional, assignment, cast and instance of operators.
• Understanding the narrowing and widening conversions of numeric data types.
• Statements - if, if-else, switch-case, for, while, do-while, break, continue and return statements.
• Various members within a class
• instance variables
• methods and their overloading
• constructors and their overloading
• Garbage collector and finalize method
• static variables and methods
• initializer blocks and the class initializer blocks



1) Features of the Java Language, Object-oriented Programming.


Platform Independent

The concept of Write-once-run-anywhere (known as the Platform independent) is one of the important key feature of java language that makes java as the most powerful language. Not even a single language is idle to this feature but java is more closer to this feature. The programs written on one platform can run on any platform provided the platform must have the JVM. 
 Object Oriented

To be an Object Oriented language, any language must follow at least the four characteristics.
  • Inheritance   :   It is the process of creating the new classes and using the behavior of the existing classes by extending them just to        reuse  the existing code and adding the additional features as needed.
  • Encapsulation:  :   It is the mechanism of combining the information and providing the abstraction.
  • Polymorphism:   :   As the name suggest one name multiple form, Polymorphism is the way of providing the different functionality by the
       functions  having the same name based on the signatures of the methods.
  • Dynamic binding  :   Sometimes we don't have the knowledge of objects about their specific types while writing our code. It is the way     of providing the maximum functionality to a program about the specific type at runtime.  
As the languages like Objective C, C++ fulfills the above four characteristics yet they  are not fully object oriented languages because they are structured as well as object oriented languages. But in case of java,  it is a fully Object Oriented language because object is at the outer most level of data structure in java. No stand alone methods, constants, and variables are there in java. Everything in java is object even the primitive data types can also be converted into object by using the wrapper class.

Robust

Java has the strong memory allocation and automatic garbage collection mechanism. It provides the powerful exception handling and type checking mechanism as compare to other programming languages. Compiler checks the program whether there any error and interpreter checks any run time error and makes the system secure from crash. All of the above features makes the java language robust.

Distributed

The widely used protocols like HTTP and FTP are developed in java. Internet programmers can call functions on these protocols and can get access the files from any remote machine on the internet rather than writing codes on their local system.

Portable

The feature Write-once-run-anywhere  makes the java language portable provided that the system must have interpreter for the JVM. Java also have the standard data size irrespective of operating system or the processor. These features makes the java as a portable language.

Dynamic

While executing the java program the user can get the required files dynamically from a local drive or from a computer thousands of miles away from the user just by connecting with the Internet.

Secure

Java does not use memory pointers explicitly. All the programs in java are run under an area known as the sand box. Security manager determines the accessibility options of a class like reading and writing a file to the local disk. Java uses the public key encryption system to allow the java applications to transmit over the internet in the secure encrypted form. The bytecode Verifier checks the classes after loading.

Performance

Java uses native code usage, and lightweight process called  threads. In the beginning interpretation of bytecode resulted the performance slow but the advance version of JVM uses the adaptive and just in time compilation technique that improves the performance.

Multithreaded

As we all know several features of Java like Secure, Robust, Portable, dynamic etc; you will be more delighted to know another feature of Java which is Multithreaded.
Java is also a Multithreaded programming language. Multithreading means a single program having different threads executing independently at the same time. Multiple threads execute instructions according to the program code in a process or a program. Multithreading works the similar way as multiple processes run on one computer.
Multithreading programming is a very interesting concept in Java. In multithreaded programs not even a single thread disturbs the execution of other thread. Threads are obtained from the pool of available ready to run threads and they run on the system CPUs. This is how Multithreading works in Java which you will soon come to know in details in later chapters.

Interpreted

We all know that Java is an interpreted language as well. With an interpreted language such as Java, programs run directly from the source code.
The interpreter program reads the source code and translates it on the fly into computations. Thus, Java as an interpreted language depends on an interpreter program.
The versatility of being platform independent makes Java to outshine from other languages. The source code to be written and distributed is platform independent.
Another advantage of Java as an interpreted language is its error debugging quality. Due to this any error occurring in the program gets traced. This is how it is different to work with Java.

Architecture Neutral

The term architectural neutral seems to be weird, but yes Java is an architectural neutral language as well. The growing popularity of networks makes developers think distributed. In the world of network it is essential that the applications must be able to migrate easily to different computer systems. Not only to computer systems but to a wide variety of hardware architecture and Operating system architectures as well.  The Java compiler does this by generating byte code instructions, to be easily interpreted on any machine and to be easily translated into native machine code on the fly. The compiler generates an architecture-neutral object file format to enable a Java application to execute anywhere on the network and then the compiled code is executed on many processors, given the presence of the Java runtime system. Hence Java was designed to support applications on network. This feature of Java has thrived the programming language.

2) Creating an Application in Java, Compiling and executing Applications in Java.

a)Writing a Program
   
//A Very Simple Example
class Demo {
  public static void main(String[] args){
    System.out.println("it's Demo");
  }
}

  b) Compiling the Program

      javac ExampleProgram.java
c) Running the programm

      java demo (Note:- use here class name which have main method)
3) Program comments

* Single-Line Comments

    /* Handle the condition. */ 
 
* Trailing Comments

if (a == 2) {
    return TRUE;            /* special case */
} else {
    return isPrime(a);      /* works only for odd a */

 
* End-Of-Line Comments

if (foo > 1) {

    // Do a double-flip.
    ...
}
else {
    return false;          // Explain why here.
}
//if (bar > 1) {
//
//    // Do a triple-flip.
//    ...
//}
//else {
//    return false;
//}


* Documentation Comments 

/**
 * The Example class provides ...
 */

 

 4) Primitive data types, Integer Data Types, Floating Point Data Types

Primitive Data Types

The Java programming language is statically-typed, which means that all variables must first be declared before they can be used. This involves stating the variable's type and name, as you've already seen:
int gear = 1;
Doing so tells your program that a field named "gear" exists, holds numerical data, and has an initial value of "1". A variable's data type determines the values it may contain, plus the operations that may be performed on it. In addition to int, the Java programming language supports seven other primitive data types. A primitive type is predefined by the language and is named by a reserved keyword. Primitive values do not share state with other primitive values. The eight primitive data types supported by the Java programming language are:
  • byte: The byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive). The byte data type can be useful for saving memory in large arrays, where the memory savings actually matters. They can also be used in place of int where their limits help to clarify your code; the fact that a variable's range is limited can serve as a form of documentation.
  • short: The short data type is a 16-bit signed two's complement integer. It has a minimum value of -32,768 and a maximum value of 32,767 (inclusive). As with byte, the same guidelines apply: you can use a short to save memory in large arrays, in situations where the memory savings actually matters.
  • int: The int data type is a 32-bit signed two's complement integer. It has a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647 (inclusive). For integral values, this data type is generally the default choice unless there is a reason (like the above) to choose something else. This data type will most likely be large enough for the numbers your program will use, but if you need a wider range of values, use long instead.
  • long: The long data type is a 64-bit signed two's complement integer. It has a minimum value of -9,223,372,036,854,775,808 and a maximum value of 9,223,372,036,854,775,807 (inclusive). Use this data type when you need a range of values wider than those provided by int.
  • float: The float data type is a single-precision 32-bit IEEE 754 floating point. Its range of values is beyond the scope of this discussion, but is specified in the Floating-Point Types, Formats, and Values section of the Java Language Specification. As with the recommendations for byte and short, use a float (instead of double) if you need to save memory in large arrays of floating point numbers. This data type should never be used for precise values, such as currency. For that, you will need to use the java.math.BigDecimal class instead. Numbers and Strings covers BigDecimal and other useful classes provided by the Java platform.
  • double: The double data type is a double-precision 64-bit IEEE 754 floating point. Its range of values is beyond the scope of this discussion, but is specified in the Floating-Point Types, Formats, and Values section of the Java Language Specification. For decimal values, this data type is generally the default choice. As mentioned above, this data type should never be used for precise values, such as currency.
  • boolean: The boolean data type has only two possible values: true and false. Use this data type for simple flags that track true/false conditions. This data type represents one bit of information, but its "size" isn't something that's precisely defined.
  • char: The char data type is a single 16-bit Unicode character. It has a minimum value of '\u0000' (or 0) and a maximum value of '\uffff' (or 65,535 inclusive).
In addition to the eight primitive data types listed above, the Java programming language also provides special support for character strings via the java.lang.String class. Enclosing your character string within double quotes will automatically create a new String object; for example, String s = "this is a string";. String objects are immutable, which means that once created, their values cannot be changed. The String class is not technically a primitive data type, but considering the special support given to it by the language, you'll probably tend to think of it as such. You'll learn more about the String class in Simple Data Objects.

byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
char '\u0000'
String (or any object)   null
boolean false

Literals

You may have noticed that the new keyword isn't used when initializing a variable of a primitive type. Primitive types are special data types built into the language; they are not objects created from a class. A literal is the source code representation of a fixed value; literals are represented directly in your code without requiring computation. As shown below, it's possible to assign a literal to a variable of a primitive type:
boolean result = true;
char capitalC = 'C';
byte b = 100;
short s = 10000;
int i = 100000; 
 
 

Integer Literals

An integer literal is of type long if it ends with the letter L or l; otherwise it is of type int. It is recommended that you use the upper case letter L because the lower case letter l is hard to distinguish from the digit 1.
Values of the integral types byte, short, int, and long can be created from int literals. Values of type long that exceed the range of int can be created from long literals. Integer literals can be expressed by these number systems:
  • Decimal: Base 10, whose digits consists of the numbers 0 through 9; this is the number system you use every day
  • Hexadecimal: Base 16, whose digits consist of the numbers 0 through 9 and the letters A through F
  • Binary: Base 2, whose digits consists of the numbers 0 and 1 (you can create binary literals in Java SE 7 and later)
For general-purpose programming, the decimal system is likely to be the only number system you'll ever use. However, if you need to use another number system, the following example shows the correct syntax. The prefix 0x indicates hexadecimal and 0b indicates binary:
// The number 26, in decimal
int decVal = 26;
//  The number 26, in hexadecimal
int hexVal = 0x1a;
// The number 26, in binary
int binVal = 0b11010;

Floating-Point Literals

A floating-point literal is of type float if it ends with the letter F or f; otherwise its type is double and it can optionally end with the letter D or d.
The floating point types (float and double) can also be expressed using E or e (for scientific notation), F or f (32-bit float literal) and D or d (64-bit double literal; this is the default and by convention is omitted).
double d1 = 123.4;
// same value as d1, but in scientific notation
double d2 = 1.234e2;
float f1  = 123.4f;

Character and String Literals

Literals of types char and String may contain any Unicode (UTF-16) characters. If your editor and file system allow it, you can use such characters directly in your code. If not, you can use a "Unicode escape" such as '\u0108' (capital C with circumflex), or "S\u00ED Se\u00F1or" (Sí Señor in Spanish). Always use 'single quotes' for char literals and "double quotes" for String literals. Unicode escape sequences may be used elsewhere in a program (such as in field names, for example), not just in char or String literals.
The Java programming language also supports a few special escape sequences for char and String literals: \b (backspace), \t (tab), \n (line feed), \f (form feed), \r (carriage return), \" (double quote), \' (single quote), and \\ (backslash).
There's also a special null literal that can be used as a value for any reference type. null may be assigned to any variable, except variables of primitive types. There's little you can do with a null value beyond testing for its presence. Therefore, null is often used in programs as a marker to indicate that some object is unavailable.
Finally, there's also a special kind of literal called a class literal, formed by taking a type name and appending ".class"; for example, String.class. This refers to the object (of type Class) that represents the type itself.


Table:- Integer Types and Their Representations
Type
Representation
Range
byte
8-bit, signed, two's complement
-128 to 127
short
16-bit, signed, two's complement
-32768 to 32767
int
32-bit, signed, two's complement
-2147483648 to 2147483647
long
64-bit, signed, two's complement
-9223372036854775808 to 9223372036854775807
char
16-bit, unsigned, Unicode
'\u0000' to '\uffff'

Table:- Assignment Compatibility Between Integer Types
To/From
byte
char
short
int
long
byte
Assignable
Cast needed
Cast needed
Cast needed
Cast needed
char
Cast needed
Assignable
Cast needed
Cast needed
Cast needed
short
Assignable
Cast needed
Assignable
Cast needed
Cast needed
int
Assignable
Assignable
Assignable
Assignable
Cast needed
long
Assignable
Assignable
Assignable
Assignable
Assignable


5)  Reference Data types
 
The non-primitive data types in Java are objects and arrays.
These non-primitive types are often called "reference types"
because they are handled "by reference"--in other words, 
the address of the object or array is stored in a variable, 
passed to methods, and so on.  By comparison, primitive types 
are handled "by value"--the actual primitive values are stored
in variables and passed to methods.

In C, you can manipulate a value by reference by taking its address with the & operator, and you can "dereference" an address with the * and -> operators. These operators do not exist in Java: primitive types are always passed by value; arrays and objects are always passed by reference.
Because objects are passed by reference, two different variables may refer to the same object:
Button p, q;
p = new Button();           // p refers to a Button object.
q = p;                      // q refers to the same Button.
p.setLabel("Ok");           // A change to the object through p...
String s = q.getLabel();    // ...is also visible through q.  
                            // s now contains "Ok."
This is not true of primitive types, however:
int i = 3;                  // i contains the value 3.
int j = i;                  // j contains a copy of the value in i.
i = 2;                      // Changing i doesn't change j.
                            // Now, i == 2 and j == 3.

Terminology: Pass by Reference

The statement that Java manipulates objects "by reference" causes confusion for some programmers, because there are several different meanings of "by reference" in common use. Regardless of what we call it, it is important to understand what Java does. Java works with references to objects. A Java variable holds only a reference to an object, not the object itself. When an object is passed to a method, only a reference to the object is actually passed, not the entire object. It is in this sense that Java manipulates objects "by reference."
Some people use the term "pass by reference" to mean that a reference to a variable is passed to a method. Java does not do this. For example, it is not possible to write a working swap() function like the following in Java:
public void swap(Object a, Object b) {
  Object temp = a;
  a = b;
  b = temp;
}
The method parameters a and b contain references to objects, not addresses of variables. Thus, while this swap() function does compile and run, it has no effect except on its own local variables and arguments.
To solve this terminology problem, perhaps we should say that Java manipulates objects "by reference," but it passes object references to methods "by value."

Copying Objects

Because reference types are not passed by value, assigning one object to another in Java does not copy the value of the object. It merely assigns a reference to the object. Consider the following code:
Button a = new Button("Okay");
Button b = new Button("Cancel");
a = b;
After these lines are executed, the variable a contains a reference to the object that b refers to. The object that a used to refer to is lost.
To copy the data of one object into another object, use the clone() method:
Vector b = new Vector;
c = b.clone();
After these lines run, the variable c refers to an object that is a duplicate of the object referred to by b. Note that not all types support the clone() method. Only classes that implement the Cloneable interface may be cloned. For more information on cloning objects, look up java.lang.Cloneable and java.lang.Object.clone
Arrays are also reference types, and assigning an array simply copies a reference to the array. To actually copy the values stored in an array, you must assign each of the values individually or use the System.arraycopy() method.

Checking Objects for Equality

Another implication of passing objects by reference is that the == operator tests whether two variables refer to the same object, not whether two objects contain the same values. To actually test whether two separate objects are the same, you must use a specially written method for that object type (just as you might use strcmp() to compare C strings for equality). In Java, a number of classes define an equals() method that you can use to perform this test.

Java Has No Pointers

The referencing and dereferencing of objects is handled for you automatically by Java. Java does not allow you to manipulate pointers or memory addresses of any kind:
  • It does not allow you to cast object or array references into integers or vice-versa.
  • It does not allow you to do pointer arithmetic.
  • It does not allow you to compute the size in bytes of any primitive type or object.
There are two reasons for these restrictions:
  • Pointers are a notorious source of bugs. Eliminating them simplifies the language and eliminates many potential bugs.
  • Pointers and pointer arithmetic could be used to sidestep Java's run-time checks and security mechanisms. Removing pointers allows Java to provide the security guarantees that it does.
To a C programmer, the lack of pointers and pointer arithmetic may seem an odious restriction in Java. But once you get used to the Java object-oriented programming model, it no longer seems like a serious restriction at all. The lack of pointers does mean that you probably can't do things like write UNIX device drivers in Java (at least not without using native methods written in C). But big deal--most of us never have to do this kind of low-level programming anyway.

null

The default value for variables of all reference types is null. null is a reserved value that indicates "an absence of reference"--i.e., that a variable does not refer to any object or array.
In Java, null is a reserved keyword, unlike NULL in C, where it is just a constant defined to be 0. null is an exception to the strong typing rules of Java--it may be assigned to any variable of reference type (i.e., any variable which has a class, interface, or array as its type).
null can't be cast to any primitive type, including integral types and boolean. It shouldn't be considered equal to zero (although it may be implemented this way).

Reference Type Summary

The distinction between primitive types passed by value, and objects and arrays passed by reference is a crucial one in Java. Be sure you understand the following:
  • All objects and arrays are handled by reference in Java. (Those object references are passed-by-value to methods, however.)
  • The = and == operators assign and test references to objects. Use clone() and equals() to actually copy or test the objects themselves.
  • The necessary referencing and dereferencing of objects and arrays is handled automatically by Java.
  • A reference type can never be cast to a primitive type.
  • A primitive type can never be cast to a reference type.
  • There is no pointer arithmetic in Java.
  • There is no sizeof operator in Java.
  • null is a special value that means "no object" or indicates an absence of reference. 

Primitives vs. References

  • primitive types are the basic types of data
    • byte, short, int, long, float, double, boolean, char
    • primitive variables store primitive values
  • reference types are any instantiable class as well as arrays
    • String, Scanner, Random, Die, int[], String[], etc.
    • reference variables store addresses

Assignment

  • copies the contents of RHS variable into LHS variable
    • primitives: the primitive value is copied
    • references: the address is copied
  • implications: for references the object is not copied, it is shared (reference variables are aliases)

Comparisons (e.g. ==)

  • compares the contents of the variables
    • primitives: the primitive values are compared
    • references: the addresses are compared
  • implications: for references the contents of the objects are not compared

Passing Parameters

  • terminology:
    • formal parameter: the parameter variable that is listed (along with its type) in the method declaration
    • actual parameter: the parameter that is given when the method is called
  • copies the contents of actual parameter into the formal parameter (i.e., pass-by-value)
    • primitives: the primitive value is copied
    • references: the address is copied
  • implications: for references the object is not copied, it is shared (i.e., actual parameter and formal parameter are aliases)
  • primitives: changing the formal parameter's value doesn't affect the actual parameter's value
  • references: changing the formal parameter's address doesn't affect the actual parameter's address but changing the formal parameter's object does change the actual parameter's object since they refer to the same object

Returning Values

  • returns a result to where the method was called
    • primitives: the primitive value is returned
    • references: the address is returned
  • recall: local variables and parameters are destroyed when the method finishes execution
  • implications: a locally created object can survive if it is returned or if it is stored in a data member

6) Arrays, single and multi-dimensional arrays

Array Types

Array types are the second kind of reference types in Java. An array is an ordered collection, or numbered list, of values. The values can be primitive values, objects, or even other arrays, but all of the values in an array must be of the same type. The type of the array is the type of the values it holds, followed by the characters []. For example:
byte b;                        // byte is a primitive type
byte[] arrayOfBytes;           // byte[] is an array type: array of byte
byte[][] arrayOfArrayOfBytes;  // byte[][] is another type: array of byte[]
Point[] points;                // Point[] is an array of Point objects
For compatibility with C and C++, Java also supports another syntax for declaring variables of array type. In this syntax, one or more pairs of square brackets follow the name of the variable, rather than the name of the type:
byte arrayOfBytes[];            // Same as byte[] arrayOfBytes
byte arrayOfArrayOfBytes[][];   // Same as byte[][] arrayOfArrayOfBytes
byte[] arrayOfArrayOfBytes[];   // Ugh! Same as byte[][] arrayOfArrayOfBytes
This is almost always a confusing syntax, however, and it is not recommended.
With classes and objects, we have separate terms for the type and the values of that type. With arrays, the single word array does double duty as the name of both the type and the value. Thus, we can speak of the array type int[] (a type) and an array of int (a particular array value). In practice, it is usually clear from context whether a type or a value is being discussed.

* Creating Arrays

To create an array value in Java, you use the new keyword, just as you do to create an object. Arrays don't need to be initialized like objects do, however, so you don't pass a list of arguments between parentheses. What you must specify, though, is how big you want the array to be. If you are creating a byte[], for example, you must specify how many byte values you want it to hold. Array values have a fixed size in Java. Once an array is created, it can never grow or shrink. Specify the desired size of your array as a non-negative integer between square brackets:
byte[] buffer = new byte[1024];
String[] lines = new String[50];
When you create an array with this syntax, each of the values held in the array is automatically initialized to its default value. This is false for boolean values, '\u0000' for char values, 0 for integer values, 0.0 for floating-point values, and null for objects or array values.

* Using Arrays

Once you've created an array with the new operator and the square-bracket syntax, you also use square brackets to access the individual values contained in the array. Remember that an array is an ordered collection of values. The elements of an array are numbered sequentially, starting with 0. The number of an array element refers to the element. This number is often called the index, and the process of looking up a numbered value in an array is sometimes called indexing the array.
To refer to a particular element of an array, simply place the index of the desired element in square brackets after the name of the array. For example:
String[] responses = new String[2];   // Create an array of two strings
responses[0] = "Yes";                 // Set the first element of the array
responses[1] = "No";                  // Set the second element of the array

// Now read these array elements
System.out.println(question + " (" + responses[0] + "/" +
                   responses[1] + " ): ");
In some programming languages, such as C and C++, it is a common bug to write code that tries to read or write array elements that are past the end of the array. Java does not allow this. Every time you access an array element, the Java interpreter automatically checks that the index you have specified is valid. If you specify a negative index or an index that is greater than the last index of the array, the interpreter throws an exception of type ArrayIndexOutOfBoundsException. This prevents you from reading or writing nonexistent array elements.
Array index values are integers; you cannot index an array with a floating-point value, a boolean, an object, or another array. char values can be converted to int values, so you can use characters as array indexes. Although long is an integer data type, long values cannot be used as array indexes. This may seem surprising at first, but consider that an int index supports arrays with over two billion elements. An int[] with this many elements would require eight gigabytes of memory. When you think of it this way, it is not surprising that long values are not allowed as array indexes.
Besides setting and reading the value of array elements, there is one other thing you can do with an array value. Recall that whenever we create an array, we must specify the number of elements the array holds. This value is referred to as the length of the array; it is an intrinsic property of the array. If you need to know the length of the array, append .length to the array name:
if (errorCode < errorMessages.length)
  System.out.println(errorMessages[errorCode]);
.length is special Java syntax for arrays. An expression like a.length looks as though it refers to a field of an object a, but this is not actually the case. The .length syntax can be used only to read the length of an array. It cannot be used to set the length of an array (because, in Java, an array has a fixed length that can never change).
In the previous example, the array index within square brackets is a variable, not an integer literal. In fact, arrays are most often used with loops, particularly for loops, where they are indexed using a variable that is incremented or decremented each time through the loop:
int[] values;                          // Array elements initialized elsewhere
int total = 0;                         // Store sum of elements here
for(int i = 0; i < values.length; i++) // Loop through array elements
  total += values[i];                  // Add them up
In Java, the first element of an array is always element number 0. If you are accustomed to a programming language that numbers array elements beginning with 1, this will take some getting used to. For an array a, the first element is a[0], the second element is a[1], and the last element is:
a[a.length - 1]         // The last element of any array named a

* Array Literals

The null literal used to represent the absence of an object can also be used to represent the absence of an array. For example:
char[] password = null;
In addition to the null literal, Java also defines special syntax that allows you to specify array values literally in your programs. There are actually two different syntaxes for array literals. The first, and more commonly used, syntax can be used only when declaring a variable of array type. It combines the creation of the array object with the initialization of the array elements:
int[] powersOfTwo = {1, 2, 4, 8, 16, 32, 64, 128};
This creates an array that contains the eight int elements listed within the curly braces. Note that we don't use the new keyword or specify the type of the array in this array literal syntax. The type is implicit in the variable declaration of which the initializer is a part. Also, the array length is not specified explicitly with this syntax; it is determined implicitly by counting the number of elements listed between the curly braces. There is a semicolon following the close curly brace in this array literal. This is one of the fine points of Java syntax. When curly braces delimit classes, methods, and compound statements, they are not followed by semicolons. However, for this array literal syntax, the semicolon is required to terminate the variable declaration statement.
The problem with this array literal syntax is that it works only when you are declaring a variable of array type. Sometimes you need to do something with an array value (such as pass it to a method) but are going to use the array only once, so you don't want to bother assigning it to a variable. In Java 1.1 and later, there is an array literal syntax that supports this kind of anonymous arrays (so called because they are not assigned to variables, so they don't have names). This kind of array literal looks as follows:
// Call a method, passing an anonymous array literal that contains two strings
String response = askQuestion("Do you want to quit?",
                              new String[] {"Yes", "No"});

// Call another method with an anonymous array (of anonymous objects)
double d = computeAreaOfTriangle(new Point[] { new Point(1,2),
                                               new Point(3,4),
                                               new Point(3,2) });
With this syntax, you use the new keyword and specify the type of the array, but the length of the array is not explicitly specified.
It is important to understand that the Java Virtual Machine architecture does not support any kind of efficient array initialization. In other words, array literals are created and initialized when the program is run, not when the program is compiled. Consider the following array literal:
int[] perfectNumbers = {6, 28};
This is compiled into Java byte codes that are equivalent to:
int[] perfectNumbers = new int[2];
perfectNumbers[0] = 6;
perfectNumbers[1] = 28;
Thus, if you want to include a large amount of data in a Java program, it may not be a good idea to include that data literally in an array, since the Java compiler has to create lots of Java byte codes to initialize the array, and then the Java interpreter has to laboriously execute all that initialization code. In cases like this, it is better to store your data in an external file and read it into the program at runtime.
The fact that Java does all array initialization explicitly at runtime has an important corollary, however. It means that the elements of an array literal can be arbitrary expressions that are computed at runtime, rather than constant expressions that are resolved by the compiler. For example:
Point[] points = { circle1.getCenterPoint(), circle2.getCenterPoint() };

* Multidimensional Arrays

As we've seen, an array type is simply the element type followed by a pair of square brackets. An array of char is char[], and an array of arrays of char is char[][]. When the elements of an array are themselves arrays, we say that the array is multidimensional. In order to work with multidimensional arrays, there are a few additional details you must understand.
Imagine that you want to use a multidimensional array to represent a multiplication table:
int[][] products;      // A multiplication table
Each of the pairs of square brackets represents one dimension, so this is a two-dimensional array. To access a single int element of this two-dimensional array, you must specify two index values, one for each dimension. Assuming that this array was actually initialized as a multiplication table, the int value stored at any given element would be the product of the two indexes. That is, products[2][4] would be 8, and products[3][7] would be 21.
To create a new multidimensional array, use the new keyword and specify the size of both dimensions of the array. For example:
int[][] products = new int[10][10];
In some languages, an array like this would be created as a single block of 100 int values. Java does not work this way. This line of code does three things:
  • Declares a variable named products to hold an array of arrays of int.
  • Creates a 10-element array to hold 10 arrays of int.
  • Creates 10 more arrays, each of which is a 10-element array of int. It assigns each of these 10 new arrays to the elements of the initial array. The default value of every int element of each of these 10 new arrays is 0.
To put this another way, the previous single line of code is equivalent to the following code:
int[][] products = new int[10][];    // An array to hold ten int[] values. 
for(int i = 0; i < 10; i++)          // Loop ten times... 
  products[i] = new int[10];         // ...and create ten arrays. 
The new keyword performs this additional initialization automatically for you. It works with arrays with more than two dimensions as well:
float[][][] globalTemperatureData = new float[360][180][100];
When using new with multidimensional arrays, you do not have to specify a size for all dimensions of the array, only the leftmost dimension or dimensions. For example, the following two lines are legal:
float[][][] globalTemperatureData = new float[360][][];
float[][][] globalTemperatureData = new float[360][180][];
The first line creates a single-dimensional array, where each element of the array can hold a float[][]. The second line creates a two-dimensional array, where each element of the array is a float[]. If you specify a size for only some of the dimensions of an array, however, those dimensions must be the leftmost ones. The following lines are not legal:
float[][][] globalTemperatureData = new float[360][][100];  // Error!
float[][][] globalTemperatureData = new float[][180][100];  // Error!
Like a one-dimensional array, a multidimensional array can be initialized using an array literal. Simply use nested sets of curly braces to nest arrays within arrays. For example, we can declare, create, and initialize a 5×5 multiplication table like this:
int[][] products = { {0, 0, 0, 0, 0},
                     {0, 1, 2, 3, 4},
                     {0, 2, 4, 6, 8},
                     {0, 3, 6, 9, 12},
                     {0, 4, 8, 12, 16} };
Or, if you want to use a multidimensional array without declaring a variable, you can use the anonymous initializer syntax:
boolean response = bilingualQuestion(question, new String[][] {
                                                   { "Yes", "No" },
                                                   { "Oui", "Non" }});
When you create a multidimensional array using the new keyword, you always get a rectangular array: one in which all the array values for a given dimension have the same size. This is perfect for rectangular data structures, such as matrixes. However, because multidimensional arrays are implemented as arrays of arrays in Java, instead of as a single rectangular block of elements, you are in no way constrained to use rectangular arrays. For example, since our multiplication table is symmetrical about the diagonal from top left to bottom right, we can represent the same information in a nonrectangular array with fewer elements:
int[][] products = { {0},
                     {0, 1},
                     {0, 2, 4},


                     {0, 3, 6, 9},
                     {0, 4, 8, 12, 16} };
When working with multidimensional arrays, you'll often find yourself using nested loops to create or initialize them. For example, you can create and initialize a large triangular multiplication table as follows:
int[][] products = new int[12][];          // An array of 12 arrays of int.
for(int row = 0; row < 12; row++) {        // For each element of that array,
  products[row] = new int[row+1];          // allocate an array of int. 
  for(int col = 0; col < row+1; col++)     // For each element of the int[],
    products[row][col] = row * col;        // initialize it to the product. 
}

7) Other reference types, classes, interfaces, enums and annotations

Reference Types

Java is an object-oriented language. An object is a collection of variables and associated methods that is described by a class. The concepts in this section that relate to objects are discussed in detail in Object-Orientation Java Style.
The name of a class can be used as a type, so you can declare an object-type variable or specify that a method returns an object. If you declare a variable using the name of a class for its type, that variable can contain a reference to an object of that class. Such a variable does not contain an actual object, but rather a reference to the class instance, or object, the variable refers to. Because using a class name as a type declares a reference to an object, such types are called reference types. Java also allows the use of an interface name to specify a reference type. In addition, array types in Java are reference types because Java treats arrays as objects.
The two main characteristics of objects in Java are that:
  • Objects are always dynamically allocated. The lifetime of the storage occupied by an object is determined by the program's logic, not by the lifetime of a procedure call or the boundaries of a block. The lifetime of the storage occupied by an object refers to the span of time that begins when the object is created and ends at the earliest time it can be freed by the garbage collector.
  • Objects are not contained by variables. Instead, a variable contains a reference to an object. A reference is similar to what is called a pointer in other languages. If there are two variables of the same reference type and one variable is assigned to the other, both variables refer to the same object. If the information in that object is changed, the change is visible through both variables.
Java references are very similar to pointers in C/C++, but they are not at all related to the C++ notion of a reference. The main difference between Java references and C++ pointers is that Java does not allow any arithmetic to be done with references. This, coupled with Java's lack of any way to explicitly deallocate the storage used by reference type values, guarantees that a reference can never point to an illegal address. 

Class Types

The name of a class can be used to specify the type of a reference. If a variable is declared as a class type, the variable either contains null or a reference to an object of that class or a subclass of that class. It is not allowed to contain any other kinds of values. For example:
class Shape { ... }
class Triangle extends Shape { ... }
...
Shape s;
Triangle t;
...
s = t;
This example declares a class called Shape and a subclass of Shape called Triangle. The code later declares a reference variable called s that can contain a reference to a Shape object and another variable called t that can contain a reference to a Triangle object. The value of s can be assigned to the value of t because an object is not only an instance of its declared class, but also an instance of every superclass of its declared class. Since instances of the Triangle class are also instances of its superclass Shape, the Java compiler has no problem with s = t.
However, saying t = s generates an error message from the compiler. Java does not allow a reference variable declared as a class type to contain a reference to a superclass of the declared class. The assignment t = s is illegal because Shape is a superclass of Triangle. The assignment can be accomplished if s is first cast to a reference to Triangle:
t = (Triangle)s;
The cast operation ensures that the object referenced by s is a class type that is either Triangle or a descendant of Triangle. When you cast an object reference to a subclass of the reference type, you are saying that you want to treat the object being referenced as an instance of the specified subclass. If the compiler cannot determine whether the argument of a cast will be of the required type, the compiler generates runtime code that ensures that the argument really is an instance of the specified subclass. At runtime, if the class of the object being referenced is not an instance of the specified subclass, a ClassCastException is thrown. 


Examining Enums

Reflection provides three enum-specific APIs:
Class.isEnum()
Indicates whether this class represents an enum type
Class.getEnumConstants()
Retrieves the list of enum constants defined by the enum in the order they're declared
java.lang.reflect.Field.isEnumConstant()
Indicates whether this field represents an element of an enumerated type
Sometimes it is necessary to dynamically retrieve the list of enum constants; in non-reflective code this is accomplished by invoking the implicitly declared static method values() on the enum. If an instance of an enum type is not available the only way to get a list of the possible values is to invoke Class.getEnumConstants() since it is impossible to instantiate an enum type.
Given a fully qualified name, the EnumConstants example shows how to retrieve an ordered list of constants in an enum using Class.getEnumConstants().
import java.util.Arrays;
import static java.lang.System.out;

enum Eon { HADEAN, ARCHAEAN, PROTEROZOIC, PHANEROZOIC }

public class EnumConstants {
    public static void main(String... args) {
 try {
     Class<?> c = (args.length == 0 ? Eon.class : Class.forName(args[0]));
     out.format("Enum name:  %s%nEnum constants:  %s%n",
         c.getName(), Arrays.asList(c.getEnumConstants()));
     if (c == Eon.class)
  out.format("  Eon.values():  %s%n",
      Arrays.asList(Eon.values()));

        // production code should handle this exception more gracefully
 } catch (ClassNotFoundException x) {
     x.printStackTrace();
 }
    }
}
Samples of the output follows. User input is in italics.
$ java EnumConstants java.lang.annotation.RetentionPolicy
Enum name:  java.lang.annotation.RetentionPolicy
Enum constants:  [SOURCE, CLASS, RUNTIME]
$ java EnumConstants java.util.concurrent.TimeUnit
Enum name:  java.util.concurrent.TimeUnit
Enum constants:  [NANOSECONDS, MICROSECONDS, 
                  MILLISECONDS, SECONDS, 
                  MINUTES, HOURS, DAYS]
This example also shows that value returned by Class.getEnumConstants() is identical to the value returned by invoking values() on an enum type.
$ java EnumConstants
Enum name:  Eon
Enum constants:  [HADEAN, ARCHAEAN, 
                  PROTEROZOIC, PHANEROZOIC]
Eon.values():  [HADEAN, ARCHAEAN, 
                PROTEROZOIC, PHANEROZOIC] 
 
For Interface Please Go to unit 2;
 


7) Unicode escapes in Java source code

java.util.regex
Class Pattern

java.lang.Object
  extended by java.util.regex.Pattern
All Implemented Interfaces:
Serializable

public final class Pattern
extends Object
implements Serializable
A compiled representation of a regular expression.
A regular expression, specified as a string, must first be compiled into an instance of this class. The resulting pattern can then be used to create a Matcher object that can match arbitrary character sequences against the regular expression. All of the state involved in performing a match resides in the matcher, so many matchers can share the same pattern.
A typical invocation sequence is thus
 Pattern p = Pattern.compile("a*b");
 Matcher m = p.matcher("aaaaab");
 boolean b = m.matches();
A matches method is defined by this class as a convenience for when a regular expression is used just once. This method compiles an expression and matches an input sequence against it in a single invocation. The statement
 boolean b = Pattern.matches("a*b", "aaaaab");
is equivalent to the three statements above, though for repeated matches it is less efficient since it does not allow the compiled pattern to be reused. Instances of this class are immutable and are safe for use by multiple concurrent threads. Instances of the Matcher class are not safe for such use.

Summary of regular-expression constructs


Construct Matches
Characters
x The character x
\\ The backslash character
\0n The character with octal value 0n (0 <= n <= 7)
\0nn The character with octal value 0nn (0 <= n <= 7)
\0mnn The character with octal value 0mnn (0 <= m <= 3, 0 <= n <= 7)
\xhh The character with hexadecimal value 0xhh
\uhhhh The character with hexadecimal value 0xhhhh
\t The tab character ('\u0009')
\n The newline (line feed) character ('\u000A')
\r The carriage-return character ('\u000D')
\f The form-feed character ('\u000C')
\a The alert (bell) character ('\u0007')
\e The escape character ('\u001B')
\cx The control character corresponding to x
Character classes
[abc] a, b, or c (simple class)
[^abc] Any character except a, b, or c (negation)
[a-zA-Z] a through z or A through Z, inclusive (range)
[a-d[m-p]] a through d, or m through p: [a-dm-p] (union)
[a-z&&[def]] d, e, or f (intersection)
[a-z&&[^bc]] a through z, except for b and c: [ad-z] (subtraction)
[a-z&&[^m-p]] a through z, and not m through p: [a-lq-z](subtraction)
Predefined character classes
. Any character (may or may not match line terminators)
\d A digit: [0-9]
\D A non-digit: [^0-9]
\s A whitespace character: [ \t\n\x0B\f\r]
\S A non-whitespace character: [^\s]
\w A word character: [a-zA-Z_0-9]
\W A non-word character: [^\w]
POSIX character classes (US-ASCII only)
\p{Lower} A lower-case alphabetic character: [a-z]
\p{Upper} An upper-case alphabetic character:[A-Z]
\p{ASCII} All ASCII:[\x00-\x7F]
\p{Alpha} An alphabetic character:[\p{Lower}\p{Upper}]
\p{Digit} A decimal digit: [0-9]
\p{Alnum} An alphanumeric character:[\p{Alpha}\p{Digit}]
\p{Punct} Punctuation: One of !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
\p{Graph} A visible character: [\p{Alnum}\p{Punct}]
\p{Print} A printable character: [\p{Graph}\x20]
\p{Blank} A space or a tab: [ \t]
\p{Cntrl} A control character: [\x00-\x1F\x7F]
\p{XDigit} A hexadecimal digit: [0-9a-fA-F]
\p{Space} A whitespace character: [ \t\n\x0B\f\r]
java.lang.Character classes (simple java character type)
\p{javaLowerCase} Equivalent to java.lang.Character.isLowerCase()
\p{javaUpperCase} Equivalent to java.lang.Character.isUpperCase()
\p{javaWhitespace} Equivalent to java.lang.Character.isWhitespace()
\p{javaMirrored} Equivalent to java.lang.Character.isMirrored()
Classes for Unicode blocks and categories
\p{InGreek} A character in the Greek block (simple block)
\p{Lu} An uppercase letter (simple category)
\p{Sc} A currency symbol
\P{InGreek} Any character except one in the Greek block (negation)
[\p{L}&&[^\p{Lu}]]  Any letter except an uppercase letter (subtraction)
Boundary matchers
^ The beginning of a line
$ The end of a line
\b A word boundary
\B A non-word boundary
\A The beginning of the input
\G The end of the previous match
\Z The end of the input but for the final terminator, if any
\z The end of the input
Greedy quantifiers
X? X, once or not at all
X* X, zero or more times
X+ X, one or more times
X{n} X, exactly n times
X{n,} X, at least n times
X{n,m} X, at least n but not more than m times
Reluctant quantifiers
X?? X, once or not at all
X*? X, zero or more times
X+? X, one or more times
X{n}? X, exactly n times
X{n,}? X, at least n times
X{n,m}? X, at least n but not more than m times
Possessive quantifiers
X?+ X, once or not at all
X*+ X, zero or more times
X++ X, one or more times
X{n}+ X, exactly n times
X{n,}+ X, at least n times
X{n,m}+ X, at least n but not more than m times
Logical operators
XY X followed by Y
X|Y Either X or Y
(X) X, as a capturing group
Back references
\n Whatever the nth capturing group matched
Quotation
\ Nothing, but quotes the following character
\Q Nothing, but quotes all characters until \E
\E Nothing, but ends quoting started by \Q
Special constructs (non-capturing)
(?:X) X, as a non-capturing group
(?idmsux-idmsux)  Nothing, but turns match flags on - off
(?idmsux-idmsux:X)   X, as a non-capturing group with the given flags on - off
(?=X) X, via zero-width positive lookahead
(?!X) X, via zero-width negative lookahead
(?<=X) X, via zero-width positive lookbehind
(?<!X) X, via zero-width negative lookbehind
(?>X) X, as an independent, non-capturing group



Backslashes, escapes, and quoting

The backslash character ('\') serves to introduce escaped constructs, as defined in the table above, as well as to quote characters that otherwise would be interpreted as unescaped constructs. Thus the expression \\ matches a single backslash and \{ matches a left brace.
It is an error to use a backslash prior to any alphabetic character that does not denote an escaped construct; these are reserved for future extensions to the regular-expression language. A backslash may be used prior to a non-alphabetic character regardless of whether that character is part of an unescaped construct.
Backslashes within string literals in Java source code are interpreted as required by the Java Language Specification as either Unicode escapes or other character escapes. It is therefore necessary to double backslashes in string literals that represent regular expressions to protect them from interpretation by the Java bytecode compiler. The string literal "\b", for example, matches a single backspace character when interpreted as a regular expression, while "\\b" matches a word boundary. The string literal "\(hello\)" is illegal and leads to a compile-time error; in order to match the string (hello) the string literal "\\(hello\\)" must be used.

Character Classes

Character classes may appear within other character classes, and may be composed by the union operator (implicit) and the intersection operator (&&). The union operator denotes a class that contains every character that is in at least one of its operand classes. The intersection operator denotes a class that contains every character that is in both of its operand classes.
The precedence of character-class operators is as follows, from highest to lowest:
1     Literal escape     \x
2     Grouping [...]
3     Range a-z
4     Union [a-e][i-u]
5     Intersection [a-z&&[aeiou]]
Note that a different set of metacharacters are in effect inside a character class than outside a character class. For instance, the regular expression . loses its special meaning inside a character class, while the expression - becomes a range forming metacharacter.

Line terminators

A line terminator is a one- or two-character sequence that marks the end of a line of the input character sequence. The following are recognized as line terminators:
If UNIX_LINES mode is activated, then the only line terminators recognized are newline characters.
The regular expression . matches any character except a line terminator unless the DOTALL flag is specified.
By default, the regular expressions ^ and $ ignore line terminators and only match at the beginning and the end, respectively, of the entire input sequence. If MULTILINE mode is activated then ^ matches at the beginning of input and after any line terminator except at the end of input. When in MULTILINE mode $ matches just before a line terminator or the end of the input sequence.

Groups and capturing

Capturing groups are numbered by counting their opening parentheses from left to right. In the expression ((A)(B(C))), for example, there are four such groups:

1     ((A)(B(C)))
2     (A)
3     (B(C))
4     (C)
Group zero always stands for the entire expression.
Capturing groups are so named because, during a match, each subsequence of the input sequence that matches such a group is saved. The captured subsequence may be used later in the expression, via a back reference, and may also be retrieved from the matcher once the match operation is complete.
The captured input associated with a group is always the subsequence that the group most recently matched. If a group is evaluated a second time because of quantification then its previously-captured value, if any, will be retained if the second evaluation fails. Matching the string "aba" against the expression (a(b)?)+, for example, leaves group two set to "b". All captured input is discarded at the beginning of each match.
Groups beginning with (? are pure, non-capturing groups that do not capture text and do not count towards the group total.

Unicode support

This class is in conformance with Level 1 of Unicode Technical Standard #18: Unicode Regular Expression Guidelines, plus RL2.1 Canonical Equivalents.
Unicode escape sequences such as \u2014 in Java source code are processed as described in §3.3 of the Java Language Specification. Such escape sequences are also implemented directly by the regular-expression parser so that Unicode escapes can be used in expressions that are read from files or from the keyboard. Thus the strings "\u2014" and "\\u2014", while not equal, compile into the same pattern, which matches the character with hexadecimal value 0x2014.
Unicode blocks and categories are written with the \p and \P constructs as in Perl. \p{prop} matches if the input has the property prop, while \P{prop} does not match if the input has that property. Blocks are specified with the prefix In, as in InMongolian. Categories may be specified with the optional prefix Is: Both \p{L} and \p{IsL} denote the category of Unicode letters. Blocks and categories can be used both inside and outside of a character class.
The supported categories are those of The Unicode Standard in the version specified by the Character class. The category names are those defined in the Standard, both normative and informative. The block names supported by Pattern are the valid block names accepted and defined by UnicodeBlock.forName.
Categories that behave like the java.lang.Character boolean ismethodname methods (except for the deprecated ones) are available through the same \p{prop} syntax where the specified property has the name javamethodname

Converting Non-Unicode Text

In the Java programming language char values represent Unicode characters. Unicode is a 16-bit character encoding that supports the world's major languages. You can learn more about the Unicode standard at the Unicode Consortium Web site .
Few text editors currently support Unicode text entry. The text editor we used to write this section's code examples supports only ASCII characters, which are limited to 7 bits. To indicate Unicode characters that cannot be represented in ASCII, such as ö, we used the \uXXXX escape sequence. Each X in the escape sequence is a hexadecimal digit. The following example shows how to indicate the ö character with an escape sequence:

String str = "\u00F6";
char c = '\u00F6';
Character letter = new Character('\u00F6'); 
 
A variety of character encodings are used by systems around the world. Currently few of these encodings conform to Unicode. Because your program expects characters in Unicode, the text data it gets from the system must be converted into Unicode, and vice versa. Data in text files is automatically converted to Unicode when its encoding matches the default file encoding of the Java Virtual Machine. You can identify the default file encoding by creating an OutputStreamWriter using it and asking for its canonical name:

OutputStreamWriter out = new OutputStreamWriter(new ByteArrayOutputStream());
System.out.println(out.getEncoding()); 
 
If the default file encoding differs from the encoding of the text data you want to process, then you must perform the conversion yourself. You might need to do this when processing text from another country or computing platform.
This section discusses the APIs you use to translate non-Unicode text into Unicode. Before using these APIs, you should verify that the character encoding you wish to convert into Unicode is supported. The list of supported character encodings is not part of the Java programming language specification. Therefore the character encodings supported by the APIs may vary with platform. To see which encodings the Java Development Kit supports, see the Supported Encodings document.
The material that follows describes two techniques for converting non-Unicode text to Unicode. You can convert non-Unicode byte arrays into String objects, and vice versa. Or you can translate between streams of Unicode characters and byte streams of non-Unicode text.

Unicode Escapes

A compiler for the Java programming language ("Java compiler") first recognizes Unicode escapes in its input, translating the ASCII characters \u followed by four hexadecimal digits to the UTF-16 code unit of
the indicated hexadecimal value, and passing all other characters unchanged. Representing supplementary characters requires two consecutive Unicode escapes. This translation step results in a sequence of Unicode input characters.

UnicodeInputCharacter:
    UnicodeEscape
    RawInputCharacter

UnicodeEscape:
    \ UnicodeMarker HexDigit HexDigit HexDigit HexDigit

UnicodeMarker:
    u
    UnicodeMarker u

RawInputCharacter:
    any Unicode character

HexDigit: one of
    0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F

The \, u, and hexadecimal digits here are all ASCII characters.
In addition to the processing implied by the grammar, for each raw input character that is a backslash \, input processing must consider how many other \ characters contiguously precede it, separating it from a non-\ character or the start of the input stream. If this number is even, then the \ is eligible to begin a Unicode escape; if the number is odd, then the \ is not eligible to begin a Unicode escape.
For example, the raw input "\\u2297=\u2297" results in the eleven characters " \ \ u 2 2 9 7 =" (\u2297 is the Unicode encoding of the character ⊗).
If an eligible \ is not followed by u, then it is treated as a RawInputCharacter and remains part of the escaped Unicode stream.
If an eligible \ is followed by u, or more than one u, and the last u is not followed by four hexadecimal digits, then a compile-time error occurs.
The character produced by a Unicode escape does not participate in further Unicode escapes.
For example, the raw input \u005cu005a results in the six characters \ u 0 0 5 a, because 005c is the Unicode value for \. It does not result in the character Z, which is Unicode character 005a, because the \ that resulted from the \u005c is not interpreted as the start of a further Unicode escape.
The Java programming language specifies a standard way of transforming a program written in Unicode into ASCII that changes a program into a form that can be processed by ASCII-based tools. The transformation involves converting any Unicode escapes in the source text of the program to ASCII by adding an extra u - for example, \uxxxx becomes \uuxxxx - while simultaneously converting non-ASCII characters in the source text to Unicode escapes containing a single u each.
This transformed version is equally acceptable to a Java compiler and represents the exact same program. The exact Unicode source can later be restored from this ASCII form by converting each escape sequence where multiple u's are present to a sequence of Unicode characters with one fewer u, while simultaneously converting each escape sequence with a single u to the corresponding single Unicode character.
A Java compiler should use the \uxxxx notation as an output format to display Unicode characters when a suitable font is not available. 

 9) Understanding super types and subtypes.


Subtypes and Subclasses
Subtypes
We have used closed arrows in module dependence diagrams and object models. In MDDs, a closed arrow from an implementation ArrayList to a specification List means that ArrayList “meets” the specification of List. In an object model, a closed arrow denotes a subset relationship between the two sets.
We can also draw a closed arrow from A to B in an MDD, where A and B are implementation parts.
Here, the specifications of A and B are not drawn, but are implied in the MDD. A and B are modules with objects and associated methods. We say that that A is a B if every A object is also a B object. For instance, every automobile is a vehicle, and every bicycle is a vehicle, and every pogo stick is a vehicle; every vehicle is a mode of transport, as is every pack animal.
This subset relationship is a necessary but not sufficient condition for a subtyping relationship. Type A is a subtype of type B when A’s specification implies B’s specification. That is, any object (or class) that satisfies A’s specification also satisfies B’s specification, because B’s specification is weaker.
The definition of subtyping depends on the definition of strong versus weak specifications. In 6.170, we will define true subtyping to mean that anywhere in the code, if you expect a B object, an A object is acceptable.1 Code written to work with B objects (and to depend on their properties) is guaranteed to continue to work if it is supplied A objects instead; furthermore, the behavior will be the same, if we only consider the aspects of A’s behavior that is also included in B’s behavior. (A may introduce new behaviors that B does not have, but it may only change existing B behaviors in certain ways; see below.)
With no hubris whatsoever, we call the 6.170 notion of subtyping, true subtyping to distinguish it from Java subtypes, which correspond to a weaker notion.
Example: Bicycles
Suppose we have a class for representing bicycles. Here is a partial implementation:
class Bicycle {
private int framesize;
private int chainringGears;
private int freewheelGears;
...
// returns the number of gears on this bicycle
public int gears() { return chainringGears * freewheelGears; }
// returns the cost of this bicycle
public float cost() { ... }
// returns the sales tax owed on this bicycle
public float salesTax() { return cost() * .0825; }
// effects: transports the rider from work to home
public void goHome() { ... }
...
}
A new class representing bicycles with headlamps can accommodate late nights (or early mornings).
class LightedBicycle {
private int framesize;
private int chainringGears;
private int freewheelGears;
private BatteryType battery;
...
// returns the number of gears on this bicycle
public int gears() { return chainringGears * freewheelGears; }
// returns the cost of this bicycle
float cost() { ... }
// returns the sales tax owed on this bicycle
public float salesTax() { return cost() * .0825; }
// effects: transports the rider from work to home
public void goHome() { ... }
// effects: replaces the existing battery with the argument b
public void changeBattery(BatteryType b);
...
}
Copying all the code is tiresome and error-prone. (The error might be failure to copy correctly or failure to make a required change.) Additionally, if a bug is found in one version, it is easy to forget to propagate the fix to all versions of the code. Finally, it is very hard to comprehend the distinction the two classes by looking for differences themselves in a mass of similarities. 2
Java and other programming languages use subclassing to overcome these difficulties. Subclassing
permits reuse of implementations and overriding of methods. A better implementation of LightedBicycle is
class LightedBicycle extends Bicycle {
private BatteryType battery;
...
// returns the cost of this bicycle
float cost() { return super.cost() + battery.cost(); }
// effects: transports the rider from work to home
public void goHome() { ... }
// effects: replaces the existing battery with the argument b
public void changeBattery(BatteryType b);
...
}
LightedBicycle need not implement methods and fields that appear in its superclass Bicycle; the Bicycle versions are automatically used by Java when they are not overridden in the subclass.
Consider the following implementations of the goHome method (along with more complete specifications).
If these are the only changes, are LightedBicycle and RacingBicycle subtypes of Bicycle? (For the time being we will talk about subtyping; we’ll return to the differences between Java subclassing, Java subtyping, and true subtyping later.)
class Bicycle {
...
// requires: windspeed < 20mph && daylight
// effects: transports the rider from work to home
void goHome() { ... }
}
class LightedBicycle {
...
// requires: windspeed < 20mph
// effects: transports the rider from work to home
void goHome() { ... }
}
class RacingBicycle {
...
// requires: windspeed < 20mph && daylight
// effects: transports the rider from work to home
// in an elapsed time of < 10 minutes
// && gets the rider sweaty
void goHome() { ... }
}
To answer that question, recall the definition of subtyping: can an object of the subtype be substituted anywhere that code expects an object of the supertype? If so, the subtyping relationship is valid. 3
In this case, both LightedBicycle and RacingBicycle are subtypes of Bicycle. In the first case, the requirement is relaxed; in the second case, the effects are strengthened in a way that still satisfies the superclass’s effects.
The cost method of LightedBicycle shows another capability of subclassing in Java. Methods
can be overridden to provide a new implementation in a subclass. This enables more code reuse; in particular, LightedBicycle can reuse Bicycle’s salesTax method. When salesTax is invoked on a LightedBicycle, the Bicycle version is used instead. Then, the call to cost inside salesTax invokes the version based on the runtime type of the object (LightedBicycle), so the LightedBicycle version is used. Regardless of the declared type of an object, an implementation of a method with multiple implementations (of the same signature) is always selected based on the run-time type.
In fact, there is no way for an external client to invoke the version of a method specified by the declared type or any other type that is not the run-time type. This is an important and very desirable
property of Java (and other object-oriented languages). Suppose that the subclass maintains some extra fields which are kept in sync with fields of the superclass. If superclass methods could be invoked directly, possibly modifying superclass fields without also updating subclass fields, then the representation invariant of the subclass would be broken.
A subclass may invoke methods of its parent via use of super, however. Sometimes this is useful when the subclass method needs to do just a little bit more work; recall the LightedBicycle implementation of cost:
class LightedBicycle extends Bicycle {
//
returns
the
cost
of this bicycle
float cost(
){
return
super.cost()
+ battery.cost(); }
}
Suppose the Rider class models people who ride bicycles. In the absence of subclassing and subtypes, the module dependence diagram would look something like this:
Rider  Bicycle  LightedBicycle  RacingBicycle  PennyFarthing
The code for Rider would also need to test which type of object it had been passed, which would be ugly, verbose, and error-prone.
With subtyping, the MDD dependences look like this:
Rider  Bicycle  LightedBicycle  RacingBicycle  PennyFarthing3
The many dependences have been reduced to a single one.
When subtype arrows are added, the diagram is only a bit more complicated:
Rider Bicycle  LightedBicycle  RacingBicycle  PennyFarthing
Even though there are just as many arrows, this diagram is much simpler than the original one: dependence edges complicate designs and implementations more than other types of edge.
Substitution principle
The substitution principle is the theoretical underpinning of subtypes; it provides a precise definition of when two types are subtypes. Informally, it states that subtypes must be substitutable for supertypes. This guarantees that if code depends on (any aspect of) a supertype, but an object of a subtype is substituted, system behavior will not be affected. (The Java compiler also requires that the extends or implements clause names the parent in order for subtypes to be used in place of supertypes.)
The methods of a subtype must hold certain relationships to the methods of the supertype, and the subtype must guarantee that any properties of the supertype (such as representation invariants or specification constraints) are not violated by the subtype.
methods There are two necessary properties:
1.For each method in the supertype, the subtype must have a corresponding method. (The subtype is allowed to introduce additional, new methods that do not appear in the supertype.)
2.Each method in subtype that corresponds to one in the supertype:


•requires less (has a weaker precondition)


–there are no more “requires” clauses, and each one is no more strict than the one in the supertype method.


–the argument types may be supertypes of the ones in the supertype. This is called contravariance, and it feels somewhat backward, because the arguments to the subtype method are supertypes of the arguments to the supertype method. However, it makes sense, because any arguments passed to the supertype method are sure to be legal arguments to the subtype method.
•guarantees more (has a stronger postcondition)
–there are no more exceptions
–there are no more modified variables
–in the description of the result and/or result state, there are more clauses, and they describe stronger properties
–the result type may be a subtype of that of the supertype. This is called covariance:
the return type of the subtype method is a subtype of the return type of the supertype method.
5 (The above descriptions should all permit equality; for instance, “requires less” should be “requires no more”, and “less strict” should be “no more strict”. They are stated in this form for ease of reading.) The subtype method should not promise to have more or different results; it merely promises to do what the supertype method did, but possibly to ensure additional properties
as well. For instance, if a supertype method returns a number larger than its argument, a subtype method could return a prime number larger than its argument. As an example of the type constraints, if A is a subtype of B, then the following would be a legal overriding:
Bicycle B.f(Bicycle arg);
RacingBicycle A.f(Vehicle arg); Method B.f takes a Bicycle as its argument, but A.f can accept any Vehicle (which includes all Bicycles). Method B.f returns a Bicycle as its result, but A.f returns a RacingBicycle (which is itself a Bicycle).
properties Any properties guaranteed by a supertype, such as constraints over the values that may appear in specification fields, must be guaranteed by the subtype as well. (The subtype is permitted to strengthen these constraints.)
As a simple example from the book, consider FatSet, which is always nonempty.
class FatSet { // Specification constraints: this always contains at least one element
...
// effects: if this contains x and this.size > 1, removes x from this void remove(int x); }
Type NotSoFatSet with additional method
// effects: removes x from this
void reallyRemove(int x)
is not a subtype of FatSet. Even though there is no problem with any method of FatSet — reallyRemove is a new method, so the rules about corresponding methods do not apply — this method violates the constraint.
If the subtype object is considered purely as a supertype object (that is, only the supertype methods and fields are queried), then the result should be the same as if an object of the supertype had been manipulated all along instead.
signatures: this is essentially the contravariant and covariant rules above. (A procedure’s signature is its name, argument types, return types, and exceptions.)

methods: this is constraints on the behavior, or all aspects of a specification that cannot be expressed in a signature

Java types are classes, interfaces, or primitives. Java has its own notion of subtype (which involves only classes and interfaces). This is a weaker notion than the true subtyping described above; Java subtypes do not necessarily satisfy the substitution principle. Further, a subtype definition that satisfies the substitution principle may not be allowed in Java, and will not compile.
In order for a type to be a Java subtype of another type, the relationship must be declared (via Java’s extends or implements syntax), and the methods must satisfy two properties similar to, but weaker than, those for true subtyping:
1.for each method in the supertype, the subtype must have a corresponding method. (The subtype is allowed to introduce additional, new methods that do not appear in the supertype.)
2.each method in subtype that corresponds to one in the supertype
•the arguments must have the same types
•the result must have the same type
•there are no more declared exceptions
Java has no notion of a behavioral specification, so it performs no such checks and can make no guarantees about behavior. The requirement of type equality for arguments and result is stronger than strictly necessary to guarantee type-safety. This prohibits some code we might like to write. However, it simplifies the Java language syntax and semantics.
4.1 Example: Square and rectangle
We know from elementary school that every square is a rectangle. Suppose we wanted to make Square a subtype of Rectangle, which included a setSize method:
class Rectangle {
...
// effects: sets width and height to the specified values
// (that is, this.width’ = w && this.height’ = h)
void setSize(int w, int h);
}
class Square extends Rectangle {
...
}
Which of the following methods is right for Square?
// requires: w = h
void setSize(int w, int h);
void setSize(int edgeLength);
// throws BadSizeException if w != h
void setSize(int w, int h) throws BadSizeException;
7
5
The first one isn’t right because the subclass method requires more than the superclass method. Thus, subclass objects can’t be substituted for superclass objects, as there might be code that called setSize with non-equal arguments.
The second one isn’t right (all by itself) because the subclass still must specify a behavior for setSize(int, int); that definition is of a different method (whose name is the same but whose signature differs).
The third one isn’t right because it throws an exception that the superclass doesn’t mention. Thus, it again has different behavior and so Squares can’t be substituted for Rectangles. If BadSizeException is an unchecked exception, then Java will permit the third method to compile; but then again, it will also permit the first method to compile. Therefore, Java’s notion of subtype is weaker than the 6.170 notion of subtype.
There isn’t a way out of this quandary without modifying the supertype. Sometimes subtypes do not accord with our intuition! Or, our intuition about what is a good supertype is wrong.
One plausible solution would be to change Rectangle.setSize to specify that it throws the exception; of course, in practice only Square.setSize would do so. Another solution would be to eliminate setSize and instead have a
void scale(double scaleFactor);
method that shrinks or grows a shape. Other solutions are also possible.
Java subclassing
Subclassing has a number of advantages, all of which stem from reuse:
•Implementations of subclasses need not repeat unchanged fields and methods, but can reuse those of the superclass
•Clients (callers) need not change code when new subtypes are added, but can reuse the existing code (which doesn’t mention the subtypes at all, just the supertype
•The resulting design has better modularity and reduced complexity, because designers, implementers,
and users only have to understand the supertype, not every subtype; this is specification reuse.
A key mechanism that enables these benefits is overriding, which specializes behavior for some methods. In the absence of overriding, any change to behavior (even a compatible one) could force a complete reimplementation. Overriding permits part of an implementation to be changed without changing other parts that depend on it. This permits more code and specification reuse, both by the implementation and the client.
A potential disadvantage of subclassing is the opportunities it presents for inappropriate reuse. Subclasses and superclasses may depend on one another (explicitly by type name or implicitly by knowledge of the implementation), particularly since subclasses have access to the protected parts of the superclass implementation. These extra dependences complicate the MDD, the design, and the implementation, making it harder to code, understand, and modify. 


 10) Operators - Arithmetic, String concatenation, Relational, Logical, Bitwise, increment-decrement

Expressions and Operators

So far in this chapter, we've learned about the primitive types that Java programs can manipulate and seen how to include primitive values as literals in a Java program. We've also used variables as symbolic names that represent, or hold, values. These literals and variables are the tokens out of which Java programs are built.
An expression is the next higher level of structure in a Java program. The Java interpreter evaluates an expression to compute its value. The very simplest expressions are called primary expressions and consist of literals and variables. So, for example, the following are all expressions:
1.7         // An integer literal
true        // A boolean literal
sum         // A variable
When the Java interpreter evaluates a literal expression, the resulting value is the literal itself. When the interpreter evaluates a variable expression, the resulting value is the value stored in the variable.
Primary expressions are not very interesting. More complex expressions are made by using operators to combine primary expressions. For example, the following expression uses the assignment operator to combine two primary expressions--a variable and a floating-point literal--into an assignment expression:
sum = 1.7
But operators are used not only with primary expressions; they can also be used with expressions at any level of complexity. Thus, the following are all legal expressions:
sum = 1 + 2 + 3*1.2 + (4 + 8)/3.0
sum/Math.sqrt(3.0 * 1.234)
(int)(sum + 33)

* Operator Summary

The kinds of expressions you can write in a programming language depend entirely on the set of operators available to you. Table 2-5 summarizes the operators available in Java. The P and A columns of the table specify the precedence and associativity of each group of related operators, respectively.

Table 2-5. Java Operators

PAOperatorOperand Type(s)Operation Performed
15L.object, memberobject member access


[]array, intarray element access


( args )method, arglistmethod invocation


++, − −variablepost-increment, decrement
14R++, − −variablepre-increment, decrement


+, numberunary plus, unary minus


~integerbitwise complement


!booleanboolean NOT
13Rnewclass, arglistobject creation


( type )type, anycast (type conversion)
12L*, /, %number, numbermultiplication, division, remainder
11L+, number, numberaddition, subtraction


+string, anystring concatenation
10L<<integer, integerleft shift


>>integer, integerright shift with sign extension


>>>integer, integerright shift with zero extension
9L<, <=number, numberless than, less than or equal


>, >=number, numbergreater than, greater than or equal


instanceofreference, typetype comparison
8L= =primitive, primitiveequal (have identical values)


!=primitive, primitivenot equal (have different values)


= =reference, referenceequal (refer to same object)


!=reference, referencenot equal (refer to different objects)
7L&integer, integerbitwise AND


&boolean, booleanboolean AND
6L^integer, integerbitwise XOR


^boolean, booleanboolean XOR
5L|integer, integerbitwise OR


|boolean, booleanboolean OR
4L&&boolean, booleanconditional AND
3L||boolean, booleanconditional OR
2R?:boolean, any, anyconditional (ternary) operator
1R=variable, anyassignment


*=, /=, %=, variable, anyassignment with operation


+=, −=, <<=,



>>=, >>>=,



&=, ^=, |=

* Precedence

The P column of Table 2-5 specifies the precedence of each operator. Precedence specifies the order in which operations are performed. Consider this expression:
a + b * c      
The multiplication operator has higher precedence than the addition operator, so a is added to the product of b and c. Operator precedence can be thought of as a measure of how tightly operators bind to their operands. The higher the number, the more tightly they bind.
Default operator precedence can be overridden through the use of parentheses, to explicitly specify the order of operations. The previous expression can be rewritten as follows to specify that the addition should be performed before the multiplication:
(a + b) * c
The default operator precedence in Java was chosen for compatibility with C; the designers of C chose this precedence so that most expressions can be written naturally without parentheses. There are only a few common Java idioms for which parentheses are required. Examples include:
// Class cast combined with member access
((Integer) o).intValue();

// Assignment combined with comparison
while((line = in.readLine()) != null) { ... }

// Bitwise operators combined with comparison
if ((flags & (PUBLIC | PROTECTED)) != 0) { ... }

* Associativity

When an expression involves several operators that have the same precedence, the operator associativity governs the order in which the operations are performed. Most operators are left-to-right associative, which means that the operations are performed from left to right. The assignment and unary operators, however, have right-to-left associativity. The A column of Table 2-5 specifies the associativity of each operator or group of operators. The value L means left to right, and R means right to left.
The additive operators are all left-to-right associative, so the expression a+b-c is evaluated from left to right: (a+b)-c. Unary operators and assignment operators are evaluated from right to left. Consider this complex expression:
a = b += c = -~d
This is evaluated as follows:
a = (b += (c = -(~d)))
As with operator precedence, operator associativity establishes a default order of evaluation for an expression. This default order can be overridden through the use of parentheses. However, the default operator associativity in Java has been chosen to yield a natural expression syntax, and you rarely need to alter it.

* Operand number and type

The fourth column of Table 2-5 specifies the number and type of the operands expected by each operator. Some operators operate on only one operand; these are called unary operators. For example, the unary minus operator changes the sign of a single number:
-n             // The unary minus operator
Most operators, however, are binary operators that operate on two operand values. The operator actually comes in both forms:
a - b          // The subtraction operator is a binary operator
Java also defines one ternary operator, often called the conditional operator. It is like an if statement inside an expression. Its three operands are separated by a question mark and a colon; the second and third operators must both be of the same type:
x > y ? x : y  // Ternary expression; evaluates to the larger of x and y
In addition to expecting a certain number of operands, each operator also expects particular types of operands. Column four of the table lists the operand types. Some of the codes used in that column require further explanation:
number
An integer, floating-point value, or character (i.e., any primitive type except boolean)
integer
A byte, short, int, long, or char value (long values are not allowed for the array access operator [])
reference
An object or array
variable
A variable or anything else, such as an array element, to which a value can be assigned

* Return type

Just as every operator expects its operands to be of specific types, each operator produces a value of a specific type. The arithmetic, increment and decrement, bitwise, and shift operators return a double if at least one of the operands is a double. Otherwise, they return a float if at least one of the operands is a float. Otherwise, they return a long if at least one of the operands is a long. Otherwise, they return an int, even if both operands are byte, short, or char types that are narrower than int.
The comparison, equality, and boolean operators always return boolean values. Each assignment operator returns whatever value it assigned, which is of a type compatible with the variable on the left side of the expression. The conditional operator returns the value of its second or third argument (which must both be of the same type).

* Side effects

Every operator computes a value based on one or more operand values. Some operators, however, have side effects in addition to their basic evaluation. If an expression contains side effects, evaluating it changes the state of a Java program in such a way that evaluating the expression again may yield a different result. For example, the ++ increment operator has the side effect of incrementing a variable. The expression ++a increments the variable a and returns the newly incremented value. If this expression is evaluated again, the value will be different. The various assignment operators also have side effects. For example, the expression a*=2 can also be written as a=a*2. The value of the expression is the value of a multiplied by 2, but the expression also has the side effect of storing that value back into a. The method invocation operator () has side effects if the invoked method has side effects. Some methods, such as Math.sqrt(), simply compute and return a value without side effects of any kind. Typically, however, methods do have side effects. Finally, the new operator has the profound side effect of creating a new object.

* Order of evaluation

When the Java interpreter evaluates an expression, it performs the various operations in an order specified by the parentheses in the expression, the precedence of the operators, and the associativity of the operators. Before any operation is performed, however, the interpreter first evaluates the operands of the operator. (The exceptions are the &&, ||, and ?: operators, which do not always evaluate all their operands.) The interpreter always evaluates operands in order from left to right. This matters if any of the operands are expressions that contain side effects. Consider this code, for example:
int a = 2;
int v = ++a + ++a * ++a;
Although the multiplication is performed before the addition, the operands of the + operator are evaluated first. Thus, the expression evaluates to 3+4*5, or 23.

* Arithmetic Operators

Since most programs operate primarily on numbers, the most commonly used operators are often those that perform arithmetic operations. The arithmetic operators can be used with integers, floating-point numbers, and even characters (i.e., they can be used with any primitive type other than boolean). If either of the operands is a floating-point number, floating-point arithmetic is used; otherwise, integer arithmetic is used. This matters because integer arithmetic and floating-point arithmetic differ in the way division is performed and in the way underflows and overflows are handled, for example. The arithmetic operators are:
Addition (+)
The + operator adds two numbers. As we'll see shortly, the + operator can also be used to concatenate strings. If either operand of + is a string, the other one is converted to a string as well. Be sure to use parentheses when you want to combine addition with concatenation. For example:
System.out.println("Total: " + 3 + 4);    // Prints "Total: 34", not 7!
Subtraction ()
When is used as a binary operator, it subtracts its second operand from its first. For example, 7-3 evaluates to 4. The operator can perform unary negation.
Multiplication (*)
The * operator multiplies its two operands. For example, 7*3 evaluates to 21.
Division (/)
The / operator divides its first operand by its second. If both operands are integers, the result is an integer, and any remainder is lost. If either operand is a floating-point value, however, the result is a floating-point value. When dividing two integers, division by zero throws an ArithmeticException. For floating-point calculations, however, division by zero simply yields an infinite result or NaN:
7/3          // Evaluates to 2
7/3.0f       // Evaluates to 2.333333f
7/0          // Throws an ArithmeticException
7/0.0        // Evaluates to positive infinity
0.0/0.0      // Evaluates to NaN
Modulo (%)
The % operator computes the first operand modulo the second operand (i.e., it returns the remainder when the first operand is divided by the second operand an integral number of times). For example, 7%3 is 1. The sign of the result is the same as the sign of the first operand. While the modulo operator is typically used with integer operands, it also works for floating-point values. For example, 4.3%2.1 evaluates to 0.1. When operating with integers, trying to compute a value modulo zero causes an ArithmeticException. When working with floating-point values, anything modulo 0.0 evaluates to NaN, as does infinity modulo anything.
Unary Minus ()
When is used as a unary operator, before a single operand, it performs unary negation. In other words, it converts a positive value to an equivalently negative value, and vice versa.

* String Concatenation Operator

In addition to adding numbers, the + operator (and the related += operator) also concatenates, or joins, strings. If either of the operands to + is a string, the operator converts the other operand to a string. For example:
System.out.println("Quotient: " + 7/3.0f);  // Prints "Quotient: 2.3333333"
As a result, you must be careful to put any addition expressions in parentheses when combining them with string concatenation. If you do not, the addition operator is interpreted as a concatenation operator.
The Java interpreter has built-in string conversions for all primitive types. An object is converted to a string by invoking its toString() method. Some classes define custom toString() methods, so that objects of that class can easily be converted to strings in this way. An array is converted to a string by invoking the built-in toString() method, which, unfortunately, does not return a useful string representation of the array contents.

* Increment and Decrement Operators

The ++ operator increments its single operand, which must be a variable, an element of an array, or a field of an object, by one. The behavior of this operator depends on its position relative to the operand. When used before the operand, where it is known as the pre-increment operator, it increments the operand and evaluates to the incremented value of that operand. When used after the operand, where it is known as the post-increment operator, it increments its operand, but evaluates to the value of that operand before it was incremented.
For example, the following code sets both i and j to 2:
i = 1;
j = ++i;
But these lines set i to 2 and j to 1:
i = 1;
j = i++;
Similarly, the − − operator decrements its single numeric operand, which must be a variable, an element of an array, or a field of an object, by one. Like the ++ operator, the behavior of − − depends on its position relative to the operand. When used before the operand, it decrements the operand and returns the decremented value. When used after the operand, it decrements the operand, but returns the un-decremented value.
The expressions x++ and x− − are equivalent to x=x+1 and x=x−1, respectively, except that when using the increment and decrement operators, x is only evaluated once. If x is itself an expression with side effects, this makes a big difference. For example, these two expressions are not equivalent:
a[i++]++;             // Increments an element of an array
a[i++] = a[i++] + 1;  // Adds one to an array element and stores it in another
These operators, in both prefix and postfix forms, are most commonly used to increment or decrement the counter that controls a loop.

* Comparison Operators

The comparison operators consist of the equality operators that test values for equality or inequality and the relational operators used with ordered types (numbers and characters) to test for greater than and less than relationships. Both types of operators yield a boolean result, so they are typically used with if statements and while and for loops to make branching and looping decisions. For example:
if (o != null) ...;           // The not equals operator
while(i < a.length) ...;      // The less than operator
Java provides the following equality operators:
Equals (= =)
The = = operator evaluates to true if its two operands are equal and false otherwise. With primitive operands, it tests whether the operand values themselves are identical. For operands of reference types, however, it tests whether the operands refer to the same object or array. In other words, it does not test the equality of two distinct objects or arrays. In particular, note that you cannot test two distinct strings for equality with this operator.
If = = is used to compare two numeric or character operands that are not of the same type, the narrower operand is converted to the type of the wider operand before the comparison is done. For example, when comparing a short to a float, the short is first converted to a float before the comparison is performed. For floating-point numbers, the special negative zero value tests equal to the regular, positive zero value. Also, the special NaN (not-a-number) value is not equal to any other number, including itself. To test whether a floating-point value is NaN, use the Float.isNan() or Double.isNan() method.
Not Equals (!=)
The != operator is exactly the opposite of the = = operator. It evaluates to true if its two primitive operands have different values or if its two reference operands refer to different objects or arrays. Otherwise, it evaluates to false.
The relational operators can be used with numbers and characters, but not with boolean values, objects, or arrays because those types are not ordered. Java provides the following relational operators:
Less Than (<)
Evaluates to true if the first operand is less than the second.
Less Than or Equal (<=)
Evaluates to true if the first operand is less than or equal to the second.
Greater Than (>)
Evaluates to true if the first operand is greater than the second.
Greater Than or Equal (>=)
Evaluates to true if the first operand is greater than or equal to the second.

2.5.6. Boolean Operators

As we've just seen, the comparison operators compare their operands and yield a boolean result, which is often used in branching and looping statements. In order to make branching and looping decisions based on conditions more interesting than a single comparison, you can use the Boolean (or logical) operators to combine multiple comparison expressions into a single, more complex, expression. The Boolean operators require their operands to be boolean values and they evaluate to boolean values. The operators are:
Conditional AND (&&)
This operator performs a Boolean AND operation on its operands. It evaluates to true if and only if both its operands are true. If either or both operands are false, it evaluates to false. For example:
if (x < 10 && y > 3) ... // If both comparisons are true
This operator (and all the Boolean operators except the unary ! operator) have a lower precedence than the comparison operators. Thus, it is perfectly legal to write a line of code like the one above. However, some programmers prefer to use parentheses to make the order of evaluation explicit:
if ((x < 10) && (y > 3)) ... 
You should use whichever style you find easier to read.
This operator is called a conditional AND because it conditionally evaluates its second operand. If the first operand evaluates to false, the value of the expression is false, regardless of the value of the second operand. Therefore, to increase efficiency, the Java interpreter takes a shortcut and skips the second operand. Since the second operand is not guaranteed to be evaluated, you must use caution when using this operator with expressions that have side effects. On the other hand, the conditional nature of this operator allows us to write Java expressions such as the following:
if (data != null && i < data.length && data[i] != -1) ... 
The second and third comparisons in this expression would cause errors if the first or second comparisons evaluated to false. Fortunately, we don't have to worry about this because of the conditional behavior of the && operator.
Conditional OR (||)
This operator performs a Boolean OR operation on its two boolean operands. It evaluates to true if either or both of its operands are true. If both operands are false, it evaluates to false. Like the && operator, || does not always evaluate its second operand. If the first operand evaluates to true, the value of the expression is true, regardless of the value of the second operand. Thus, the operator simply skips that second operand in that case.
Boolean NOT (!)
This unary operator changes the boolean value of its operand. If applied to a true value, it evaluates to false, and if applied to a false value, it evaluates to true. It is useful in expressions like these:
if (!found) ...          // found is a boolean variable declared somewhere
while (!c.isEmpty()) ... // The isEmpty() method returns a boolean value
Because ! is a unary operator, it has a high precedence and often must be used with parentheses:
if (!(x > y && y > z)) 
Boolean AND (&)
When used with boolean operands, the & operator behaves like the && operator, except that it always evaluates both operands, regardless of the value of the first operand. This operator is almost always used as a bitwise operator with integer operands, however, and many Java programmers would not even recognize its use with boolean operands as legal Java code.
Boolean OR (|)
This operator performs a Boolean OR operation on its two boolean operands. It is like the || operator, except that it always evaluates both operands, even if the first one is true. The | operator is almost always used as a bitwise operator on integer operands; its use with boolean operands is very rare.
Boolean XOR (^)
When used with boolean operands, this operator computes the Exclusive OR (XOR) of its operands. It evaluates to true if exactly one of the two operands is true. In other words, it evaluates to false if both operands are false or if both operands are true. Unlike the && and || operators, this one must always evaluate both operands. The ^ operator is much more commonly used as a bitwise operator on integer operands. With boolean operands, this operator is equivalent to the != operator.

* Bitwise and Shift Operators

The bitwise and shift operators are low-level operators that manipulate the individual bits that make up an integer value. The bitwise operators are most commonly used for testing and setting individual flag bits in a value. In order to understand their behavior, you must understand binary (base-2) numbers and the twos-complement format used to represent negative integers. You cannot use these operators with floating-point, boolean, array, or object operands. When used with boolean operands, the &, |, and ^ operators perform a different operation, as described in the previous section.
If either of the arguments to a bitwise operator is a long, the result is a long. Otherwise, the result is an int. If the left operand of a shift operator is a long, the result is a long; otherwise, the result is an int. The operators are:
Bitwise Complement (~)
The unary ~ operator is known as the bitwise complement, or bitwise NOT, operator. It inverts each bit of its single operand, converting ones to zeros and zeros to ones. For example:
byte b = ~12;           // ~00000110 ==> 11111001 or -13 decimal
flags = flags & ~f;     // Clear flag f in a set of flags
Bitwise AND (&)
This operator combines its two integer operands by performing a Boolean AND operation on their individual bits. The result has a bit set only if the corresponding bit is set in both operands. For example:
10 & 7                   // 00001010 & 00000111 ==> 00000010 or 2
if ((flags & f) != 0)    // Test whether flag f is set
When used with boolean operands, & is the infrequently used Boolean AND operator described earlier.
Bitwise OR (|)
This operator combines its two integer operands by performing a Boolean OR operation on their individual bits. The result has a bit set if the corresponding bit is set in either or both of the operands. It has a zero bit only where both corresponding operand bits are zero. For example:
10 | 7               // 00001010 | 00000111 ==> 00001111 or 15
flags = flags | f;   // Set flag f
When used with boolean operands, | is the infrequently used Boolean OR operator described earlier.
Bitwise XOR (^)
This operator combines its two integer operands by performing a Boolean XOR (Exclusive OR) operation on their individual bits. The result has a bit set if the corresponding bits in the two operands are different. If the corresponding operand bits are both ones or both zeros, the result bit is a zero. For example:
10 & 7               // 00001010 ^ 00000111 ==> 00001101 or 13
When used with boolean operands, ^ is the infrequently used Boolean XOR operator.
Left Shift (<<)
The << operator shifts the bits of the left operand left by the number of places specified by the right operand. High-order bits of the left operand are lost, and zero bits are shifted in from the right. Shifting an integer left by n places is equivalent to multiplying that number by 2n. For example:
10 << 1    // 00001010 << 1 = 00010100 = 20 = 10*2
7 << 3     // 00000111 << 3 = 00111000 = 56 = 7*8
-1 << 2    // 0xFFFFFFFF << 2 = 0xFFFFFFFC = -4 = -1*4
If the left operand is a long, the right operand should be between 0 and 63. Otherwise, the left operand is taken to be an int, and the right operand should be between 0 and 31.
Signed Right Shift (>>)
The >> operator shifts the bits of the left operand to the right by the number of places specified by the right operand. The low-order bits of the left operand are shifted away and are lost. The high-order bits shifted in are the same as the original high-order bit of the left operand. In other words, if the left operand is positive, zeros are shifted into the high-order bits. If the left operand is negative, ones are shifted in instead. This technique is known as sign extension; it is used to preserve the sign of the left operand. For example:
10 >> 1      // 00001010 >> 1 = 00000101 = 5 = 10/2
27 >> 3      // 00011011 >> 3 = 00000011 = 3 = 27/8
-50 >> 2     // 11001110 >> 2 = 11110011 = -13 != -50/4
If the left operand is positive and the right operand is n, the >> operator is the same as integer division by 2n.
Unsigned Right Shift (>>>)
This operator is like the >> operator, except that it always shifts zeros into the high-order bits of the result, regardless of the sign of the left-hand operand. This technique is called zero extension ; it is appropriate when the left operand is being treated as an unsigned value (despite the fact that Java integer types are all signed). Examples:
-50 >>> 2     // 11001110 >>> 2 = 00110011 = 51
0xff >>> 4    // 11111111 >>> 4 = 00001111 = 15  = 255/16

* Assignment Operators

The assignment operators store, or assign, a value into some kind of variable. The left operand must evaluate to an appropriate local variable, array element, or object field. The right side can be any value of a type compatible with the variable. An assignment expression evaluates to the value that is assigned to the variable. More importantly, however, the expression has the side effect of actually performing the assignment. Unlike all other binary operators, the assignment operators are right-associative, which means that the assignments in a=b=c are performed right-to-left, as follows: a=(b=c).
The basic assignment operator is =. Do not confuse it with the equality operator, = =. In order to keep these two operators distinct, I recommend that you read = as "is assigned the value."
In addition to this simple assignment operator, Java also defines 11 other operators that combine assignment with the 5 arithmetic operators and the 6 bitwise and shift operators. For example, the += operator reads the value of the left variable, adds the value of the right operand to it, stores the sum back into the left variable as a side effect, and returns the sum as the value of the expression. Thus, the expression x+=2 is almost the same x=x+2. The difference between these two expressions is that when you use the += operator, the left operand is evaluated only once. This makes a difference when that operand has a side effect. Consider the following two expressions, which are not equivalent:
a[i++] += 2;
a[i++] = a[i++] + 2;
The general form of these combination assignment operators is:
var op= value
This is equivalent (unless there are side effects in var) to:
var = var op value
The available operators are:
+=    −=    *=    /=    %=    // Arithmetic operators plus assignment
&=    |=    ^=                // Bitwise operators plus assignment
<<=   >>=   >>>=              // Shift operators plus assignment
The most commonly used operators are += and − =, although &= and |= can also be useful when working with boolean flags. For example:
i += 2;          // Increment a loop counter by 2
c −= 5;          // Decrement a counter by 5
flags |= f;      // Set a flag f in an integer set of flags
flags &= ~f;     // Clear a flag f in an integer set of flags

* The Conditional Operator

The conditional operator ?: is a somewhat obscure ternary (three-operand) operator inherited from C. It allows you to embed a conditional within an expression. You can think of it as the operator version of the if/else statement. The first and second operands of the conditional operator are separated by a question mark (?), while the second and third operands are separated by a colon (:). The first operand must evaluate to a boolean value. The second and third operands can be of any type, but they must both be of the same type.
The conditional operator starts by evaluating its first operand. If it is true, the operator evaluates its second operand and uses that as the value of the expression. On the other hand, if the first operand is false, the conditional operator evaluates and returns its third operand. The conditional operator never evaluates both its second and third operand, so be careful when using expressions with side effects with this operator. Examples of this operator are:
int max = (x > y) ? x : y;
String name = (name != null) ? name : "unknown";
Note that the ?: operator has lower precedence than all other operators except the assignment operators, so parentheses are not usually necessary around the operands of this operator. Many programmers find conditional expressions easier to read if the first operand is placed within parentheses, however. This is especially true because the conditional if statement always has its conditional expression written within parentheses.

* The instanceof Operator

The instanceof operator requires an object or array value as its left operand and the name of a reference type as its right operand. It evaluates to true if the object or array is an instance of the specified type; it returns false otherwise. If the left operand is null, instanceof always evaluates to false. If an instanceof expression evaluates to true, it means that you can safely cast and assign the left operand to a variable of the type of the right operand.
The instanceof operator can be used only with array and object types and values, not primitive types and values. Object and array types are discussed in detail later in this chapter. Examples of instanceof are:
"string" instanceof String      // True: all strings are instances of String
"" instanceof Object            // True: strings are also instances of Object
new int[] {1} instanceof int[]  // True: the array value is an int array
new int[] {1} instanceof byte[] // False: the array value is not a byte array
new int[] {1} instanceof Object // True: all arrays are instances of Object
null instanceof String          // False: null is never instanceof anything

// Use instanceof to make sure that it is safe to cast an object
if (object instanceof Point) {
  Point p = (Point) object;
}

* Special Operators

There are five language constructs in Java that are sometimes considered operators and sometimes considered simply part of the basic language syntax. These "operators" are listed in Table 2-5 in order to show their precedence relative to the other true operators. The use of these language constructs is detailed elsewhere in this chapter, but is described briefly here, so that you can recognize these constructs when you encounter them in code examples:
Object member access (.)
An object is a collection of data and methods that operate on that data; the data fields and methods of an object are called its members. The dot (.) operator accesses these members. If o is an expression that evaluates to an object reference, and f is the name of a field of the object, o.f evaluates to the value contained in that field. If m is the name of a method, o.m refers to that method and allows it to be invoked using the () operator shown later.
Array element access ([])
An array is a numbered list of values. Each element of an array can be referred to by its number, or index. The [] operator allows you to refer to the individual elements of an array. If a is an array, and i is an expression that evaluates to an int, a[i] refers to one of the elements of a. Unlike other operators that work with integer values, this operator restricts array index values to be of type int or narrower.
Method invocation (())
A method is a named collection of Java code that can be run, or invoked, by following the name of the method with zero or more comma-separated expressions contained within parentheses. The values of these expressions are the arguments to the method. The method processes the arguments and optionally returns a value that becomes the value of the method invocation expression. If o.m is a method that expects no arguments, the method can be invoked with o.m(). If the method expects three arguments, for example, it can be invoked with an expression such as o.m(x,y,z). Before the Java interpreter invokes a method, it evaluates each of the arguments to be passed to the method. These expressions are guaranteed to be evaluated in order from left to right (which matters if any of the arguments have side effects).
Object creation (new)
In Java, objects are created with the new operator, which is followed by the type of the object to be created and a parenthesized list of arguments to be passed to the object constructor. A constructor is a special method that initializes a newly created object, so the object creation syntax is similar to the Java method invocation syntax. For example:
new ArrayList();
new Point(1,2)
Type conversion or casting (())
As we've already seen, parentheses can also be used as an operator to perform narrowing type conversions, or casts. The first operand of this operator is the type to be converted to; it is placed between the parentheses. The second operand is the value to be converted; it follows the parentheses. For example:
(byte) 28          // An integer literal cast to a byte type
(int) (x + 3.14f)  // A floating-point sum value cast to an integer value
(String)h.get(k)   // A generic object cast to a more specific string type
 11) Understanding the narrowing and widening conversions of numeric data types.

* The Narrowing Conversion

The narrowing conversion occurs from a type to a different type that has a smaller size, such as from a long (64 bits) to an int (32 bits).
In general, the narrowing primitive conversion can occur in these cases:
  1. short to byte or char
  2. char to byte or short
  3. int to byte, short, or char
  4. long to byte, short, or char
  5. float to byte, short, char, int, or long
  6. double to byte, short, char, int, long, or float
  1. The narrowing primitive conversion must be explicit.
  2. You need to specify the target type in parentheses.
public class MainClass {

  public static void main(String[] args) {
    long a = 10;
    int b = (inta; // narrowing conversion

    System.out.println(a);
    System.out.println(b);
  }

}


The widening conversion is permitted in the following cases:
  1. byte to short, int, long, float, or double
  2. Short to int, long, float, or double
  3. char to int, long, float, or double
  4. int to long, float, or double
  5. long to float or double
  6. float to double
Narrowing conversion with information loss

Narrowing conversion may incur information loss, if the converted value is larger than the capacity of the target type.
In the following conversion, there is some information loss because 9876543210L is too big for an int.
public class MainClass {

  public static void main(String[] args) {
    long a = 9876543210L;
    int b = (inta;

    System.out.println(b);
  }

}
1286608618
 
* Casting Incompatible Types

public class MainClass {
  public static void main(String args[]) {
    byte b;
    int i = 257;
    double d = 323.142;
   
    System.out.println("\nConversion of int to byte.");
    b = (bytei;
    System.out.println("i and b " + i + " " + b);
   
    System.out.println("\nConversion of double to int.");
    i = (intd;
    System.out.println("d and i " + d + " " + i);
   
    System.out.println("\nConversion of double to byte.");
    b = (byted;
    System.out.println("d and b " + d + " " + b);
  }
}
Conversion of int to byte.
i and b 257 1

Conversion of double to int.
d and i 323.142 323

Conversion of double to byte.
d and b 323.142 67
 

* Convert byte array to Integer and Long

public class Utils  
{


  public static void putInt(int value, byte[] array, int offset) {
    array[offset]   (byte)(0xff (value >> 24));
    array[offset+1(byte)(0xff (value >> 16));
    array[offset+2(byte)(0xff (value >> 8));
    array[offset+3(byte)(0xff & value);
  }

  public static int getInt(byte[] array, int offset) {
    return
      ((array[offset]   0xff<< 24|
      ((array[offset+10xff<< 16|
      ((array[offset+20xff<< 8|
       (array[offset+30xff);
  }

  public static void putLong(long value, byte[] array, int offset) {
    array[offset]   (byte)(0xff (value >> 56));
    array[offset+1(byte)(0xff (value >> 48));
    array[offset+2(byte)(0xff (value >> 40));
    array[offset+3(byte)(0xff (value >> 32));
    array[offset+4(byte)(0xff (value >> 24));
    array[offset+5(byte)(0xff (value >> 16));
    array[offset+6(byte)(0xff (value >> 8));
    array[offset+7(byte)(0xff & value);
  }

  public static long getLong(byte[] array, int offset) {
    return
      ((long)(array[offset]   0xff<< 56|
      ((long)(array[offset+10xff<< 48|
      ((long)(array[offset+20xff<< 40|
      ((long)(array[offset+30xff<< 32|
      ((long)(array[offset+40xff<< 24|
      ((long)(array[offset+50xff<< 16|
      ((long)(array[offset+60xff<< 8|
      ((long)(array[offset+70xff));
  }


}
* Pass a string to the Integer class constructor and call the intValue()

public class Main {
  public static void main(String[] argv) {

    String sValue = "5";

    try {
      int iValue = new Integer(sValue).intValue();
    catch (NumberFormatException ex) {
      ex.printStackTrace();
    }
  }
}


12) Statements - if, if-else, switch-case, for, while, do-while, break, continue and return statements.
Methods and constructors are sequences of statements, along with variable definitions. The statements specify the sequence of actions to be performed when a method or constructor is invoked. They can alter the value of variables, generate output, process input, or respond to user mouse or keyboard actions.
Different types of statements are described in the following sections.

Assignment Statements

An assignment statement has the following form.
    variable = expression;
This statement changes the value of the variable on the left side of the equals sign to the value of the expression on the right-hand side. The variable is often just specified by a variable name, but there are also expressions that specify variables. Java treats an assignment as both an expression and as a statement. As an expression, its value is the value assigned to the variable. This is done to allow multiple assignments in a single statement, such as
    a = b = 5;
By treating b = 5 as an expression with value 5, Java makes sense of this statement, assigning the value 5 to both a and b.

Statements involving Messages

Messages are the fundamental means of communication between objects in a Java program. A message has the following form.
    receiver.method-name(parameters)
Here,
  • receiver is an expression (often just a variable name) that specifies the object that should respond to the message.
  • method-name is the name of the method that the receiver should execute.
  • parameters is a comma-separated list of expressions that provide data that the receiver can use in its execution of the method.
The receiver can be omitted if it is the object that you are writing code for. That is, you do not need to specify the receiver for messages sent from an object to itself. Messages can be used in three ways to form statements. First, if the method specified by a message returns a value then the message can be used as the expression in an assignment statement.
    variable = message;
For messages with methods that do not return values, a statement can also be formed by just terminating the message with a semicolon.
    message;
This statement form can also be used when the method returns a value, although it is not usually a good idea to ignore a returned value. Finally, if a message returns an object, then that object can be used directly as the receiver of a message. In an applet method, for example, getContentPane() returns a container to which components can be added. This container is the receiver of the add() message in the following statement.
    getContentPane().add(button);

Statement Blocks

In Java, any sequence of statements can be grouped together to function as a single statement by enclosing the sequence in braces. These groupings are called statement blocks. A statement block may also include variable declarations. Statement blocks are used to define methods and to allow multiple statements in the control structures described in the following sections.

Control Statements

Normally, statements in a method or constructor are executed sequentially. Java also has control statements that allow repetitive execution of statements and conditional execution of statements. Java has the following types of control statements.
  • Conditional Execution And Selection
    If Statements - conditional execution of a single statement
    If-Else Statements - conditional selection among two statements
    Switch Statements - conditional selection among several statements
    Extended If-Else Statements - conditional selection among several statements
  • Repetition
    While Loops - pretest loops
    For Loops - pretest loops
    Do-While Loops - posttest loops
  • Special Control Statements
    Return Statements - return values from and terminate methods
    Continue Statements - skip the remaining statements in an iteration of a loop
    Break Statements - exit a loop or switch statement

Conditional Execution and Selection

Java has three kinds of statements that permit execution of a nested statement based on the value of a boolean expression or selection among several statements based on the value of a boolean expression or a control variable. These statements are the if statement, the if-else statement, and the switch statement.
If Statements
The if statement has the following form.
    if (boolean-expression) {
 then-clause
    }
Here,
  • boolean-expression is an expression that can be true or false.
  • then-clause is a sequence of statements. If there is only one statement in the sequence then the surrounding braces may be omitted. The then-clause statements are executed only if the boolean-expression is true.

If-Else Statements
The if-else statement has the following form.
    if (boolean-expression) {
 then-clause
    } else {
 else-clause
    }
Here,
  • boolean-expression is an expression that can be true or false.
  • then-clause and else-clause are sequences of statements. If there is only one statement in a sequence then the surrounding braces may be omitted. The then-clause statements are executed only if the boolean-expression is true. The else-clause statements are executed if the boolean-expression is false.

Switch Statements
The switch statement allows execution of different statements depending on the value of an expression. It has the following form.
    switch (control-expression) {
    case constant-expression-1:
 statements-1
     .
     .
     .
    case constant-expression-n:
 statements-n
    default:
 default-statements
    }
Here,
  • control-expression is an expression of a simple type, such as int, char, or an enum type. It cannot have float or double type.
  • constant-expression-1 through constant-expression-n are expressions of a type that converts to the type of control-expression. The compiler must be able to evaluate these expressions to constant values.
  • statements-1 through statements-n are sequences of statements.
When the switch statement is executed, control-expression is evaluated. The resulting value is compared to the values of constant-expression-1 through constant-expression-n in order until a matching value is found. If a match is found in constant-expression-i then statements-i through statements-n and default-statements are executed, with switch statement execution terminated if a break statement is encountered. Normally, the last statement in each sequence is a break statement so that only one sequence is executed.
The default clause is optional. If it is present then the default-statements are executed whenever the value of control-expression does not match any of the constant-expression-i values.

Extended If-Else Statements
Often, a programmer needs a construction that works like a switch statement, but the selection between choices is too complex for a switch statement. To make this work, a programmer can use a sequence of if statements where each if statement is nested in the else clause of the preceding if statement. This construction is called an extended is statement. It has the following form.
    if (boolean-expression-1) {
 statements-1
    } else if (boolean-expression-2) {
 statements-2
 .
 .
 .
    } else if (boolean-expression-n) {
 statements-n
    } else {
 default-statements
    }
Here,
  • boolean-expression-1 through boolean-expression-n are expressions that can be true or false.
  • statements-1 through statements-n and default-statements are sequences of statements.
When this extended if-else statement is executed, the boolean expressions are evaluated in order until one is found that is true. Then the corresponding sequence of statements is executed. If none of the boolean expressions is true then the default-statements are executed. In either case, execution continues with the next statement after the extended if-else statement.

Repetition

Java has three kinds of loop statements: while loops, for loops, and do-while loops. Loop statements allow a nested statement to be executed repetitively. The nested statement can be a block statement, allowing repetition of a sequence of statements. When a loop is executed its nested statement can be executed any number of times. Each execution of the nested statement is called an iteration of the loop. The number of iterations is controlled by a boolean expression. The boolean expression is evaluated before each iteration (pretest) in while loops and for loops, and after each iteration (post-test) in do-while loops. When the boolean expression becomes false the loop is terminated.

While Loops
The while loop is a pretest loop statement. It has the following form.
    while (boolean-expression) {
 nested-statements
    }
Here,
  • boolean-expression is an expression that can be true or false.
  • nested-statements is a sequence of statements. If there is only one statement then the braces can be omitted.
The boolean expression is tested before each iteration of the loop. The loop terminates when it is false.

For Loops
The for loop is a pretest loop statement. It has the following form.
    for (initialization; boolean-expression; increment) {
 nested-statements
    }
Here,
  • initialization is an expression (usually an assignment expression).
  • boolean-expression is an expression that can be true or false.
  • increment is an expression.
  • nested-statements is a sequence of statements. If there is only one statement then the braces may be omitted.
When a for loop is executed the initialization expression is evaluted first. This expression is usually an assignment (for example, i = 0) that sets the initial value of a loop control variable.
The boolean expression is tested before each iteration of the loop. The loop terminates when it is false. The boolean expression is frequently a comparison (for example, i < 10).
At the end of each iteration, the increment expression is evaluated. The expression is often an expression that increments the control variable (for example, i++).

Do-While Loops
The do-while loop is a post-test loop statement. It has the following form.
    do {
 nested-statements
    } while (boolean-expression);
Here,
  • nested-statements is a sequence of statements. If there is only one statement then the braces may be omitted.
  • boolean-expression is an expression that can be true or false.
The boolean expression is tested after each iteration of the loop. The loop terminates when it is false.

Special Control Statements

Return Statements
The return statement is used in the definition of a method to set its returned value and to terminate execution of the method. It has two forms. Methods with returned type void use the following form.
    return;
Methods with non-void returned type use the following form.
    return expression;
Here,
  • expression is an expression that yields the desired return value. This value must be convertible to the return type declared for the method.

Continue Statements
The continue statement is used in while loop, for loop, or do-while loop to terminate an iteration of the loop. A continue statement has the following form.
    continue;
After a continue statement is executed in a for loop, its increment and boolean expression are evaluated. If the boolean expression is true then the nested statements are executed again.
After a continue statement is executed in a while or do-while loop, its boolean expression is evaluated. If the boolean expression is true then the nested statements are executed again.

Break Statements
The break statement is used in loop (for, while, and do-while) statements and switch statements to terminate execution of the statement. A break statement has the following form.
    break;
After a break statement is executed, execution proceeds to the statement that follows the enclosing loop or switch statement.

13) Various members within a class

In this section, we discuss the use of the static keyword to create fields and methods that belong to the class, rather than to an instance of the class.

Class Variables

When a number of objects are created from the same class blueprint, they each have their own distinct copies of instance variables. In the case of the Bicycle class, the instance variables are cadence, gear, and speed. Each Bicycle object has its own values for these variables, stored in different memory locations.
Sometimes, you want to have variables that are common to all objects. This is accomplished with the static modifier. Fields that have the static modifier in their declaration are called static fields or class variables. They are associated with the class, rather than with any object. Every instance of the class shares a class variable, which is in one fixed location in memory. Any object can change the value of a class variable, but class variables can also be manipulated without creating an instance of the class.
For example, suppose you want to create a number of Bicycle objects and assign each a serial number, beginning with 1 for the first object. This ID number is unique to each object and is therefore an instance variable. At the same time, you need a field to keep track of how many Bicycle objects have been created so that you know what ID to assign to the next one. Such a field is not related to any individual object, but to the class as a whole. For this you need a class variable, numberOfBicycles, as follows:
public class Bicycle{
        
    private int cadence;
    private int gear;
    private int speed;
        
    // add an instance variable for
    // the object ID
    private int id;
    
    // add a class variable for the
    // number of Bicycle objects instantiated
    private static int numberOfBicycles = 0;
        ...
}
Class variables are referenced by the class name itself, as in
Bicycle.numberOfBicycles
This makes it clear that they are class variables.

Note: You can also refer to static fields with an object reference like
myBike.numberOfBicycles
but this is discouraged because it does not make it clear that they are class variables.
You can use the Bicycle constructor to set the id instance variable and increment the numberOfBicycles class variable:
public class Bicycle{
        
    private int cadence;
    private int gear;
    private int speed;
    private int id;
    private static int numberOfBicycles = 0;
        
    public Bicycle(int startCadence, int startSpeed, int startGear){
        gear = startGear;
        cadence = startCadence;
        speed = startSpeed;

        // increment number of Bicycles
        // and assign ID number
        id = ++numberOfBicycles;
    }

    // new method to return the ID instance variable
    public int getID() {
        return id;
    }
        ...
}

Class Methods

The Java programming language supports static methods as well as static variables. Static methods, which have the static modifier in their declarations, should be invoked with the class name, without the need for creating an instance of the class, as in
ClassName.methodName(args)

Note: You can also refer to static methods with an object reference like
instanceName.methodName(args)
but this is discouraged because it does not make it clear that they are class methods.
A common use for static methods is to access static fields. For example, we could add a static method to the Bicycle class to access the numberOfBicycles static field:
public static int getNumberOfBicycles() {
    return numberOfBicycles;
}
Not all combinations of instance and class variables and methods are allowed:
  • Instance methods can access instance variables and instance methods directly.
  • Instance methods can access class variables and class methods directly.
  • Class methods can access class variables and class methods directly.
  • Class methods cannot access instance variables or instance methods directly—they must use an object reference. Also, class methods cannot use the this keyword as there is no instance for this to refer to.

Constants

The static modifier, in combination with the final modifier, is also used to define constants. The final modifier indicates that the value of this field cannot change.
For example, the following variable declaration defines a constant named PI, whose value is an approximation of pi (the ratio of the circumference of a circle to its diameter):
static final double PI = 3.141592653589793;
Constants defined in this way cannot be reassigned, and it is a compile-time error if your program tries to do so. By convention, the names of constant values are spelled in uppercase letters. If the name is composed of more than one word, the words are separated by an underscore (_).

Note: If a primitive type or a string is defined as a constant and the value is known at compile time, the compiler replaces the constant name everywhere in the code with its value. This is called a compile-time constant. If the value of the constant in the outside world changes (for example, if it is legislated that pi actually should be 3.975), you will need to recompile any classes that use this constant to get the current value.

The Bicycle Class

After all the modifications made in this section, the Bicycle class is now:
public class Bicycle{
        
    private int cadence;
    private int gear;
    private int speed;
        
    private int id;
    
    private static int numberOfBicycles = 0;

        
    public Bicycle(int startCadence,
                   int startSpeed,
                   int startGear){
        gear = startGear;
        cadence = startCadence;
        speed = startSpeed;

        id = ++numberOfBicycles;
    }

    public int getID() {
        return id;
    }

    public static int getNumberOfBicycles() {
        return numberOfBicycles;
    }

    public int getCadence(){
        return cadence;
    }
        
    public void setCadence(int newValue){
        cadence = newValue;
    }
        
    public int getGear(){
    return gear;
    }
        
    public void setGear(int newValue){
        gear = newValue;
    }
        
    public int getSpeed(){
        return speed;
    }
        
    public void applyBrake(int decrement){
        speed -= decrement;
    }
        
    public void speedUp(int increment){
        speed += increment;
    }
} 
 
 14) instance variables ion java

When a number of objects are created from the same class,  the same copy of  instance variable is provided to all. Remember, each time you call the instance the same old value is provided to you, not the updated one . In this program we are showing that how a instance variable is called in each instance, but the copy remains same irrespective the counter we have used in the constructor of a class. We can't call the non-static variable in a main method. If we try to call the non-static method in the main method then the compiler will prompt you that non-static variable cannot be referenced from a static context. We can call the non-static variable by the instance of the class.
The example will show you how you can use a non-static variables. First create a class named NonStaticVariable. Declare one global variable and call it in the constructor overloaded method in which you will have to increment the value of the variable by the counter. To access a  non-static variable we will have to make a object of NonStaticVariable by using new operator. Now call the instance variable. Now again make a new object of the class and again call the instance variable. Now you can realize that the value of the instance variable in both the object is same.

Code of this program is given below:
public class NonStaticVariable{
  int noOfInstances;
  NonStaticVariable(){
  noOfInstances++;
  }
  public static void main(String[] args){
  NonStaticVariable st1 = new NonStaticVariable();
  System.out.println("No. of instances  for st1  : " 
  + st1.noOfInstances
);

  NonStaticVariable st2 = new NonStaticVariable();
  System.out.println("No. of instances  for st1  : "
 
+ st1.noOfInstances);
  System.out.println("No. of instances  for st2  : "
 
+ st2.noOfInstances);

  NonStaticVariable st3 = new NonStaticVariable();
  System.out.println("No. of instances  for st1  : "
 
+ st1.noOfInstances);
  System.out.println("No. of instances  for st2  : " 
   + st2.noOfInstances
);
  System.out.println("No. of instances  for st3  : "
 
+ st3.noOfInstances);

  }
}
 
15) Methods and their overloading

Overloading Methods

The Java programming language supports overloading methods, and Java can distinguish between methods with different method signatures. This means that methods within a class can have the same name if they have different parameter lists (there are some qualifications to this that will be discussed in the lesson titled "Interfaces and Inheritance").
Suppose that you have a class that can use calligraphy to draw various types of data (strings, integers, and so on) and that contains a method for drawing each data type. It is cumbersome to use a new name for each method—for example, drawString, drawInteger, drawFloat, and so on. In the Java programming language, you can use the same name for all the drawing methods but pass a different argument list to each method. Thus, the data drawing class might declare four methods named draw, each of which has a different parameter list.
public class DataArtist {
    ...
    public void draw(String s) {
        ...
    }
    public void draw(int i) {
        ...
    }
    public void draw(double f) {
        ...
    }
    public void draw(int i, double f) {
        ...
    }
}
Overloaded methods are differentiated by the number and the type of the arguments passed into the method. In the code sample, draw(String s) and draw(int i) are distinct and unique methods because they require different argument types.
You cannot declare more than one method with the same name and the same number and type of arguments, because the compiler cannot tell them apart.
The compiler does not consider return type when differentiating methods, so you cannot declare two methods with the same signature even if they have a different return type.

Note: Overloaded methods should be used sparingly, as they can make code much less readable. 
 
16)constructors and their overloading 
 
Here, you will learn more about Constructor and how constructors are overloaded in Java. This section provides you a brief introduction about the Constructor that are overloaded in the given program with complete code absolutely in running state i.e. provided for best illustration about the constructor overloading in Java.
Constructors are used to assign initial values to instance variables of the class. A default constructor with no arguments will be called automatically by the Java Virtual Machine (JVM). Constructor is always called by new operator. Constructor are declared just like as we declare methods, except that the constructor don't have any return type. Constructor can be overloaded provided they should have different arguments because JVM differentiates constructors on the basis of arguments passed in the constructor.
Whenever we assign the name of the method same as  class name. Remember this method should not have any return type. This is called as constructor overloading.
We have made one program on a constructor overloading, after going through it the concept of constructor overloading will get more clear. In the example below we have made three overloaded constructors each having different arguments  types so that the JVM can differentiates between the various constructors.
The code of the program is given below:
public class ConstructorOverloading{
  public static void main(String args[]){
  Rectangle rectangle1=new Rectangle(2,4);
  int areaInFirstConstructor=rectangle1.first();
  System.out.println(" The area of a rectangle in
  first constructor is :  " 
+ areaInFirstConstructor);
  Rectangle rectangle2=new Rectangle(5);
  int areaInSecondConstructor=rectangle2.second();
  System.out.println(" The area of a rectangle in
   first constructor is :  " 
+ areaInSecondConstructor);
  Rectangle rectangle3=new Rectangle(2.0f);
  float areaInThirdConstructor=rectangle3.third();
  System.out.println(" The area of a rectangle in first
  constructor is :  " 
+ areaInThirdConstructor);
  Rectangle rectangle4=new Rectangle(3.0f,2.0f);
  float areaInFourthConstructor=rectangle4.fourth();
  System.out.println(" The area of a rectangle in first
  constructor is :  " 
+ areaInFourthConstructor);
  }
}

class Rectangle{
  int l, b;
  float p, q;
  public Rectangle(int x, int y){
  l = x;
  b = y;
  }
  public int first(){ 
  return(l * b);
  }
  public Rectangle(int x){
  l = x;
  b = x;
  }
  public int second(){
  return(l * b);
  }
  public Rectangle(float x){
  p = x;
  q = x;
  }
  public float third(){
  return(p * q);
  }
  public Rectangle(float x, float y){
  p = x;
  q = y;
  }
  public float fourth(){
  return(p * q);
  }
}
17)Garbage collector and finalize method  

Garbage collection

            Since objects are dynamically allocated by using the new operator, you might be wondering how such objects are destroyed and their memory released for later reallocation. In some languages, such as C++, dynamically allocated objects must be manually released by use of a delete operator.

Java takes a different approach; it handles deallocation for you automatically. The technique that accomplishes this is called garbage collection. It works like this: when no references to an object to an object exist, that object is assumed to be no longer needed, and the memory occupied by the object can be reclaimed. There is no explicit need to destroy objects as in C++. Garbage collection only occurs sporadically (if at all) during the execution of your program. It will not occur simply because one or more objects exist that are no longer used. Furthermore, different java run-time implementations will take varying approaches to garbage collection, but for the most part, you should not have to think about it while writing your programs

The finalize () Method

            Sometimes an object will need to perform some action when it is destroyed. For example, if an object is holding some non-java resource such as a file handle or window character font, then you might want to make sure these resources are freed before an object is destroyed. To handle such situations, java provides a mechanism called finalization. By using finalization, you can define specific actions that will occur when an object is just about to be reclaimed by the garbage collector.

            To add a finalizer to a class, you simply define the finalize() method. The java run time calls that method whenever it is about to recycle an object of that class. Inside the finalize() method you will specify those actions that must be performed before an object is destroyed. The garbage collector runs periodically, checking for objects that are no longer referenced by any running state or indirectly through other referenced objects. Right before an asset is freed, the java run time calls the finalize() method on the object.

            The finalize() method has this general form:

            protected void finalize()
            {
            // finalization code here
            }

            Here, the keyword protected is a specifier that prevents access to finalize() by code defined outside its class.

            It is important to understand that finalize() is only called just prior to garbage collection. It is not called when an object goes out-of-scope, for example. This means program should provide other means of releasing system resources, etc., used by the object. It must not rely on finalize() for normal program operation.
 18) static variables and methods
The static keyword can be used in 3 scenarios
  1. static variables
  2. static methods
  3. static blocks of code.
Lets look at static variables and static methods first.

static variable

  • It is a variable which belongs to the class and not to object(instance)
  • Static variables are initialized only once , at the start of the execution . These variables will be initialized first, before the initialization of any instance variables
  • A single copy to be shared by all instances of the class
  • A static variable can be accessed directly by the class name and doesn’t need any object
  • Syntax : <class-name>.<variable-name>

static method

  • It is a method which belongs to the class and not to the object(instance)
  • A static method can access only static data. It can not access non-static data (instance variables)
  • A static method can call only other static methods and can not call a non-static method from it.
  • A static method can be accessed directly by the class name and doesn’t need any object
  • Syntax : <class-name>.<method-name>
  • A static method cannot refer to “this” or “super” keywords in anyway
Side Note:
  • main method is static , since it must be be accessible for an application to run , before any instantiation takes place.
Lets learn the nuances of the static keywords by doing some excercises!
Assignment: To Learn working of static variables & methods
Step 1) Copy the following code into a editor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Student {
int a; //initialized to zero
static int b; //initialized to zero only when class is loaded not for each object created.
 
  Student(){
   //Constructor incrementing static variable b
   b++;
  }
 
   public void showData(){
      System.out.println("Value of a = "+a);
      System.out.println("Value of b = "+b);
   }
//public static void increment(){
//a++;
//}
 
}
 
class Demo{
   public static void main(String args[]){
     Student s1 = new Student();
     s1.showData();
     Student s2 = new Student();
     s2.showData();
     //Student.b++;
     //s1.showData();
  }
}
Step 2) Save & Compile the code. Run the code as, java Demo.
Step 3) Expected output show below
java-static-variable
Following diagram shows , how reference variables & objects are created and static variables are accessed by the different instances.
java-static
Step 4) It is possible to access a static variable from outside the class using the syntax ClassName.Variable_Name. Uncomment line # 27 & 28 . Save , Compile & Run . Observe the output.
Step 5) Uncomment line 15,16 & 17 . Save , Compile & Run.
Step 5) Error = ? This is because it is not possible to access instance variable “a” from static method “increment“.

static block

The static block, is a block of statement inside a Java class that will be executed when a class is first loaded in to the JVM
1
2
3
4
5
class Test{
 static {
 //Code goes here
 }
}
A static block helps to initialize the static data members, just like constructors help to initialize instance members
 
 19)initializer blocks and the class initializer blocks

Initializing Fields

As you have seen, you can often provide an initial value for a field in its declaration:
public class BedAndBreakfast {

    // initialize to 10
    public static int capacity = 10;

    // initialize to false
    private boolean full = false;
}
This works well when the initialization value is available and the initialization can be put on one line. However, this form of initialization has limitations because of its simplicity. If initialization requires some logic (for example, error handling or a for loop to fill a complex array), simple assignment is inadequate. Instance variables can be initialized in constructors, where error handling or other logic can be used. To provide the same capability for class variables, the Java programming language includes static initialization blocks.

Note: It is not necessary to declare fields at the beginning of the class definition, although this is the most common practice. It is only necessary that they be declared and initialized before they are used.

Static Initialization Blocks

A static initialization block is a normal block of code enclosed in braces, { }, and preceded by the static keyword. Here is an example:
static {
    // whatever code is needed for initialization goes here
}
A class can have any number of static initialization blocks, and they can appear anywhere in the class body. The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code.
There is an alternative to static blocks — you can write a private static method:
class Whatever {
    public static varType myVar = initializeClassVariable();
        
    private static varType initializeClassVariable() {

        // initialization code goes here
    }
}
The advantage of private static methods is that they can be reused later if you need to reinitialize the class variable.

Initializing Instance Members

Normally, you would put code to initialize an instance variable in a constructor. There are two alternatives to using a constructor to initialize instance variables: initializer blocks and final methods.
Initializer blocks for instance variables look just like static initializer blocks, but without the static keyword:
{
    // whatever code is needed for initialization goes here
}
The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors.
A final method cannot be overridden in a subclass. This is discussed in the lesson on interfaces and inheritance. Here is an example of using a final method for initializing an instance variable:
class Whatever {
    private varType myVar = initializeInstanceVariable();
        
    protected final varType initializeInstanceVariable() {

        // initialization code goes here
    }
}

This is especially useful if subclasses might want to reuse the initialization method. The method is final because calling non-final methods during instance initialization can cause problems.
 


No comments:

Post a Comment