Saturday, December 29, 2012

Core Java

Core Java
 
1. 
Floating-point numbers without an F suffix (such as 3.402) are always considered to be of type double. You can optionally supply the D suffix (for example, 3.402D).
    Floating-point numbers are not suitable for financial calculation in which roundoff errors cannot be tolerated. If you need precise numerical computations without roundoff errors, use the BigDecimal class.
Methods tagged with the strictfp keyword must use strict floating-point operations that yield reproducible results. For example, you can tag main as
public static strictfp void main(String[] args)
    Then all instructions inside the main method use strict floating-point computations. If you tag a class as strictfp, then all of its methods use strict floating-point computations. the only difference between default and strict mode is that strict computations may overflow when default computations don't.
The functions in the Math class use the routines in the computer's floating-point unit for fastest performance. If completely predictable results are more important than fast performance, use the StrictMath class instead.
 
2.
When applied to boolean values, the & and | operators yield a boolean value. These operators are similar to the && and || operators, except that the & and | operators are not evaluated in "short circuit" fashion. That is, both arguments are first evaluated before the result is computed. 
 
3. The Java programming language always uses call by value. That means that the method gets a copy of all parameter values. In particular, the method cannot modify the contents of any parameter variables that are passed to it.
Employee a = new Employee("Alice", . . .);
Employee b = new Employee("Bob", . . .);
swap(a, b);
// does a now refer to Bob, b to Alice?
Some programmers (and unfortunately even some book authors) claim that the Java programming language uses call by reference for objects. However, that is false.
Here is a summary of what you can and cannot do with method parameters in the Java programming language:
A method cannot modify a parameter of primitive type (that is, numbers or Boolean values).
A method can change the state of an object parameter.
A method cannot make an object parameter refer to a new object. 
 
4.
The name and parameter type list for a method is called the method's signature.
The return type is not part of the signature. However, when you override a method, you need to keep the return type compatible. Prior to JDK 5.0, the return types had to be identical. However, it is now legal for the subclass to change the return type of an overridden method to a subtype of the original type. (In JDK1.4, it will report compile error). 
The fact that an object variable can refer to multiple actual types is called polymorphism. Automatically selecting the appropriate method at run time is called dynamic binding.
It is important to understand what happens when a method call is applied to an object. Here are the details:
1)The compiler looks at the declared type of the object and the method name. The compiler enumerates all methods called f in the class C and all public methods called f in the superclasses of C.
Now the compiler knows all possible candidates for the method to be called.
2)Next, the compiler determines the types of the parameters that are supplied in the method call. If among all the methods called f there is a unique method whose parameter types are a best match for the supplied parameters, then that method is chosen to be called. This process is called overloading resolution.
Now the compiler knows the name and parameter types of the method that needs to be called.
3)If the method is private, static, final, or a constructor, then the compiler knows exactly which method to call. This is called static binding. Otherwise, the method to be called depends on the actual type of the implicit parameter, and dynamic binding must be used at run time.
4)When the program runs and uses dynamic binding to call a method, then the virtual machine must call the version of the method that is appropriate for the actual type of the object to which x refers. It would be time consuming to carry out this search every time a method is called. Therefore, the virtual machine precomputes for each class a method table that lists all method signatures and the actual methods to be called.
Because the getSalary method is not private, static, or final, it is dynamically bound.
Dynamic binding has a very important property: it makes programs extensible without the need for modifying existing code. Suppose a new class Executive is added and there is the possibility that the variable e refers to an object of that class. The code containing the call e.getSalary() need not be recompiled. The Executive.getSalary() method is called automatically if e happens to refer to an object of type Executive.
if a class is declared as final, only the methods, not the fields, are automatically final.
There is only one good reason to make a method or class final: to make sure that the semantics cannot be changed in a subclass.

5. This is an important difference between fields and local variables. You must always explicitly initialize local variables in a method. But if you don't initialize a field in a class, it is automatically initialized to a default (0, false, or null). 
Here is what happens in detail when a constructor is called.
All data fields are initialized to their default value (0, false, or null). 
All field initializers and initialization blocks are executed, in the order in which they occur in the class declaration. 
If the first line of the constructor calls a second constructor, then the body of the second constructor is executed. 
The body of the constructor is executed. 
All static field initializers and static initialization blocks are executed in the order in which they occur in the class declaration. 
If the subclass constructor does not call a superclass constructor explicitly, then the default (no-parameter) constructor of the superclass is invoked. If the superclass has no default constructor and the subclass constructor does not call another superclass constructor explicitly, then the Java compiler reports an error.
 
6.
Some people think of super as being analogous to the this reference. However, that analogy is not quite accurate—super is not a reference to an object. For example, you cannot assign the value super to another object variable. Instead, super is a special keyword that directs the compiler to invoke the superclass method.
An abstract class can have no any abstract method, but if only a class has an abstract method, then it must be declared to abstract.
 
7.
There are two kinds of exceptions: unchecked exceptions and checked exceptions. With checked exceptions, the compiler checks that you provide a handler. However, many common exceptions, such as accessing a null reference, are unchecked. The compiler does not check whether you provide a handler for these errors-after all, you should spend your mental energy on avoiding these mistakes rather than coding handlers for them. 
A method must declare all the checked exceptions that it might throw. Unchecked exceptions are either beyond your control (Error) or result from conditions that you should not have allowed in the first place (RuntimeException). If your method fails to faithfully declare all checked exceptions, the compiler will issue an error message.
But not all errors are avoidable. If an exception can occur despite your best efforts, then the compiler insists that you provide a handler. The Class.forName method is an example of a method that throws a checked exception. 
It is easy to find out which methods throw checked exceptions-the compiler will complain whenever you call a method that threatens to throw a checked exception and you don't supply a handler. 
 
8. Inner Classes
An inner class is a class that is defined inside another class. Why would you want to do that? There are three reasons:
1) Inner class methods can access the data from the scope in which they are defined-including data that would otherwise be private.
2) Inner classes can be hidden from other classes in the same package.
3) Anonymous inner classes are handy when you want to define callbacks without writing a lot of code.
Only inner classes can be private. Regular classes always have either package or public visibility.
you can write the inner object constructor more explicitly, using the syntax
outerObject.new InnerClass(construction parameters)
Inner classes are translated into regular class files with $ (dollar signs) delimiting outer and inner class names, and the virtual machine does not have any special knowledge about them.
Local classes are never declared with an access specifier (that is, public or private). Their scope is always restricted to the block in which they are declared.
Local classes have a great advantage: they are completely hidden from the outside world-not even other code in the TalkingClock class can access them. No method except start has any knowledge of the TimePrinter class.
Local classes have another advantage over other inner classes. Not only can they access the fields of their outer classes, they can even access local variables! However, those local variables must be declared final. 
A local variable that is declared final cannot be modified after it has been initialized.
Thus, it is guaranteed that the local variable and the copy that is made inside
the local class always have the same value.
     Date now = new Date() {
     public void setHours(int hours) {
     System.out.println("sethours....");
     }
     };
     now.setHours(3);
     System.out.println(now);
only inner classes can be declared static. A static inner class is exactly like any other inner class, except that an object of a static inner class does not have a reference to the outer class object that generated it.
Inner classes that are declared inside an interface are automatically static and public.
 
9.
You use a proxy to create at run time new classes that implement a given set of interfaces. Proxies are only necessary when you don't yet know at compile time which interfaces you need to implement. This is not a common situation for application programmers. However, for certain system programming applications, the flexibility that proxies offer can be very important. By using proxies, you can often avoid the mechanical generation and compilation of "stub" code. As of JDK 5.0, the proxy facility is used to generate RMI stubs without having to run a utility.
Remember that proxy classes are created on the fly in a running program. However, once they are created, they are regular classes, just like any other classes in the virtual machine.
The names of proxy classes are not defined. The Proxy class in Sun's virtual machine generates class names that begin with the string $Proxy.
The proxy class can create brand-new classes at runtime. Such a
proxy class implements the interfaces that you specify. In particular, the proxy class has
the following methods:
? All methods required by the specified interfaces; and
? All methods defined in the Object class (toString, equals, and so on).
However, you cannot define new code for these methods at runtime. Instead, you must
supply an invocation handler. An invocation handler is an object of any class that implements
the InvocationHandler interface. That interface has a single method:
Object invoke(Object proxy, Method method, Object[] args)
 
10.
The getFields method returns an array containing Field objects for the public fields of this class or its superclasses. The geTDeclaredField method returns an array of Field objects for all fields of this class. 
getMethods returns public methods and includes inherited methods; getdeclaredMethods returns all methods of this class or interface but does not include inherited methods. 
 
11.
Be careful not to write accessor methods that return references to mutable objects. We violated that rule in our Employee class in which the getHireDay method returns an object of class Date:
You can define an instance field as final. Such a field must be initialized when the object is constructed. That is, it must be guaranteed that the field value has been set after the end of every constructor. Afterwards, the field may not be modified again.
private final Date hiredate;
merely means that the object reference stored in the hiredate variable doesn't get changed after the object is constructed. That does not mean that the hiredate object is constant. Any method is free to invoke the setTime mutator on the object to which hiredate refers. 
 
12.
The bytecodes in class files always use full package names to refer to other classes.
Suppose the interpreter searches for the class file of the com.horstmann.corejava.Employee class. It first looks in the system class files that are stored in archives in the jre/lib and jre/lib/ext directories. It won't find the class file there, so it turns to the class path. It then looks for the following files:
/home/user/classdir/com/horstmann/corejava/Employee.class
com/horstmann/corejava/Employee.class starting from the current directory
com/horstmann/corejava/Employee.class inside /home/user/archives/archive.jar. 
 
13.
The javac compiler always looks for files in the current directory, but the java interpreter only looks into the current directory if the "." directory is on the class path. If you have no class path set, this is not a problem-the default class path consists of the "." directory. But if you have set the class path and forgot to include the "." directory, then your programs will compile without error, but they won't run. 
 
14.
As it happens, protected features in Java are visible to all subclasses as well as to all other classes in the same package. This is slightly different from the C++ meaning of protected, and it makes the notion of protected in Java even less safe than in C++.
Here is a summary of the four access modifiers in Java that control visibility:
Visible to the class only (private).
Visible to the world (public).
Visible to the package and all subclasses (protected).
Visible to the package-the (unfortunate) default. No modifiers are needed.
The default behavior of the reflection mechanism is to respect Java access control. However,
if a Java program is not controlled by a security manager that disallows it, you can
override access control. To do this, invoke the setAccessible method on a Field, Method, or
Constructor object. For example:
f.setAccessible(true); // now OK to call f.get(harry); 
 
15.
Design Hints for Inheritance:
1). Place common operations and fields in the superclass
2). Don't use protected fields
    However, protected methods can be useful to indicate methods that are not ready for general use and should be redefined in subclasses. The clone method is a good example
3). Use inheritance to model the "is-a" relationship
4). Don't use inheritance unless all inherited methods make sense.
    Holiday should not extend GregorianCalendar
5). Don't change the expected behavior when you override a method.
6). Use polymorphism, not type information.
7). Don't overuse reflection 
Object and Class
The most common relationships between classes are
Dependence ("uses-a")      Order--->Account
Aggregation ("has-a")      Order<>----Item  
Inheritance ("is-a")       RushOrder------|>Order
 
16.
Class Design Hints
Always keep data private.
Always initialize data.
Don't use too many basic types in a class.
Not all fields need individual field accessors and mutators.
Use a standard form for class definitions.
Break up classes with too many responsibilities.
Make the names of your classes and methods reflect their responsibilities. 
 
17.
Although you cannot put instance fields or static methods in an interface, you can supply
constants in them. Just as methods in an interface are automatically public, fields are always
public static final. It is legal to tag interface methods as public, and fields as public static final. Some programmers do that, either out of habit or for greater clarity. However, the Java Language
Specification recommends that the redundant keywords not be supplied, and we follow that
recommendation.
 
18.
LinkedList An ordered sequence that allows efficient insertions and
removal at any location.
As we already discussed, a queue lets you efficiently add elements at the tail and
remove elements from the head. A double ended queue or deque lets you efficiently add
or remove elements at the head and tail. Adding elements in the middle is not supported.
Java SE 6 introduced a Deque interface. It is implemented by the ArrayDeque and
LinkedList classes, both of which provide deques whose size grows as needed.
The Collections class has methods that produce unmodifiable views of collections. These
views add a runtime check to an existing collection. If an attempt to modify the collection
is detected, then an exception is thrown and the collection remains untouched.
 
19.
The assertion mechanism allows you to put in checks during testing and to have them
automatically removed in the production code.
TIP: The default logging configuration logs all records with level of INFO or higher. Therefore,
you should use the levels CONFIG, FINE, FINER, and FINEST for debugging messages that are
useful for diagnostics but meaningless to the program user.
The default log record shows the name of the class and method that contain the logging
call, as inferred from the call stack. However, if the virtual machine optimizes execution,
accurate call information may not be available. You can use the logp method to give the
precise location of the calling class and method. The method signature is
void logp(Level l, String className, String methodName, String message)
There are convenience methods for tracing execution flow:
void entering(String className, String methodName)
void entering(String className, String methodName, Object param)
void entering(String className, String methodName, Object[] params)
void exiting(String className, String methodName)
void exiting(String className, String methodName, Object result)
For example:
int read(String file, String pattern)
{
  logger.entering("com.mycompany.mylib.Reader", "read",
     new Object[] { file, pattern });
  . . .
  logger.exiting("com.mycompany.mylib.Reader", "read", count);
  return count;
}
These calls generate log records of level FINER that start with the strings ENTRY and RETURN.
You can change various properties of the logging system by editing a configuration file.
The default configuration file is located at
jre/lib/logging.properties
To use another file, set the java.util.logging.config.file property to the file location by
starting your application with
java -Djava.util.logging.config.file=configFile MainClass
As you see later in this section, the loggers don’t actually send the messages to the con-
sole—that is the job of the handlers. Handlers also have levels. To see FINE messages on
the console, you also need to set
java.util.logging.ConsoleHandler.level=FINE
Handlers
By default, loggers send records to a ConsoleHandler that prints them to the System.err
stream. Specifically, the logger sends the record to the parent handler, and the ulti-
mate ancestor (with name "") has a ConsoleHandler.
Like loggers, handlers have a logging level. For a record to be logged, its logging level
must be above the threshold of both the logger and the handler. The log manager config-
uration file sets the logging level of the default console handler as
java.util.logging.ConsoleHandler.level=INFO
To log records with level FINE, change both the default logger level and the handler level
in the configuration. Alternatively, you can bypass the configuration file altogether and
install your own handler.
To send log records elsewhere, add another handler. The logging API provides two use-
ful handlers for this purpose, a FileHandler and a SocketHandler. The SocketHandler sends
records to a specified host and port. Of greater interest is the FileHandler that collects
records in a file.
You can simply send records to a default file handler, like this:
FileHandler handler = new FileHandler();
logger.addHandler(handler);
The records are sent to a file javan.log in the user’s home directory, where n is a number
to make the file unique. If a user’s system has no concept of the user’s home directory
(for example, in Windows 95/98/Me), then the file is stored in a default location such as
C:\Windows. By default, the records are formatted in XML.
A common use for logging is to log unexpected exceptions. Two convenience methods
include a description of the exception in the log record.
void throwing(String className, String methodName, Throwable t)
void log(Level l, String message, Throwable t)
Having stack traces of uncaught exceptions show up in System.err is not ideal. These
messages are confusing to end users if they happen to see them, and they are not
available for diagnostic purposes when you need them. A better approach is to log
them to a file. As of Java SE 5.0, you can change the handler for uncaught exceptions
with the static  Thread.setDefaultUncaughtExceptionHandler method:
Thread.setDefaultUncaughtExceptionHandler(
     new Thread.UncaughtExceptionHandler()
     {                     
         public void uncaughtException(Thread t, Throwable e)
         {
            save information in log file
         };
     });
 
21.
Java SE 5.0 added the -Xlint option to the compiler for spotting common code prob-
lems. For example, if you compile with the command
javac -Xlint:fallthrough
then the compiler reports missing break statements in switch statements. (The term
“lint” originally described a tool for locating potential problems in C programs, and
is now generically applied to tools that flag constructs that are questionable but not
illegal.)
The following options are available:
-Xlint or -Xlint:all Carries out all checks
-Xlint:deprecation Same as -deprecation, checks for deprecated methods
-Xlint:fallthrough Checks for missing break statements in switch statements
-Xlint:finally Warns about finally clauses that cannot complete normally
-Xlint:none Carries out none of the checks
-Xlint:path Checks that all directories on the class path and source
path exist
-Xlint:serial Warns about serializable classes without serialVersionUID
(see Chapter 1 of Volume II)
-Xlint:unchecked Warns of unsafe conversions between generic and raw
types (see Chapter 12)
 
22.
A useful doclet is DocCheck, at http://java.sun.com/j2se/javadoc/doccheck/. It scans a set of source files for missing documentation comments.
The case labels must be integers or enumerated constants.
Java SE 6 introduces a Console class specifically to read password from console.
System.console().readPassword()
The virtual machine manages a unique Class object for each type. Therefore, you can use
the == operator to compare class objects. For example:
if (e.getClass() == Employee.class) . . .
For historical reasons, the getName method returns somewhat strange names for
array types:
? Double[].class.getName() returns "[Ljava.lang.Double;"
? int[].class.getName() returns "[I"
The src.zip file contains the source code for all public libraries. To obtain even more source (for the compiler, the virtual machine, the native methods, and the private helper classes), go to http://www.sun.com/software/communitysource/j2se/java2/index.html.
 
23.
The JFrame is one of the few Swing components that is not painted on a canvas. 
Thus, the decorations (buttons, title bar, icons, and so on) are drawn by the user's windowing system, not by Swing.
For a frame, the coordinates of the setLocation and setBounds are taken relative to the whole screen. for other components inside a container, the measurements are taken relative to the container.
To accelarate the startup, you can first display a splash screen. Then manually force the loading of other classes by calling Class.forName 
If you ever looked at a Swing window and wondered how its designer managed
to get all the components to line up so nicely, you can spy on the contents. Press
CTRL+SHIFT+F1, and you get a printout of all components in the hierarchy:
If you design your own custom Swing component and it doesn’t seem to be dis-
played correctly, you’ll really love the Swing graphics debugger. And even if you
don’t write your own component classes, it is instructive and fun to see exactly
how the contents of a component are drawn. To turn on debugging for a Swing
component, use the setDebugGraphicsOptions method of the JComponent class. The follow-
ing options are available:

In 2005, the NetBeans team invented the Matisse technology, which combines a layout
tool and a layout manager.
Even if you don’t use NetBeans as your IDE, we
think you should consider using its GUI builder tool. You can design your GUI in Net-
Beans and paste the resulting code into your IDE of choice.


24.

As of Java SE 6, you can use the e option of the jar command to specify the entry point of
your program—the class that you would normally specify when invoking the java program
launcher:
jar cvfe MyProgram.jar com.mycompany.mypkg.MainAppClass files to add
On Windows, you can use third-party wrapper utilities that turn JAR files into Windows
executables. A wrapper is a Windows program with the familiar .exe extension that
locates and launches the Java virtual machine (JVM), or tells the user what to do when no
JVM is found. There are a number of commercial and open source products, such as
JSmooth ( http://jsmooth.sourceforge.net) and Launch4J (http://launch4j.sourceforge.net). The
open source installer generator IzPack (http://izpack.org) also contains a native launcher.
For more information on this topic, see http://www.javalobby.org/articles/java2exe.
you can seal a Java language package to ensure that no
further classes can add themselves to it. You would want to seal a package if you use
package-visible classes, methods, and fields in your code. Without sealing, other classes
can place themselves into the same package and thereby gain access to its packagevisible
features.

25.
The Preferences class of Java
SE 1.4 provides such a central repository in a platform-independent manner.
InputStream in = new FileInputStream(chooser.getSelectedFile());
Preferences.importPreferences(in);
OutputStream out = new FileOutputStream(chooser.getSelectedFile());
node.exportSubtree(out);


26.

all exceptions descend from Throwable, but the hierarchy immediately splits
into two branches: Error and Exception.
The Error hierarchy describes internal errors and resource exhaustion inside the Java
runtime system. You should not throw an object of this type. There is little you can do if
such an internal error occurs, beyond notifying the user and trying to terminate the
program gracefully. These situations are quite rare.
When doing Java programming, you focus on the Exception hierarchy. The Exception hierarchy
also splits into two branches: exceptions that derive from RuntimeException and those
that do not. The general rule is this: A RuntimeException happens because you made a programming
error. Any other exception occurs because a bad thing, such as an I/O error,
happened to your otherwise good program.
The rule “If it is a RuntimeException, it was your fault” works pretty well.
The Java Language Specification calls any exception that derives from the class Error or
the class RuntimeException an unchecked exception. All other exceptions are called checked
exceptions. This is useful terminology that we also adopt. The compiler checks that you
provide exception handlers for all checked exceptions.
you should not advertise unchecked exceptions inheriting from RuntimeException.
These runtime errors are completely under your control. If you are so concerned about
array index errors, you should spend the time needed to fix them instead of advertising
the possibility that they can happen.
In summary, a method must declare all the checked exceptions that it might throw.
Unchecked exceptions are either beyond your control (Error) or result from conditions
that you should not have allowed in the first place (RuntimeException). If your method fails
to faithfully declare all checked exceptions, the compiler will issue an error message.
Here is how you can catch an exception and rethrow it:
try
{
access the database
}
catch (SQLException e)
{
throw new ServletException("database error: " + e.getMessage());
}
Here, the ServletException is constructed with the message text of the exception. As of Java
SE 1.4, you can do better than that and set the original exception as the “cause” of the
new exception:
try
{
access the database
}
catch (SQLException e)
{
Throwable se = new ServletException("database error");
se.initCause(e);
throw se;
}
When the exception is caught, the original exception can be retrieved:
Throwable e = se.getCause();
This wrapping technique is highly recommended. It allows you to throw high-level
exceptions in subsystems without losing the details of the original failure.
A finally clause can yield unexpected results when it contains return statements.
Suppose you exit the middle of a try block with a return statement. Before the method returns,
the contents of the finally block are executed. If the finally block also contains a return statement,
then it masks the original return value. Consider this contrived example:
public static int f(int n)
{
try
{
int r = n * n;
return r;
}
finally
{
if (n == 2) return 0;
}
}
If you call f(2), then the try block computes r = 4 and executes the return statement. However,
the finally clause is executed before the method actually returns. The finally clause
causes the method to return 0, ignoring the original return value of 4.

 27.


The assertion mechanism allows you to put in checks during testing and to have them
automatically removed in the production code.
As of Java SE 1.4, the Java language has a keyword assert. There are two forms:
assert condition;
and
assert condition : expression;
Both statements evaluate the condition and throw an AssertionError if it is false. In the second
statement, the expression is passed to the constructor of the AssertionError object and
turned into a message string.
When assertions are disabled,
the class loader strips out the assertion code so that it won’t slow execution.
You can also disable assertions in certain classes and packages with the -disableassertions
or -da option:
java -ea:... -da:MyClass MyApp
Some classes are not loaded by a class loader but directly by the virtual machine. You
can use these switches to selectively enable or disable assertions in those classes.
assertions are a tactical tool for testing and debugging.


It is also possible to change logging levels in a running program by using the jconsole
program.
By default, loggers send records to a ConsoleHandler that prints them to the System.err
stream. Specifically, the logger sends the record to the parent handler, and the ultimate
ancestor (with name "") has a ConsoleHandler.
if (System.getProperty("java.util.logging.config.class") == null
&& System.getProperty("java.util.logging.config.file") == null)
{
try
{
Logger.getLogger("").setLevel(Level.ALL);
final int LOG_ROTATION_COUNT = 10;
Handler handler = new FileHandler("%h/myapp.log", 0, LOG_ROTATION_COUNT);
Logger.getLogger("").addHandler(handler);
}
catch (IOException e)
{
logger.log(Level.SEVERE, "Can't create log file handler", e);
}
}
Having stack traces of uncaught exceptions show up in System.err is not ideal. These
messages are confusing to end users if they happen to see them, and they are not
available for diagnostic purposes when you need them. A better approach is to log
them to a file. As of Java SE 5.0, you can change the handler for uncaught exceptions
with the static Thread.setDefaultUncaughtExceptionHandler method:
Thread.setDefaultUncaughtExceptionHandler(
new Thread.UncaughtExceptionHandler()
{
public void uncaughtException(Thread t, Throwable e)
{
save information in log file
};
});
jconsole processID
The console gives you a wealth of information about your running program.
T extends Comparable & Serializable
The virtual machine does not have objects of generic types—all objects belong to ordinary
classes. An earlier version of the generics implementation was even able to compile
a program that uses generics into class files that executed on 1.0 virtual machines!
This backward compatibility was only abandoned fairly late in the development for
Java generics. If you use the Sun compiler to compile code that uses Java generics, the
resulting class files will not execute on pre-5.0 virtual machines.
The raw type replaces type variables with the first bound.

There are no generics in the virtual machines, only ordinary classes and methods.
All type parameters are replaced by their bounds.
Bridge methods are synthesized to preserve polymorphism.
Casts are inserted as necessary to preserve type safety.

arrays of
parameterized types are outlawed.
public Pair() { first = new T(); second = new T(); } // ERROR
Type erasure would change T to Object, and surely you don’t want to call new Object().
public class Singleton<T>
{
public static T getSingleInstance() // ERROR
{
if (singleInstance == null) construct new instance of T
return singleInstance;
}
private static T singleInstance; // ERROR
}
The generics specification cites another rule: “To support translation by erasure, we
impose the restriction that a class or type variable may not at the same time be a subtype
of two interface types which are different parameterizations of the same interface.” For
example, the following is illegal:
class Calendar implements Comparable<Calendar> { . . . }
class GregorianCalendar extends Calendar implements Comparable<GregorianCalendar>
{ . . . } // ERROR
In general, there is no relationship between Pair<S> and Pair<T>, no matter how S and T are
related
the wildcard type
Pair<? extends Employee>
denotes any generic Pair type whose type parameter is a subclass of Employee, such as
Pair<Manager>, but not Pair<String>.
The type Pair<Manager> is a subtype of Pair<? extends Employee>


you can specify a supertype bound, like this:
? super Manager
Intuitively speaking, wildcards with supertype bounds let you write to a generic object,
wildcards with subtype bounds let you read from a generic objects.
You can even use wildcards with no bounds at all, for example, Pair<?>.
One of the notable features of Java generics is the erasure of generic types in the virtual
machine. Perhaps surprisingly, the erased classes still retain some faint memory of their
generic origin. For example, the raw Pair class knows that it originated from the generic
class Pair<T>, even though an object of type Pair can’t tell whether it was constructed as a
Pair<String> or Pair<Employee>.
public static <T> void swapHelper(Pair<T> p)
{
T t = p.getFirst();
p.setFirst(p.getSecond());
p.setSecond(t);
}


The TreeSet class is similar to the hash set, with one added improvement. A tree set is a
sorted collection. You insert elements into the collection in any order. When you iterate
through the collection, the values are automatically presented in sorted order.
(The current implementation
uses a red-black tree.)

a queue lets you efficiently add elements at the tail and
remove elements from the head. A double ended queue or deque lets you efficiently add
or remove elements at the head and tail. Adding elements in the middle is not supported.

A priority queue retrieves elements in sorted order after they were inserted in arbitrary
order. That is, whenever you call the remove method, you get the smallest element currently
in the priority queue. However, the priority queue does not sort all its elements. If
you iterate over the elements, they are not necessarily sorted. The priority queue makes
use of an elegant and efficient data structure, called a heap. A heap is a self-organizing
binary tree in which the add and remove operations cause the smallest element to gravitate
to the root, without wasting time on sorting all elements.

The garbage collector traces live objects. As long
as the map object is live, then all buckets in it are live and they won’t be reclaimed. Thus,
your program should take care to remove unused values from long-lived maps. Or, you
can use a WeakHashMap instead. This data structure cooperates with the garbage collector to
remove key/value pairs when the only reference to the key is the one from the hash
table entry.
Here are the inner workings of this mechanism. The WeakHashMap uses weak references to
hold keys. A WeakReference object holds a reference to another object, in our case, a hash
table key. Objects of this type are treated in a special way by the garbage collector. Normally,
if the garbage collector finds that a particular object has no references to it, it simply
reclaims the object. However, if the object is reachable only by a WeakReference, the
garbage collector still reclaims the object, but it places the weak reference that led to it
into a queue. The operations of the WeakHashMap periodically check that queue for newly
arrived weak references. The arrival of a weak reference in the queue signifies that the
key was no longer used by anyone and that it has been collected. The WeakHashMap then
removes the associated entry.

Java SE 1.4 added classes LinkedHashSet and LinkedHashMap that remember in which order
you inserted items. That way, you avoid the seemingly random order of items in a hash
table. As entries are inserted into the table, they are joined in a doubly linked list
If you have an array, you need to turn it into a collection. The Arrays.asList wrapper
serves this purpose. For example:
String[] values = . . .;
HashSet<String> staff = new HashSet<String>(Arrays.asList(values));
Obtaining an array from a collection is a bit trickier:
staff.toArray(new String[staff.size()]);


Java Defects:
1. The sort method in the Arrays class is defined to accept a Comparable[] array so that the compiler can complain if anyone ever calls sort with an array whose element type doesn't implement the Comparable interface. Sadly, that is not the case. 
 2.

At least up to Java SE 6, the API documentation of the LogManager class claims
that you can set the java.util.logging.config.class and java.util.logging.config.file
properties via the Preferences API. This is false—see http://bugs.sun.com/bugdatabase/
view_bug.do?bug_id=4691587.
3.
However, the Stack class extends the Vector class, which is not satisfactory from
a theoretical perspective—you can apply such un-stack-like operations as insert and
remove to insert and remove values anywhere, not just at the top of the stack.





Chap14 MULTITHREADING
for more intricate system-level
programming, we suggest that you turn to a more advanced reference, such as Java Concurrency
in Practice by Brian Goetz (Addison-Wesley Professional, 2006).
When the interrupt method is called on a thread, the interrupted status of the thread is set.
This is a boolean flag that is present in every thread. Each thread should occasionally
check whether it has been interrupted.
However, if a thread is blocked, it cannot check the interrupted status. This is
where the InterruptedException comes in. When the interrupt method is called on a
thread that blocks on a call such as sleep or wait, the blocking call is terminated by
an InterruptedException.
There is no language requirement that a thread that is interrupted should terminate.
Interrupting a thread simply grabs its attention. The interrupted thread can
decide how to react to the interruption.
If you call the sleep
method when the interrupted status is set, it doesn’t sleep. Instead, it clears the
status (!) and throws an InterruptedException. Therefore, if your loop calls sleep, don’t
check the interrupted status. Instead, catch the InterruptedException

Threads can be in one of six states:
• New: When you create a thread with the new operator—
• Runnable: Once you invoke the start method, the thread is in the runnable state.
• Blocked: When the thread tries to acquire an intrinsic object lock that is currently held by another thread
• Waiting: When the thread waits for another thread to notify the scheduler of a condition 
This happens by calling the Object.wait or Thread.join method,
or by waiting for a Lock or Condition in the java.util.concurrent library. In practice, the
difference between the blocked and waiting state is not significant.
• Timed waiting: 
Several methods have a timeout parameter. Calling them causes the thread to enter
the timed waiting state.
• Terminated
On a machine with multiple processors, each processor can run a thread, and you can
have multiple threads run in parallel. Of course, if there are more threads than processors,
the scheduler still has to do time-slicing.
Terminated Threads
A thread is terminated for one of two reasons:
• It dies a natural death because the run method exits normally.
• It dies abruptly because an uncaught exception terminates the run method.
When
only daemon threads remain, the virtual machine exits.
To avoid corruption of shared data by multiple threads, you must learn how to synchronize
the access.
private Lock bankLock = new ReentrantLock(); // ReentrantLock implements the Lock interface
bankLock.lock();
try{}
finally{bankLock.unlock();}

private Condition sufficientFunds;
sufficientFunds = bankLock.newCondition();
If the transfer method finds that sufficient funds are not available, it calls
sufficientFunds.await();
When another thread transfers money, then it should call
sufficientFunds.signalAll();
It is also legal to declare static methods as synchronized. If such a method is called, it
acquires the intrinsic lock of the associated class object. For example, if the Bank class has
a static synchronized method, then the lock of the Bank.class object is locked when it is
called. As a result, no other thread can call this or any other synchronized static method
of the same class.
1. It is best to use neither Lock/Condition nor the synchronized keyword. For example, to use a blocking queue to synchronize threads that work on a common task.
2. If the synchronized keyword works for your situation, by all means, use it. 
You write
less code and have less room for error.
3. 
Use Lock/Condition if you specifically need the additional power that these constructs
give you.
“If you write a variable
which may next be read by another thread, or you read a variable which may have last been
written by another thread, you must use synchronization.”
Volatile variables do not provide any atomicity.

The
implementation uses efficient machine-level instructions that guarantee atomicity without
using locks. There are a number of wrapper classes in the java.util.concurrent.atomic
package for atomic integers, floating point numbers, arrays, and so on. These classes are
intended for systems programmers who produce concurrency utilities, not for the application
programmer.

In summary, concurrent access to a field is safe in these three conditions:
• The field is final, and it is accessed after the constructor has completed.
• Every access to the field is protected by a common lock.
• The field is volatile.
the ReentrantReadWriteLock class 
is useful when there are
many threads that read from a data structure and fewer threads that modify it.
A blocking queue causes a thread to block when you try to add an element when the queue
is currently full or to remove an element when the queue is empty. Blocking queues are a
useful tool for coordinating the work of multiple threads.
A Callable is similar to a Runnable,
but it returns a value.
Constructing a new thread is somewhat expensive because it involves interaction with
the operating system. If your program creates a large number of short-lived threads,
then it should instead use a thread pool.
Another reason to use a thread pool is to throttle the number of concurrent threads.
The Executors class has a number of static factory methods for constructing thread pools

No comments:

Post a Comment