Java in a Nutshell, 3rd Edition by David Flanagan Unconfirmed error reports are from readers. They have not yet been approved or disproved by the author or editor and represent solely the opinion of the reader. This page was updated June 12, 2002. Here's the key to the markup: [page-number]: serious technical mistake {page-number}: minor technical mistake : important language/formatting problem (page-number): language change or minor formatting problem ?page-number?: reader question or request for clarification UNCONFIRMED errors and suggestions from readers: (7) under security section, last paragraph, last sentence; If Java's security is not yet perfect, it is has been proven strong enough for practical day-to-day use and is certainly better than any of the alternatives. should be: If Java's security is not yet perfect, it has been proven strong enough for practical day-to-day use and is certainly better than any of the alternatives. [26] top of page; The text says: "Floating-point literals cannot be expressed in hexadecimal or octal notation" But doing something like: double d = 0xFFFFFFFC; compiles just fine {39} line 10 byte b = ~12; // ~00000110 ==> 11111001 or -13 decimal this should read: byte b = ~12; // ~00001100 ==> 11110011 or -13 decimal {40} first line of 2nd paragraph; The operator shifts ... should read The >> operator shifts ... {40} top of 2nd paragraph; Signed Right Shift () should read Signed Right Shift (>>) [59] while/try/finally pseudocode just ABOVE the heading "Methods"; On page 51, in a footnote, the author acknowledges that the obvious, naïve rewriting of a for loop as a while loop is incorrect, because it doesn't take into account the effect of a possible continue statment in the loop body. On page 53, in the discussion of the continue statement, he elaborates, explaining that a continue statement in a for loop body does not bypass the increment expression, as it would in the naïve rewriting into a while loop. This lays the foundation for the error he commits later. On page 59, where the error actually occurs, the author attempts to rewrite a for loop into a genuinely equivalent while loop, with the help of a try/finally construct. Specifically, he rewrites for( initialize; test; increment ) statement into initialize; while (test) { try { statement } finally { increment; } } However, this is not a genuinely equivalent formulation of the loop. The author is correct that a continue statement in the body of the statement will now be intercepted by the try/finally structure and thus not bypass the increment. Unfortunately, a try block intercepts more than just continue, break, and return. It also intercepts exceptions (which most programmers would consider its main purpose, I think). If the statement in the code above throws an exception (outside the scope of an enclosing try block inside the loop body), the for loop version of the loop will NOT execute the increment code "on its way out", but the putatively equivalent while loop version WILL execute the increment code before propagating the exception. I would have considered the fact that a Java for loop cannot be exactly re-written as a Java while loop to be a very minor oddity of the language, and had I been the author, I would have given it at most a one-sentence comment in passing. Therefore I was inclined at first to call this a "minor technical mistake". However, the author chose to dignify this point with an extended treatment stretching across several pages, and made it the subject of his ONLY (pseudo)code example in the entire discussion of try/catch/finally. Therefore I have to rank the failure to observe that try blocks catch exceptions (which, I reiterate, is what most programmers think they are for in the first place) to be a serious technical error in the discussion of this feature of the language. To remedy this, I would suggest that the author give up the effort to translate for into while (an exercise most programmers wouldn't care to perform anyway, even if they could), mention the discrepancy only once (in a brief sentence in the description of the for loop), and dedicate the space in the try/catch/finally discussion to an example that involves exceptions rather than continue. I would like to say that overall I have found this book to be exceptionally well organized, and in the main it does an excellent job of transmitting an enormous amount of detailed technical information concisely and efficiently, and almost always (so far as I have observed) accurately. This book has been extremely valuable to me. It is partly because of the generally high quality of the material that I thought it was worth while to point out this one failing. (128) 4th line ; The 4th line of example 3-11 on page 128 reads: Linkable current; = head; I don't think this will compile. I am pretty sure this should read: Linkable current; {188} bottom; Example 10-1 ShowComponents, 2nd edition Component elements are never added to the components vector so the panel comes out blank. To correct, the very bottom of the code should read: continue nextarg; } } System.err.println("Warning: No such property: " + name); } components.addElements(component); // this line added } return components; } } {225} middle; The okay and cancel buttons pop down the dialog but do not destroy it. If the user trys to bring the dialog up a second time, it appears to hang. Ad ding the dispose() command after the hide() command fixes the problem. okay.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { hide(); dispose(); } }); cancel.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { selectedFont = null; hide(); dispose(); } }); (271), 1st line after "Running the applet" - spelling error: "knruow" instead of "know". {330?} lines 212 and 214 of ExecuteSQL.java; The ExecuteSQL sample code uses the getObject() method to obtain a generic col umn value and then the toString() method of class Object is used to print it. This can lead to mismatches between the column width (obtained earlier with ge tColumnDisplaySize()) and the actual value being printed. One such case is a D OUBLE datatype -- a longer value may be stored than what is returned as the di splay size. A superior approach to using getObject().toString() is to use the getString(i) method which the ResultSet implements just for this purpose and w hich should return a length compatible with the display size. {297} FilterOutputStream; The text describing FilterOutputStream says, "This class ... must be subclassed to perform some sort of filtering operation and may not be instantiated directly." This is untrue. Although FilterInputStream cannot be instantiated, because its only constructor is protected, the same is not true of FilterOutputStream, whose constructor is public. Although instantiating a FilterOutputStream is not very useful (the Sun 1.4 documentation says, "The class FilterOutputStream itself simply overrides all methods of OutputStream with versions that pass all requests to the underlying output stream. Subclasses of FilterOutputStream may further override some of these methods as well as provide additional methods and fields."), it can be done. The following code creates the file "foo.out" in the current directory: import java.io.*; public class foo { public static void main(String[] unused) throws IOException { FilterOutputStream fos = new FilterOutputStream(new FileOutputStream("foo.out")); fos.close(); } } {336} StringBuffer text; The text says to use toString() to convert a StringBuffer to a String. Doing this copies the entire buffer to a string, and not just the contents. Using substring(0) will create a String containing only the contents of the StringBuffer. See also: Bug Parade: 4259569 StringBuffer.toString() can cause large memory usage [360] java.lang.Runtime Description does not list two new exec methods. See http://java.sun.com/j2se/1.3/docs/api/java/lang/Runtime.html [384] 2rd paragraph in intro to Field class; It should be stated that, for static fields, the Object parameter of the get.. .() methods is ignored, and null is the correct and valid parameter in these c ases. (A similiar statement is given for the set() method, but it also only states t hat "no object need be specified", which in fact is not possible, of course, s ince the methods all require one Object parameter; null will work here also.) (393) 1st Paragraph (under BigInteger heading), Line 5; In the book, on Page 393, Line 4: "The compareTo() method compares to BigInteger objects and returns 1, 0, or 1 to indicate the result of the comparison.' This is incorrect (most likely a typo). The compareTo() method returns -1 (MINUS ONE), 0 or 1 as. >From Sun's JDK 1.2 Javadoc: "compareTo public int compareTo(BigInteger val) Compares this BigInteger with the specified BigInteger. This method is provided in preference to individual methods for each of the six boolean comparison operators (<, ==, >, >=, !=, <=). The suggested idiom for performing these comparisons is: (x.compareTo(y) 0), where is one of the six comparison operators. Parameters: val - BigInteger to which this BigInteger is to be compared. Returns: -1, 0 or 1 as this BigInteger is numerically less than, equal to, or greater than val." Here's a simple test and it's output: import java.math.BigInteger; /** * Java In a Nutshell Book Errata (Page 393) * * @author moshe.nativ * @version 1.0 */ public class TestErrata { /** Creates new TestErrata */ public TestErrata() { } public static void main(String[] args) { BigInteger x = new BigInteger("1"); BigInteger y = new BigInteger("2"); BigInteger z = new BigInteger("2"); // Compare "1" and "2" System.out.println("x compareTo y returns " + x.compareTo(y)); // Compare "2" and "2" System.out.println("y compareTo z returns " + y.compareTo(z)); // Compare "2" and "1" System.out.println("y compareTo x returns " + y.compareTo(x)); } } Output: x compareTo y returns -1 y compareTo z returns 0 y compareTo x returns 1 {494} last paragraph; [2/00 printing; this is the description of java.text.SimpleDateFormat] The last sentence on the page reads "Any characters in the format string that do not appear in this table appear literally in the f ormatted date." This is not quite true: alphabetic characters (or rather, the ASCII subset of alphabetic characters, that is, uppe r and lowercase letters A-Z) are reserved even if they do not have any assigned meaning in the table. If an unassigned letter appe ars unquoted in a format string, any attempt to use that format string will result in an IllegalArgumentException being thrown with the message "Illegal pattern character 'X'". Fortunately, although not mentioned in the book, it is possible to include such char acters - along with actual pattern characters from the table - literally in the format string, by surrounding them with single quot ation marks. For example, you can use the string "yyyy-MM-dd'T'HH:mm:ss" to get the ISO 8601 recommended format for combined date/ time strings. (791) Example 26-7. static initializer for class; The sample code uses System.load("libhello.so"), whereas the explanation on the previous page (790) mentions the use of System.load Library(). The use of System.load, only works if the path to the shared library (or dll under windows) is fully qualified and absol ute. Consulting Java documentation, I found that it would be more portable to use System.loadLibrary("hello") which uses the appropriate operating system path, and composes the specific shared object name depending on the underlying OS, i.e. libhello.so under UNIX li ke OSs and hello.dll under Win32. {index} Section "T" missing references to the Java keyword "this" This keyword is an important core part of the Java language. I think because it's also a common word, it may have been dropped by mistake.