Few interesting keypoints to be noted in this book are.
1) Section 1.5 says
In pre-Tiger versions of Java, Unicode 3.0 was supported, and all of these Unicode characters fit into 16 bits (and therefore a char). Things are different, now.
In Tiger, Java has moved to support Unicode 4.0, which defines several characters that don't fit into 16 bits. This means that they won't fit into a char, and that has some far-reaching consequences.
You'll have to use int to represent these characters, and as a result methods like
Character.isUpperCase( ) and Character.isWhitespace( ) now have variants that accept int arguments. So if you're needing values in Unicode 3.0 that are not available in Unicode 3.0, you'll need to use these new methods..
NOTE
Most of the new characters in Unicode 4.0 are Han ideographs.
2) In Chapter 3 Enums few key points to be noted about Enums are
a) Enums are classes.
b) Enum extend java.lang.Enum
c) Enumerated types aren't integers
d) Enums have no public constructor
e) Enum values are public static and final.
f) Enum values can be compared with == or equals()
g) Enum implements java.lang.Comparable
h) Enums override toString() method
i) Enum provide a valueOf() method
j) Enums define a final instance method named ordinal( )
oridinal( ) returns the integer position of each enumerated value, starting at zero, based on the declaration order in the enum. This isn't a method you should use in your own code, but it's used by other enum-related functionality, so is worth knowing about.
k) Enums define a values( ) method
l) Nested enum's are implicitly static
3) In Chapter 4 Autoboxing and Unboxing few key points to be noted are.
a) Can you predict the output of this program?
Integer i1 = 256;
Integer i2 = 256;
if (i1 == i2) System.out.println("Equal!");
else System.out.println("Not equal!");
The result of running this code, at least in my JVM, is the text "Not equal!" In this case, there is not an unboxing operation involved. The literal 256 is boxed into two different Integer objects (again, in my JVM), and then those objects are compared with ==. The result is false, as the two objects are
different instances, with different memory addresses. Because both sides of the == expression contain objects, no unboxing occurs.
But what if when we change both Integer values in the program to 100? Here, you would get the text "Equal!" Remember that int values from -127 to 127 are in that range of immutable wrapper types, so the VM actually uses the same object instance (and therefore memory address) for both i1 and i2. As a result, == returns a true result. You have to watch out for this, as it can result in some very tricky, hard-to-find bugs.
b) In 4.5 Conditionals and Unboxing it states
String s = "hello";
StringBuffer sb = new StringBuffer("world");
boolean mutable = true;
CharSequence cs = mutable ? sb : s;
In pre-Tiger environments, this would generate an error, as sb (a StringBuffer) and s (a String) cannot be assigned to each other. However, this code should really work, as both String and StringBuffer implement the CharSequence interface. However, you have to perform some casting:
CharSequence cs = mutable ? (CharSequence)sb : (CharSequence)s;
In Tiger, though, any valid intersection of the two operands can be used. This is essentially any object, walking up the inheritance chain, that is common to both operands. In this case, CharSequence fits that criteria, and so is a valid return type.
c) In Section 4.7 Method Overload Resolution it states that Java handles method resolution by using the name of the method. In cases where a method is overloaded, though, an extra step must be taken. The arguments to the method are examined, and matched up with the arguments that a specific version of the requested method accepts.
Now can you predict output of the following program?
int i=10;
doSomething(10);
public void doSomething(double num);
public void doSomething(Integer num);
Which method is called? In a pre-Tiger environment, this is easy to determine. The int is widened to a double, and doSomething(double num) is called. However, in a Tiger environment, it would seem that boxing would occur, and doSomething(Integer num) would be what the method invocation would resolve to. While that's reasonable, it is not what happens.
Imagine writing a program like this, compiling and testing it in Java 1.4, and then recompiling it under Tiger. Suddenly, things start going haywire! Obviously, this isn't acceptable. For that reason,method resolution in Tiger will always select the same method that would have been selected in Java
1.4. As a rule, you really shouldn't mess around with this sort of overloading anyway, if at all possible. Be as specific as possible in your method naming and argument lists, and this issue goes away.
In Tiger, because of these restrictions, method resolution is a three-pass process:
1) The compiler attempts to locate the correct method without any boxing, unboxing, or vararg invocations. This will find any method that would have been invoked under Java 1.4 rules.
2) If the first pass fails, the compiler tries method resolution again, this time allowing boxing and unboxing conversions. Methods with varargs are not considered in this pass.
3) If the second pass fails, the compiler tries method resolution one last time, allowing boxing and unboxing, and also considers vararg methods.
4) In Chapter 8 Static Imports in section 8.4 Importing Multiple Members with the Same Name it states
a) Suppose you import the sort( ) method from the java.util.Arrays class:
import static java.util.Arrays.sort;
There are 18 different versions of this method, and you get all of them via overloading. However,let's also assume that you also need the Collections.sort( ) methods as well (there are two versions of that one). Since this method takes different sets of arguments than any of the 18 versions you've already imported into your namespace, just add another import statement:
import static java.util.Arrays.sort;
import static java.util.Collections.sort;
b) Now the compiler will actually
decide, based on your arguments, which method, and even which class, to use to process your method call. Pretty cool!
5) a) In Chapter 10 when we navigate to "10.1 Handling Uncaught Exceptions in Threads" section it states that
Normally a Java thread (represented by any class that extends java.lang.Thread) stops when its run( ) method completes. In an abnormal case, such as when something goes wrong, the thread can terminate by throwing an exception. This exception trickles up the thread's ThreadGroup hierarchy, and if it gets to the root ThreadGroup, the default behavior is to print out the thread's name,exception name, exception message, and exception stack trace.
To get around this behavior (at least in Java 1.4 and earlier), you've got to insert your own code into the ThreadGroup hierarchy, handle the exception, and prevent delegation back to the root ThreadGroup. While this is certainly possible, you'll have to define your own subclass of ThreadGroup, make sure any Threads you create are assigned to that group, and generally do a lot of coding that has very little to do with the task at hand—actually handling the uncaught exception.
Tiger simplifies all this dramatically, and lets you define uncaught exception handling on a per-Thread basis.
Luckily,The java.lang.Thread class defines a nested interface in Tiger, called Thread.UncaughtExceptionHandler. You can create your own implementation of this interface
and pass it to your target Thread's setUncaughtExceptionHandler( ) method (also new in Tiger).
public class BubbleSortThread extends Thread {
private int[] numbers;
public BubbleSortThread(int[] numbers) {
setName("Simple Thread");
setUncaughtExceptionHandler(
new SimpleThreadExceptionHandler());
this.numbers = numbers;
}
public void run() {
int index = numbers.length;
boolean finished = false;
while (!finished) {
index--;
finished = true;
for (int i=0; i<index; i++) {
// Create error condition
if (numbers[i+1] < 0) {
throw new IllegalArgumentException(
"Cannot pass negative numbers into this thread!");
}
if (numbers[i] > numbers[i+1]) {
// swap
int temp = numbers[i];
numbers[i] = numbers[i+1];
numbers[i+1] = temp;
finished = false;
}
}
}
}
}
class SimpleThreadExceptionHandler implements Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread t, Throwable e) {
System.err.printf("%s: %s at line %d of %s%n",
t.getName( ),
e.toString( ),
e.getStackTrace( )[0].getLineNumber( ),
e.getStackTrace( )[0].getFileName( ));
}
}
First, there is a rather odd condition thrown into the sorting algorithm: if an int less than zero is in the supplied array, an
IllegalArgumentException is tossed out. Second, to handle this (rather odd) case, an implementation of Thread.UncaughtExceptionHandler is defined, which prints out some additional information about the problem, including a line number and filename.
Finally there are many good examples of how tiger introduced enhanced lot of thread related classes like ConcurrentHashMap etc but frankly i am very poor in Multithreading except for few basics in Threads.
Hence you may try your luck by peeing code inside Doug Lea's fav subject.
Any comments most welcome.
No comments:
Post a Comment