Learning Java, 3rd Edition by Patrick Niemeyer, Jonathan Knudsen The 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. Here's a 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 This page was updated February 21, 2008. UNCONFIRMED errors and comments from readers: {36} Halfway down the page; Missing "import javax.swing.*;" before "import java.awt.*;". If you place the HelloComponent in its own file the java compiler will not find JComponent as it is not in the java.awt name space. {36} 2 lines of code 2/3rds down the page;; HelloComonent hello = new HelloComponent(); frame.add( hello ); should be: frame.getContentPane().add( new HelloComponent() ); -------------- This is a correction to the current errata for this page. The current errata suggests frame.add(new HelloComponent() ); which results in a run-time error, e.g.: Exception in thread "main" java.lang.Error: Do not use javax.swing.JFrame.add() use javax.swing.JFrame.getContentPane().add() instead at javax.swing.JFrame.createRootPaneException(JFrame.java:465) at javax.swing.JFrame.addImpl(JFrame.java:491) at java.awt.Container.add(Container.java:307) at HelloJava.main(HelloJava.java:19) For java version "1.4.2-02" Java(TM) 2 Runtime Environment, Standard Edition (build Blackdown-1.4.2-02) Java HotSpot(TM) Client VM (build Blackdown-1.4.2-02, mixed mode) {39} diagram at top of page; The "HelloJava1" class in the diagram should be "HelloComponent." This is because in the example code, HelloJava1 never inherits from JComponent, HelloComponent does. {39} Figure 2-2; HelloJava1 is shown. This should be HelloComponent. {44} 3 lines of code 2/3rds down the page; frame.add( new HelloComponent2("Hello, Java!") ); should be: frame.getContentPane().add( new HelloComponent2("Hello, Java!") ); (The equivalent line is correct on page 42) Likewise HelloComponent2 newObject = new HelloComponent2("Hello, Java!"); frame.add( newObject ); should be: HelloComponent2 newObject = new HelloComponent2("Hello, Java!"); frame.getContentPane().add( newObject ); (probably worth checking for s/frame\.add/frame.getContentPane().add/g thoughout) {44} First and second code sections; Extracted code refers to "frame.add" when actual code on page 42 is frame.getContentPane().add... [72] code snippet near bottom of page; The example code is: package animals.birds; public class BigBird extends Bird { } The text instructs you to compile this, saying it "produces the class file BigBird.class..." The problem is, Bird isn't anywhere in the classpath, so this doesn't compile. The error is "cannot find symbol...symbol:class Bird" I searched the entired CD for a Bird class and it does not exist. {76} all three command line examples; The text shows three examples of using the jar utility: % jar xvf spaceblaster.jar % jar xvf spaceblaster.jar filename % jar tvf spaceblaster.jar None of these examples actually work in practice, because the jar option list needs to be prefixed with a "-". For example, the correct version of the first command line would be: % jar -xvf spaceblaster.jar {79} code snippet near bottom of page; The code snippet involves creating a socket with the IP address: 207.46.131.13. When I tried the example it failed to connect; in fact, I couldn't even ping that address. Consider using a URL that's more likely to be always-on (e.g., www.google.com). I tried www.google.com instead and it worked. {99} 4th paragraph; The last sentence ends with "as does a method with a conditional that the compiler can tell will NEVER be fulfilled:" (emphasis mine) It then shows the code snippet: if (1 < 2) return; // unreachable statements The problem with this sentence is that the condional will ALWAYS be fulfilled, because it will always be true that the integer constant 1 is less than the integer constant 2. {120} in first code snippet array of primes; The number 1 is not a prime. At least according to all the number theory books I have read. [121] Code example near middle of page; The authors give a code snippet for creating an array of buttons: Button [] keyPad = new Button [10]; for (int = 0; i < keyPad.length; i++) keyPad[i] = new Button(Integer.toString(i)); Soon after, they say "Here we'll use it to print all the values we just assigned:" for (int i : keyPad) System.out.println(i); This won't work because keyPad is an array of objects, not integers. I verified with the java compiler that this doesn't compile. I get "Type mismatch: cannot convert from element type button to int" (122) second paragraph from the bottom; The sentence that reads "The syntax looks just like the initialization of an array in a variable declaration" isn't entirely true. Their anonymous array parameter looks like this: new Animal [] { pokey, boojum, simon } whereas the initialization of an array in a variable declaration would look like this: new Animal [] = { pokey, boojum, simon } Consider changing "just like" to "similar to". {127} 2nd paragraph; The last sentence in the paragraph says "In either case, if you don't initialize a variable when you declare it, it's given a default value appropriate for its type (null, zero, or false)." "zero" is typeset in constant width font. According to the book preface, in the "Conventions Used in This Book" section, constant width is for: - anything that might appear in a Java program - tags in HTML or XML - keywords, objects and environment variables I don't believe the author's intent is to say there is a Java keyword "zero", or a constant named "zero", or an object with the name "zero", etc., which some variables are initialized to. Instead, I believe they just mean the numeric value zero: "0". Consider changing "zero" to "0", or eliminating the constant width font and using regular font for "zero", so as to avoid implying that the string "zero" has special significance in Java code. {130} 3rd paragraph; The problematic sentence reads: "This means that if you change a static final variable, you may have to recompile all code that uses that class (this is really the only case where you have to do that in Java)." The parenthetical seems wrong. What if you change the name of a method--isn't it possible that you would have to recompile all clients, if they were callers of that method? Or what if you changed the type of a public member variable? Couldn't that also require a recompile of all clients--if all the clients relied on it? The parenthetical is at best ambiguous and at worst false. [138] Table 5.1; The entries in the left column should not be capitalized. A Void is not a void, and there's no such thing as an Int in the core language. {138} Table 5.1; The table contains two columns: one for primitive types and one for wrapper classes. The names for primitive types are capitalized. This is a mistake because Java primitive type names are case sensitive, and always begin with a lower-case letter. (146) first code sample and second paragraph; The instance variable in the first code sample for class Car is "default_doors" while in the first sentance of the second paragraph (immediately following the code sample), the variable is called "defaultDoors". In the second code sample the variable is renamed to "DEFAULT_DOORS". The usage in the second sample is consistent with Java naming conventions. The usage in the first sample is not consistent with Java naming conventions. However, the usage in the second paragraph is consistent with Java naming conventions. [151] 2nd paragraph; The sentence reads: "Because enumerations are static values, they can be imported with the new Java static import, saving us some typing:" Then follows this code snippet: import mypackage.Weekday.*; But this isn't really a static import. It should be: import static mypackage.Weekday.*; {151} 5th paragraph; The text explains an enum's compareTo() method as returning an integer greater than zero when the target enum is greater than the reference enum (in the enum ordering). Then the authors present the code snippet: Level level = Level.HIGH; Level anotherLevel = Level.LOW; if (level.compareTo( anotherLevel ) > 0 ) // true doSomething(); The "true" comment would lead one to believe that compareTo() returns an integer greater than zero in this case. Since anotherLevel is the target enum, and level is the reference enum, this implies that Level.LOW is greater than Level.HIGH in the enum order. It seems odd that LOW would be higher than HIGH, until one realizes that this condition could be true, given the (counter-intuitive) enum order: { HIGH, ..., LOW }. But since we aren't told in the example what the actual enum order is, it's not possible to determine whether the "// true" comment is in fact accurate. It would be helpful in this case to either include the enum declaration, provide more detail in the text, or perhaps switch the places of the Level.HIGH and Level.LOW tokens in the code. {173} 2nd paragraph; The text reads: "The java.io.Serializeable interface is a good example. Classes that implement Serialize don't have to add any methods or variables." The problem is the text first calls this interface Serializeable, but then calls it Serialize. The correct name is Serializeable. (174) 5th paragraph; The paragraph begins: "The source code for a Java class is organized into compilation units. A simple compilation unit contains a single class definition and is named for that class." Isn't this a contradiction? First it says: "...a Java class", that is ONE Java class, "is organized into compilation units", that is, MORE THAN ONE compilation unit. Then it says "A simple compilation unit contains a single class definition", that is, ONE Java class is organized into ONE compilation unit. A class must either be organized as one compilation unit, or more than one, but not both at the same time (unless the one compilation unit is an aggregation of many sub-compilation units--although the text makes no mention of this). (178) 5th paragraph; The text reads: "By treating an object in some respects as a "black box" and ignoring the details of its implementation, we can write stronger, simpler code..." "stronger" code is an odd choice of words here. What is "stronger" code? I've heard it said that encapsulation improves maintainability, modifiability, reusability, and even testability, but never that it makes code "strong." [185] code snippet near bottom of page; In the example code, the next() method of the inner Iterator class calls hasMoreElements() to determine whether there is another Employee in the list to return. However, the Iterator class does not define a hasMoreElements() method, although it does define a hasNext() method. In this code, hasNext() would work as the condition, so this is probably what the authors were intending. However, the code snippet also contains an ellipses, and hasMoreElements() theoretically could have been defined there as a method of EmployeeList. However, if hasMoreElements() were a method of EmployeeList, it wouldn't have access to the iterator's state, and therefore wouldn't be able to determine whether there was another iteration candidate available. So this probably isn't what the authors intended. (185) Bottom of page in code snippet; I believe that the hasMoreElements() method under the next() implementation could actually be hasNext(). Not certain if that was meant to be or not. (189) In first code snippet; The boolean hasMore() method should actually be boolean hasNext(). Also, once again I believe the hasMoreElements() method should be hasNext(). (210) Last line of first code snippet; I believe the myInterface.anyMethod() call should be interfaceProxy.anyMethod(). I couldn't see a myInterface instantiation of the object. {228} 5th (last) paragraph; In the last code example, in the try block, the code should read "new ExceptionTester().test(new ClassNotFoundException());" rather than "new E().test(new ClassNotFoundException());". (246) 3rd paragraph, 2nd Sentence; Says: It tests, first, whether window.getComputedStyle is supported, and if not, tests for getComputedStyle. Should say: It tests, first, whether obj.currentStyle is supported, and if not, tests for window.getComputedStyle. (267) public class Producer implements Runnable{; Was under the assumption that the Producer class was an inner class of Consumer (no import statement(s) before class declar... I removed the public class modifier and the app. ran as expected; however, I checked the examples that came on the CD and see that they were separate class files; I'm not sure if I just read it wrong or if the example is a little unclear. (302) second code sample in 10.2.2 Strings From Things; // Equivalent, e.g., "Sun Dec 19 05:45:34 CST 1969" shows 12/19/69 as a Sunday, but you may recall that it was actually a Friday. Picky? Me? (341) It's missing!; My copy brought several months ago in the UK contains pages 1-340 (ie chapters 1-10) then pages 293-340 (chapter 10 *again*) then continues from page 389 (chapter 12), chapter 11 is missing :( Other chapters might be affected I've yet to read them. I went to my local bookstore today to get a correct printing but all copies they had were also affected - they have contacted the distrubitor and I am awaiting a phone call to see if they can get a correct printing. [360] Description of List Interface; public void add( E element ) should be public boolean add( E element ) [407] 1st full paragraph; In the book it says "getPath() returns the directory information without the filename" I did some testing and it seems getCanonicalPath() - returned the full path, plus filename getAbsolutePath() - returned the full path, plus filename getPath() - only returned the filename (407) Code listing, bottom of the page; Collections.sort(l); should be Collections.sort(list); {472} 5th line of code: WorkRequest , WorkListener listener); The line WorkRequest request , WorkListener listener) should read final WorkRequest request , final WorkListener listener) The example code given on this site is correct, but the book leaves out both instances of the word "final". [472] MyClientAsync code; When the section entitled "An RMI Example" starts on page 465, the Remote interface is called ServerRemote. It also called ServerRemote in the middle of page 470. However, in the MyClientAsync.java code at the bottom of page 472 it is called RemoteServer. The example code given on this site also uses RemoteServer instead of ServerRemote. [473] First paragraph down to and including the result listing in the middle of the page; First, since we created a new client class, the line that reads % rmic MyClient MyServer MyStringIterator should read % rmic MyClientAsync MyServer MyStringIterator The book states that the output you receive when you run the client is: Sun Mar 5 23:57:19 PDT 2006 4 Foo Bar Gee Async work result = 10000 However, the actual result of running MyClientAsync is: call done... Async work result: 10000 The first sentence of the first paragraph on page 473 reads "We use getList() to get the iterator from the server and the loop, printing the strings." This is not the case in either the book or in the example code. StringIterator is never used in the code given for MyClientAsync.java. In fact, the example code given on this site does not even have the getList() method for MyServer.java from the bottom of page 471. To get results similar to what the book shows, the following code needs to be added before the "server.asyncExecute" line in the code given near the bottom of page 472: System.out.println(server.getDate()); System.out.println(server.execute(new MyCalculation(2))); StringIterator iterator = server.getList(); while (iterator.hasNext()) System.out.println(iterator.next()); [597] code example; On page 596 (bottom-half) the text reads as follows: ... The following example, DateSelector, creates a JSpinner showing the current date and time. It allows the user to change the date in increments of one week, ... It did not (in my case), not until I had changed the spinner's editor, as follows: ... (from the main method) JFrame frame = new JFrame("Date Selector 1.0"); Calendar now = Calendar.getInstance(); Calendar earliest = (Calendar)now.clone(); earliest.add( Calendar.MONTH, -6 ); Calendar latest = (Calendar)now.clone(); latest.add( Calendar.MONTH, 6 ); SpinnerDateModel model = new SpinnerDateModel( now.getTime(), earliest.getTime(), latest.getTime(), Calendar.WEEK_OF_YEAR); final JSpinner spinner = new JSpinner(model); spinner.setEditor(new JSpinner.DefaultEditor(spinner) ); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ i.e. I was forced to "deactivate" the DateEditor. [625] Example on page Formatting fields; SimpleDateFormat ( "mm/dd/yy"); should be ( "MM/dd/yy"); mm is minutes. MM is Months. (668) In constructor for class Border2; In adding the EAST layout "add(p, BorderLayout.E*);" should read " add(p, BorderLayout.EAST);" [721] End of first paragraph; The book states that "All Swing components implement Printable for you; you can override it in your own components to customize their printed appearance or do arbitrary printing." This is not true. Swing components do not implement Printable and cannot be directly used as such with the Print Service API. [850] SAX Example -Chapter 24; Page number might be incorrect. I am viewing this on the Oreilly book shelf and cannot see page numbers. This is the SAX example in chapter 24. I have downloaded the code as well as copy and pasted and I am getting the same error: SimpleElement: No attributes allowed. (872) 1st paragraph ("Building the Ant-Based Examples"); The penultimate sentence of this paragraph directs users to build the magicbeans.jar file from Chapter 22 by navigating in Eclipse's Package Explorer pane to "ch22/learningjava/build.xml". The path to this file is actually "ch22/magicbeans/build.xml". (903ff) entire index - especially pages 903-907; 927-934; etc.; More of an annoyance than an error: when looking for something in your index, I often at first mistake some lengthy sub-index list (e.g. those under the index entries for "classes" and "methods") for the top-level index itself. This could easily be avoided if you would adopt the convention of preceding each sub-index entry with a dot for each level of indentation - this making it immediately obvious the level of sub-index for any line. For example,the index entries under "class" would look something like: classes, 5, 563-569 . 2D API, 689 . . drawing, 712-720 . . filling shapes, 700 etc. . . viewing images, 707-712 . AbstractFormatter, 626 . AbstractTableModel, 645 With this sort of visual clue, I would not be as likely to waste time by opening to the middle of the index and begin searching alphabetically for a top-level entry in the middle of the "classes" sub-entries.