Archive-name: computer-lang/java/programmers/faq Posting-Frequency: weekly Last-modified: 1999/05/19 URL: http://www.afu.com/javafaq.html Frequently Asked Questions (with answers) for Java programmers _____________________________________________________ ________| |________ \ | Java Programmers FAQ http://www.afu.com | / \ | Last modified May 19, 1999 Peter van der Linden | / / |_____________________________________________________| \ /___________) (__________\ The Java FAQs here are intended for people who already have some programming experience, though maybe not in Java. Go to the FAQ home page at http://www.afu.com for other Java information and downloads, and the most up-to-date copy of the FAQ. Report FAQ updates to faqidea at the address afu.com. ------------------------------------------------------------------------ The sections of the Java FAQ are: * 1. Java Book Information * 2. Getting Started * 2.5 Portability * 3. General Information * 4. Compilers and Tools * 5. Compiler Messages * 6. Java Language issues * 7. I/O * 8. Core library issues * 9. Computer Dating * 10. AWT * 11. Swing * 12. Browsers * 13. Applets * 14. Multi-Media * 15. Networking * 16. Security * 17. For C, C++ Afficionados * 18. Java Idioms * 19. Java Gotcha's * 20. Further Resources * 21. Acknowledgements ------------------------------- 1. Java Book Information 1. (sect. 1) How do I choose a Java book? [*] There is no one right answer to "which is the right Java book for me?" A lot depends on what you already know, and how you like to learn. If you already know how to program in another language, and Just want to learn Java, consider Just Java 1.2 from the FAQ author. Everything in one handy volume (language basics, Swing, networking, I/O, database access, etc) and it comes with a CD with tons of Java applets, games, applications, compiler tools, complete with source. Includes a Java compiler for Windows, the Mac, Linux, and Solaris (sparc and x86). look at http://www.amazon.com for details If you or your manager instead want a briefing on Java technology, thin clients, XML, CORBA, TCP/IP, Java beans, etc., take a look at Not Just Java from the FAQ author. [Image] This book doesn't teach you how to program in Java; it tells you why you might want to, and what kind of systems are most suited to Java. It describes E-Commerce and XML. look at http://www.amazon.com for details Here are the points to check when evaluating a programming book. o Above all, make sure that it is a Java book. If it comes with a CD, check that it has a Java compiler on it, not a J++ compiler. VJ++ does not implement Java 2. VJ++ is also a different language in some important ways, and is missing the latest Java libraries (Swing, Collections, JFC, RMI). If your interest is Java, leave the downrev VJ++ book back on the shelf. o Does the book cover the current level of Java, which is Java 1.2 (aka Java 2)? Look up "JApplet" in the index. If it's not there the book doesn't cover JDK 1.2, and you probably need a more up-to-date book. o Check that the book has a reasonable number of figures, diagrams, and illustrations. It is not possible to explain how to program a window system without pictures and diagrams. Other topics benefit from pictures, too. o Check what the book says about itself. Is it a reference work, intended for Java-experts to look things up in? This is the role of "Java in a Nutshell", and "The Java Almanac". Do you need that, or are you looking for a book that teaches by examples and explanations? o Read Peter Norvig's excellent advice on learning programming languages and being a programmer. o Appraise your own level of programming knowledge: are you proficient in some other language, or are you learning programming as well? Does the book cater to your level? o Read a section of the book. Does the style keep you interested, as it educates you? Will you get bored if you read many pages? Is the book too long for your initial purpose? Browse Amazon online and see what other readers say about the text. o If the book comes with a CD, how much other software is on the CD? You want at least a Java compiler plus all the examples from the book. Does the Java compiler work on your platform (Mac, Linux, etc)? Additional software on the CD is a big plus, as we learn the most from reading other people's code. Most people buy one book to begin with, then four or five more as they wish to learn more, and about more specialized topics. The FAQ author has purchased and read probably 60 Java books in the last three years. 2. (sect. 1) Where can I find a some lists of Java books and book reviews? [*] Here are some good ones: http://www.hszk.bme.hu/~werner/Java2BookReviewBETA.html and http://www.geocities.com/RainForest/Canopy/4774/Java/education.html also http://www.flathill.com/languages/java/ also http://www.fastgraph.com/books/java.html also http://teamjava.com/links/tj-srv.cgi?MUF=0,tj-booklist.muf also http://www.javaworld.com/javaworld/books/jw-books-index.html (an exhaustive list -- takes a long time to load). ------------------------------- 2. Getting Started 1. (Sect. 2) What is the easiest way to get started with Java? [*] Follow these steps. 1. Look at the books section of the FAQ to see what kind of book will suit you. There is no one perfect Java book. The right book depends on the style, pace, and detail that you are comfortable with. Amazon has good info and reviews on Java books. 2. Download a free Java compiler from http://java.sun.com Service packs for Solaris (if any are needed) can be found at: http://www.sun.com/solaris/jdk/download.1.2.1_02/en/sparc/1.2.1_02_sparc_jdk_patches.tar 3. Read the free Java tutorial, at http://java.sun.com/docs/books/tutorial/index.html (bookmark it, so you will easily find it again). 4. Avoid Microsoft's J++ product, which is in the words of Microsoft's own employees "polluted Java". It is designed to undermine standard Java, and has many deliberate platform-specific incompatibilities, including new keywords in the language. 5. To get some tips on getting started with a programming homework assignment, look at http://www.concentric.net/~pats/beginner.html. 6. Search this FAQ when something in Java confuses you. Many people have trodden this path before you, and the FAQ contains the accumulated knowledge and pointers to other references. 2. (Sect. 2) Why doesn't my "Hello World!" program compile? [*] There are three basic possibilities: 1. Are you successfully running the javac compiler? Try javac -garbage to see if it prints out a message about correct usage. If not, invoke javac using the full pathname, or set your PATH variable to include the directory that contains javac. 2. Is the CLASSPATH environment variable used correctly? In JDK 1.0.2, beginners had to set CLASSPATH, and it had to include both system libraries and your programs. In JDK 1.2, CLASSPATH is no longer needed for system libraries. You do want CLASSPATH to point to the directories containing any "user classes" you're using. Getting started, you will probably want at a minimum "." (the current directory) in your CLASSPATH. When CLASSPATH is wrong, javac will tell you it can't find definitions for classes you reference in the source file. For information on setting up the CLASSPATH, see Question 1.3 3. Is the source correct? Here javac will emit error and warning messages. See the questions on compiler messages in the next section. 3. (Sect. 2) Why doesn't my "Hello World!" program run? [*] There are five common mistakes that cause your VM (java or browser) to be unable to execute your classes 1. First, did you write an applet or an application? If an applet, you must make sure that you did extend the java.applet.Applet class. Your starting code should be in the init routine. If you wrote an application, your starting code should be in a routine called main(). Don't mix applets with applications until you have a bit more experience. 2. You must declare your main class as "public". If you don't, unfortunately some systems will still run the code, while others won't. The main class is either the one with the main() method in, or in the case of an Applet, the class that extends Applet. 3. Your class name and the file name must match exactly, even letter case. If your class is HelloWorld, your source file must be HelloWorld.java and your class file will be "HelloWorld.class". 4. If an Applet, and you used ftp to transfer the classes to the server, you must ftp all the classes, and you must use BINARY transfer not ASCII. 5. Errors in setting the CLASSPATH (and/or codebase in an applet). Even seasoned programmers do this, pointing inside a package or mistyping a path delimiter. For information on setting up the CLASSPATH and codebase, see Question 1.3 If you are running an applet, you should check the following further points: 1. If your class isn't loading, recheck the HTML applet tag. 2. If you are writing to System.out, the results are displayed in the browser's java console. You'll have to create a window if you want one. 3. Make sure your browser is compatible with the Java language features you are using. Internet Explorer and older versions of Netscape's browsers have omitted some support for JDK 1.1. Try your applet in the JDK's appletviewer first. 4. How do I set the CLASSPATH? [*] The CLASSPATH environment variable tells the VM's class loader where to find classes that are directly or indirectly invoked, including system classes. The CLASSPATH variable should o point to the directory containing the class file, for classes not in a package. o point to the package root, for classes in a package. The root is the parent directory of the highest directory of the package name. o point directly to the zip or jar file, if the classes are in an archive file. You may have to list the contents of the archive to get the correct package/path name for the class. Separate multiple paths and archives with a platform-specific separator, ";" for Windows; ":" for Solaris Also remember that o Browsers set the CLASSPATH to the directory of the HTML file, plus the codebase parameter. o in JDK 1.1 and after, java adds the system classes (lib/classes.zip), so you don't have to. o JDK 1.2 versions of java add "." (current directory), so you don't have to. (But jre doesn't - see below.) o JDK 1.1 jre tool does not use the CLASSPATH variable or assume the current directory. (On Solaris, CLASSPATH does work.) From JDK 1.1.2 on, it is generally an error if the user sets the CLASSPATH to include classes.zip. But CLASSPATH will need to be set to o point to the roots of the programmer's own packages, and third party packages o use rmic o use unbundled packages like Swing in JDK 1.1 o point to native code libraries. For the sake of consistency, the minimal classpath setting should be: " set CLASSPATH=. " Below you'll find examples for Windows (basic application class), Solaris (package class), javac (multiple packages), and browsers (applet codebase). ----------------------------- Here's some Windows examples, assuming the application class is D:\src\tries\HelloWorld.class ## JDK 1.1, no CLASSPATH set > cd D:\src\tries\ > D:\jdk11\bin\java HelloWorld # OK: 1.1 implicitly adds classes.zip and current dir > D:\jdk11\bin\jre HelloWorld # FAILS: jre does not automatically add . to CLASSPATH > cd D:\ > D:\jdk11\bin\jre -cp D:\src\tries HelloWorld # OK: jre adds classes.zip, -cp adds class directory ## JDK 1.1, CLASSPATH set > set CLASSPATH=D:\src\tries > D:\jdk11\bin\java HelloWorld # OK: java using CLASSPATH > D:\jdk11\bin\jre HelloWorld # FAILS: jre does not use CLASSPATH (on Windows) ## JDK 1.0.2, CLASSPATH set > set CLASSPATH=D:\jdk102\lib\classes.zip;D:\src\tries > D:\jdk102\bin\java HelloWorld # OK: > set CLASSPATH=D:\jdk102\lib\classes.zip;D:\src\tries > D:\jdk11\bin\java HelloWorld # FAILS: exception in thread NULL - wrong system classes ----------------------------- Here's some Solaris examples, assuming the application class is /usr/src/com/devjoes/killer/App.class and it is in package com.devjoes.killer: # JDK 1.1, no CLASSPATH set $ /usr/bin/jdk11/bin/jre -cp /usr/src com.devjoes.killer.App # OK: $ cd /usr/src/com/devjoes/killer/ $ /usr/bin/jdk11/bin/java App # fails: class name and path are wrong $ CLASSPATH=/usr/src/ $ /usr/bin/jdk11/bin/java App # fails: class name is com.devjoes.killer.App $ /usr/bin/jdk11/bin/java com.devjoes.killer.App # OK: ----------------------------- Here's some javac examples, for both Solaris and Windows, based on the following: Source files package Makes the call /usr/src/pack/Minimal.java package pack pack.sub.Try.run() /usr/src/pack/sub/Try.java package pack.sub (nothing) $ CLASSPATH="" $ /usr/bin/jdk11/bin/javac /usr/src/pack/sub/Try.java # OK: works fine $ /usr/bin/jdk11/bin/javac /usr/src/pack/Minimal.java # FAILS: can't find pack.sub.Try $ cd /usr/src $ /usr/bin/jdk10/bin/javac pack/Minimal.java # OK: finds pack.sub.Try based on . as package root $ cd /usr/src/pack $ CLASSPATH=/usr/src $ /usr/bin/jdk11/bin/javac Minimal.java # OK: finds pack.sub.Try based on CLASSPATH Now assume the killer application class /usr/src/com/devjoes/killer/FastApp.java (in package com.devjoes.killer) uses a third-party package in a jar file /usr/jars/JShapes.jar but makes no other reference to other classes. The following works fine: $ CLASSPATH=/usr/jars/JShapes.jar $ cd /usr/src/com/devjoes $ /usr/bin/jdk11/bin/javac killer/FastApp.java Finally, some applet examples. Many applets only use one class, in the same directory as the html file: <applet code=ArcTest.class height=400 width=400> To use classes in subdirectory, use the codebase parameter: <applet codebase="mysubdir/" code=ArcTest.class .. To use classes in an archive, use the archive parameter: <applet archive="applets.jar" code=ArcTest.class .. See also: JDK 1.1 ReadMe Solaris JDK 1.1 tool documentation Win32 JDK 1.1 tool documentation 5. (Sect. 2) How do I do keyboard (interactive) I/O in Java? [*] Interactive I/O in Java is very poorly supported. Programmers must piece together several library classes in non-obvious ways to get the required functionality. See the answer to Question 7.1. 6. (Sect. 2) How do I do file I/O in an applet? [*] By default, an applet can read files on the server, but not write them, and has no access to the client. This is for reasons of security. It would be very unsafe to let any old applet that you downloaded from an unknown origin on the Internet read/write your files. It would be as unwise as allowing this kind of access to an ActiveX control (which is one reason ActiveX is dead on the Internet). There are several different ways to relax the default rules. See the answer to Question 7.8. 7. (Sect. 2) How do I do I/O to the serial port on my computer? [*] Java 1.0 and 1.1 do not have a serial port API. There are several commercially-available libraries that supply the needed functionality. JDK 1.2 introduces access to the serial and parallel ports as an extension (optional extra) library. See also the answer to Question 6.3. 8. (Sect. 2) How do I do formatted I/O like printf and scanf in C/C++? [*] The java.text package introduced with Java 1.1 supports formatted I/O. See also the answer to questions 7.11, 7.12, and 17.7. 9. (Sect. 2) I have spent more debugging time finding case (upper vs lower) typos than everything else put together and squared! [*] Do not forget that your remark must be phrased in the form of a question to win on FAQ Jeopardy. In any event, it is worth reminding those new to Java that letter case really matters in Java, and that the names of public classes should exactly match (including case) the names of the files they live in. See also the answer to Question 1.1.2 10. (Sect. 2) Why do I get this compiler error: "Can't make static reference to method..."? [*] Your code probably looks something like this: class myclass { public static void main(String args[]) { myMethod(); } public void myMethod() { //some code } } The issue is this: a static method means it belongs to the class, not each individual object. If you leave the static keyword off (the usual case) as is done here with the method "myMethod()", it means that method can only be invoked on an object. But your call from main() has not told myMethod() which object it is to be invoked on. Inside a non-static method, you don't have to provide this information, as it assumes you mean the same object on which it was invoked. But when calling from a static method, you must provide the information, and you haven't - hence the error message. A common fix is to instantiate a member of the class, on which to invoke myMethod(), like this: public static void main(String args[]) { myclass m = new myclass(); m.myMethod(); } This problem is especially common when you are writing code that you want to run as an applet and as an application. Naturally, you call init() and start() from main. What you really need to do is: public static void main(String[] args) { Applet ma = new myApplet(); ma.init(); ma.start(); } 11. (Sect. 2) Why can't I do myArray.length() ? Arrays are just objects, right? [*] Yes, the Java specification says that arrays are object references [JLS 10.2] just like classes are. However, arrays cannot contain methods. Instead you have to use myArray.length, which is a data item (not a method) called "length", belonging to myArray. 12. (Sect. 2) How do I close a Java window by using the icon in the upper right hand corner of a window? [*] Create an event handler class to extend WindowAdapter. Then override WindowAdapter's windowClosing() to do the actions you want when a window's "close" action is clicked. Then add that to the listeners for that window. import java.awt.*; import java.awt.event.*; public class MyFrame extends Frame { public MyFrame(String s) {super(s);} public class WL extends WindowAdapter { public void windowClosing(WindowEvent e) {System.exit(0);} } // do your other Frame stuff } Somewhere in your initialization code, put: f1.addWindowListener( f1. new WL() ); This last syntax is not commonly known to many people yet, it's another wacky artifact of inner classes. Alternatively, combining the inner class and setting the handler in one go, you could do this: MyFrame f1 = new f("wave"); f1.addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent e) { // and/or setVisible(false) and/or dispose() System.exit(0); } }); See also the answer to questions 1.0.19, 1.0.30 and 15.7. 13. (Sect. 2) Why is b+=100; OK, but b = b+100; fails to compile? [*] You have code like this byte b = 0; Incompatible type for =. Explicit cast needed to convert int to byte. b = b + 100; // compiler error message ^ b += 100; // works OK The reason is "promotion". Arithmetic expressions are promoted to the type of the longest, floatiest operand in them, or at least to int. The first statement involves the assignment of an expression. The expression is promoted to 32 bits, and must be cast back down to 8 bits, like this "b = (byte) (b+100);". The second is an operator assignment, and the cast back to byte takes place automatically. The Java Specification says: "A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (typecast)((E1) op (E2)), where "typecast" is the type of E1, except that E1 is evaluated only once" [JLS 15.25.2] The compile-time narrowing of constants means that code such as: byte theAnswer = 42; is allowed, with no cast necessary. [JLS 5.2] 14. (Sect. 2) How do I add two Float objects together? [*] You want to write code like this Float One; Float Two; Float Hard = One + Two; but the compiler does not allow it. Java has two separate ways of representing a 32 bit floating point number, Float and float. Float is a class, that whose sole purpose is to "wrap" a floating point number so it can be treated as an object. The class does not support floating point arithmetic, because the performance would be too slow. float is a primitive type (like int) that is used for floating point arithmetic. You choose one or the other depending on your predominant use. If all you need of your floating point numbers is arithmetic, declare them to be "float". If you need to use them as objects, for example to place them in a Vector, declare them as "Float". If you need both, tough. You have to declare them one way and convert whenever you need the capabilities of the other. Your specific code can be written as: Float One = new Float(1.0); Float Two = new Float(2.0); Float Hard = new Float(One.floatValue() + Two.floatValue()); See also questions 6.n , 5.1, and 10.1. 15. (Sect. 2) How can I put all my classes and resources into one file and have java run it? [*] Use a JAR file. Put all the files in a JAR, then run the app like this: java -jar [-options] jarfile Mainclass [args...] 16. (Sect. 2) How can I see line numbers in a stack trace using JDK 1.1.6? [*] From JDK 1.1.5 on (i.e. JDK 1.1.6, JDK 1.2) the stack trace of an uncaught exception no longer has source code line numbers. It only says "(Compiled Code)". To see the line numbers where your program throws an exception, use the command line argument in JDK 1.2: java -Djava.compiler=NONE myapp This info is well-concealed in the release note at: http://java.sun.com/products/jdk/1.2/changes.html#aaa24 ----------------------------- Specify standard Java on your new PC! Your new PC can come with the most up-to-date standard version of Java, but only if you ask for it! The JavaLobby is asking PC vendors to support Java, and to ship new machines with the Java Plug-In pre-installed. See http://www.javalobby.org/servlet/PetitionServlet/pjpc Please help the Java Lobby to promote this initiative. ----------------------------------------------------------------------- Please support Java Portability. The biggest value of Java is its portability. o Portability makes it easier for companies to change/upgrade operating systems and platforms, without losing their investment in applications software. o Portability makes it easier for Java programmers to transfer their skills to new employers. o Portability makes a wider variety of software available on all computers. Software portability is very much in the interest of most software developers and customers. Even if you only use Windows 95, portability matters to you. If your software was all written in Java, it would all just run when you moved from MS-DOS to Windows 3.1 to Windows 95 to Windows 98 to Windows NT, and even on Windows CE. Instead, you typically need to buy new applications software all over again when Windows changes. Portability is not in Microsoft's interest, as it removes a revenue stream and makes it easy for users to try other operating systems. The 1998 anti-monopoly case against Microsoft revealed a Microsoft internal memo. The memo revealed that Microsoft's "strategic objective" was to "kill cross-platform Java." by "grow[ing] the polluted Java market." This is Exhibit 101 (MS7 033448) in the case. In November 1998, a Federal judge ruled that Microsoft was probably breaking its written agreement with Sun by distributing incompatible Java, and that Microsoft had to stop doing that. If portability matters to you or your users, avoid Java products from Microsoft; it is deliberately trying to sabotage it. Microsoft's own internal documents make this goal unambiguous. See http://www.usdoj.gov/atr/cases/f1700/1762.htm. See also "The Microsoft Java Dilemma" paper at http://www.geocities.com/ResearchTriangle/Node/2005/msjava.htm ----------------------------- Windows-Specific 17. Is there a Java implementation for Windows 3.1? [*] Yes. See Question 1.6 It's not that great though because Windows 3.1 has inadequate features to support great software. 18. (Sect. 2) I'm using Win95, and my DOS window won't accept filenames longer than 8.3. "This program cannot be run in DOS mode" [*] Both these problems are resolved by the same process. Assuming you're running the Win95/98 command.com, then you've changed the MS-DOS Prompt options under the "Properties" menu item. In the Properties dialog, Program->Advanced gets you a dialog. Here, make sure the "Prevent MS-DOS-based programs from detecting Windows" checkbox is UNCHECKED. If the option is checked you get exactly the kind of behavior you're seeing. The option is unchecked by default, so it must have been selected at some time in the past. Change it back to unchecked. 19. (Sect. 2) I'm using Notepad to edit my files, and how can I save them with the extension ".java"? Also, in notepad some source files have all the characters on one line. Why is that? [*] First answer: put the entire filename in quotes in the save dialog. Once you have created your first Java file, double click on it in Explorer, select "Notepad" from the "Open with" box, and Notepad will stop adding the spurious ".txt" to your .java files. Second answer: Notepad expects to see a "carriage return/line feed" pair at the end of each line, rather than just the "newline" (line-feed) commonly used on Unix. Use this program to expand all newlines, /* * Usage: jre crlf file1.java file2.java ... fileN.java */ import java.io.*; class crlf { public static void main(String s[]){ byte b[]; byte p; FileInputStream is; BufferedOutputStream os; File f; for (int i=0; i < s.length;i++){ try{ f=new File(s[i]); b=new byte[(int)f.length()]; is = new FileInputStream(f); is.read(b); is.close(); os = new BufferedOutputStream( new FileOutputStream(s[i]),b.length); p='?'; for(int j=0; j < b.length; j++){ if((p!='\r')&&(b[j]=='\n')) os.write('\r'); p=b[j]; os.write(p); } os.flush(); os.close(); }catch(IOException e){ System.err.println(e.toString()); } } } } The source code is to show new users a way to make a simple program which can read a file and write it out buffered. Compile with "javac crlf.java" and run with java crlf outfile.txt or just use Wordpad instead of Notepad. Wordpad is under Start->Programs->Accessories->WordPad 20. (Sect. 2) How do I fix the message about "out of environment space"? [*] This occurs under Windows when you have long CLASSPATH names. You need to increase the environment space. On Windows 95,8 put this in your c:\windows\system.ini [NonWindowsApp] CommandEnvSize=4096 On NT you can right-click on My Computer, select System Properties then go to the Environment tab and then increase COMSPEC to the value you want. The previous suggestion to put this in your config.sys: shell=command /e:4096 apparently causes you to create two copies of command.com which wastes memory. ------------------------------- 3. General Information 1. (Sect. 3) Is Java "Open" or "Proprietary"? [*] The Java specification is publicly available, and anyone is free to do clean-room implementations of the JVM and core Java API's. Sun includes a perpetual, irrevocable, free and royalty-free license in the front of the Addison-Wesley books containing the specification. Sun also provides free access to the Java source. See http://java.sun.com/communitysource/ Using the Java trademark does requires licensing from Sun. It is not clear if the Embedded or Personal Java specifications are open, as it is not clear if a clean-room implementation may be done without licensing from Sun. The relative openness of Java contrasts with systems that are only available from one vendor, whose interfaces are developed in secret, without an open process for others to participate, whose owners do not allow competing implementations of the same API, and whose owners change the APIs as a strategic weapon against competitors. Typically, such systems also feature "private" APIs that are published late or not published at all, to allow the single vendor to gain a competitive advantage for their other products. Typically such proprietary systems do not make the source code available for inspection by all. 2. (Sect. 3) What is the best way to refer someone to the FAQ when they ask a question I know is answered there? [*] The Java Programmers FAQ (at http://www.afu.com) answers your question in section N.n. ... This gives them the answer, and shows them where to go for future questions. It also demonstrates that the FAQ can answer their questions, supplying an incentive to go there next time. It's regarded as elementary politeness to look for the FAQ of a newsgroup and read it before posting any questions. In general, FAQs for any newsgroup are available by looking at past postings in a group, or by searching Deja News (see Q 1.4), or via anonymous FTP at directories under ftp://rtfm.mit.edu. The pathnames are called things like /pub/usenet-by-group/comp.lang.java.programmer/Java_Programmers_FAQ which may help you get to the right one directly, as it takes some time to get a directory listing there. Alternatively, you can look for newsgroup names on the same ftp site by going to the same site and looking under /pub/usenet-by-hierarchy/. That has subdirectories such as alt/, ba/, ca/, comp/, and subdirectories under them such as /pub/usenet-by-hierarchy/comp/lang/ and so on. This helps you explore the world of newsgroups with FAQs. If you do not have anonymous FTP access, you can access the rtfm.mit.edu archives by mail server as well. Send an E-mail message to mail-server@rtfm.mit.edu with "help" in the body for more information. "RTFM" stands for "Read The effing Manual" - you must expect to put in some time and effort to master a new area of study. If you want to look at the definition of Internet standards like FTP, telnet, visit the IETF site at http://www.ietf.org where all the RFC's (Request For Comments) can be found. 3. (Sect. 3) What if my question is not answered in this FAQ? [*] Go to http://www.dejanews.com/home_ps.shtml In May 1999, Dejanews changed their name to Deja.com, and their web design to a truly horrible garish interface, covered with ads and harder to search. Consider using these search sites instead: http://www.exit109.com/~jeremy/news/deja.html http://www.dogpile.com http://www.google.com http://www.hotbot.com http://www.mamma.com o Under "Newsgroups" enter "comp.lang.java.programmer" (or whatever) o Under "Subject" enter "Frotteur" (or other topic you find pressing) o Click "Create Filter" o It will go to a new document, and you should click the link labeled nnn Documents (nnn is some number). The chances are that you will find several answers to your question. Some may not be complete or completely accurate however. That is the nature of Usenet, and free information. If you still don't have an answer, then post your question on the most appropriate of the newsgroups. Don't spam the newsgroups by posting to multiple groups. Knowledgeable posters tend to ignore questions like that. Also look at http://sunsite.unc.edu/java/cgi-bin/query and look at http://asknpac.npac.syr.edu/ for a Java newsgroup search. http://www.javaworld.com/search.html can search the Javaworld newspaper. 4. (Sect. 3) What Java mailing lists are there? [*] There are quite a few Java mailing lists. http://java.miningco.com/msub7.htm has a comprehensive list. 5. (Sect. 3) Where can I look at the definitive Java Language Specification? [*] This is available online at: http://java.sun.com/docs/books/jls/html/index.html (Java 1.0) and the Java 1.1 inner classes document at: http://java.sun.com/products/jdk/1.1/docs/guide/innerclasses/ spec/innerclasses.doc.html and the other Java 1.1 update at: http://java.sun.com/docs/books/jls/html/1.1Update.html and the Java API is at: http://java.sun.com/products/jdk/1.1/docs/api It is also available as a book in printed form (details at website). Also see the "Clarifications and Amendments" http://java.sun.com/docs/books/jls/clarify.html. You can also see the virtual machine (execution environment) specification at http://docs.sun.com:80/ab2/coll.127.1/@Ab2CollToc?subject=java 6. (Sect. 3) Where can I find information about future Java APIs? [*] JavaSoft has followed a policy of creating new APIs in consultation with leading industry participants, then posting the draft specification for public review and comments. Check the JavaSoft roadmap of new APIs and products at http://java.sun.com:80/products/api-overview/index.html Also, some APIs that are under consideration, possibly for JDK 1.2 are at: http://java.sun.com/products/jdk/preview/docs/ 7. (Sect. 3) I'm looking for a Java style guide on naming conventions. [*] Check out the section "Naming Conventions" in the language specification http://java.sun.com/docs/books/jls/html/6.doc.html#11186 Also take a look at Doug Lea's draft coding standard - http://gee.cs.oswego.edu/dl/html/javaCodingStd.html See also naming conventions for some basic rules of thumb. 8. (Sect. 3) How do I check on known bugs in the JDK? [*] Look at the Java Developer Connection at http://java.sun.com/jdc. All the Java bugs that Sun knows about are listed there, with the exception of security-related bugs. The legal department in Sun vetoed the open publication of security bugs. After you have checked that the bug is not already listed, you can submit a bug report through: http://java.sun.com:80/cgi-bin/bugreport.cgi You should check that the bug doesn't already exist for two reasons: first, you might find the bug with a workaround listed. Second, you don't want to waste everyone's time with a duplicate bug report. You can also send in an RFE (Request For Enhancement) or ease-of-use issue there. You can even vote on the priority you would assign to a particular bug fix! Join the Java Developer Connection (it's free) by going to http://java.sun.com/jdc. Then browse http://developer.javasoft.com/developer/bugParade/#votes 9. (Sect. 3) What computers have Java ports? Is there a port to Win 3.1? [*] A partial list of JDK ports is available from http://java.sun.com/cgi-bin/java-ports.cgi An (impressive) list of the systems that the GPL Kaffee JVM runs on is at http://www.transvirtual.com/ports.html A list of the software updates you should install to run Java on Solaris is at http://java.sun.com/products/jdk/1.2/install-solaris-patches.html#2.6 There are several Java ports to Win 3.1. IBM's ADK1.02 is available at the following locations: o http://ncc.hursley.ibm.com/javainfo/latest/answers/faq0.html o http://www.alphaworks.ibm.com/formula IBM offers a port to Linux, as do others. The IBM Jikes port is at http://www.alphaworks.ibm.com/ There is a large amount of useful software there, including a profiling tool called jinsight. Netscape Navigator for Win3.1 has Java support. Java will never be well-supported under Win3.1 because Win3.1 lacks the basic features expected of a modern OS (primarily lengthy filenames and multithreading support). Also take a look at JavaSoft's JavaPC kit that can switch a PC into a thin client Java system (and back to Win3.1/DOS when you want). It's meant for software OEMs and large corporations running lots of older PCs, but you can use it on the latest Pentium II too. Details are at http://java.sun.com/products/javapc/index.html. JavaPC is available now for $100, runs on 486's with 8Mb or more Unlike the 16-bit versions of Netscape Navigator and Microsoft Internet Explorer, which provide a Java Virtual Machine that is only compliant with the JDK 1.0.2 API, the JavaPC software allows IS managers to deploy JDK 1.1-compatible Java applications on PCs running DOS and Windows 3.x. 10. (Sect. 3) Where can I find information on Java 3D? [*] The Java 3D FAQ at http://tintoy.ncsa.uiuc.edu/~srp/java3d/faq.html may have the answers you're looking for. It contains general information about Java 3D, as well as programming tips. 11. (Sect. 3) Where can I find information about Java Certification? [*] Sun is sponsoring an examination which programmers worldwide can take. Those passing can use the designation "Sun Certified Java Programmer". There is also a second-level test, involving writing a program to spec, and taking a further test. That results in the qualification "Sun Certified Java Developer". You can find out all about the exam at: http://www.sun.com/service/suned/ and then search for "sun certified java". It costs $150 to sit the Java Programmer exam. It is not trivial to pass the Java certification exam. It requires understanding the objectives of the test, and the material that is tested for. These are given, along with sample questions, at the URL mentioned above. There is a Java certification FAQ at: http://www.marcusgreen.co.uk 12. (Sect. 3) How can I find links to recent news about Java? [*] This site contains links to late-breaking online news stories about Java. http://www.intelligence.com/java/ Another good Java news source is http://www.nikos.com/javatoys. This site is a fine site for programmers who want to be well-informed about computer industry topics. It has a lot of coverage of Linux as well as more general news. http://slashdot.org Highly recommended. This site is a source of independent news and commentary on the computer industry, including Java. http://www.pjprimer.com/media.html. You have to subscribe ($10/year, 30 day free trial). 13. (Sect. 3) What are the folks at GNU doing with Java? [*] First note that the URLs in this section change quickly, and soon become outdated. If you have an update, send it in. There is a Gnu Java page at http://www.gnu.org/software/java/java.html Guava (a GPL'd Java compiler) can be found at ftp://ftp.yggdrasil.com/pub/dist/devel/compilers/guavac/ Alternatively, it may be available at http://http.cs.berkeley.edu/~engberg/guavac Work is progressing on the Cygnus Java frontend to gcc. See http://www.cygnus.com/product/javalang/ Kaffe (a JVM) can be found at http://www.transvirtual.com This is Tim Wilkenson's company devoted to commercializing the Kaffe JVM for the embedded systems market. He also releases a version of it under the GPL. It also comes with a the beginnings of a class library and the Pizza compiler. Classpath is a free implementation of Sun's Java libraries (v1.1), being developed for the GNU Project ( http://www.gnu.org). Information regarding classpath is at http://www.classpath.org They aim to develop a 100% free drop in replacement for Sun's class libraries, targeting first the Japhar JVM (below). They are always looking for help, so feel free to stop by and volunteer. See also http://www.japhar.org This is the Hungry Programmer's JVM. Currently it is development grade only. 14. (Sect. 3) What is "San Francisco"? [*] San Francisco is the code name for a very large Java project led by IBM, and involving other companies. The project is to provide a Java framework for data processing applications. A large number of classes are provided for general ledger, sales order, inventory management, etc., and these classes can be extended and customized for particular industries (vertical markets). It is a large and ambitious software project. IBM's SF project competes with products from companies like SAP and Baan. Of course, the SF project is multi-platform and uses Java beans and GUI interfaces. More information on SF is available at http://www.ibm.com/Java/Sanfrancisco 15. (Sect. 3) What large Office-style or other applications have been written in Java? [*] Well, the first one to consider is IBM's San Francisco project, mentioned above. There is also Lotus's e-suite - a suite of Java applets and beans including a spreadsheet and a word processor. See http://esuite.lotus.com. These became available in March 1998. Another office suite in Java is Applix Anyware at http://www.applix.com/anyware/index.htm. Applix became available in downloadable demo form in April 1998. Yet another is Star Division's Client/Server Office. It is an office suite with the client part written in Java and able to run on JavaStations. The server part will run on Solaris, NT, OS/390, and AS/400. The older (non-Java) version is bundled with all Sun workstations sold in Germany. The Linux version is freely downloadable from http://www.stardivision.com. Another is Digital Harbor's Wav word processor. It supports component software, and it runs in 1MB, not the 114Mb of the latest MS Word. A free trial is avilable. See: http://www.digitalharbor.com Another Java application is Formula One for Java, an Excel-compatible spreadsheet written in 100% pure Java, and available for all systems that support Java. It runs as a Java Bean, so can easily be assembled as one component of a larger system. It also runs as an application, and as an applet! Formula One is a product of Visual Components, Inc. See http://www.f1j.com. Another one is Ncode Research Inc. who write Java viewers for office suites. They are file-format specialists. Their mission is to make all popular file formats available for the Java platform. They write 100% Pure Java viewers for Word, Excel and PowerPoint (including Office 95 and 97 formats). See http://www.ncode.com/ Another company operating in the same space is JSoft, at http://www.jsoftinc.com Intentia, the 8th largest ERP vendor (annual sales of $320 million), has moved their entire suite of applications (Movex - covering 8 markets) from RPG to Java - 20 million lines worth. See their press release. However, the industry is seeing few new office productivity applications written in any language. The niche for single-user office productivity applications is already dominated by Microsoft products, and it is unrealistic to think that Java software will unseat shrink-wrapped software simply because it is written in Java. This is why Corel replanned its Java rewrite of Corel Office before taking it to FCS. When Corel did that, it also increased its investment in Java from 33% of R&D budget to 50%, at the expense of Windows. Most of Java development is taking place for custom applications internal to a company. Most programmers of any kind have never worked on MS Office, but work on internal applications, and so it is with Java. These projects don't have the high profile of major vendors' products, but they are the mainstay of the industry. There are many companies working on Java Beans, like http://www.quadbase.com who have Java graphing software (see also GraphMaker mentioned later in this document). EspressChart is a Java Bean that gives you the ability to add 2D and 3D graphs in your applications/applets. This bean is easy to use, 100% Java, and runs anywhere. There are some excellent Java games applets at http://www.javaarcade.com Check out the pinball -- dig that crazy rhythm, man. There are more good Java games applets at http://www.frontiernet.net/~imaging/java_games.html and at http://www.gamesdomain.co.uk/GamesArena If you want to use Java to learn math & computer graphics, visit http://www.frontiernet.net/~imaging/math_is_a_game.html ObjectDesign Inc., has an ODBMS written in 100% java. The product is named PSE Pro for Java. See http://www.objectdesign.com Another database written in Java is available from http://www.cloudscape.com. Another database written in Java is available from http://www.instantdb.co.uk. InstantDB is available free to non-commercial organizations, and is very well documented and maintained. (Recommended!) Finally, note that Sun's Java compiler is written in Java. This is a really big application in widespread use on millions of platforms. The compile command "javac test.java" is equivalent to java sun.tools.javac.Main test.java javac has a script wrapper just to set the heap size as a command line argument, as you can do in your own programs. 16. (Sect 3.) What Java User Groups are there? [*] There are scores of Java User groups around the world, mostly in urban areas, and centers of software technology development. A partial list with contact information can be found at http://sunsite.unc.edu/javafaq/usergroups.html. If you can't find a user group in your area/school, it's easy and satisfying to start one. 17. (Sect 3.) What is a Java Bean? [*] A Java bean is a Java class that follows some simple conventions. Because it follows conventions, it can easily be processed by a software tool that connects Beans together at runtime. Java beans are reusable software components. Think of Java beans as being the software equivalent of Lego[tm] bricks. Instead of plugging together plastic bricks, you can easily plug together classes, and have them fit and work with each other. See http://www.jc100.org/ See the Java Bean FAQ at http://java.sun.com/beans/faq/faq.general.html 18. (Sect 3.) Where can I find examples of the use of the Java class libraries? [*] The two volumes of "Java Class Libraries" by Chan, Lee and Krama published by Addison Wesley, have extensive examples of how to use the standard libraries. One programmer comments "When I need to use an unfamiliar area of the class libraries one of the first things I do is read their examples." You can see them online at http://java.sun.com/docs/books/chanlee/second_edition/vol1/examples.html and http://java.sun.com/docs/books/chanlee/second_edition/examples.html 19. (Sect 3.) How can I find out exactly what version of Java I have on my system? [*] On a Solaris system, you can use the pkginfo command, like this: pkginfo -l SUNWjvrt It will give a reply like this: PKGINST: SUNWjvrt NAME: JavaVM run time environment CATEGORY: system ARCH: sparc VERSION: 1.1.6,REV=1998.07.30.16.21 BASEDIR: / VENDOR: Sun Microsystems, Inc. ...etc You may also try java -fullversion Although that's not an officially-supported command option, and has gone away in JDK 1.2. Try also java -version 20. (Sect 3.) What Java newsgroups are there? [*] comp.lang.java.beans comp.lang.java.corba comp.lang.java.databases comp.lang.java.gui comp.lang.java.help (it renamed comp.lang.java.setup) comp.lang.java.machine (it renamed comp.lang.java.tech) comp.lang.java.programmer (it renamed c.l.j.api and c.l.j.misc) comp.lang.java.advocacy (argue all day with anonymous shills) comp.lang.java.softwaretools alt.comp.lang.java-games New Java newsgroups are added every so often. Try not to crosspost. ------------------------------- 4. Compilers and Tools 1. (Sect. 4) Is there a lex and yacc or preferably a flex and bison equivalent for Java? [*] There is a lex equivalent called JavaLex and a yacc equivalent called CUP. LALR(1) parser JavaLex and JavaCup: http://www.cs.princeton.edu/~appel/modern/java/ LL(k) parser JavaCC: http://www.suntest.com/JavaCC/ LALR(1) parser SableCC from McGill U. http://www.sable.mcgill.ca/sablecc/index.html is generously made available under GNU license. 2. (Sect. 4) Where can I find a byte code obfuscator? [*] Java Obfuscators replace the original class, field and methods names in the bytecode with meaningless strings. Second generation obfuscators are now appearing that also obfuscate the control flow and encrypt String literals. People use obfuscators on their applets if they want to hide their code from others. Generally, you wouldn't do this with software that you put on your website for others to enjoy. It runs counter to the "open source" philosophy of learning from other's code and allowing them to learn from yours. Zelix KlassMaster is a commercially supported obfuscator. It has a free evaluation version at http://www.zelix.com/klassmaster Another commercially supported obfuscator, with a downloadable free trial is at http://www.4thpass.com/SourceGuard. There are also some free works from students and others. http://www.primenet.com/~ej/ http://www.math.gatech.edu/~mladue/HoseMocha.java Some people have reported problems using these with JDK 1.1. This obfuscator has been updated to be fully compatible with JDK 1.1: http://www.monmouth.com/~neil/Obfuscate.html Obfuscators are intended to foil decompilers. Decompilers translate byte code back into Java source code. Mocha was the first and most well known of the decompilers; it's no longer supported. There is a decompiler (written in C++) at http://www.geocities.com/SiliconValley/Bridge/8617/jad.html Because it is in C++, there are different versions for every architecture (hah!) There are also commercial products, such as SourceAgain from http://www.ahpah.com/ There's a very good Java Code Engineering and Reverse Engineering FAQ page at http://www.meurrens.org/ip-Links/Java/codeEngineering/. 3. (Sect. 4) Which program is used to create .zip files compatible with the java* programs? (e.g. classes.zip, moz3_0.zip) [*] Use the jar-tool from JDK1.1(.1): jar [ options ] [manifest] destination input-file [input-files] E.g.: jar cvf myJarFile.jar *.class creates a compressed archive. And watch out -- the order of the options ("cvf") determine the order of the arguments! jar cvfO myJarFile.zip *.class creates it fullsize (uncompressed) (note the 'O'-option used for JDK1.0.2) On Unix you can also use: zip -rn ".class" my_file.zip * Info-ZIP home page: http://www.cdrom.com/pub/infozip/ Latest source code: ftp://ftp.uu.net/pub/archiving/zip/src/zip21.zip Netscape's command line version of its JAR packager and signing tool is called "zigbert". They also have a signing tool with GUI written in Java. More info http://developer.netscape.com/software/signedobj/jarpack.html If you zip your .class files for JDK 1.0.2 (for 1.1 you'll use a Jar): 1. zip your files uncompressed (can use WinZip 6.2 up); Unix command: zip -r0 classes.zip <directories> 2. Make sure the main class has no parent directory inside the archive, (in other words, don't build an archive with foo/bar/myMain.class, unless your myMain is in a package called foo.bar. Instead start it at myMain.class). Your packages must be placed in the archive using their corresponding filesystem pathnames. 3. Put the archive in the same directory as the .html page. 4. Put something like the following tag in the .html file: <APPLET CODEBASE="." ARCHIVE=my_zip_file.zip,myOtherZip.zip,thirdfile.zip CODE="my_main_class.class" WIDTH=600 HEIGHT=250> </APPLET> From JDK 1.1 on, an example of the applet tag used with a jar file is <APPLET ARCHIVE=myfile.jar CODE=myapplet.class WIDTH=600 HEIGHT=250> </APPLET> These lines will use an applet called myapplet that can be found in the jarfile myfile.jar. An example applet tag of a jar file used to hold classes in packages is <APPLET ARCHIVE="myclasses.jar" CODE="linden.net.MyApplet.class" WIDTH=480 HEIGHT=120> </APPLET> You can supply several jar filenames in a comma-separated list. Jar files are in compressed PKZIP format. 4. (Sect. 4) Can I compile a Java program to a binary executable, .exe on a PC? [*] Compiling into native code destroys portability, which is one of the main benefits of Java. If you want to create a native executable because you wanted to make it easy to distribute and use programs, consider a Jar file instead. Some companies make products that do this. See the webpages for Symantec http://www.symantec.com, Supercede http://www.supercede.com, and Tower Technology http://www.twr.com. The first two are targeted to Windows. Tower Technology supports several flavors of Unix. Also, there is a native Java compiler from IBM, known as the HPJ (High Performance Java) compiler. One user has reported that it created a 2Mb executable from a 12K java file, and did not run any faster. See http://www.alphaworks.ibm.com/ See also Instantiations JOVE http://www.instantiations.com/jove.htm, the paper about the Toba project http://research.microsoft.com/research/lt/toddpro/papers/coots97.pdf, Network World, "Vendors Rush To Speed Java Performance", Feb 9 1998, at http://www.nwfusion.com/news/0209java.html Compiling to native code takes away the most significant benefit of Java: portability of executables. Further, if you want your Java DLL (or .exe) to interact with C++, you'll have to specify which specific C++ compiler and/or actually compile some sort of linkage via the appropriate C++ compiler. C++ does not have a standard ABI, so there is a big problem with interoperability. Every C++ compiler uses a different object model, a different way of laying out class members, and a different way of "mangling" names for the linker. C is much simpler. The only question here is how structures are "packed" (i.e., are integers aligned on four-byte bounds?). All the C++ compilers can interact with C code, thanks to 'extern "C"' declarations. Consider carefully why you want to compile to a native executable, and whether there is a Java way to accomplish your goal. There may be a good reason for compiling to native code, but it needs to be thought through. 5. (Sect. 4) How can I performance profile my Java code? [*]java -prof MyClass produces some basic output in a file called java.prof, showing the number of times methods were invoked. The output lines are of the form: # of calls method called called by time spent On a Unix system, you can sort the file with something like sort -r +82 <java.prof > java.sort More and better Java tools are a third party opportunity. One Java profiler is JProbe Profiler, available from http://www.klg.com/jprobe. JProbe is said to be easy to use. Another profiler is OptimizeIt, available from http://www.optimizeit.com. Each of these profilers has performance tuning, which shows which methods took how much time, and also memory tuning, which shows what objects are in memory and how they were allocated. Both are important things to know. The latest version of the CodeWarrior IDE http://www.metrowerks.com has a time-based profiler for Java code. Java Workshop from Sun also has a time-based profiler. JDK 1.2 comes with some limited profiling capability built-in. Depending on your needs, it may be all that you need. Execute the following to get a short summary of what you can do: java -Xrunhprof:help For example, you can see which methods are taking the most time to execute, in the context of particular stack traces. 6. (Sect. 4) When I use javadoc and I click on any java class included in the JDK why do I get this message? Netscape is unable to find the file or directory named: /E|/Jwrkshop/JDK/bin/java.lang.Throwable.html [*] References to the JDK classes assume that all generated html files are in the same directory and, in fact, that all files for all classes referenced are generated at the same time. There is no way to generate files incrementally and have them all reference each other, as you would like. As long as you have source for everything involved (including the JDK and all third-party classes), you can list all of your packages and all of the others on the javadoc command line and generate the whole set at once, but it is burdensome. Of course, if you receive any libraries as .class files, even this workaround will not suffice. Also javadoc will not generate the image files - you need to get them from the images directory under the JDK API documentation files. You can just copy the entire directory into your own doc directory. javadoc is a very nice concept, with a few implementation flaws. 7. (Sect. 4) I'm working on a project with lots of classes and I use the JDK. A recompile from scratch takes forever when I do it a class at a time. How do I recompile everything? [*] The first way is javac *.java Another way is javac -depend tip.java where "tip.java" is a class "at the tip of the iceberg", i.e. that depends on (uses) all the other classes. Typically, this may be your main class. However, "-depend" is known to be buggy and cannot be relied upon. It also doesn't issue compile commands in parallel to make use of multi-processor systems. Without the "-depend" option, the standard "javac files" doesn't look beyond the immediately adjacent dependencies to find classes lower down the hierarchy where the source has changed. The -depend options searches recursively for depending classes and recompiles it. This option doesn't help when you have dynamically loaded classes whose names cannot be determined by the compiler from the dependency graph. E.g. you use something like Class.forName(argv[0]); The author of the code using those classes should make sure that those classes are mentioned in a Makefile. 8. (Sect. 4) Why do I get the java.lang.UnsatisfiedLinkError when I run my Java program containing Native Method invocations? [*] Your program is not able to find your shared library or DLL. On Windows 95/NT, make sure that the DLL exists in a path that is included within the PATH environment variable. (This need is true for both standard (untrusted) applications and trusted applets. At least, if you use the Java Plug-in to give yourself standard Java inside a browser). On Solaris, make sure that the environment variable LD_LIBRARY_PATH includes the path of your shared library. Note that jdb looks for libraries with "_g" appended to their names. Thus, if you intend to use jdb on a Java application that invokes native methods, you must ensure that the appropriately named libraries are in jdb's path. The "debug" nm libraries can simply be renamed copies of the nondebug libraries. For example, if your app invokes native methods in a library named mynm.dll (on Windows) or mynm.so (on Solaris), make a copy in the same directory and name it mynm_g.dll or mynm_g.so. 9. (Sect. 4) An anonymous class can't seem to access a private outer method. Why is that? [*] It's a known bug in the JDK 1.1.4. The code is: public class MyDialog { void Setup() { addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent e) { myCloseWindow(); } } ); // anon inner class } private void myCloseWindow() { // private outer method dispose(); } } This code sends javac into an infinite loop. The workaround is to make the private method non-private, or to make the inner class a named class. Sun put a workaround in the compiler to silently set the field to package access. 10. (Sect. 4) What are the major Java releases and their contents? [*] There have been three Java releases from Sun so far, plus a number of bugfix (dot-dot) releases. The releases are: o JDK 1.0.2 This was the release FCS in May 1996. It had some security fixes over JDK 1.0. o JDK 1.1 This release (Feb 1997) introduced a new event model in the window system. It also made JDBC support and beans support a standard feature. It changed and standardized the native code interface to JNI. It also introduced inner classes. o JDK 1.2 This release (Dec 1998) made the Swing library a standard feature. Swing is a set of rich platform-independent graphical components. It also introduced the Collections library, and Java 2D. 11. (Sect. 4) What is the difference between jre and java? [*] They are functionally equivalent, with minor differences in the handling of default classpath and options supported. To reduce confusion, the jre command was removed in JDK 1.2. Instead there is a "java" command in both bin and jre/bin. jre.exe is the java launcher that comes with the Java Runtime Environment. It ignores the CLASSPATH environment setting in favor of its own internally generated default and whatever is supplied on the cmd line using -cp or -classpath. It's intended to be a bit simpler for those who are only ever running Java programs, not developing them. java.exe is the java launcher that comes with the JDK. It uses the CLASSPATH environment setting as a starting point and then tacks on its own internally generated entries. They both serve the same purpose and that's to start a Java VM, have it run a Java application, then terminate. The source for jre.exe is provided in the JDK. The source to java.exe is provided only in the JDK Source distribution. 12. (Sect. 4) What IDEs (Integrated Development Environments) are there? [*] Some popular IDEs include: (... if you have info on the platforms that each of these support, send it in, and I'll add it to the FAQ). Apptivity (Progress) http://www.apptivity.com Blue J (free) http://www.sd.monash.edu.au/bluej Bluette (free) http://www.bluette.com Chicory (free) http://www.chicory.com CodeWarrior Professional http://www.metrowerks.com Freebuilder (free) http://www.freebuilder.org GRASP (free) http://www.eng.auburn.edu/grasp Grinder http://www.tpex.com Java WorkShop (Sun) http://www.sun.com/workshop/java Javelin, Visual Object Development for Java http://www.stepahead.com.au JBuilder (Inprise) http://www.inprise.com/jbuilder JDE for emacs http://sunsite.auc.dk/jde/ Jirvana (free) http://www.jirvana.com/Jirvana/Jirvana.html JPadPro http://www.modelworks.com Kawa (Webcetera) http://www.tek-tools.com/kawa Metamata http://www.metamata.com NetBeans (Swing-based) http://www.netbeans.com PARTS alpha (ObjectShare) http://www.objectshare.com PowerJ (Sybase) http://www.sybase.com/products/powerj SilverStream http://www.silverstream.com Simplicity for Java http://www.datarepresentations.com Super Mojo (Penumbra) http://www.penumbrasoftware.com SuperCede (Asymetrix) http://www.supercede.com teikade (PFU Ltd) http://www.pfu.co.jp/teikade Together/J (Object Intl Inc.) http://www.oi.com Visaj (Imperial SW Tech) http://www.imperial-software-tech.co.uk VisualAge (IBM) http://www.software.ibm.com/ad/vajava Visual Cafe (Symantec) http://cafe.symantec.com Visual J++ (Microsoft) http://msdn.microsoft.com/visualj/default.asp (not recommended) Xelfi 0.94 http://www.xelfi.com 13. (Sect. 4) Why is Visual J++ not recommended? Because Microsoft's strategic objective is "Kill cross-platform Java" [*] It is not in Microsoft's financial interest to allow users to easily move software to different platforms. Microsoft is the only company in the computer industry that is actively trying to undermine Java. This is not speculation -- the Department of Justice's lawsuit quoted a Microsoft memo describing the strategic objective to "kill cross-platform Java by grow[ing] the polluted Java market". See http://www.usdoj.gov/atr/cases/f1700/1762.htm VJ++ can be used in a compatible way, but the tool encourages use of Windows lock-ins. The J++ compiler introduced new keywords and other deliberate incompatibilities. Microsoft is being sued because of unauthorized changes it made in Java. A federal judge issued a preliminary injunction against Microsoft in March 1998, prohibiting them from labelling their incompatible J++ product as Java. Another injunction was issued against Microsoft in Nov 1998, requiring them to remove some deliberate incompatibilities with standard Java. (Recall that Microsoft did not create Java, but contracted with Sun to distribute it). Microsoft is in a real jam over Java; it contracted with Sun to distribute standard Java, and then made many changes to its product to make it deliberately non-portable. Sun sued Microsoft to enforce the contract, and the preliminary legal decisions have been in Sun's favor. Some analysts speculate that Microsoft will leave its customers in the lurch and cancel VJ++. See http://cnn.com/TECH/computing/9903/23/javajam.idg/index.html Speak to your management chain - how comfortable do they feel using a Microsoft product that is embroiled in a legal dispute, that introduces deliberate incompatibilities, and whose stated goal is to lock you in to one platform? It is a safer choice to get standard Java from any other source than Microsoft. You can use these facts to move your company to standard Java. As a Java programmer please join the Java Lobby, an independent organization dedicated to representing independent non-vendor interests in Java. It's free, and you can sign up by visiting http://www.javalobby.org for details. Other ways to encourage portable java: o Use development environments from other vendors, or convert Microsoft Visual J++ to use Sun's JDK, following the instructions at http://www.orbiter.demon.co.uk/ o Use Netscape Communicator (not Internet Explorer) o If required to use Internet Explorer, use the Java Plug-In to get a standard Java system inside it. o Use a standard JVM from GNU, Kaffe, any of the IDE vendors, or Sun (but not Microsoft's J++ SDK) o Free standard Java compilers and the Java Plug-In can be downloaded from http://java.sun.com. o Free standard Java Virtual Machines can be downloaded from http://www.kaffe.org, http://www.oryxsoft.com/projects/gvm, and http://www.redhat.com/linux-info/jolt o Free Java AWT software can be downloaded from http://www.biss-net.com/biss-awt.html and the files are all at ftp.java-linux.org (the linux site) too. o Free Java software can be downloaded from http://www.gnu.org/software/java/java.html Just for the record, the May 1998 federal case against Microsoft has nothing to do with innovation or product design, as Microsoft frequently insists. Microsoft is actually charged with o taking anti-competitive action to exclude competition in browsers, in order to protect its monopoly in desktop operating systems. o using its monopoly to impose restrictive agreements that require PC manufacturers to accept the Microsoft browser with Windows, and that hinder the promotion of competing browsers. Many people think that contracts between "A" and "B", restricting/discouraging "B" from distributing "C's" products are sleazy. ["A" is Microsoft, "B" is AOL, many ISPs, computer vendors, etc. "C" is Netscape"]. Such contracts are in restraint of competition and illegal when used by a monopoly. This is why Microsoft is facing mounting legal problems in the United States, Italy, Brazil, and the European Union. 14. (Sect. 4) What language is the Java compiler and JVM written in? [*] Sun's javac Java compiler is written in Java. Sun's java JVM interpreter is written in Java with some C, C++ for platform-specific and low level routines. Sun's Java Web Server is written in Java. Other companies have chosen other approaches. IBM's Jikes compiler (which is praised for its speed) is written in C++, but of course each version only runs on one platform. Jikes versions have been prepared for IBM AIX, Linux Intel (glibc), Win95/NT and Solaris Sparc at http://www.alphaworks.ibm.com/formula/jikes. 15. (Sect. 4) How do I turn off the JIT in the JDK? [*] The command that works in both JDK 1.1.6 on, and JDK 1.2/2 is java -Djava.compiler=NONE ... One reason for turning off the JIT is to get more information about any exception that is thrown in your code. But HotSpot is able to produce line numbers in stack traces even for JIT'd code. HotSpot rocks. 16. (Sect. 4) How can I store the errors from the javac compiler in a DOS file? javac foo.java > errorfile doesn't work. [*] javac writes errors to stderr, The problem is that DOS doesn't allow stderr to be redirected (as command.com is very poor software). So you have to use a special error redirection mechanism in the compiler: javac -J-Djavac.pipe.output=true myfile.java > errors.txt In JDK 1.2, you can use: javac -Xstdout You typically use this when a compilation produces a lot of error messages, and they scroll off the DOS window before you can read them. Alternatively, you can get a scollbar to appear on a DOS window by changing the properties with the "Layout" tab. Change the Screen Buffer Size Height: to some multiple > 1 of the Window Size Height. E.g. use a buffer height of 100 and screen height of 25 (the default). This will give you three buffers of scroll "history." The DOS limitation is improved in NT, where you can write javac myfile.java 2> errors.dat 17. (Sect. 4) How can I pretty-print Java source? [*] For tools that reformat code, try: o http://www.parallax.co.uk/~rolf/download/jpp.pl o http://www.bigfoot.com/~davidsont/jstyle o http://www.mmsindia.com/JPretty.html o http://www.almide.demon.co.uk/source_code/java/JavaCC/Pretty/Pretty.html o http://www.geocities.com/~starkville For tools that print code neatly, try: o http://www.eng.auburn.edu/department/cse/research/grasp/ Some Unix utilities work adequately: o cb (very few style choices though) o alias printjava 'vgrind -lC++ -t -w \!* | lp' works pretty well too. Perhaps the best tools are the GNU utilities. Use enscript to generate postscript files with Java-specific formatting. Then use GhostScript/GhostView to preview and print the files to a non-PostScript printer, if necessary. The scripts can be found at: o GNU Enscript - pretty printer and PostScript formatter o Ghostscript, Ghostview, and GSView for Unix o gsv25w32.zip - GSView for NT (requires the following Ghostscript files) o gs510ini.zip - Ghostscript configuration, initialization, and example files o gs510w32.zip - Ghostscript core binaries for Windows NT o gs510fn1.zip - Ghostscript standard fonts ------------------------------- 5. Compiler Messages Most of the "questions" in this section are diagnostic messages from the compiler. Each answer explains what the message means, and how to avoid it. 1. (Sect. 5) Why did I get an OutOfMemory error when porting working code from JDK 1.0.2 to 1.1? [*] The preset memory limit has changed. It went down to 16MB so as not to penalize low memory machines. You can adjust it with java -mx128m Frotz # jdk 1.1 java -Xmx128m Frotz # jdk 1.2 to get a 128MB extent. Also see the Runtime methods freeMemory() and totalMemory(). 2. (Sect. 5) Why do I get a "Statement not reached" error from javac for no apparent reason? [*] JDK 1.0 has a limit of 63 words of storage for local variables in any method. longs and doubles require two words of storage, and all other primitive types and all reference types require one word. If you assign values to more than 63 words of local variables, you will get a "Statement not reached" error on the statement after you assign to the variable that contains the 64th word. In JDK 1.1, the low limit was removed. 3. (Sect. 5) class MyOrdinaryClass must be declared abstract. It does not define void actionPerformed(java.awt.event.ActionEvent) [*] This is one of those error messages where the compiler tries to guess what you meant, and gives you a message based on a wrong guess! So the message is confusing. Your MyOrdinaryClass class implements ActionListener, which means you must include a definition of the methods from the ActionListener interface. But you did not. You either left a method out, or (more likely) you misspelled its name. Perhaps you wrote "ActionListener" instead of "actionListener". So the compiler did not find the method to fulfill the interface. Since there was a method promised but not supplied, the compiler thinks you were aiming at an abstract class, and it prints an error message accordingly. 4. (Sect. 5) Variable may not have been initialized. URL test; try { test = new URL("http://osprey.avs.dec.com"); } catch (MalformedURLException e) { System.out.println("bad URL:" + e.getMessage()); } System.out.println("this is url " + test); [*] The compiler will warn you if you use a variable before it is certain to have been initialized (not just with the default value) since this means you probably forgot to set it. In the case of exceptions, you have to consider that the flow of control may terminate abruptly, with no operations completed. In the example above, if an exception is raised in the try clause, variable test will not be assigned a value, yet you are using it after the catch clause. One solution would be to declare test with an explicit initial value of null, but this works only because toString() works on a null reference. (toString() is invoked implicitly by operator + with String operand.) Always initialize to a value that will work notwithstanding exceptions being thrown. 5. (Sect. 5) No constructor {superclass}() I extended the class called Frotz, and the compiler is giving me an error message "No constructor Frotz()" in the child class. Why? [*] When you define a constructor for a class, the compiler inserts a call to the superclass' parameterless constructor unless you explicitly call the superclass' constructor at the start of your constructor. If the superclass doesn't *have* a parameterless constructor, the compiler emits a message to that effect. The solution is usually to call the superclass' constructor at the start of your constructor. 6. (Sect. 5) No constructor matching MyCheckbox(myApplet) MyApplet.java:11: No constructor matching MyCheckbox(myApplet) found in class MyCheckbox. bp1 = new MyCheckbox(this); ^ [*] If a compiler isn't finding a constructor you thought you created, check whether you gave a return value to the method (remember, constructors have no return value). E.g., public void MyCheckbox( Container parent ) If you did, the compiler will think it is an ordinary method, not a constructor. This is a common mistake and hard to spot. 7. (Sect. 5) Type expected {public method variable} public static void main(String[] args) { ^ Statement expected. public static final float Conversion_Factor = 39.37; ^ Type expected. [*] Argument and variable declarations inside methods are never public or static because they are local to a method. (Before JDK 1.1 they couldn't be final either, but there was no good reason for that restriction and it was dropped.) If you have public or static variables, move them outside the method. They are usually put at the beginning of the class. 8. (Sect. 5) Can't access protected method clone in class java.lang.Object T.java:96: Can't access protected method clone in class java.lang.Object. OtherT is not a subclass of the current class. [*] Object.clone() is protected because subclasses might want to restrict access to cloning, and if Object.clone() were declared public, subclasses could never make it more restrictive. The subclass can make access to the clone() operation less restrictive. This means that a method can clone its own objects, but a method cannot clone objects of another class, unless you do something like: class SomeObject implements Cloneable { public Object clone() throws CloneNotSupportedException { return super.clone(); } } i.e., override clone() to make it public, and call the superclass clone(). class Foo { Bar bar; Foo (Bar b) { try {bar = (Bar) b.clone();} catch (Exception e) {} } ... class Bar implements Cloneable { public Object clone() throws java.lang.CloneNotSupportedException { return super.clone(); } } Another refinement is to note that Object.clone() only throws a CloneNotSupportedException when the object doesn't implement Cloneable. Since you control what your classes do and don't implement, you can ensure that Cloneable classes implement the interface, and you don't need to make the overridden clone() throw the exception. public class X implements Cloneable { public Object clone() { // no throws try { // in case members need cloning X c = (X)super.clone(); return c; } catch (CloneNotSupportedException e) { // should not happen, because of Cloneable throw new InternalError(); } } } 9. (Sect. 5) Deprecated methods What does "deprecated" mean? I got this in a compiler error message. [*] "Deprecated" means you are using an older API, that Sun has replaced with a newer one (usually to follow more consistent naming conventions). Deprecated methods are not recommended for use. They are supported in the short term, but your code should be updated with the new. To update your code, compile your old code using javac's "-deprecation" option to list deprecated methods, then find the replacement methods in the current HTML API documentation for the old deprecated methods. As an example of a deprecated API, Component.size() was replaced by Component.getSize(). See also http://java.sun.com/products/jdk/1.1/docs/guide/ misc/deprecation/index.html, "1.1 Deprecated Methods" and http://java.sun.com/products/jdk/1.1/docs/guide/ awt/DeprecatedMethods.html, "Deprecated methods in the 1.1 AWT" 10. (Sect. 5) double y = sin(90); What's wrong? That code provokes compiler messages. [*] You need to write it this way: double cvtDegToRad = Math.PI/180; double x = 90*cvtDegToRad; double y = Math.sin(x); sin is a static method of the Math class that takes radians. You need to use the "Math" classname, e.g. Math.sin instead of plain sin, because you have to say what class or object these methods belong to. A very common mistake is to assume that importing a class means that you don't have to qualify the names of its members. When you call a method you have to state the name of the class or object it belongs to, regardless of any imports you have done. (Except inside the class itself, obviously). The trig functions are static methods of the Math class, so you give the name of the class in invoking them. Further, the Math class works in radians, not degrees. 360 degrees = 2 pi radians, so use a conversion factor as shown if you are working with degrees. 11. (Sect. 5) Can't make static reference to method... [*] Your code probably looks something like this: class myclass { public static void main(String args[]) { myMethod(); } public void myMethod() { //some code } } Static (class) methods can only call without qualification other static methods, so you either have to qualify the call in (static) main() to (nonstatic) myMethod() with an object of type myclass, or you have to make myMethod() static. People often forget that even though main is "in" myclass, there is no implicit object when you are in main() because it is static. This happens especially when writing code to run an applet as an application, where you want to call init() and start() from main. public static void main(String[] args) { Applet ma = new myApplet(); // have to create object ma.init(); // use to qualify access to non-static methods ma.start(); } 12. (Sect. 5) Incompatible type for =. Explicit cast needed... byte b = 0; Incompatible type for =. Explicit cast needed to convert int to byte. b = b + 100; // compiler error message b += 100; // works OK [*] Arithmetic expressions are promoted to the type of the longest, floatiest operand in them, or at least to int. The first statement involves the assignment of an expression. The expression is promoted to 32 bits, and must be cast back down to 8 bits, like this: b = (byte) (b+100); The second is an operator assignment, and the cast back to byte takes place automatically. The Java Language Specification says that a compound assignment expression of the form E1 op= E2 is equivalent to E1 = (typecast)((E1) op (E2)), where "typecast" is the type of E1, except that E1 is evaluated only once. (See JLS 15.25.2 Compound Assignment Operators) The compile-time narrowing of constants means that code such as: byte theAnswer = 42; is allowed, with no cast necessary. (See JLS 5.2 Assignment Conversion) Other sites: JLS 5.2 Assignment Conversion JLS 15.25.2 Compound Assignment Operators 13. (Sect. 5) Class {package}.{class} not found in type declaration. I am trying to compile file "{class2}.java" in a package, and I get this compiler error. {class2}.java refers to {package}.{class}, but the file {class}.java and {class2}.java are in the same {package} directory, which is the current directory and which is in the CLASSPATH variable. Both files have "package {package};" at the top of the file. What's the problem? [*] When the source refers to classes in packages, the CLASSPATH has to point to the root of the package/directory hierarchy for a reference to resolve correctly. This is true even for source files in the same package (and directory). I.e., assuming {class} and {class2} are both in {package}, {class} can't make a reference to {class2} unless the CLASSPATH is set so javac can find {package}/{class2}.java. It should make no difference what directory you are in when you invoke javac, unless you are relying on "." in the CLASSPATH to point to the package root or are specifying the source file with a relative path (e.g., {package}/{class}.java). Some examples, assuming o - Foo.java and Bar.java are in /java/source/pack/ o - Both have "package pack;" as the first statement o - Foo.java includes "Bar b = new Bar();" # solaris ksh $ alias jc=/java/jdk11/bin/javac $ CLASSPATH=/java/source/ $ jc /java/source/pack/*.java # works fine $ cd /java/source/pack $ CLASSPATH=. $ jc *.java # fails - Foo.java can't find class Bar $ cd .. # now . is package root, /java/source/ $ jc pack/*.java # works 14. (Sect. 5) public class "Foo" must be defined in "Foo.java" I get this message even though it is in Foo.java. What gives? [*] Javac verifies that a public class is defined in a file of the same name (e.g., that public class Foo is defined in Foo.java). Two things you can check: First, make sure the case matches exactly. public class Foo cannot be in foo.java; it has to be in Foo.java. Second, are you using MKS on win32? Javac on win32 assumes you are using the DOS path separator (\) even though MKS accepts the Unix path separator (/). When javac tries to parse a your Unix-style path, it won't produce the correct filename, the match will fail, and it will emit an error. You have to use the DOS path separator (\), which must be escaped in MKS - e.g., "javac H:\\source\\package\\Foo.java". Alternatively, you can traverse to each source directory and avoid pathnames altogether. ------------------------------- 6. Java Language Issues How-to 1. (Sect 6.) How do I compare two Strings? if (s1 == s2) is giving me funny results. [*] The comparison using "==" on objects, such as Strings, is asking, "Do these two objects have the same reference?" Do they have the same address, and hence are the same object? What you really want to do is ask, "Do these two Strings have the same *contents*?" Compare String contents with any of the following: if (s1.equals(s2) ) if (s1.equalsIgnoreCase(s2) ) if (s1.startsWith(s2) ) if (s1.endsWith(s2) ) if (s1.regionMatches(s1_offset, s2, s2_offset, length) ) if (s1.compareTo(s2) < 0) (There are other ways, too.) Note that you can do this with literals: if ("apple".equals(s2) ) ... If you compare these the other way round, like this: if ( s2.equals("apple") ) ... and s2 is null, you will get a null pointer exception. 2. (Sect. 6) How do you get the code value of a char? I would like to transform a char into the corresponding int value, that represents the code value of the char. How? [*] Like this. char c = 'A'; int i = c; Going the other way is just c = (char) i; This question crops up so frequently because the BASIC language uses functions to map characters into ints, ASC( 'A' ) => 65 causing BASIC programmers to seek the corresponding Java functions. The same is true for Pascal, Ada, and other languages. 3. (Sect. 6) Why does b >>>= 1 give me the same result as b >>= 1? [*] ">>" is a "signed" or "arithmetic" shift, namely, it replicates the sign bit on the left as it shifts. The ">>>" operator is an "unsigned" or "logical" shift; it does a shift right and zero fill. However, ">>>" looks like it does a signed shift with negative bytes and shorts, where int promotion alters the sign. This occurs when you have a non-canonical type, byte, or short, with a negative value, e.g. byte b = -15; // 0xf1 b = (byte) b >>> 4; // why isn't b 0x0f ? The initial expectation is that an unsigned shift right of 0xf1 would successively be (in binary) 0111_1000 then 0011_1100 then 0001_1110 then 0000_1111 But that doesn't happen. The rules of arithmetic in Java say that all operands are converted at least to int before the operation (and possibly to a more capacious type). That means our byte is promoted to an int, so instead of shifting 0xf1, we are shifting 0xfffffff1. If you shift right unsigned 4 places, you get 0x0fffffff. When you cast that to a byte it becomes 0xff, or -1. The bottom line is that the final result is the same as if you had performed the signed shift because the unsigned shift applied to the intermediate int, not to the original byte. This anomaly means that ">>>" is useless for negative bytes and shorts. It is probably safer and clearer not to use it at all, but to mask and shift instead: // not recommended byte b = -15; b = (byte) (b>>>4); System.out.println("b= "+Integer.toHexString(b) ); // recommended b = -15; b = (byte) ( (b & 0xFF) >> 4 ); System.out.println("b= "+Integer.toHexString(b) ); 4. (Sect. 6) Why does the <unexpected> happen in floating point? [*] There are several unexpected things that seem to bite programmers with floating point. This is almost always a result of the programmer not being fully conversant with floating point arithmetic in general, rather than a problem relating to Java. The question of floating point accuracy comes up with Java more than with C++ (for example) because of Java's decision in the println() method to print enough digits to distinguish the number from the next-closest number, rather than rounding it to 6 significant digits by default as the C/C++ libraries do. [ISO C, Sect 7.9.6.1, line 21 of "the double argument"] If you seem to be having problems with floating point, the problem probably stems from the fact that floating-point arithmetic is inherently imprecise. You can expect up to 7 digits of precision with floats and 16 digits with doubles. However, that does not mean that a number that can be exactly represented in 7 digits decimal or can be exactly represented as a binary floating point number. On the contrary, that is usually not the case. Additionally, when Java converts floating point numbers to a String, as is done when they are output, enough digits are printed so the number can be read back in with no loss of precision. For this reason, you may see more "inaccuracies" in floating point output than you are used to. You are actually getting more accuracy than on systems (like C,C++) that suppress the less significant digits. For more information and detailed specifications on how Java deals with floating point, see the URLs listed below. Other sites: What Every Computer Scientist Should Know About Floating Point. http://java.sun.com/products/jdk/1.1/compatibility.html#incompatibilities JLS 4.2.3 Floating-Point Types and Values JLS 4.2.4 Floating-Point Operations JLS 3.10.2 Floating-Point Literals JLS 5.2.3 Narrowing Primitive Conversions http://gams.nist.gov/javanumerics/jgfnwg-01.html See also "the guff from Hough" at http://www.validgh.com/java If you want the rounded floating point output that most languages have, use the new java.text package of Java 1.1 to limit the number of digits that are output. If you need more precision than about 16 digits, use the BigInteger and BigDecimal classes of Java 1.1. Understanding the Java Language 5. (Sect. 6) How can I program linked lists if Java doesn't have pointers? [*] Of all the misconceptions about Java, this is the most egregious. Far from not having pointers, in Java, object-oriented programming is conducted exclusively with pointers. In other words, objects are only ever accessed through pointers, never directly. The pointers are termed "references" and they are automatically dereferenced for you. Java does not have pointer arithmetic or untyped casting. By removing the ability for programmers to create and modify pointers in arbitrary ways, Java makes memory management more reliable, while still allowing dynamic data structures. Also note that Java has NullPointerException, not NullReferenceException. A linked list class in Java might start like this: public class LinkedList { public LinkedList head; public LinkedList next; public Object data; public LinkedList advanceToNext(LinkedList current) { ... } Another choice for a linked list structure is to use the built-in class java.util.Vector which accepts and stores arbitrary amounts of Object data (as a linked list does), and retrieves it by index number on demand (as an array does). It grows automatically as needed to accommodate more elements. Insertion at the front of a Vector is a slow operation compared with insertion in a linked list, but retrieval is fast. Which is more important in the application you have? 6. (Sect. 6) Are parameters in Java passed by value or by reference? [*] All parameters (values of primitive types and values that are references to objects) are passed by value. However this does not tell the whole story, since objects are always manipulated through reference variables in Java. Thus one can equally say that objects are passed by reference (and the reference variable is passed by value). This is a consequence of the fact that variables do not take on the values of "objects" but values of "references to objects" as described in the previous question on linked lists. Bottom line: The caller's copy of primitive type arguments (int, char, etc.) _do not_ change when the corresponding parameter is changed. However, the fields of the caller's object _do_ change when the called method changes the corresponding fields of the object (reference) passed as a parameter. Also in this FAQ: How can I program linked lists if Java doesn't have pointers? Other sites: JLS 8.4.1 Formal Parameters 7. (Sect. 6) What are "class literals"? [*] A feature introduced in JDK 1.1. They are literals of type "Class" that hold a value representing any class. There are even values to represent "void" and an array, like this: Class myCl1 = Character.class; Class myCl2 = Void.class; Class myCl3 = Object.class; Class myCl4 = String[].class; Class myCl5 = int[][].class; You might use it like this: Class cl = thing.getClass(); if (cl.equals(myCl1)) System.out.println("It's a Character class"); Note that a class literal Component.class is the equivalent of Class.forName("java.awt.Component") The second can throw an exception, but the first cannot. If you don't know the name of the class when you write the code, you cannot use the first form. 8. (Sect. 6) What are the naming conventions in Java? [*] The naming conventions are straightforward: 1. Package names are guaranteed uniqueness by using the Internet domain name in reverse order: com.javasoft.jag - the "com" or "edu" (etc.) part used to be in upper case, but now lower case is the recommendation. 2. Class and interface names are descriptive nouns, with the first letter of each word capitalized: PolarCoords. Interfaces are often (not always) called "something-able", e.g. "Runnable", "Sortable". Caution: java.util.Observable is not an interface, though java.util.Observer is. These two are poorly designed. 3. Object and data (field) names are nouns/noun phrases, with the first letter lowercase, and the first letter of subsequent words capitalized: currentLimit 4. Method names are verbs/verb phrases, with the first letter lowercase, and the first letter of subsequent words capitalized: calculateCurrentLimit 5. Constant (final) names are in caps: UPPER_LIMIT 6. Also in the FAQ: Where can I find a Java style guide on naming conventions? Other sites: JLS 6.8 Naming Conventions 9. (Sect. 6) Should I prefer importing {package}.{class} over {package}.*? Does it make a difference to the class file in any way, if I import a package versus use the full name, i.e. import java.rmi.server.*; ... RemoteObject ro; versus: java.rmi.server.RemoteObject ro; [*] No, it makes no difference to the class files or runtime speed. Import is just a shorthand for quoting the full name package and class name (as in the examples in the question). Importing a class does not cause the class to be loaded at run time. There is no runtime penalty for using the * form of import. The class file will contain the name of the packages it uses, and the loader will look for those classes as needed at runtime. At compile time, the different forms of import may or may not make a difference to compile time. Such a difference is likely to be negligible, and should not be a factor in which form of import you use. However, there are style advantages. Some say that stating which classes you are importing can help program readability. In a program with many * import statements, it may take a programmer time to find which package an obscure class is imported from. If you explicitly list each class you import at the top of the program, you document which package each class you use comes from. These people suggest that you use import java.rmi.server.RemoteObject; in preference to: import java.rmi.server.*; Other people say that it is clearer still to use the full package and class name, at the point where you use classes in other packages. These people suggest that you use: java.rmi.server.RemoteObject ro; But that gets a little lengthy when you instantiate: java.rmi.server.RemoteObject ro = new java.rmi.server.RemoteObject(); You always have the option of stating the full package and class name, whether you use import or not. Another good reason not to use the * form is when you are importing two packages that have classes of the same name and you want to use only one of those classes. E.g. import com.sun.*; import com.ms.*; where there is a class called Modem in both those packages. If you use the * form of import, you import both of the Modem classes and then must fully qualify the class each time you use it, to say which of the two you mean. In Java 1.2, the class java.util.List was introduced. That had the same unqualified name as java.awt.List. If your code had "import java.awt.*; import java.util.*;" it would no longer compile. You'd get a message about ambiguous classname. If you import all of a package indiscriminately you might get bitten when the package API changes. In Java 1.0, if you import a class that has the same name as a class defined in that source file, you will get an error that the class names clash. In Java 1.1, the local class will be used when the package name is not given; to use the imported class, you have to use the full package name. The best advice is to write the program so that it is as readable as possible. Where you have a group of well-known classes, as in java.awt, there is no reason not to use "import java.awt.*;" 10. (Sect. 6) How can I use Math.cos() etc. without the prefix "Math."? Is there some declaration that I can use to make "acos", "cos", "sin", etc. (from java.lang.Math) recognizable in my own class, so I don't have to prefix "Math." to them? [*] No. There is no good alternative. There are several bad alternatives: 1. Using "import" doesn't work. The import stament only imports packages, subpackages, and classes, not class members. This doesn't work: import java.lang.Math.*; 2. Minimizing class name usage is unclear and bad style. - You could wrap the functions in your own class. double sin(double x) { return Math.sin(x); } // etc. for each function But you'd have to use your class name everywhere but inside your class, so it doesn't help. - You can make a null reference to the Math class and use it to refer to the static methods. Declare java.lang.Math M = null; angle = M.cos(i); Besides not being clear, this invites abuse and errors. - You could inherit the names If java.lang.Math were not final and your class did not extend another class, you could have your class extend Math, to bring the namespace in. However, it is poor OOP style to use inheritance to obtain a name abbreviation rather than to express a type hierarchy. 11. (Sect. 6) Why is there a standard JNI? [*] JNI is the Java Native Interface. It defines the way that a Java program can call C programs. The industry has agreed on, and Sun has codified, JNI as the standard. Microsoft shuns the standard and uses a protocol of its own called Raw Native Interface, RNI. You might think that once a Java program uses JNI, portability is lost, and hence it doesn't matter if vendors diverge from the JNI standard. Not so. Code that accesses a native library using JNI can run on any VM that supports JNI, so it's portable across VMs on the same platform. Further, you can port a native library to all platforms Java supports (indeed, this is how Sun implements the Java Platform), so JNI _enables_ cross-platform development where it's necessary to use platform-specific idioms for certain functionality. Conversely, code that uses RNI can only run on Microsoft's VMs on the win32 platform. Microsoft's RNI has the effect of limiting RNI programs to the Microsoft VM. Further, Microsoft's failure to support JNI locks out JNI-based functionality on Windows. Microsoft's non-standard RNI is the reason that programs using the Microsoft JVM cannot use the standard Java jdbc-odbc library. That library has a piece written in C. It works for all JVMs except Microsoft's. The standard JNI thus has two purposes: 1. Source code compatibility between different platforms. 2. Binary code compatibility between different JVMs on the same platform. Microsoft's use of RNI locks in programmers who use it, and Microsoft's failure to support JNI locks out programmers who don't use RNI. Users can't run standard JNI applications on Microsoft VMs, or RNI applications on non-Microsoft VM's. As a result, since most users will support only one VM, they'll be locked in to complementary software - in the case of Microsoft, a proprietary standard. A standard JNI means that you can use any standard JVM to run your code on this platform. 12. (Sect. 6) How do I find out more about JNI? How do I find out more about Java Anything? [*] Taking the questions one at a time. Use of JNI detracts from program portability. So you would only do it when you need some critical single-platform effect. The documentation on JNI is at: http://java.sun.com/docs/books/tutorial/native1.1/index.html If your interest extends to reading a book on JNI, a good one is "Essential JNI Java Native Interface" by Rob Gordon; ISBN 0-13-679895-0. See http://www.amazon.com/exec/obidos/ASIN/0136798950/afuinc In general, if you want to find out about topic "X" in Java, your first stop should be to search the http://java.sun.com website for "X". For example if you want to know about Internationalization in Java, a search at the site quickly takes you to http://java.sun.com/products/jdk/1.1/docs/guide/intl/intlTOC.doc.html. 13. (Sect. 6) How do I get unsigned ints in Java? [*] Java doesn't have unsigned ints. The reason is that this is a poorly designed area of C. The rules for what type you end up with when you mix signed and unsigned in expressions are complicated, and they changed between K&R and ANSI C (you might have heard this under the name "unsigned preserving vs. value preserving"). Worse, they depended on the underlying hardware, so they varied from platform to platform, causing bugs in all kinds of unexpected places. The book "Expert C Programming" goes into this in more depth (page 25). So, to avoid bringing over the hidden complexities, Java does not bring over unsigned types from C. Use type char if you are OK with 16-bit unsigned quantities. Otherwise, go to the next larger type and use masking. If you don't have to worry about division by numbers with the high bit set, then when you use >>> for right shift and remember to AND each byte with 0xFF where they are being expanded into a larger type, then there is no difference in the bit patterns generated. Specifically, to convert an int to its unsigned representation, use: ((long)i) & 0x00000000FFFFFFFFL This promotes the signed (and possibly negative) int to long (with sign extension) then chops off the sign-extension, leaving it as the same 32-bit quantity held in a 64-bit type. Also worth noting is that if you're going to work with unsigned bytes, int is a more efficient larger type to use than short or char, since smaller values have to be promoted to int to do any arithmetic or testing on them. 14. (Sect. 6) What happened to "private protected"? [*] It first appeared in JDK 1.0 FCS (it had not been in the betas). Then it was removed in JDK 1.0.1. It was an ugly hack syntax-wise, and it didn't fit consistently with the other access modifiers. It never worked properly: in the versions of the JDK before it was removed, calls to private protected methods were not dynamically bound, as they should have been. It added very little capability to the language. It's always a bad idea to reuse existing keywords with a different meaning. Using two of them together only compounds the sin. The official story is that it was a bug. That's not the full story. Private protected was put in because it was championed by a strong advocate. It was pulled out when he was overruled by popular acclamation. Inheritance 15. What are the differences between an interface and an abstract class? [*] Some use a semantic distinction: an abstract superclass models the "is" relationship, while an interface models the "has" relationship. The rule would be, if it's a subtype, inherit; otherwise, implement. But, in the absence of real-world characteristics to distinguish the objects from their properties and parents, that becomes a circular argument. In this case, you have to look at the practical differences in Java (compared with C++). Most differences between interfaces and abstract classes stem from three characteristics: 1. Both define method signatures that a derived class will have. 2. An abstract class can also define a partial implementation. 3. A class can implement many interfaces, but inherit from only one class. In greater detail, these topics are: 1. Method signatures Both interfaces and abstract classes permit one to treat the derived-type class as the derived-from-type class. Both define a set of available methods in a way that can be enforced by the type-checking mechanism. This is typically used to permit different (derived) types to behave in the same way (as what they are derived from - i.e., they all support particular methods). For example, all java.* types can be printed as Strings because Object, the superclass of all java.* types, has a toString() method. Similarly, all types that implement the Observable interface can be passed an Observer to signal when an event has occurred. This permits an algorithm or service to operate on different (derived) types as if they were the same (derived-from) type. This mechanism supports not only polymorphism (one object treated as another), but differentiation. In either case, the (derived) types can implement the method in the way appropriate to that type. However, you're not likely to override inherited functionality, but you must implement interface methods, so if you expect significant differentiation, then an interface might be warranted. Finally, this mechanism supports a weak variant of access control. Only inherited methods are available to callers who only have a reference to the superclass or interface type. It's weak because they can attempt a narrowing cast if they know their target type. Nonetheless, it reduces some complexity. 2. Inheriting implementation Inheriting an implementation is useful where the code should be shared. This happens where derived types vary the functionality only a little bit, or where a complex set of method interfaces can through mutual reference be implemented with relatively few methods that can be implemented by derived types. You can also reuse code by having your class use or keep an object of another type that implements that code, but that doesn't permit your callers to treat you in a particular way. To both "get" functionality and to be treated "as" the superclass are the essentials of the type/subtype relationship. 3. Java's rule of single inheritance Java differs from C++ in permitting only single inheritance. This makes for some difficult choices, if you would like to share combinations of inherited functionality and polymorphism from more than one source. However, it does reinforce the notion of inheritance as a subtyping (is) relationship, and implicitly that type relationships form a tree rather than a network. Other differences to consider: 1. Abstract class implementations may include fields 2. Interfaces may include final data members 3. It is slightly slower to call an implemented method via an interface reference. There is an even smaller penalty for calling a superclass method via a subclass reference (i.e., where the subclass does not override the method). There is almost no penalty for calling a subclass method via a superclass reference. (All are compared to a direct method call, i.e., calling the derived class method via a derived class reference). 16. (Sect. 6) How do static methods interact with inheritance? [*] Static (per-class, rather than per-object) methods do not participate in overriding (choosing the right method at runtime based on the class of the object). Probably the best and simplest way to think about this (and to write your code) is to write every invocation of a static method using the fully qualified class name: class A { public static method1() { A.method2(); } public static method2() { } } class B extends A { public static method3() { A.method1(); } public static method2() { } } Now it is perfectly clear that the static method2() that is called is A.method2(), not B.method2(). A.method2() will be called regardless of whether you use the fully-qualified class name or not, but using "A." makes it obvious to all. 17. (Sect. 6) Why is the String class final? I often want to override it. [*] Being final guarantees that instances of String are read-only. (The String class implements read-only objects, but if it were not final it would be possible to write a subclass of String which permitted instances to be changed.) Strings need to be read-only for security and efficiency. As for efficiency, Strings are very commonly used, even behind the scenes by the Java compiler. Efficiency gains in the String class yield big dividends. If no one can change a String, then you never have to worry about who else has a reference to your String. It's easier to optimize accesses to an object that is known to be unchanging. Security is a more compelling reason. Before String was changed to be final (while Java 1.0 was still in beta) there was a race condition which could be used to subvert security restrictions. It had to do with one thread changing a pathname to a file after another thread had checked that the access was permitted and was about to open it. There are other ways to solve these problems, but the designers preferred making String final, particularly since the StringBuffer class is available as an alternative. 18. (Sect. 6) If I extend/subclass a class, are the constructors inherited? [*] "Constructor declarations are not members. They are never inherited and therefore are not subject to hiding or overriding." The default constructor is not inherited, but provided. (See JLS 8.6.7 Default Constructors) If you don't give your child class any constructors, a default no-arg constructor that invokes the superclass' constructor is provided for you. If the superclass doesn't have a no-arg constructor, you should create a constructor and call the appropriate superclass constructor. Also in the FAQ: Compiler message No constructor {superclass}() Other sites: JLS 8.6.7 Default Constructors 19. (Sect. 6) How can I safely store particular types in general containers? I often want to store particular types of objects but don't want to subclass my basic storage classes to enforce the particular type; that would make for too many subclasses (e.g., IntegerLinkedList, StringLinkedList, etc.). [*] Generic programming in java (the rough equivalent of C++'s templates) works reasonably well since all java classes are subclasses of Object. There is, however one potential problem - there is always a possibility that a generic container may contain different classes of objects. This naturally leads to the question of how to do this in a type-safe way. If you've created a generic LinkedList class, how can you be type safe without having to create a multitude of subclasses (IntegerLinkedList, StringLinkedList, etc.)? One way to handle this would be to offer up an additional constructor in your generic class that takes a parameter of type "Class" and uses that parameter along with Class's "isInstance" method to guarantee that Objects added to the container are the expected type. public class LinkedList { Protected Class type = Object.class; public LinkedList(Class type) { this.type = type; } public void addElement(Object element) throws Exception { if(!type.isInstance( element )) throw new Exception( "Expected element of type (" + type + ")" + " got element of type (" + element + ")" ); ... } } Note that the comments in the source for isInstance() refer to a "specified Class parameter", suggesting that you are supposed to write something like: public void addElement(Object element) throws Exception { Class c = element.getClass(); if(!type.isInstance(c)) This works, but the documentation for isInstance is clear that the parameter should be an Object rather than a Class. Also, note that "Collections" are coming in JDK 1.2, and they provide a much safer and more extensible mechanism. More information about this is available at the Java Developer Connection at the Java website: http://java.sun.com/ Method interfaces 20. How do I send a variable number of arguments to a method? [*] 1. (Easy) Use method overloading to support different parameters. This makes things easy on the caller but can get out of hand if you want to support a wide number and variety of parameter types. You should ask yourself if your code design is well-organized if you need to do this. 2. (More complicated) Use arrays. It's even possible to declare arrays inline as shown below: foo("A param", new Object[] {"param3", "param4", new Integer(5)} ); // ... void foo(String param1, Object param2[]) { System.out.println(param1); for (int i = 0; i < param2.length; i++) { System.out.println(param2[i].toString()); } } You can even pass arrays of arrays using this method. Of course, inside the method you need to be able to decode what the arguments are and how you use them. 3. Alternatively you can invent a class that just contains all the possible fields you might want to pass into a method (plus booleans to say if each field is set or not), and make an object of that class be a parameter to the method. You can return multiple values from a method the same ways; either have the method return an array or a wrapper object. However, remember the wise words of Professor Alan Perlis, "if your procedure has more than about half a dozen parameters, you probably forgot a few." Passing large numbers of arguments into a function suggests your function is badly organized. 21. (Sect. 6) How can I return a different object in a method parameter? How can I pass an object to a method, and have the method change the reference so it points to a different object back in the calling code? indirection". Wrap the object in another class, whose purpose is simply to be passed as a parameter, allowing the nested object reference to be modified. The second alternative is a clearer variant of this. Pass in a single element array. Since arrays are objects, this works. void jfoo(Object ref[]){ ref[0] = new Object(); } ... Object kludge[] = new Object[1]; kludge[0]= myObj; jfoo(kludge); if (kludge[0] == myObj) ... else ... Note that changing a global variable/object inside a method is an egregious programming practice; it usually violates basic OOP constructs. 22. (Sect. 6) How do I get multiple return values back from a method? [*] You can just have the function return a Vector. This is particularly convenient when you're not sure how much you are going to be returning, based on what occurs in the method. A Vector is essentially a dynamically-growable array. Regular arrays can't grow after you declare them - you have to declare a bigger array and move the old stuff into it. Arrays 23. (Sect. 6) How do I allocate a multidimensional array? [*] There are several ways. If you want a rectangular array, you can allocate the space for the array all at once. The following creates a 4x5 array: int arr[][] = new int[4][5]; If you want each row to have a different number of columns, you can use the fact that a two-dimensional array is actually an array of arrays. The following code allocates a triangular array: int arr[][] = new int[4][]; // allocate the four row arrays for (int i = 0; i < 4; i++) // initialize each of the four rows arr[i] = new int[i + 1]; // row i has i + 1 columns Note that if you allocate an array of any kind of object (as opposed to primitive type), all the references will be null by default. These null references can result in NullPointerExceptions if you try to dereference them. In other words, after doing: int arr[] = new int[4]; you can say if (arr[2] == 0) But after doing Integer Iarr[] = new Integer[4]; you must fill in the object reference before using it. E.g., Iarr[2] = myInt; or arr[2] = new Int(27); before you can say if (Iarr[2].equals(myInt)) 24. (Sect. 6) How do I copy an array? [*] If the array only contains primitive types or if you want to copy only the object references, not duplicate the objects, then use the method java.lang.System.arraycopy(Object src, int src_position, Object dst, int dst_position, int length); Otherwise, if you want to duplicate the objects, you have to initialize your new array and write a loop that duplicates each object in the old array into the new. Note that the documentation for arraycopy() says that if src and dst refer to the same object, then arraycopy behaves as if the source array elements are copied into a temporary array (i.e., they are preserved). Some interpret this as meaning a temporary array will be so allocated, but that's not Sun's implementation. Other sites: JLS 20.18.16 {java.lang.System.arraycopy()} 25. (Sect. 6) How do I clear an array? [*] There is no method to clear an array to 0.0, 0, null, false, '\u0000' etc. When you allocate an array, the elements are set to their default values, but that doesn't help when you want to reuse an array. If you want to set the same array to the same set of values many times, create a template array. Fill it with the reset value, then use System.arraycopy() to copy it into the work array each time you need to set the work array. 26. (Sect. 6) What is a fast way to set all elements of an array? I don't want to use a template array. I would like to set all array elements to a given value without duplicating the (possibly large) array. [*] Using a loop that does it one by one is probably 20 to 40 times slower than good old memset() in C. A fast way on many VM's is to set the first byte of the array, then use System.arraycopy() repeatedly to fill the next byte, the next two bytes, the next four bytes, the next eight bytes, etc., and when you get past halfway, fill in the rest. public static void bytefill(byte[] array, byte value) { int len = array.length; if (len > 0) array[0] = value; for (int i = 1; i < len; i += i) System.arraycopy( array, 0, array, i, ((len - i) < i) ? (len - i) : i); } This is faster on Sun's VM than a simple loop, and probably even faster under JITs because it only performs at most log2(array.length) bounds checks. This is a clever code idiom applying the binary chop algorithm to arrays even when their size is not a power of 2. ------------------------------- 7. I/O 1. (Sect. 7) How do I read a file containing ASCII numbers? [*] There are several ways to do this. Here is one way. Let's assume your file is called "C:\work\mydata.txt" and it contains lines like: 135 7512 3659814 328 1 54829 68522 19982810 38 i.e. lines contain several ASCII strings that are numbers separated by spaces. The code fragment is as follows: // Open the file with RandomAccessFile f = new RandomAccessFile("c:\\work\\datafile.txt", "r"); // read an entire line from it String s= f.readLine(); // get some methods to break up a line into tokens StringTokenizer st = new StringTokenizer(s); // extract the next int from the line i = Integer.parseInt(st.nextToken()); We use a RandomAccessFile because that supports the readLine() method directly. An alternative would be to instantiate a FileReader, and wrap a BufferedReader around it. Putting it all together, including the exception handling in the event the file is missing, the code looks like: import java.io.*; import java.util.*; public class c { public static void main(String args[]) { try { RandomAccessFile f = new RandomAccessFile ("datafile.txt", "r"); String s; while ( (s=f.readLine()) != null ) { System.out.println("read: "+s); StringTokenizer st = new StringTokenizer(s); int i=0; while (st.hasMoreTokens()) { i = Integer.parseInt(st.nextToken()); // i now holds the next int on the line // could also use Double.parseDouble(), etc. System.out.print(" "+ i); } System.out.println(); } } catch (Exception e) {System.out.println("Excpn: "+e); } // file I/O, from book "Just Java" by Peter van der Linden } } See also the next question on how to read data interactively. 2. (Sect. 7) How do I read a String/int/boolean/etc from the keyboard? [*] The easiest way is to pick up the source for the 100% pure Java class EasyIn from http://www.afu.com/ (same place as this FAQ). Compile it with your code and use it like this: EasyIn easy = new EasyIn(); int i = easy.readInt(); // gets an int from System.in boolean b = easy.readBoolean(); // gets a boolean from System.in double d = easy.readDouble(); // gets a double from System.in ... etc. EasyIn is free, comes with source, and you can do what you like with it, including improve it, and send me back the results. If, instead, you want to "roll your own" code (why?!), in JDK 1.0.2 java.io.DataInputStream in = new java.io.DataInputStream(System.in); String s = in.readLine(); One way in JDK 1.1: java.io.BufferedReader in = new java.io.BufferedReader( new InputStreamReader(System.in)); String s = in.readLine(); Once you have the token in a String, it is easy to parse it into one of the other types, as shown earlier in the FAQ. Yes, it is bone-headed, as it makes the simplest case of keyboard I/O unnecessarily complicated. A bug was filed with Javasoft to record this problem, but don't count on this being fixed any time soon. 3. (Sect. 7) Why do I have trouble with System.out.println()? [*] Check the spelling. The last two characters are the letters "ell enn" not "one enn". The name of the method stands for "print line", since it prints a String and goes to the next line, rather than staying on the same line as System.out.print() does. Yes, the name is yet another Java naming inconsistency, since the input equivalent is readLine(), not readln(). 4. (Sect. 7) How do I write to the serial port on my PC using Java? [*] There is a platform-independent serial port API introduced in JDK 1.2. You can download the documentation by registering with the Java Developer Connection (it's free, http://java.sun.com) and browsing http://java.sun.com/jdc/earlyAccess/communications.html. For systems prior to JDK 1.2, read on. At least two companies have written a library to drive the port. See o http://www.sc-systems.com has a library for Windows 95, WindowsNT, OS/2, Macintosh PPC, Solaris Sparc, Linux x86, FreeBSD x86, HP/UX PA-RISC, and possibly others too. o http://www.cd.com/portio o In addition, there is a Unix serial port utility available with source at http://jarvi.ezlink.com/rxtx/ It's free under the GPL, and works on Linux, Irix, Solaris, Windows 95, and NT. While not helpful to typical home users, there is an alternative portable COM port solution for Java 1.1 and even 1.0. Buy your COM ports in the form of "terminal servers". Using a COM port is now as easy as connecting to it with a Socket. Port parameters can be changed programatically using SNMP for most terminal servers (but this is never necessary when a modern modem or other fixed-rate equipment is attached). Any networked box can serve as a terminal server - even Win95 - with a simple native server application for that box, but buying an actual firmware based hardware box is much easier. Furthermore, your Win95 native applications can now share the COM ports (and any attached modems) via a Win95 product called "Dial-out IP" at http://www.tactical-sw.com/. If the port exists as a pathname in the filesystem, you can open it as a file and read/write. You can also print text this way by writing to "prn" or "lpt1" on a pc, and "/dev/something" on Unix. Writing a formfeed at the end of the file is essential on Windows 95. Here is some sample code: // class that opens the printer as a file // and writes "Hello World" to it import java.io.*; public class lpt { public static void main (String[] argv) { try { FileOutputStream os = new FileOutputStream("LPT1"); //wrap stream in "friendly" PrintStream PrintStream ps = new PrintStream(os); //print text here ps.println("Hello world!"); //form feed -- this is important //Without the form feed, the text will simply sit // in print buffer until something else gets printed. ps.print("\f"); //flush buffer and close ps.close(); } catch (Exception e) { System.out.println("Exception occurred: " + e); } } } If you wish to change the characteristics of the port (e.g. baud rate, parity, etc.), not just read/write data, Java currently offers no portable way to do this. You will need to use one of the packages mentioned above or some native code or a system command. 5. (Sect. 7) How do I append to a file? [*] There are two ways. JDK 1.1 introduced new constructors for two of the output classes that allowed you to set a boolean flag: public FileWriter(String fileName, boolean append) throws IOException public FileOutputStream(String name, boolean append) throws IOException Another way is to do this: RandomAccessFile fd = new RandomAccessFile(file,"rw"); fd.seek(fd.length()); Then write using fd. Note that the latter method does not take advantage of the "append" mode present in many operating systems (such as all Unixes). Such a difference may make a difference with multiple processes or threads appending to the same output file. This can happen frequently, even if not intended by the programmer, e.g. with logfiles in multitasking environments. 6. (Sect. 7) Is it possible to lock a file using Java ? [*] JDK 1.2 introduces the ability to lock a file (indirectly) using the File class. Use createTempFile() with delete on exit. Prior releases of Java do not feature an API to lock a file or regions within a file. Code that needs to do this must take one of four approaches: 1. Implement an advisory locking scheme using features that Java does have (synchronized methods). This allows you to lock files against use by other Java code running in the same JVM. 2. Use the atomic operation File.createNewFile(), and mark it as deleteOnExit(). Have all processes (Java and non-Java) follow the same protocol: if the create operation succeeded, you have the lock. To give up the lock, you either delete the file or exit the JVM. Note that this may fail if the file is remotely mounted using NFS version 2. (There's a window of opportunity bewteen the LOOKUP to see if it's already there, and the CREATE if it's not). However, NFS version 3 does guarantee exclusive create of remotely mounted files, and is not subject to this race condition failure. 3. Make calls to native code to issue the locking ioctls. This approach is not portable, but gives you a shot at having your locks respected by legacy code in non-Java programs using standard locking ioctls. 4. Push the work to a central server. Since socket connection requests arrive in a single queue on the server, this can be used to serialize lock requests. There might be some merit in copying the NFS lockd protocol for a general approach. Rolling your own simple version for a specific application is pretty easy. A database would be better off locking records or fields, not byte offsets. In theory, the server socket approach would make it easier to perform automatic cleanup of a lock on abrupt VM process failure, e.g. by asking "are you still alive?" to the lock holder occasionally. 7. (Sect. 7) How do I make the keyboard beep in Java? [*] In JDK 1.1, java.awt.Toolkit has the method beep(). The pre-1.1 alternative of System.out.print("\07"); System.out.flush(); (the ASCII BEL character) doesn't work on Macs, but does on some other platforms. Java doesn't support the C abstraction of '\a' for an alert character. 8. (Sect. 7) How do you do file I/O from an applet? [*] For security reasons, untrusted applets accessed across the network are restricted from doing certain operations, including I/O. This prevents rogue applets from sending out your private data, or deleting it. A trusted (signed) applet can perform these operations (JDK 1.1 on). The simplest approach for server-side I/O is to use the Linlyn class available from http://www.afu.com. This is free software under the GNU license, and uses FTP to move files between an applet and the server. It is suitable for low-volume non-critical use like keeping a high-score file. The Linlyn class has a very simple application programmer interface. o The following suggestion is for server-side input. You can read a file on the server if you can create a URL referencing the file. Then open a stream, then use any of the stream-based methods to read. This allows reading but not writing. It requires an http daemon running on the server, which will usually be the case. try{ URL url = new URL("http://somewhere.com/test.txt"); // or URL url = new URL( getDocumentBase(), filename); BufferedReader in = new BufferedReader( new InputStreamReader( url.openStream() ) ); String s = in.readLine(); //read till you get a null line. } catch(MalformedURLException e){ System.out.println("URLException:"+e); } catch(IOException e){ System.out.println("IOException:"+e); } } You cannot write a file on the server this way. o The following suggestions are for server-side output. It absolutely requires the cooperation of the server to allow an applet to write a file to the server. This cooperation may take any of several forms: + FTP server + File server (webnfs or custom written) + Listening on a socket for data from applets + CGI script + Java RMI (remote method invocation) + JDBC process In particular: + FTP code. Use the Linlyn class mentioned above. + WebNFS. This is an evolution of the NFS (Network File System) to make file resources visible in browsers. More information at http://www.sun.com/webnfs + Open a socket back to the server and read/write the data. Have a process on the server that listens for socket connections from applets and does the requisite I/O. This does I/O on the server. + Or use a CGI script or servlet on the server to write when browsed. o The following suggestions are for client-side I/O. Use a trusted applet (see section on security). This will permit local I/O without any of the restraints mentioned above. In this regard, the appletviewer and many other browsers regard applets loaded from a local filesystem (rather than across the net) as being more trustworthy, and perhaps even allowed to do I/O. o The simplest form of output is probably for the applet to connect to the mailserver port on the server, and prompt the user to enter his email address. Then email him the data to save locally if he wishes. If a small amount of data he can later enter it by cut-and-paste into the applet when he next invokes it. o Or use a browser that has a security policy that is configured to allow file I/O (such as Sun's appletviewer). o Read this article http://www.javareport.com/html/features/archive/9802/somers.shtml for an introduction to the basics. 9. (Sect. 7) What are Resources files and how do they work? [*] In Java 1.1 and above, a resource file is a file that your code should be able to access no matter where it was loaded from: the local file system, via http, or some other means. This is a different concept than system resources. See question (TBD) for more information about system resources. (Volunteer sought to write answer on system resource files). There are two ways to specify resources. o using an absolute path name, such as "/myPackage/resourcedir/myResource.txt" With an absolute path name, the resource file is actually relative to the classpath. o using a relative path such as "dir/myResource.txt". If you specify a relative path, then the file is found relative to where the class loader found the package of the Class that is loading the resource. The consequence of this is that relative resource files can only be in the same directory as your class file or in a directory below. If you want to access resources from an unsigned applet, use relative resources. There are a couple of methods to get at resources, including methods in the java.lang.Class and java.lang.Classloader. It uses the class loader because that code knew where to find the class on the filesystem. If the resource file is nearby, it can be found the same way. One simple method to get a stream for a resource for a particular class, say Mypackage.MyClass, is as follows: String relativePath = "resourceDir/somefile.txt"; String absolutePath = "/somePackage/somefile.txt"; InputStream in=Mypackage.MyClass.class.getResourceAsStream(relativePath); If the class cannot be loaded, "in" would be assigned a null value. Otherwise, you can use the inputStream just as any other. A brief note about the syntax used above. In java 1.1 and above, a java.lang.Class object for a particular class can be acquired by appending .class to the class's name. Though it looks like every object has a static member variable, this is not actually the case. When using resources with Netscape, be aware of the Netscape restrictions that: o Netscape does not implement the getResource() methods in java.lang.Class and java.lang.ClassLoader, but only getResourceAsStream() methods. o All resources must be in a Jar/archive file o Resource files must have a Netscape-approved extension, or you must call certain functions before hand. See the following for details: http://developer.netscape.com/docs/technote/java/getresource/getresource.html Internet Explorer does not seem to have these restrictions. One final "gotcha" is that jpgStream.available() (wrongly) returns 1 when .gif files in the .jar file are compressed! Some people now create a .jar file in two steps, essentially: jar cvf x.jar *.class jar uf0 x.jar *.gif This ensures .gifs are not compressed, and hence that available() doesn't lie to you. David Alex Lamb stumbled onto this after wondering why his .gif files looked bad, then realized that compression of a .gif might throw away detail. The conjecture is that available() returns 1 because it has to block to do uncompression. 10. (Sect. 7) How do I execute a command from Java? How do I do I/O redirection in Java using exec()? [*] See the answer to Question 18.7. 11. (Sect. 7) I used a C program to write a binary file. When I instantiate a DataInputStream on the file in Java, and try to readInt, I do not get the correct numbers. Why is this? [*] Java does everything in network byte order (big-endian order), as do many computers including Motorola, and SPARC. The Intel x86 uses little-endian order in which the 4 bytes of an int are stored least significant first. Rearranging the bytes on the way in will get you the results you need. This is only necessary when the file was written by a non-Java program on a little-endian machine such as a PC. The following code will byte-swap little-endian integers into network standard order: public int swap(int i) { int byte0 = i & 0xff; int byte1 = (i>>8) & 0xff; int byte2 = (i>>16) & 0xff; int byte3 = (i>>24) & 0xff; // swap the byte order return (byte0<<24) | (byte1<<16) | (byte2<<8) | byte3; } Alternatively, the following code assembles bytes from a byte array that is in big-endian order (as used by Java) into an int: byte[] bytes = ... // whatever int start_index = ... // wherever int value = 0; for ( int i = start_index; i < start_index+4; ++i ) { value = ( value << 8 ) | ( bytes[i] & 0xFF ); } If the bytes are in little-endian order, just change the "for" for ( int i = start_index+3; i >= start_index; --i ) And this code will assemble a double that has been written in reverse byte order: byte[] gnol = new byte[8]; stream.read(gnol); long l = ( ( (gnol[7] & 0xff) << 56) | ( (gnol[6] & 0xff) << 48) | ( (gnol[5] & 0xff) << 40) | ( (gnol[4] & 0xff) << 32) | ( (gnol[3] & 0xff) << 24) | ( (gnol[2] & 0xff) << 16) | ( (gnol[1] & 0xff) << 8) | (gnol[0] & 0xff) ); double d = Double.longBitsToDouble(l); 12. (Sect. 7) How do I make I/O faster? My file copy program is slow. [*] This is the purpose of BufferedInputStream. It is a flaw in Java that buffered I/O is not the default, with a flag or different constructor to turn it off. I/O is the second worst designed package in Java, after the Date class. , 13. (Sect. 7) How do I do formatted I/O of floating point numbers? [*] Use the class java.text.NumberFormat. Or use http://www.newbie.net/sharky/lava/. Or use Cay Horstmann's http://www.horstmann.com/corejava/Format.java Although many utilities claim to handle all varieties of C's printf, as far as has been found, this is the only one to correctly handle the equivalent of %e in printf. See also the standard packages java.text.DecimalFormat and java.text.NumberFormat 14. (Sect. 7) How do I read numbers in exponential format in Java? [*] The program below (written by Steve Chapel) uses StreamTokenizer to read data from the standard input and recognizes doubles in exponential format (e.g. -1.23e-45). import java.io.*; public class ReadExponential { public static void main(String argv[]) { DataInputStream in = new DataInputStream(System.in); StreamTokenizer st = new StreamTokenizer(in); try { while (st.nextToken() != StreamTokenizer.TT_EOF) { switch (st.ttype) { case StreamTokenizer.TT_NUMBER: double num = st.nval; int exp = 0; st.ordinaryChars('\0', ' '); st.nextToken(); st.whitespaceChars('\0', ' '); if (st.ttype == StreamTokenizer.TT_WORD && Character.toUpperCase(st.sval.charAt(0)) == 'E') { try { exp = Integer.parseInt(st.sval.substring(1)); } catch (NumberFormatException e) { st.pushBack(); } } else if (st.ttype < 0 || st.ttype > ' ') st.pushBack(); System.out.println("Num " + num * Math.pow(10, exp)); break; case StreamTokenizer.TT_WORD: System.out.println("Word " + st.sval); break; default: System.out.println("Char '" + (char) st.ttype + "'"); break; } // end switch } // end while } catch (IOException e) { System.out.println("IOException: " + e); } } // end main } 15. (Sect. 7) I'm trying to read in a character from a text file using the DataInputStream's readChar() method. However, when I print it out, I get ?'s. [*] Remember that Java characters are 16-bit Unicode characters, while many hosts systems store characters as 8-bit ASCII characters. Therefore, to read individual chacters from a text file, you need to ensure the proper conversion. The proper way to do this is to use an InputStreamReader, which converts from 8 to 16 bit streams: FileInputStream fis = new FileInputStream("myfile.txt"); InputStreamReader isr = new InputStreamReader(fis); char c3 = (char) isr.read(); The less-favored way (because it is not so portable, as the encodings translation is not done) is just to read a byte and cast it into a character: FileInputStream fis = new FileInputStream("myfile.txt"); DataInputStream dis = new DataInputStream(fis); char c1 = (char) dis.readByte(); 16. (Sect. 7) How do I delete a directory in Java? [*] JDK 1.0 did not support directory removal. JDK 1.1 supports directory removal with the method: public boolean delete() in class java.io.File Make sure you don't have any open streams in the directory you're trying to remove. Do a close() on all streams, even if the underlying file is gone. 17. (Sect. 7) How do I tell how much disk space is free in Java? [*] There currently aren't any good Java APIs for system introspection. There is no Java way to control processes, or look at system resources. You can use Runtime.getRuntime().exec() to do "df" on unix or "dir" on Windows right now. Alternatively, check out JConfig: http://www.tolstoy.com/samizdat/jconfig.html JConfig is a cross-platform library that fills in many of the gaps in the core Java API, and makes it possible to work with files, processes, file types, video monitors, etc. in a much more Windows- and Mac-friendly manner. 18. (Sect. 7) How do I get a directory listing of the root directory C:\ on a PC? [*] The obvious approach of calling File.list("C:\"); does not work. There are two reasons why this fails. First, slash is an escape character in Java, so if you want a literal slash, you have to repeat it. Second, you need to give the name of the directory, i.e. dot. Putting this together, either of the following calls will work File.list("C:\\."); or File.list("C:/."); Note: a file separator of "/" works just as well as "\" in most Windows programs and library calls. It is an artifact of DOS's origin's as a ripped-off port of CP/M. When Microsoft bought the rights to DOS from Seattle Computer Products (what, you didn't know Microsoft didn't develop DOS? They didn't even own the rights to DOS at the time the contracted with IBM to supply DOS for the PC) they were buying software which was an unauthorized port of the CP/M operating system. CP/M didn't have directories, so it didn't use pathname separators. The forward slash "/" was already used for giving options to CP/M commands, so "\" was pressed into service as the DOS pathname separator, but the DOS shell was taught to understood "/" for compatibility with other OS's. See also JConfig in Q6.15. 19. (Sect. 7) What is the difference between the various ZIP formats: ZIP, GZIP, and PKZIP? [*] Zip is an archive file format, popularized on PCs, that contains multiple compressed files. GZIP comes from Gnu. It is essentially a one file subset of the Zip format. You can't put a whole directory into a GZIP archive, just a single file. It's intended for compressing a tarball of many files. PKZIP is a set of commercially available programs that create Zip files. All three use the deflate compression format, which is based on the LZ77 algorithm. This compression is also used by the ZLIB library and hence the PNG graphics file format (which uses ZLIB). PNG - Portable Network Graphics - provides a patent-free replacement for GIF and TIFF. An alternative compression technology, LZW compression, is encumbered by Unisys's patent. LZW is used in GIF files and by the Unix compress command. Luckily, as well as being free from patent restrictions, LZ77 also gives better compression than LZW. LZW is the initial letters of the last names of the three computer scientists who developed the algorithm (Lempel, Ziv, Welch). The basic classes (all in java.util.zip) that read LZ77 Zip format are Deflater and Inflater. These are used by the stream classes DeflaterOutputStream and InflaterInputStream. The java.util.zip classes GZIPInputStream and ZipInputStream inherit from InflaterInputStream. PKZIP is a commercial program for DOS, Windows, and OS/2, sold by PKWARE Their FAQ, at http://www.pkware.com/zipgfaq.html, specifically says "Because PKWARE has dedicated the .ZIP file format to the public domain, it is possible for other people to write programs which can read .ZIP files. NOTE THAT THE PKZIP, PKUNZIP, PKSFX PROGRAMS AND THEIR ASSOCIATED SOURCE CODE AND SUPPORT PROGRAMS ARE THE EXCLUSIVE PROPERTY OF PKWARE INC. AND ARE NOT PUBLIC DOMAIN SOFTWARE PROGRAMS. The "other people" PKZIP's FAQ refers to is the InfoZIP project, a group of public-minded programmers spread over the world producing free software that works on most ANSI C compilers and platforms. See http://www.cdrom.com/pub/infozip/. Jar files are in ZIP format, but are not as complete as a full filesystem archive format since file permissions are not saved. Some versions of WinZip are known to be inadequate for processing the full PKZIP format. Use InfoZIP instead. 20. (Sect. 7) How can I use characters other than ASCII in Java? [*] Search for the article titled "Adding Fonts to the Java Runtime" or visit: http://java.sun.com/products/jdk/1.2/docs/guide/internat/fontprop.html The article explains how to add fonts to Sun's JDK 1.2 using the font.properties file. [If anyone has summarised the information, please send it in]. 21. (Sect. 7) I did a read from a Buffered stream, and I got fewer bytes than I specified. [*] This is the way that BufferedInputStream works up to and including the current release. The behavior is so unintuitive that it really represents a bug. Javasoft has "resolved" the bug by writing comments in the program so that the broken behavior is in the range of legal outcomes. Ugh. When you instantiate a buffered input stream, you can specify the size of buffer it should use. Let's call this the internal buffer. When you call read() you can say how many bytes to read. Let's call this the request. If the request is smaller than the internal buffer and not a multiple of the internal buffer, then the last read returns only the odd bytes left in the internal buffer! The more reasonable and intuitive behavior would be for the internal buffer to be refilled, so that the whole request can be granted. For example, if you create a BufferedInputStream with an internal buffer of 1000 bytes, and try to read 512 byte chunks, your first read will return 512 bytes, but your second read will only return (1000-512), or 488, bytes. (Assuming that the file has at least that many bytes in it). The following code illustrates the problem. // troubleshooting by Tov Are Jacobsen import java.io.*; class filebug { public static void main(String args[]) throws FileNotFoundException, IOException { BufferedInputStream bis = new BufferedInputStream( new FileInputStream("test.txt"), 1000 ); byte[] buf = new byte[2000]; int numread; System.out.println( "Available: "+bis.available() ); while (true) { numread = bis.read(buf,0,512); if (numread<0) break; System.out.println( "got "+numread +", avail:"+ bis.available()); } } } Of course, a valid reason for getting less than you asked for is that you asked for more data than is actually available in the Stream, e.g. you requested 512 bytes from a file that only contains 40 bytes. In general, there are no guarantees about how much data is returned for a given buffered input stream read request. To avoid this problem, push a DataInputStream on top of your buffered stream. Then you can call readFully(), which will do what you want. A similar "got less than I asked for" occurs when reading a socket. Network protocols frequently packetize data and send it across in bursts. Nothing is lost of course, and you are always told how many bytes you actually got. You will get the remaining bytes on a subsequent read. This happens regardless of the language used. Be sure to check the "amount of data returned" when using the read(byte[], int, int) method of BufferedInputStream, or when reading from a socket. Another problem with java.io.InputStream.read(byte[], int, int) is that it catches and ignores IOExceptions. Instead, these exceptions should be passed on to the caller. Ace programmer Jef Poskanzer, jef@acme.com, has a version to do this at http://www.acme.com/java/software/Acme.Utils.html. See Jef's read() and readFully() routines. 22. (Sect. 7) How do I redirect the System.err stream to a file? [*] You cannot assign a new FileOutputStream to System.err, as it is final. Instead use the System.setErr() library call, like this: FileOutputStream err = new FileOutputStream("stderr.log"); PrintStream errPrintStream = new PrintStream(err); System.setErr(errPrintStream); This was introduced with JDK 1.1. There is also a corresponding setIn() for redirecting standard in, and a setOut() for standard out. Note that you will get a compiler warning about a deprecated construct when you do this. PrintStreams are deprecated in favor of PrintWriters, which handle Unicode properly. The PrintStream is marked as deprecated by marking all its constructors as deprecated. There is no way to create the PrintStream needed to redirect System.err or System.out without triggering the deprecated warning. 23. (Sect. 7) What are the values for the Unicode encoding schemes? [*] If you review the String constructor with this signature String(byte[] bytes, String encoding) you can see that one argument is a value for the encoding scheme that the conversion of 8-bit bytes to 16-bit Unicode chars is to use. There are three: "Unicode", "UnicodeBig" and "UnicodeLittle". The first one expects the first two bytes of your data to be a Byte Order Mark, FEFF or FFFE, which specifies whether the data is in little-endian or big-endian order. If there isn't a BOM but you already know the endianness, you can use "UnicodeBig" or "UnicodeLittle" directly. There is also a Sun document at http://java.sun.com/products/jdk/1.1/docs/guide/intl/encoding.doc.html with some related information (not much). There is another Sun document at http://java.sun.com/products/jdk/1.1/intl/html/intlspec.doc7.html which shows the table of encodings. There is a new system property called "file.encoding" which translates between codes known to Java like "Cp1252", and locale encoding names like "Windows Western Europe / Latin-1" 24. (Sect. 7) Is there a way to read a char from the keyboard without having to type carriage-return? [*] You can do this in a GUI (e.g. in a text component). There is no pure Java way to do character-by-character I/O without using a GUI. ------------------------------- 8. Core Libraries 1. (Sect. 8) I can't seem to change the value of an Integer object once created. [*] Correct. Integer (Float, Double, etc) are intended as an object wrapper for a specific value of a number, not as a general-purpose way of shipping a primitive variable around as an Object. If you need that it's easy enough to create: class General { public int i; } 2. (Sect. 8) How do I print from a Java program? [*] Use the Toolkit.getPrintJob() method Component c = this.getParent(); while (c!=null && !(c instanceof Frame)) c=c.getParent(); // With a JComponent use c=getTopLevelAncestor(); PrintJob pj = getToolkit().getPrintJob((Frame) c, "test", null); Graphics pg = pj.getGraphics(); printAll(pg); pg.dispose(); pj.end(); This feature was introduced with JDK 1.1. A common place to put this is in the code that handles a button press. Printing from an untrusted applet is subject to a check from the SecurityManager. The JDK 1.1 printing API is more a screen hardcopy facility than a full blown publishing and illustration hardcopy API. JDK 1.2 offers a more full-featured printing API. If you simply want to print text, then write it to a file and print the file. Or open a filename that corresponds to the printer. On Windows, that is "LPT1" and the code looks like: try { FileOutputStream fos = new FileOutputStream("LPT1"); PrintStream ps = new PrintStream(fos); ps.print("Your string goes here"); ps.print("\f"); ps.close(); } catch (Exception e) { System.out.println("Exception occurred: " + e); } The final formfeed is needed by windows to start the printjob. 3. (Sect. 8) What are the properties that can be used in a PrintJob? [*] The properties are o awt.print.destination - can be "printer" or "file" o awt.print.printer - printer name o awt.print.fileName - name of the file to print o awt.print.numCopies - obvious o awt.print.options - options to pass to the print command o awt.print.orientation - can be "portrait" or "landscape" o awt.print.paperSize - can be "letter","legal","executive" or "a4" paperSize=letter, and numCopies=1. You can search for info like this by joining the Java Developer Connection (it's free) at http://java.sun.com/jdc. and doing a search for "PrintJob". 4. (Sect. 8) Is there any package in Java to handle HTML? [*] See the answer to Question 13.14. 5. (Sect. 8) Why don't Dialogs work the way I want them to? [*] Modal dialogs (dialog windows that stay up until you click on them) are buggy in many browsers and in the 1.0.2 JDK. One bug is that the dialog is not necessarily put on top when it is displayed. Most of the modal dialog bugs are fixed in JDK 1.1. 6. (Sect. 8) Where can I find information about the sun.* classes in the JDK? [*] You're not supposed to. Those classes are only to support functions in the java.* hierarchy. They are not part of the API, and won't be present in Java systems from non-Sun vendors. Some people have reverse-engineered the code and published an API for these classes but you use it at your own risk, and it may change without warning. Worst of all, those programs will not have the portability of true Java but will only run on Sun JDKs. For the same reason you shouldn't use classes outside the java.* packages when using JDKs from other vendors. If you still insist on going ahead, check these URLs: http://java.sun.com/products/api-overview/index.html http://www.parmly.luc.edu/javaudio/ http://www.users.interport.net/~mash/javamidi.html 7. (Sect. 8) How do you read environment variables from with a Java program? [*] Environment variables are not used in Java, as they are not platform-portable. The Mac doesn't have environment variables, for example. A Windows 95 application not started from a DOS window does not have environment variables. Use properties instead. It was a design error in JDK 1.0 that programmers had to set the CLASSPATH environment variable. This should have been set in a property file Create your own properties file (see java.util.Properties) or specify them with the -D option when you invoke the interpreter or JRE. Additionally, on some systems you can set a property from the command invocation line like this: java -Dfoo=$foo MyClass (Unix) or java -Dfoo=%foo% MyClass (Win95/NT) This sets the "foo" property to the value of the environment variable foo, and makes it available in the System properties. Make sure you do not leave any spaces after the -D or around the = sign. Inside the program you get the value with: String env = System.getProperty("foo"); More simply, just put the environment variable on the command line and read it as arg[0]. java MyClass %FOO% ; Win32 java MyClass $FOO ; Unix Finally, you could execute a Runtime process to get the environment variables if you are on a platform that has them. import java.io.*; import java.util.Properties; public class Main { public static void main(String[] argv) { Properties envVars = new Properties(); try { envVars.load( // use "set" on Windows Runtime.getRuntime().exec("/bin/env").getInputStream()); } catch (Throwable t) {t.printStackTrace();} System.out.println("\n\n" + argv[0] + " = <" + envVars.get(argv[0]) + ">"); } } This is not a Pure Java approach as it builds platform-specific knowledge into the program. See Question 10.6 for more details. On Unix, the command that prints environment variables is "/usr/bin/env". On Windows95, it is "set" 8. (Sect. 8) How do I get Java talking to a Microsoft Access database? [*] Use the JDBC-ODBC bridge. It is not especially challenging to set up, but it does require painstaking attention to detail. There is a step-by-step example in the van der Linden text "Just Java" mentioned in the sponsorship section of this document. Note that the Microsoft version of the Java kit does not support JDBC-ODBC access because it uses a non-standard native code interface. The JDBC FAQ can be found at http://java.sun.com/products/jdbc/jdbc-frequent.html 9. (Sect. 8) I can't seem to change the current working directory. [*] Correct. This missing functionality is an oversight that we hope will be corrected in the future. The bug id is 4156278, please feel free to join the JDC, and vote to have this (or any other) fixed. Changing the user.dir property merely changes the text property, not the underlying reality that it is supposed to reflect. There are several workarounds. o Run your java app from a .bat or .sh file and do the "cd" in that (before you run your java app), assuming that all the external processes you need to exec can be run from the same directory. o Do: exec("cd /home/wherever; externalApp.exe") on unix, (there doesn't seem to be an equivalent on NT). o Instead of running the .exe directly, run (or write on the fly) a .bat or .sh file that does the cd and then runs the .exe for you (this could well create trouble with getting back the correct return status) 10. (Sect. 8) How do I create a Vector of ints? [*] ints are primitive types and hence can't be stored by the Vector class, which stores objects. You'll need to wrap the ints. Try this: int i =7; Vector holdsInts = new Vector(5,1); holdsInts.addElement(new Integer(i)); int j = ((Integer)holdsInts.elementAt(0)).intValue(); 11. (Sect. 8) I have several worker threads. I want my main thread to wait for any of them to complete, and take action as soon as any of them completes. I don't know which will complete soonest, so I can't just call Thread.join on that one. How do I do it? [*] You need to use the wait/notify mechanism to allow any of the worker threads to wake up your main thread when the worker has completed. 12. (Sect. 8) How do I get random numbers? [*] If you just need a quick random double between 0.0 and just less than 1.0 double myrandom = Math.random(); // [0,1) The notation "[0,1)" is common math notation for "zero to .9999999 etc" The Sun documents say this returns 0.0 to 1.0, but inspection of the source shows they are wrong. However, due to the inherent inaccuracies of floating point arithmetic, multiplying N by 0.999999 etc can result in an answer of N, not N * .999999. So watch out when N is big. JDK 1.2 adds another version of nextInt that accepts a parameter for returning ranged random numbers. Where things get trickier is when you use JDK 1.1 and want an int in a certain range, say 1 to 6 to simulate the throw of a die or 1 to 52 to represent a playing card. Class Random has a nextInt method that will return any integer: import java.util.Random; Random r = new Random(); int i = r.nextInt(); However, that has an (almost) 50% chance of being negative, and it doesn't come from the right range. So you just take the abs() value and then mod it into the right range: int dice_throw = 1 + Math.abs(i) % 6; Except, the abs() method fails gracelessly in the presence of the Integer.MIN_VALUE (it returns the same, negative, result!). So it is better to AND to get the non-negative value: In general, to get a random int between high and low limits (inclusive): java.util.Random r = new java.util.Random(); int j = (r.nextInt() & Integer.MAX_VALUE) % (high-low+1) + low; The sentence above states "(almost) 50% chance" because there is one more value in the negative integers than in the positive integers in two's complement arithmetic as used by Java. For most purposes, the bias introduced will be insignificant, but we "and" the nextInt() to convert it to zero. Sure, it's unlikely to occur, but you don't want the reactor going critical just because you missed this case while testing. A worse problem is that with the algorithm used, the low order bits are significantly less random than the higher order bits. And the low order bits are precisely the ones you get when you do a (mod 2^n) operation. You may consider using java.security.SecureRandom which provides much better randomness by using a Cryptographic hash, although it is much more expensive to compute. 13. (Sect. 8) What does "deprecated" mean? I got this in a compiler error message. [*] The compiler will flag a now-obsolete API as "deprecated". The word means "officially disapproved of". Compile again with the "-deprecation" option to see what is deprecated. In almost all cases, the old API has been replaced by a new one. Update your code to use the new one. An example of using a deprecated API is calling component.size(). That has been replaced by component.getSize(). 14. (Sect. 8) Where/why should I use the Enumeration interface? [*] It's a very convenient way to step through some of the library data structures, such as HashTable, Vector, and ZipFile. It is thread safe. If you're looking at an element in one thread while another thread is trying to delete it, it won't half vanish. Here's how you might look at every file in a ZIP file: ZipFile z = new ZipFile("foo.zip"); Enumeration e = null; for (e=z.entries(); e.hasMoreElements(); ) { ZipEntry ze = (ZipEntry)e.nextElement(); System.out.println("got " + ze.getName() ); } And here's how you might look at all the tokens in a String: StringTokenizer tokens = new StringTokenizer (SomeArbitraryString, "\n", false); Enumeration enum = tokens.elements(); while enum.hasMoreElements() System.out.println(enum.nextElement()); You should look for opportunities in your own data structures to implement Enumeration anywhere where the structure has repeated elements. 15. (Sect. 8) Which version of WinZip is compatible with java.util.zip? [*] You need WinZip version 6.2 or later. Version 6.1 or earlier is not good enough. WinZip can be downloaded from http://www.winzip.com/download.cgi. The pkzip software works fine. Infozip is better than WinZip because it lacks the winzip "feature" of failing to recreate directories unless given a special option. Use Infozip. 16. (Sect. 8) How can Java access other fonts on my system? [*] You do it by editing the fontnames in the font.properties file in the lib directory of your JDK release. Watch out for program portability when you do this. For more details, check the website http://www.alumni.caltech.edu/~dank/javafont.htm and the JavaSoft site at http://java.sun.com/products/jdk/1.1/docs/guide/intl/fontprop.html They have lots of information on this. 17. (Sect. 8) How can I trap Control-C in Java? [*] Control-C is used on some OS's to break into a running program interactively and terminate it. On Unix Control-C is sent to the process as a signal. If a C program declares a handler for that signal, the program will be able to continue even if Control-C is sent to it. Control-C is not a Java concept, and there is no way to do this portably. On Unix you can write the signal handler in C, and impose the handler by calling the C routine through the Java Native Interface. On Win32 in a GUI a KeyPressedListener will see a control-C as java.awt.event.KeyEvent[KEY_PRESSED,keyCode=67,modifiers=Ctrl] On Win32 in a command line app you can't read a control-C in Java because it is sent to the process as a signal (as with Unix). Instead of interposing a signal handler thru JNI, you could launch java from perl or a shell script which is capable of doing this. Alternatively, use javaw to launch the JVM so that it has no keyboard which can ctrl-C it. 18. (Sect. 8) How do you parse commandline arguments to a Java program? [*] Perhaps surprisingly, commandline arguments are not encouraged, as they make a program not 100% pure Java. The reason is that some systems like MacOS don't normally have a command line or command-line arguments. Consider using properties instead so that your programs fit more naturally into the environment. If you must use command-line arguments, have them comply with the POSIX conventions, i.e. they should o use a "-" instead of a "/" o be case sensitive, and o be concatenatable (-pst == -p-s-t). See http://java.sun.com/docs/books/tutorial/essential/attributes/_posix.html If such arguments are used, it should NOT be up to the invocating application (ie java.exe) to propperly parse them. According to the getopts routine from gnu, getopts is required to know exactly what the usable parameters are before it can properly parse them and create argc/argv. Because of that, it becomes unduly hard for calling programs such as java.exe to properly parse class arguments by themselves. Instead, they should create an argc/argv pair (actually a java specific array dependant on the way in which the method is called) where the number of elements equals the number of text words in the options. Text word means a group of ascii characters outside of quotation marks, not separated by white space. Once these text words are passed to the class, it is up to the class to actually parse them correctly. The text words passed to the class can be parsed however the class author wishes. It is up to the author to correctly parse the options. There are several implementations of getopts which perform such parsing, in C, Perl, and Java. You will find one at http://www.urbanophile.com/arenn/hacking/download.html#getopt 19. (Sect. 8) How many threads can I create? [*] By default, on a Win32 machine, each ("native") thread gets one MB (1024*1024 bytes) of stack space reserved for it. The memory is not actually allocated. If it were, you'd run out of memory with dozens of threads instead of hundreds. The space needs to be reserved as a contiguous block of memory so the stack can grow as needed. Under Win32, the max amount of memory is 2GB, which corresponds to 2,000 threads each reserving 1MB of memory. That's an upper bound; in practice you'd run out of other OS resources before running out of memory. Each thread has some system resources that will be used to manage the thread -- register storage area, thread-local storage, state information, exception condition info, etc. You should design your programs so that you use threads only where necessary. It's almost always a mistake to have one thread per object. Successful programs are much more likely to have 5 threads (or fewer) than 500. ------------------------------- 9. Dates and Times Credit to Paul Hill who completely rewrote this section, and to the programmers at IBM who implemented much of the Java Date code, and reviewed this section of the FAQ for accuracy. java.util.Date 1. (Sect. 9) Is Java "Year 2000"-compliant? [*] Java is Y2K compliant in release JDK 1.1.6 and later. See http://www.sun.com/y2000/cpl.html. Prior to this release there were certain corner case bugs that had to be fixed. The Date class, as you can see from the discussion, contains more than enough resolution to represent dates in this century and the next and the last. The SimpleDateFormat when parsing a 2 digit year could cause problems; see discussion below. 2. (Sect. 9) What happen to java.util.Date between JDK 1.0 and JDK 1.1? [*] In JDK 1.1 the java.util.Date class was split to provide better support for timezones, and internationalization. The classes specifially related to dates are summarized below: 1. The class Date represents a specific instant in time, with millisecond precision. 2. The class TimeZone is an abstract class that represents a time zone offset, and also figures out daylight savings time adjustment. 3. The class SimpleTimeZone is the only concrete subclass of TimeZone in the JDK. It is what defines an ordinary timezone with a simple daylight savings and daylight savings time period. 4. The class Calendar is an abstract class for converting between a Date object and a set of integer fields such as year, month, day, and hour. 5. The class GregorianCalendar is the only concrete subclass of Calendar in the JDK. It does the Date-to-fields conversions for the calendar system in common use. 6. The class DateFormat is an abstract class that lets you convert a Date to a printable string with fields in the way you want (e.g. dd/mm/yy or dd.MMM.yyyy). 7. The class SimpleDateFormat is the only concrete subclass of DateFormat in the JDK. It takes a format string and either parses a string to produce a date or takes a date and produces a string. At least one critic has used the term "baroque" when describing the complexities of the Java date related classes, but other critics would spell that "broke". The good news is that as of JDK 1.2 all of the common problems have been corrected and many of the bugs were corrected in 1.1.4 and 1.1.6. Even in 1.1.1, you can avoid most of the most annoying bugs by always keeping in mind which timezone each class is using. 3. (Sect. 9) Exactly what is a java.util.Date? [*] A java.util.Date stores a moment in time as a long integer representing the number of milliseconds since 00:00:00 Jan 1, 1970 UTC (Coordinated Universal Time). This zero moment is known as the "Epoch". This is the same Epoch as is used on Unix systems. Dates earlier than the Epoch are represented as negative numbers, counting away from 1/1/1970. The scheme is sufficient to represent dates from 292,269,053 B.C. to 292,272,993 A.D. (64 bits covers -9,223,372,036,854,775,808 to +9,223,372,036,854,775,807 milliseconds. But note that prior to JDK 1.2, a GregorianCalendar will not accept values earlier than 4713 B.C. A java.util.Date is the light-weight object intended to just hold a millisecond value. It is used to hold, communicate and store a moment in time. Other tasks like creating a formated string, or calculating dates are best done using other classes. 4. (Sect. 9) Does a java.util.Date really represent the true UTC? [*] No, but it is close enough for most human time-keeping purposes. On most computers, it only represents the time since the epoch as converted from the value on the underlying hardware. If you have hardware that is synchronized with an atomic clock your time is UTC; most hardware assumes a day is 24 hours long, but there have been more than 20 leap seconds added to UTC, since the first one was added in 1972. 5. (Sect. 9) How do I create a Date object that represents the current time? [*] The default value of a date object is the current time, so the following code creates a date object that contains the current time. Date now = new Date(); 6. (Sect. 9) I want to create a string that represents a date in a format other than what is returned by java.util.Date.toString() do I have to use a Calendar? [*] No. Instead of creating a Calendar and pulling out all of the appropriate fields and making a string, you could use SimpleDateFormat.format() to create a string. 7. (Sect. 9) Why are all the methods in java.util.Date deprecated? [*] Mostly because the original java.util.Date was not completely aware of the timezone and "not amenable to internationalization". To make it timezone aware and internationalizable would have required adding some of the functionality which can now be seen in java.util.Calendar and some of the functionality in java.util.DateFormat. If you find the combination all of the date related classes complex, just be glad they were separated into different classes. 8. (Sect. 9) I really don't need a internationalizable, timezone aware, extra flexible formating set of date classes. Is there anything else I can use that stores only a date, and allows me to do some date calculations? [*]You could consider using the BigDate class written by Roedy Green, and available in his very informative glossary (search for BigDate). If you want to store the result in a database as a Date or TimeStamp, you should read the section below on java.sql.Date. 9. (Sect. 9) Since the Date( String ) constructor is deprecated what do I use instead? [*] The best choice is to use SimpleDateFormat.parse() to create a java.util.Date object. The Date constructor that accepts a string calls Date.parse( String ). The Date.parse() function had its own rules for converting 2 digit years (it used a 1980 pivot date) and other limitiations which makes it of limited value. Other "features" of Date.parse() that are not supported in SimpleDate have not been missed by many developers. 10. (Sect. 9) Since Date(int year, int month, int date) and related constructors are deprecated what do I use instead? [*] The constructor GregorianCalendar(int year, int month, int date) is the newer replacement. Other choices are the Calendar.set( year, month, day ) method. Note that the year in the GregorianCalendar starts at 1 A.D., not at 1901 like the old Date constructor. java.util.TimeZone 11. (Sect. 9) How can I see if my JVM is using the right timezone? [*] The following codes displays the ID of the current default timezone. System.out.println( TimeZone.getDefault().getID() ); 12. (Sect. 9) The value of TimeZone.getDefault is not what I expected. What is the problem? [*] The value of the default timezone is based on the value of the system property "user.timezone". The JVM is supposed to set this value. In releases such as JDK 1.1 the value of user.timezone was often not set to anything, so TimeZone.getDefault() used its own built in "fallback" value (the default when there is no default value). In later JDK 1.1 releases and in JDK 1.2 the setting of the value of user.timezone is much better and the "fallback" value is now GMT (Greenwich Mean Time). Up until JDK 1.1.3, the fallback value was "PST" (North American Pacific Timezone). 13. (Sect. 9) Do all the standard objects use the same default timezone? [*] Not until JDK 1.2. In JDK 1.1, Date.toString() and Calendar used the value of TimeZone.getDefault() which could often be undefined (see the previous question). In JDK 1.1, The Calendar in a SimpleDateFormat was set to the 1st timezone resource for the locale (for the US this is PST). System.out.println( "Date format TZ = " + TimeZone.getDefault().getID() ); sdf = DateFormat.getDateTimeInstance( DateFormat.LONG, DateFormat.LONG ); System.out.println( "Date format TZ = " + sdf.getTimeZone().getID() ); Calendar cal = Calendar.getInstance(); System.out.println( "Calendar TZ = " + cal.getTimeZone().getID() ); When run on a system running JDK 1.1.6, NOT in the North American Pacific Time nor in the GMT timezone results in: Timezone default = GMT Date format TZ = PST Calendar TZ = GMT This example shows two bugs, the value of user.timezone is undefined, so its defaulting to GMT (see discussion of TimeZone.getDefault()) and it shows that the DateFormat depends on the 1st locale entry which in this case is PST. If you don't want the DateFormat to use the Locale timezone, see the code provided below. 14. (Sect. 9) If I explicitly set the default timezone, don't I need code to choose between (a) the daylight savings version or (b) the standard version of a timezone? [*] No. The ID that you use to select a timezone with TimeZone.getTimeZone refers to a predefined timezone that contains daylight savings information (when applicable). For example, the following code selects the timezone used in New York, USA. // Get the North American Eastern Time definition. TimeZone theTz = TimeZone.getTimeZone( "EST" ); // get a really detailed date format and set it to the right timezone DateFormat df = DateFormat.getDateTimeInstance( DateFormat.LONG, DateFormat.LONG ); df.setTimeZone( theTz ); // create a date in the locale's calendar, set its timezone and hour. Calendar day = Calendar.getInstance(); day.setTimeZone( theTz ); day.set( 1998, Calendar.FEBRUARY, 1 ); day.set( Calendar.HOUR, 12 ); // print that date/time and // that date/time 150 full days of milliseconds later. System.out.println( df.format( day.getTime() ) ); System.out.println( df.format( new Date( day.getTime().getTime() + // get the millis 150L*24*60*60*1000L ) ) ); // add exactly 150 days of millis Results in: February 1, 1998 12:00:00 PM EST July 1, 1998 1:00:00 PM EDT Notice that this example selected something refered to as "EST", but that this TimeZone was aware of the daylight savings time change and either printed as "EST" or "EDT". The confusion is reduced in JDK 1.2, you can use longer TimeZone IDs each maps to its own set of text resources. For example the following IDs are 5 hour West of GMT and have various DST rules: "America/Nassau", "America/Montreal", "America/Havana", "America/Port-au-Prince", "America/Grand_Turk", "America/New_York" and "EST". You can look at a list of other timezone names and offsets in the file $JAVAHOME/src/java/util/TimeZone.java 15. (Sect. 9) How do I create my own Time Zone to apply to dates? [*] You can create a TimeZone object with the GMT offset of your choice. The following code creates British Time, a timezone that was not defined in 1.1. britTime = new SimpleTimeZone(0*ONE_HOUR, "Europe/London" /*GMT/BST*/, Calendar.MARCH, -1, Calendar.SUNDAY /*DOW_IN_DOM*/, 1*ONE_HOUR, Calendar.OCTOBER,-1, Calendar.SUNDAY /*DOW_IN_DOM*/, 1*ONE_HOUR, 1*ONE_HOUR), TimeZone.setDefault( britTime ); Or you can then apply that TimeZone to a particular Calendar object like so: Calendar myCal = Calendar.getInstance(); myCal.setTimeZone( britTime ); If you are running 1.2, You can choose this existing timezone as the default with the code: TimeZone.setDefault( TimeZone.getTimeZone( "Europe/London" ) ); Note that BST is defined from JDK 1.1 and later, but it is Bangladesh Standard Time. For a longer example of creating and testing the British timezone, Tony Dahlman provides a nice example in his BSumTime.java code. 16. (Sect. 9) How do I create the BST timezone specifically? [*] You can create an arbitrary TimeZone object with the code below. In most or all other timezones, daylight savings time is handled automatically and internally. But GMT is the reference for all other timezones, and so does not have the summertime update applied automatically. The rules for BST can be found at http://www.rog.nmm.ac.uk/leaflets/summer/summer.html Here is the code to create a British Summer Time timezone that is offset one hour from GMT between two dates: import java.util.*; import java.text.*; // create a BST timezone (code courtesy of Tony Dahlman). public static GregorianCalendar setBritSummTime(String zoneName){ // Set up the default GMT0BST time zone SimpleTimeZone bst_tz = new SimpleTimeZone( 0, // no offset from GMT zoneName, // individualized tz id // last Sun Mar 1AM Calendar.MARCH,-1,Calendar.SUNDAY,1*60*60*1000, // last Sun Oct 2AM Calendar.OCTOBER,-1,Calendar.SUNDAY,2*60*60*1000 ); SimpleTimeZone.setDefault(bst_tz); // Apply TimeZone to create a Calendar object for UK locale return (new GregorianCalendar(bst_tz,Locale.UK) ); } and here is how you would print out values using BST: // create a template for printing the date DateFormat df = DateFormat.getTimeInstance( DateFormat.LONG,Locale.UK); // tell the template to use BST tz. df.setTimeZone(TimeZone.getDefault()); System.out.println("Using British Summer Time " +"the time is: " + df.format( BritishSummerTime.getTime() ) ); // Now get and compare with current time in GMT df.setTimeZone(TimeZone.getTimeZone("GMT") ); System.out.println("\nCurrent time in GMT is: " + df.format(BritishSummerTime.getTime() ) ); In the winter, this BST zone is aligned with GMT; in the summer it is one hour later (4 a.m. GMT is 5 a.m. BST). You can look at a list of timezone names and offsets in the file $JAVAHOME/src/java/util/TimeZone.java java.util.Calendar and java.util.GregorianCalendar 17. (Sect. 9)How do I a create a specific date in the Gregorian Calendar? [*]If you have a Date use: myCal.setTime( myDate ); If you have a set of integers representing the year, month and day of month use: Calendar myCal = Calendar.getInstance(); myCal.set( 1998, Calendar.MARCH, 15 ); Note: Months start with January = 0! 18. (Sect. 9) How do I use a GregorianCalendar to extract a few fields from a Date? [*]The following code shows how to get some fields from a Date. Calendar g = Calendar.getInstance(); g.setTime( aDate ); int year = g.get( Calendar.YEAR ); int mon = g.get( Calendar.MONTH ); int date = g.get( Calendar.DATE ); mon++; // in class Calendar & GregCal, months run 0-11 ;-( System.out.println( mon + "/" + date + "/" + year); If you want to build a string that has a formated date consider using SimpleDateFormat.format(). 19. (Sect. 9) Some people use Calendar.getInstance() while others use new GregorianCalendar(). Which one is the correct way to get a Calendar? [*] Either way is correct, it depends on what you want to be able to do. You should use Calendar.getInstance(), if you want your code to be ready when the loading of other Calendars are added to the JDK and some other calendar is the default for the locale. A particular locale might have configured a Hebrew or Islamic Calendar as the default calendar and you might want a user to enter a date in his own Calendar, i.e. 1-Jan-2000 (Gregorian) = 23-Tevet-576 (Hebrew) = 24-Ramadan-1420 (Islamic). If you really are trying to place a particular Gregorian date, i.e. 4-July-1776, into a Date object, you might as well create a GregorianCalendar directly. 20. (Sect. 9) I changed a field using Calendar.set() and then I checked another field. Its value is inconsistent with the value I just set. What is going on? [*]In JDK 1.1.0 the Calendar class did not update all of its fields until you called getTime to retrieve the Date that corresponds to the fields in the Calendar. To get the earlier version of the Calendar to "turn the crank" and calculate all fields you can use the trick: myCal.setTime( myCal.getTime() ) // pull the date out and put it back in. 21. (Sect. 9) When I create the date July 4th, 1776 using new GregorianCalendar( 1776, 7, 4 ) the month is off by one. What is the problem? [*]You need to be be aware that months start with January equal to 0. A better way to create that date would be: independanceDayUSA = new GregorianCalendar( 1776, Calendar.JULY, 4 ); 22. (Sect. 9)Why aren't there constants for milliseconds per day, week or year? [*]The short answer is: these values are not constants. While some date calculations would find these useful, it is important to remember that in areas with daylight savings time rules, there are two days per year that are not 24 hours long, therefore not all weeks are the same length (2 out of 52). Also, because of leap years, not all years are the same length. If you adding values to a calendar consider using either add or roll; for example: myCal.add(Calendar.YEAR, 1 ); // get a value 1 year later. 23. (Sect. 9) By my count the week of the Year is off by one. What is the problem? [*]The GregorianCalendar class uses the value set by setMinimalDaysInFirstWeek() to determine if the fractional week at the beginning of the year should be week 1 or week 0. If you don't change it, any fractional week could be week 1, depending on the value defined for the locale. 24. (Sect. 9) What timezone does a calendar use when I don't explicitly set one? [*]The Calendar uses the TimeZone.getDefault() (see discussion under TimeZone). 25. (Sect. 9) Should I stop using Date all together and just use Calendar? [*] Probably not. The Calendar class is a much larger than a Date object. Many other interfaces in standard APIs are defined using a Date object. Use Date objects to hold, store or communicate a date-time value. Use a Calendar object to manipulate a date-time value. 26. (Sect. 9) The GregorianCalendar will not accept a date prior to 4713 B.C. Why? [*]January 1, 4713 B.C. is the "epoch" date for the Julian Day calendar which was invented in the 16th century by the Joseph Justus Scaliger. "[T]he Julian day calendar, ... does not use individual years at all, but a cycle of 7980 astronomical years that counts a day at a time, with no fractional days, no mean year, and no leap years. He came up with his number by mulitplying three chronological cycles: an 18-year solar cycle, a 19-year lunar cycle, and the 15-year indication period used by Romans. All three cycles began together at the same moment at the start of the "Julian cycle. ... [This] Calendar lives on among astronomers." -- David Ewing Duncan, "Calendar", Avon Books, 1998; p 207 Note that the Julian Day calendar is not the same as the Julian calendar. The Julian Calendar is named for Julius Caesar. The Julian Calendar was used in the Europe from what we now call January 1, 45 B.C. until at least October 4, 1582 and is still used today by the Eastern Orthodox Church to date holidays. The limitation on dates prior to 4713 BC has been dropped in JDK 1.2. 27. (Sect. 9) The Calendar class is said not to handle certain historical changes. Can you explain some of the limitations? [*]The date of change from the Julian to the Gregorian calendar depends on where you lived at the time. The date can vary from 1582 (most Catholic countries, which of course followed the Papal edict) to 1949 (China). The date of the cutover from using the Julian Calendar (leap years ever 4 years) to using the Gregorian Calendar (every 4 years, except every 100 unless divisable by 400) is controlled by the method GregorianCalendar.setGregorianChange(Date). It is also the case that January 1 was not always the beginning of the year. January 1 was standardized by Julius Caesar in 45 B.C. and Pope Gregory XIII in 1582, but others who used the Julian Calendar between those dates used other dates for New Years Day. (Anyone who has ever been involved in a standardization effort may find it interesting that neither an emperor nor a pope could actually complete the standardization effort). The Calendar class uses a TimeZone which does not handle historical changes, i.e. the SimpleTimeZone contains only two dates the "spring forward" and "fall back" dates and a date that the DST starts (see SimpleTimeZone.setStartYear() ). If the local definitions have changed then a date/time may not accurately reflect the historical local time. As noted above, the Date object does not usually include leap seconds, unless your hardware includes leap seconds. While the Calendar class is more than useful for international business, it may not be what you want for doing UTC timebased calculations or historical dates and times without a more careful analysis of its design limits. java.text.DateFormat and java.text.SimpleDateFormat 28. (Sect. 9) How do I convert a date in one format to another? [*] The following code illustrates the technique: import java.text.*; public class DateTest { public static void main( String[] args ) { SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.S"); SimpleDateFormat df2 = new SimpleDateFormat("dd-MMM-yy"); String startdatetime = "1998-09-09 06:51:27.0"; try { System.out.println("Date is " + df2.format( df1.parse(startdatetime) )); } catch (ParseException pe) { System.out.println("ParseException " + pe ); } } } When run, the program outputs "Date is 09-Sep-98" 29. (Sect. 9) How do I use DateFormat to parse a string containing a date? [*] The easiest way to parse a date that is in a known format is to use SimpleDateFormat.parse(). DateFormat df = new SimpleDateFormat( "HH:mm" ); df.setTimeZone( TimeZone.getDefault() ); // if using JDK 1.1 libraries. df.setLenient( false ); // to not allow 26:65 etc. Date lateLunchOnDayZero = df.parse( "12:30" ); System.out.println( lateLunchOnDayZero ); The above code would result in (when in the MST timezone). Thu Jan 01 12:30:00 MST 1970 To parse other date and time fields, refer to the SimpleDateFormat documentation. 30. (Sect. 9) How do I use a DateFormat to create a text string from a Date? [*] The easiest way to create a string from a date is to use a SimpleDateFormat.format(). The following code illustrates how this can be done. DateFormat df = new SimpleDateFormat( "yyyy.MMM.dd HH:mm:ss.SSS z" ); df.setTimeZone( TimeZone.getDefault() ); // JDK 1.1 System.out.println( df.format( d ) ); // where d is a Date For other possible fields from the calendar, see the document for SimpleDateFormat. 31. (Sect. 9) What timezone does a SimpleDateFormat use when I don't specify one? [*]In JDK 1.1, the SimpleDateFormat uses the first timezone defined for the locale. In JDK 1.2, it uses the default timezone. See the discussion above on how this differs from the Calendar class). 32. (Sect. 9) I'm not yet using JDK 1.2 and I don't want the DateFormat to use the 1st timezone for the locale. How do I change the timezone in a SimpleDateFormat to use a different timezone? [*] The following code sets the timezone of a DateFormat to the current default. DateFormat df = DateFormat.getDateInstance(); df.setTimeZone(TimeZone.getDefault()); or to set it to a timezone of your chioce. df.setTimeZone(TimeZone.getTimeZone( "MST" ) ) // Mtn Time, Denver USA 33. (Sect. 9) What century is assumed when I use a two digit year in a SimpleDateFormat string? [*]In JDK 1.1, the default start for the century used by SimpleDateFormat for 2 digit years is 80 years before the current date. This means that in 1998: 1 = 2001, 2 = 2002, ... 17 = 2017, 18 = 2018, 19 = 1919, 20 = 1920, ... 98 = 1998, 99 = 1999, In JDK 1.2 you can change this "default century start date" with the method set2DigitYearStart( Date) and get its current value with the method get2DigitYearStart(). One thing to note is that since set2DigitYearStart takes a date not a year, you can have your default century begin at any day or hour. When running under JDK 1.1, it is probably best to avoid two-digit year fields, when the dates entered could possibly fall outside of the range -- now less 80 years and now plus 20 years. If you want to allow two-digit year fields in JDK 1.2 and beyond, consider setting the 2DigitYearStart property to something appropriate, For example, set it to today, when all dates to be entered are in the future (i.e. an expiration date), or set it to today less 100 years, when the value is always in the past (i.e. birthdate, death date). 34. (Sect. 9) Does the above mentioned limitation of 2 digit years in JDK 1.1 mean that java.text.SimpleDateFormat is not Y2K compliant? [*] No. It means that any code you write that (1) allows the entry of 2 digit years and (2) does not make sure they are in an appropriate century, would not pass a careful Y2K analysis. This code was put here so you could sensibly read old files with non-Y2K compliant dates, not so you could create new ones. Once you are using JDK 1.2 it is better to set the 2DigitYearStart property to something appropriate for any two-digit year field which you are parsing. java.sql.Date and java.sql.TimeStamp 35. (Sect. 9) What timezone does a java.sql.date use when converting to an SQL DATE? [*]This is another hidden use of the default java.util.TimeZone. If you have carefully set every timezone in every Calendar and DateFormat you are using, but you don't set the default in java.util.TimeZone when a java.util.Date is converted to a java.sql.Date you may not end up with the value you expected in your database. 36. (Sect. 9) When I print a jave.sql.Timestamp it doesn't include any milliseconds. What is the problem? [*] If you print the java.sql.Timestamp directly you will see this problem. The following code demonstrates this surprising behavior. // incorrect use of java.sql.Timestamp DateFormat df = new SimpleDateFormat( "MM/dd/yy hh:mm:ss.SSS a" ); df.setTimeZone( TimeZone.getDefault() ); // needed in JDK 1.1 java.sql.Timestamp t = new java.sql.Timestamp( 94, Calendar.JANUARY, 1, 13, 45, 59, 987654321 ); System.out.println( df.format( t ) ) ; // Wrong! no fractions of a second. The results of the above code are: 01/01/94 01:45:59.000 PM The above code is using whatever is in the super class (java.util.Date) and assumes all of those parts are filled in. java.sql.Timestamp could have stored the whole milliseconds in the millisecond part of a java.util.Date, and stored the nanoseconds that are not whole milliseconds in an additional field. They chose to ignore the fractions of a second in the java.util.Date and put all fractional parts in an additional nanosecond field. The following code shows how to convert a java.sql.timestamp to a java.util.Date. Date d = new Date(t.getTime() + (t.getNanos() / 1000000 )); // 1 Milli = 1x10^6 Nanos System.out.println( df.format( d ) ) ; // Right! At least we have the millis The result of the above code is a better approximation of the timestamp value: 01/01/94 01:45:59.987 PM 37. (Sect. 9) How do I calculate the number of days between two dates? [*] There is no API for this (there should be), but you can calculate static final long ONE_HOUR = 60 * 60 * 1000L; Calendar earlierDate = new GregorianCalendar(); Calendar laterDate = new GregorianCalendar(); earlierDate.set(1997, 1, 5, 0, 0, 0); // FEB!! 05, 1997 laterDate.set(1998, 1, 5, 0, 0, 0); // Feb 05, 1998 // the first getTime() returns a Date, the second takes // that Date object and returns millisecs since 1/1/70. // The API has misleading and horrible naming here, sorry. long duration = laterDate.getTime().getTime() - earlierDate.getTime().getTime(); // Add one hour in case the duration includes a // 23 hour Daylight Savings spring forward day. long nDays = ( duration + ONE_HOUR ) / (24 * ONE_HOUR); System.out.println("difference in days: " + nDays); Note: this method works only if the two times are both created to be exactly midnight. Otherwise you might end up finding that for example, 11 PM tonight is 0 days away from 6 AM tomorrow, instead of 1 day as many applications expect. This is because 24 hours haven't elapsed between 11pm on one day and 6am on the next. Or, use int julian = myCalendar.get(Calendar.DAY_OF_YEAR); and subtract, making sure to subtract the years too. Alternatively, use BigDate at http://mindprod.com. For the ultimate in generality, you could get ACM's Collected Algorithm 199, recode it in Java (takes about 30 minutes), compute the Julian date for each end point, and subtract the two numbers. Here is the code in Java to get the GMT Julian day number and a "local Julian Day" that leverages the existing algorithms in the GregorianCalendar. import java.util.*; import java.text.*; /** * This Calendar provides Julian Day and "Calendar Day" methods, * The Calendar Day starts at _local_ midnight. * * @author Paul A. Hill * @version 1.1 * @since JDK 1.1.7 3/99 * @see java.util.Calendar */ public class FAQCalendar extends GregorianCalendar implements Cloneable { /** ** this constant and the ones that follow are actually private ** in the GregorianCalendar, so we'll redefine them here. **/ public static final long ONE_SECOND = 1000, ONE_MINUTE = ONE_SECOND * 60, ONE_HOUR = ONE_MINUTE * 60; /** * this next constant and the others with it have their uses, * but watch out for DST days and the weeks that contain them. * Note also that 1/1/1970 doesn't start on the first day of the week. */ protected static final long ONE_DAY = ONE_HOUR * 24, ONE_WEEK = ONE_DAY * 7; /** The number of days from Jan 1, 4713 BC (Proleptic Julian) ** to 1/1/1970 AD (Gregorian). 1/1/1970 is time 0 for a java.util.Date. **/ public static final long JULIAN_DAY_OFFSET = 2440588L; /** * Same as GregorianCalendar(). Creates a calendar with the time set to * the moment it was created. * Note: for Brevety I have not provided all of the other * constructors that you can find in GregorianCalendar. * * @see java.util.GregorianCalendar#GregorianCalendar */ public FAQCalendar() { super(); } /** * A calendar day as defined here, is like the Julian Day but it starts * and ends at _local_ 12 midnight, as defined by the timezone which is * attached to this calendar. This value is useful for comparing * any date in the calendar to any other date to determine how many days * between them, i.e. tomorrow - today = 1 * * @return the calendar day (see above). * @see #getCalendarDay */ public long getCalendarDay() { TimeZone tz = getTimeZone(); // Figure the exact offset for the exact time of day. int offset = tz.getOffset( get( ERA ), get( YEAR ), get( MONTH ), get( DAY_OF_MONTH ), get( DAY_OF_WEEK ), (int)((long)get( HOUR_OF_DAY ) * ONE_HOUR + get( MINUTE ) * ONE_MINUTE + get( SECOND ) * ONE_SECOND ) ); return round( ONE_DAY, getTime().getTime() + offset ) + JULIAN_DAY_OFFSET; } /** * Sets the date in the calendar to 00:00 (midnight) on the local calendar day. * See getCalendarDay for the definition of calendar day as used in this class. * * @param calendarDay the day to set the calendar to. * @see #setCalendarDay * @see java.util.TimeZone#getRawOffset */ public void setCalendarDay( long calendarDay ) { // Set to the beginning of the Julian day. // Then add in the difference to make it 00:00 local time. setJulianDay( calendarDay ); setTimeInMillis( getTime().getTime() - getTimeZone().getRawOffset() ); // we may have gone slightly too far, because we used the // raw offset (diff between Standard time to GMT/UT, instead of the // actual value for this day, so during DLS we may be at 1 AM or whatever // the local DLS offset is), so we'll just drop back to midnight. set( HOUR_OF_DAY, 0 ); } /** * Finds the number of days after 12/31/4312 BC 24:00 GMT on a proleptic * Julian Calendar (i.e. extending the Julian Calendar into pre-history) * to the current time. * The Astronomers Julian Day begins at noon. The Julian Day used here * sometimes called the Chronologists or Historians Julian Day * starts at midnight. For more information see * http://www.magnet.ch/serendipity/hermetic/cal_stud/jdn.htm#astronomical * Note: This routine does NOT take into consideration * leap seconds. * * @return the day number of the current time from 1/ * @see #getCalendarDay */ public long getJulianDay() { return round( ONE_DAY, getTime().getTime() ) + JULIAN_DAY_OFFSET; } /** * Sets the current date contained in this calendar to exactly * 00:00 GMT on the date defined by the Julian Day provided. * * @param julianDay the Julian Day to set the calendar to * @see #setCalendarDay */ public void setJulianDay( long julianDay ) { setTimeInMillis( ( julianDay - JULIAN_DAY_OFFSET ) * ONE_DAY ); } /** * This is a utility routine for rounding (toward negative) to the nearest * multiple of the conversion factor. * BUG? Why is this different than the formula given in * java.util.GregorianCalendar private millisToJulianDay? * * @param conversion typically one of the constants defined * above ONE_MINUTE, ONE_DAY etc. * @param fractions the value to convert expressed in the same units * as the conversion factor (i.e milliseconds). * * @return the value divided by the conversion factor, rounded to the negative. * @see java.util.Calendar */ protected static final long round( long conversion, long fractions ) { long wholeUnits; // round toward negative: // For secs rounded to minutes -61/60=-1, -60/60=-1, -59/60=0, // but we want -2, -1, -1 not -1,-1,0 // or month 0..11 => year 1; -12..-1 => 0; -24..-13 => -1 if ( fractions >= 0 ) { wholeUnits = fractions / conversion; } else { wholeUnits = ( fractions + 1 )/ conversion - 1; } return wholeUnits; } } // FAQCalendar ------------------------------- 10. AWT Text, Textfield, and TextArea 1. (Sect. 10) How can I write text at an angle? [*] Check out http://www.nyx.net/~jbuzbee/font.html. Jim has some code to do exactly this. A good way to do it is to draw the text to an offscreen image and write an ImageFilter to rotate the image. Also, from JDK 1.2 on, the Java 2D API handles arbitrary shapes, text, and images and allows all of these to be rotated, scaled, skewed, and otherwise transformed in a uniform manner. A code example would be: import java.awt.*; import java.awt.geom.*; public class r extends Frame { public static void main(String args[]) { new r(); } r() { setSize(200,200); setVisible(true); } public void paint(Graphics g) { Graphics2D g2D = (Graphics2D) g; AffineTransform aft = new AffineTransform(); aft.setToTranslation(100.0, 100.0); g2D.transform(aft); aft.setToRotation(Math.PI / 8.0); String s = "Rotated Hello World"; for (int i = 0; i < 16; i++) { g2D.drawString(s, 0.0f, 0.0f); g2D.transform(aft); } } } There is more info about the 2D API at http://java.sun.com/products/java-media/2D/index.html and http://developer.javasoft.com/developer/technicalArticles/ 2. (Sect. 10) How do you change the font type and size of text in a TextArea? [*] Like this. myTextArea.setFont(new Font("NAME", <STYLE>, <SIZE>)); where: o NAMEis the name of the font (e.g. Dialog or TimesRoman). o <STYLE> is Font.PLAIN, Font.ITALIC, Font.BOLD or any additive combination (e.g. Font.ITALIC+Font.BOLD). o <SIZE> is the size of the font, e.g. 12. Example: new Font("TimesRoman", Font.PLAIN, 18); 3. (Sect. 10) Can you have different fonts for individual words in a TextArea? [*] No. If you're trying to write a word processor, use the Canvas class to render on. Note that this can be done using the Swing JText classes. 4. (Sect. 10) How much text can be put in a TextArea? [*] TextArea just uses the corresponding widget of the underlying window system. It will be bounded by the limit imposed in the native window system. In Windows 95 TextAreas can hold about 28Kb. The native widget allows 32Kb, but there is some overhead which reduces the amount available to the programmer. The limit is removed in JTextComponent in Swing (JDK 1.2) which dispenses with peer controls. 5. (Sect. 10) How do I clear the contents of a TextArea? [*] Set it to an empty String with this: area.setText(""); 6. How do I get back to a normal echo after I have used TextField.setEchoChar('*')? [*] TextField.setEchoChar('\0') works on most Windows-based browsers...but for most other platforms (i.e. Netscape under UNIX), it just locks up the textfield. There is only one good solution, and that is to make two TextFields on top of each other, one normal, and one with .setEchoChar('*'), and switch between them. 7. (Sect. 10) How do I get word wrap in a TextArea? [*] It's a little obscure. Creating a TextArea with no horizontal scrollbar causes wrapping to occur automatically. The idea is that if you ask for a scroll to scroll viewing over to the right, there is no reason for the widget to do word wrap. So take away the scrollbar, and word wrap will be done instead. Supply TextArea.SCROLLBARS_NONE or TextArea.SCROLLBARS_VERTICAL_ONLY to the TextArea constructor to get word wrap. By default, a TextArea is created with both horizontal and vertical scrollbars. 8. (Sect. 10) How can I limit a TextField to no more than N characters, or to only allow numeric input? [*] The approach is to look at keystrokes as they happen, and disallow input that does not meet your criteria. A neat variation is to extend the basic AWT component, and in your subclass also include the handler that will look at the keystrokes. This bundles everything neatly in one place. The code may look like: import java.awt.*; import java.awt.event.*; public class XCTextField extends java.awt.TextField implements java.awt.event.TextListener { public XCTextField(int columns) { super(columns); enableEvents(AWTEvent.FOCUS_EVENT_MASK); addTextListener(this); } // other constructors may be useful, too public void textValueChanged(java.awt.event.TextEvent event) { int col = this.getColumns(); int len = getText().length(); // int caret = getCaretPosition(); if (col > 0 && len > col) { // or if the char just entered is not numeric etc. String s = this.getText(); Toolkit.getDefaultToolkit().beep(); this.setText(s.substring(0,col)); this.setCaretPosition(col-1); // caret at end } } public void processFocusEvent(java.awt.event.FocusEvent e) { // this routine highlights according to focus gain/loss. super.processFocusEvent(e); int id = e.getID(); if (id==java.awt.event.FocusEvent.FOCUS_GAINED) this.selectAll(); else if (id==java.awt.event.FocusEvent.FOCUS_LOST) this.select(0,0); } } Here is a much briefer example, which very cleverly does the work in the Listener. Oracle really dislikes the "apostrophe" character in a data text fields, as it is interpreted as part of an SQL statement. Here is the code that James Cloughley wrote to suppress apostrophes ("ticks") in a TextField. import java.awt.*; import java.awt.event.*; public class NoTick extends KeyAdapter { final char tick = '\''; public void keyPressed( KeyEvent event ) { TextComponent tc = ( TextComponent )event.getSource(); char c = event.getKeyChar(); if ( c == tick ) { event.consume(); } } } Use it like this: TextField sometextfield = new TextField(); sometextfield.addKeyListener( new NoTick() ); Brief and clever - make the event handler consume unwanted characters. However, it doesn't filter out text that arrives in the component via cut & paste! If you use ctrl-v to paste, you get key events for the ctrl and v, but not for the characters that are pasted. Finally, check out iDate, iTime, and iNumeric from IBM's alphaworks javabeans, available free at http://www.alphaworks.ibm.com/alphaBeans. These beans do the kind of validation you want. Size and Position 9. (Sect. 10) I use add(Component) to add Components to the Container. Is there any way to explicitly set the z-order of these Components? [*] JDK 1.0 has no way to explicitly set the z-order of components. You can try it heuristically, based on the browser you're using, or you can use CardLayoutManager to ensure the panel you want is at the front. In JDK 1.1, the z-order of components ("z-order" means "front-to-back" order, i.e. which window is in front of which) can be controlled by using the the method add(Component comp, int index). By default, components are added 0 to N. The method paint of class Container paints its visible components from N to 0. 10. (Sect. 10) How can I get the dimensions and resolution of the screen? [*] Use java.awt.Toolkit.getDefaultToolkit().getScreenSize() or java.awt.Toolkit.getDefaultToolkit().getScreenResolution() Screen resolution is in dots-per-inch. Take a look in the Toolkit class for other useful methods. Toolkit.getDefaultToolkit().getColorModel().getPixelSize() gets you the color model in terms of bits per pixel. Math.pow(2, Toolkit.getDefaultToolkit(). getColorModel().getPixelSize()) gets you the color model in terms of number of colors. Or use this: 1 << Toolkit.getDefaultToolkit(). getColorModel().getPixelSize() That does a shift left to calculate the power of two. 11. (Sect. 10) How do I allow for the size of the title bar and border when I draw a Frame? [*] Use MyFrame.getInsets(). This returns a java.awt.Insets object which has four ints: top, left, bottom, right, giving the number of pixels each of those margins are inset from the top. You can use these value to adjust the Dimension object returned by component.getSize(). If you are doing this in the constructor you need to ensure that the Frame's peer object is created first. Otherwise the Insets object returned by getInsets() will have all zero values. Make a call to Frame.addNotify() to have the peer created. 12. (Sect. 10) How do I resize a List? I had a List defined as List tlist = new List(10); but the Strings in the list were 80 characters long and only the first 15 were being shown. I was not able to resize the List to display the contents without using the scroll bar. [*] A List cannot be resized in a constructor, so add the following to the Applet (or wherever): public void paint (Graphics g) { tlist.setSize(200,200); } Then before showing panel/frame with the List: tlist.resize(400,400); 13. (Sect. 10) How can my program tell when a window is resized? [*] Override the setBounds(int,int,int,int) method of Component to do what you want. Of course, have it call super.setBounds() as well. Note that setBounds() replaces reshape() which is deprecated. Note the new APIs call the deprecated APIs instead of the other way round. For example, Component.setBounds calls Component.reshape, instead of reshape calling setBounds. This is because the AWT sometimes needs to call these for its own purposes. If it called the old one which then called the new one, and you overrode the new one, the AWT would (wrongly) not call your routine. By having the AWT call the new one (and then the new one call the old one), any overrides of the new one will correctly be called by the AWT as needed. If that didn't make sense, forget I mentioned it. 14. (Sect. 10) How do I center a dialog box? [*] You cannot currently get the applet's absolute screen coordinates. Its location (0,0) is relative to the browser, not the screen itself. But you can center something that it pops up or displays centered on the screen with code like this: Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); my_window.move( ( screen.width - my_window.size().width ) / 2, ( screen.height - my_window.size().height ) / 2 ); my_window.show(). In a related fashion, you can center something on its parent like this. Note the intelligent use of APIs like translate() to do the work for you. void center(Component parent) { pack(); Point p = parent.getLocation(); Dimension d = parent.getSize(); Dimension s = getSize(); p.translate((d.width - s.width) / 2, (d.height - s.height) / 2); setLocation(p); } 15. (Sect. 10) How can I get the absolute mouse coordinates? [*] You mean, if the browser is about 640x480, you want a y-coord between 0 and 480. If the browser window is about 800x600 you want a y-coord between 0 and 600. This might be needed for a pop-up menu, where you want to pop up at the absolute mouse position. The approach is to sum up the event's (x,y) and the locations of the target and its parents until there is no parent. Though on some browsers, it seems this is not reliable. [Better suggestions are solicited.] 16. (Sect. 10) How do I detect a resize of a Frame or other Component? [*] If you are using JDK 1.0.2, you can override the reshape(int, int, int, int) method of Component to do what you want; of course, have it call super.reshape() as well. In JDK 1.1.x, setBounds() replaces reshape(), which is deprecated - however, there is a better way of detecting the resize using the new event model, than overriding setBounds(). Note the new APIs call the depecated one. The proper way to detect the resize in 1.1.x is to register a ComponentListener on the Frame, like this: import java.awt.*; import java.awt.event.*; class MyFrame extends Frame { public MyFrame() { addComponentListener(new CmpAdapter()); } class CmpAdapter extends ComponentAdapter { public void componentResized(ComponentEvent evt) { //doSomething(); } } } Alternatively, the same effect can be achieved like this: class MyFrame extends Frame implements ComponentListener { public MyFrame() { addComponentListener(this); } public componentHidden(ComponentEvent evt) { } public componentMoved(ComponentEvent evt) { } public componentShown(ComponentEvent evt) { } public componentResized(ComponentEvent evt) { //doSomething } } Or even with an anonymous inner class public MyFrame() { addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent evt) { // doSomething; } } ); } 17. (Sect. 10) What are those preferredSize() and minimumSize() methods in Component? [*] Those methods allow a LayoutManager to calculate the preferred and minimum sizes of the Components it is arranging. You can control the values that the LayoutManager gets by creating subclasses of the Components you are using and overriding these methods. You don't call them; you override them and they are called on your behalf. 18. (Sect. 10) Why isn't my component showing up at all? Or in some cases not until I resize the main window? [*] The initial sizes of components are not always exactly what the programmer would expect. When a component doesn't show up, often it is getting added to its parent, but with a size of 0x0. Even when getPreferredSize gives a non-zero value. If this seems to be what's happening, try calling setSize(getPreferredSize()). If that doesn't seem to be the problem, look into your layout manager. Drawing and Pixels 19. (Sect. 10) How do I plot a single pixel to the screen? [*] Use g.drawLine(x1,y1,x1,y1) to draw a line one pixel in length. If you are drawing a very large number of individual pixels, consider using a java.awt.MemoryImageSource object and measure whether this offers better performance. 20. (Sect. 10) Is it possible to draw a polygon or a line more than 1 pixel wide? [*] JDK 1.1 doesn't have support for this. The standard workaround for drawing a thick line is to draw a filled polygon. The standard workaround for drawing a thick polygon is to draw several polygons. There is a useful class at http://www.apl.jhu.edu/~hall/java/GraphicsUtil.html which extends the drawxxx and fillxxx methods of java.awt.Graphics. It adds a Line Width argument to most of the drawxxx methods, a Color argument to most of the drawxxx and fillxxx methods, and a Font argument to drawString and drawChars. JDK 1.2 introduces the java.awt.BasicStroke class. You set the stroke on a Graphics object, and line rendering is done using that info. BasicStroke bs = new BasicStroke(width, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1.0f, null, 0.0f); g.setStroke(bs); g.drawLine( ... ); 21. (Sect. 10) How can I make an offscreen image with transparent pixels? How can I grab the pixel values from an offscreen image? How can I use AWT drawing primitives (e.g. drawString() or drawOval()) on an image I created from an ImageProducer? [*] None of these things can be done. Despite the fact that there is only one class called Image in the AWT libraries, it suffers from a (currently undocumented) severe case of schizophrenia: The code behaves as though there are two unrelated types of Image. The first type are those created by the Component.createImage(int, int) call, known as "offscreen" images, and the second are those created by the Component.createImage(ImageProducer) call, or by the Toolkit/Applet.getImage() calls, which I will call "produced" images. The only common ground between these kinds of Image is the following: o You may find their width and height by the methods of the Image class. o You may use them as the argument to the various Graphics.drawImage() calls. The differences between these objects are the following: o You may not put transparent pixels into an offscreen - note that all Java primitives accept Color objects, which all represent completely opaque colours as if Produced from an int with the upper 8 bits equal to 0xff. (See also Question 8.3.) o You may not call Image.getGraphics() on a produced image, and hence may not use any AWT primitives. o You may not grab pixels from an offscreen image using PixelGrabber. o Anyone know of any other limitations? In these cases, "you may not" generally means "you may not successfully". Symptoms on attempting these range from Exceptions to garblings of the Image. Any or all of these restrictions may be removed in Java 1.2, which features a new 2D API. Wait and see. Workaround: cause a peer to be created for the Image, and then do the operation. It will work. You can add it to a Frame, for example. You do not have to show() the Frame. Causing the peer to be created is enough. There are some relevant bugs shown in the Java Developer Connection: Bug ID 4098505. Apparently, from the report from the Sun engineer, PixelGrabber is specified to work with offscreen images, just it is currently buggy, and invariably gets the wrong color model. No fix has been scheduled yet. Bug ID 4077718 reports that setting transparent Colors in offscreen images has been available since Java 1.2b1. I am personally unable to verify this. There is an incorrect answer from Sun to the third matter, of getGraphics() on produced images, in article 1501 in Questions&Answers. 22. (Sect. 10) How can I grab a pixel from an Image object? [*] This is the purpose of the java.awt.image.PixelGrabber class. A fragment of code showing its use is: import java.awt.image.PixelGrabber; import java.awt.Image; ... public static int pixelValue(Image image, int x, int y) { // precondition: buffer must not be created from ImageProducer! // x,y should be inside the image, // Returns an integer representing color value of the x,y pixel. int[] pixel=new int[1]; pixel[0]=0; // pixel grabber fills the array with zeros if image you are // trying to grab from is non existent (or throws an exception) PixelGrabber grabber = new PixelGrabber(image, x, y, 1, 1, pixel, 0, 0); try { grabber.grabPixels(); } catch (Exception e) {System.err.println(e.getMessage());} return pixel[0]; } By the way, one issue on working with images is that the Java VM will consume virtual memory pretty fast if you are loading lots of images without calling the Image.flush() method when done. The getImage() method probably caches old images so they aren't garbage collected. Other AWT FAQs 23. (Sect. 10) How do I change the icon on my Frame or JFrame from the Java coffee cup to my own icon? [*] Just use f.setIconImage( Toolkit.getDefaultToolkit().getImage(iconfilename) ); On Windows, the icon must be 16-by-16 pixels. 24. (Sect. 10) What's all this about subclassing Canvas and overriding paint() ? Can't I just do a getGraphics() for a component, and draw directly on that? [*] You can do that, and it might work up to a point (or it might not). A problem arises when the window system wants to refresh that component e.g. because it has been partially obscured and is now revealed. It calls paint(), and paint() has no knowledge of the other g.drawing() you have just done. 25. (Sect. 10) But couldn't the AWT just remember what has been drawn to a Graphics context, and replicate that instead of calling paint()? [*] Possibly it could, but how do you unremember something that has been drawn? How do you start drawing over again with different contents? You could solve these by creating extra methods, but that is not how it works. In practice it is a lot simpler to be able to look at the paint method, and see explicitly all the things that will be done to draw that component. Bottom line: Use paint(), not g=getGraphics(); g.drawString( ... 26. (Sect. 10) When I call repaint() repeatedly, half my requests get lost and don't appear on the screen. Why is this? [*] repaint() just tells the AWT that you'd like a paint to happen. AWT will fold several adjacent repaint requests into one, so that only the most current paint is done. One possible workaround might be to use a clip rectangle and only paint the different areas that have changed. 27. (Sect. 10) Why do I get this when using JDK 1.1 under X Windows? java.lang.NullPointerException at sun.awt.motif.MFramePeer.<init>(MFramePeer.java:59) at sun.awt.motif.MToolkit.createFrame(MToolkit.java:153) at java.awt.Frame.addNotify(Frame.java) at java.awt.Window.pack(Window.java) [*] There's a missing font on your system. Move font.properties from the "lib" subdirectory aside to font.properties.bak. Then it won't look for the font and fail to find it. The problem occurs because the Motif AWT libraries use the Font "plain Dialog 12 point" as a fall-back default font. Unfortunately, when using a remote X server sometimes this font isn't available. On an X terminal, the diagnostic may be slightly different, a segv % appletviewer HelloWorldApplet.html SIGSEGV 11* segmentation violation si_signo [11]: SIGSEGV 11* segmentation violation si_errno [0]: Error 0 si_code [1]: SEGV_ACCERR [addr: 0x14] To determine which fonts you have, issue a command such as xlsfonts > ~/fonts.txt Then pick through the long list of fonts to determine which ones you want to use. The xfd program will let you look at a font: xfd -fn "your font name here" & 28. (Sect. 10) Why is GridBagLayout so hard to use? [*] There are two reasons. First, while simple layouts are easy. detailed GUI layout is difficult. Second, GridBagLayout wasn't designed with human factors and ease of use in mind. If that bothers you (it bothers me) then don't use it. Create your GUI on several panels and use the other layout managers as appropriate to get the exact effect you want. The official story from the project leader of the AWT project, as explained to the Mountain View Java Users Group on December 4 1996, is: "The case has been made and is now accepted that GridBagLayout is too hard to use for what it offers. GBL will continue to be supported, and something better and simpler will eventually be provided as well. This 'better GBL' can be used instead of GBL." Bottom line: nobody has to spend any effort on GBL, there are simpler alternatives available now. In addition GBL is the source of a memory leak. GBL puts "added" components into a hashtable, but removeLayoutComponent() never removes them. See bug 4195295. GBL documentation is hard to come by. Based on the obvious similarity, it could have been derived from the Tk (of Tcl/Tk) grid layout manager. If you're not a fan of nesting panels, and none of the other layout managers do what you want (or you're working with legacy code that already uses it), you might find some Tk documentation worth a look. 29. (Sect. 10) MyClass works fine except when I try to set a particular font. I just can't seem to get it to work in Win95, but I can get it to work on a MacOS and Unix. [*] You probably specified a font name that isn't available under your Win95 installation; this is one of those cross-platform differences that can bite you if you over-specify for one platform, like specifying "Arial" as a font and expecting it to work on something other than Windows. On both Windows 95 and Solaris 2.6, these fonts o Dialog o SansSerif o Serif o Monospaced o Helvetica o TimesRoman o Courier o DialogInput o ZapfDingbats are revealed by this code: import java.awt.*; class foonly { static public void main(String s[]) { String n[]= new Frame().getToolkit().getFontList(); for (int i=0;i<n.length; i++) System.out.println(n[i]); System.exit(0); } } In other words, You can get a String array of the names of the fonts by String[] fonts = Toolkit.getDefaultToolkit().getFontList() The names of actual fonts like Helvetica, TimesRoman, and Courier are deprecated in JDK 1.1 in favor of font styles like SansSerif, Serif, and Monospaced (respectively). The font style will be mapped into the nearest actual font on a platform. The font styles are now mapped into a system font name using the entries in one of the font.properties files in $JAVAHOME/lib. There are multiple font.properties files corresponding to different locales. If you wanted a quick hack for testing, you could modify the file or add to it so a different mapping is done to a new font you want to try. 30. (Sect. 10) I've made a Lightweight Component (a Component directly extending Component), and it keeps flickering/doesn't repaint itself properly. Why is this? [*] Lightweight Components, since they are notionally meant to be "transparent", aren't painted directly in response to repaint(), but in fact, Component.repaint() goes up the stack of Components until it finds an "Opaque" Heavyweight Component (necessarily a Container), and then calls repaint() on *that*. At this point, a call is eventually scheduled to Container.update(). His first action is to call super.update, plunging us into Component.update(), which clears the component to the background color, since it has been called on a heavyweight, and returns. Then Container.update() proceeds merrily to call update on all contained Lightweight Components, recursively. The bottom line: "transparency" of lightweight components will only work correctly (without flickering) if the first upwardly accessible heavyweight component in the containment hierarchy is o a double-buffered heavyweight Component (necessarily a Container), or o a heavyweight that never updates, but always paints (i.e. one that has overriden the default update() mechanism to not clear the background). If this is not done, the default Component update() will always clear the background before any repainting is done, leading to annoying flickering. Another important point is that if your Container has its own paint() method, that paint method of the container must call super.update/paint(), otherwise the contained lightweight components will never be painted. Putting this all together, the minimal alteration to code to cause it to work in this case is to place the method public void update(Graphics g) { super.paint(g); } in the most closely containing heavyweight Container, in a Component hierarchy where you want to smoothly render lightweights that do not paint areas extending past that painted by their parents, i.e. ones that are not "transparent". This is dirty, but quick. If you want smooth transparency, the call above should read public void update(Graphics g) { // standard offscreen generation here. offg.fillRect(required background colour, full size); super.paint(offg); g.drawImage(myimage, 0, 0, null); } public void paint(Graphics g) { // can generally expect resizes will hit update() first. super.paint(offg); g.drawImage(myimage, 0, 0, null); } It's possible to intertwine these, by having this.update() calling this.paint(), with various replacings of the argument, but it is clearest to override them separately, as in the example. 31. (Sect. 10) What is the difference between Component's setForeground(Color c) and Graphics's setColor(Color c) ? [*] First of all, these methods do the same thing: Set the foreground color to the value of the parameter. The difference lies in where you use them. There is also a Component.setBackground that will set the background color. If you are in a constructor or an event handler (e.g. "click here to turn the canvas blue") you have a Component and should use the setForeground() method. If you are in a paint() method, that takes a Graphics context as its argument so you will typically use g.setColor(c). Unlike a Component, a Graphics object doesn't have a background color and a foreground color that you can change independently. A Graphics object arrives in the color(s) inherited from the drawing surface. From then on, any rendering (drawLine(), drawRect(), fillOval(), etc.) will be done in the setColor() color. Because they do different things, the Component and Graphics methods have different names. 32. (Sect. 10) When I start a mouse drag inside a Component, and go outside the Component, still dragging, the mouse events still get sent to the Component, even though I am outside it. Is this a bug? [*] No, it is the specified behavior. The Java API documentation says: "... Mouse drag events continue to get sent to this component even when the mouse has left the bounds of the component. The drag events continue until a mouse up event occurs...." It is done for the convenience and ease of the application programmer. It allows you to handle all drags from the place of origin. If you don't want this, simply look at the coordinates of the mouseDrag Event, and if they are outside the Component, ignore them. 33. (Sect. 10) Why doesn't my window close when I click on the X in the title bar? [*] Here's how to make your program do that. o JDK 1.0.2: Handle Event.WINDOW_DESTROY to do a hide() and dispose() on the Frame. o JDK 1.1: + Listen for WindowEvent and do hide(); dispose(); in windowClosing() - this really ought to be the "default" behaviour, so was made so for a Swing JFrame. + Enable AWTEvent.WINDOW_CLOSING and do the hide() and dispose() in processWindowEvent(). o JDK 1.2: The Component JFrame does a close by default (see section 10). 34. (Sect. 10) How can I force a synchronization of the graphics state, e.g. of a cursor change, or an animation frame to be rendered? [*] This is done by the sync() method in Toolkit. So just use: AnyComponent.getToolkit().sync(); 35. (Sect. 10) How can I tab between components? [*] In JDK 1.0, you have to read the key press, and program it explicitly. JDK 1.1 supports tab and shift-tab (previous field) automatically. The tab order is the order that the components were added to the container. 36. (Sect. 10) What is the difference between "low level" and "semantic" events? [*] Low-level events are tied to a specific component (resizing a window, dragging the mouse, striking a key, adding a Component to a Container, etc.). Semantic events are those generated when you frob a control (move a scrollbar, click on a button, select from a menu, etc.), and the same kind of event can be generated by several different components. A Button and a List both fire an Action event when they are clicked on. To the programmer, the important difference is that you can change a low-level event such as the key value in a keypress, and it will display the new value. You can also consume low level events so that they do not appear in the widget. You can't do these things with semantic events - they have already "occurred" to the widget. Semantic events: Use the method addXListener() to add a listener object which implements the XListener interface to get XEvent objects delivered (usually via the AWTEventMulticaster). Low level events: Use the method enableEvents() and override performX() to grab those events in the object itself. 37. (Sect. 10) Is it possible to have a Java window float above all other windows. For example, a tool palette floats in a super-layer always above all the regular document windows on which you use the palette's tools? [*] On MS Windows, a Window object floats above all other windows, unlike a Frame, which is layered in with ordinary windows. This behavior yields a "floating" effect. Whether a Window object is really supposed to float is another question entirely. On Mac, a Window object is either layered in with other windows, just like a Frame is, or else it is entirely modal - depending on which VM you use. In Java - there appears to be no easy way to get floating behavior. If anyone knows otherwise, please send in your comments. 38. (Sect. 10) How can iconify/deiconify a window in Java? [*] JDK 1.1 had no way to write code to force a window to iconify or deiconify. Support was added in JDK 1.2. MyFrame.setState( Frame.ICONIFIED ); MyFrame.setState( Frame.NORMAL ); will do the trick. There is a corresponding getState(); 39. (Sect. 10) How do I know which mouse button was pressed, and how often? [*] To handle mouse events you have to implement the MouseListener interface, or derive from the MouseAdapter class in order to use one of the mouse-handling methods. The MouseEvent argument passed to the handling methods contains fields that say which button was pressed, and the click count. Use code like this. public void mouseClicked(MouseEvent m) { boolean leftButtonPush = (m.getModifiers() & java.awt.event.InputEvent.BUTTON1_MASK) != 0; boolean centerButtonPush = (m.getModifiers() & java.awt.event.InputEvent.BUTTON2_MASK) != 0; boolean rightButtonPush = (m.getModifiers() & java.awt.event.InputEvent.BUTTON3_MASK) != 0; int click = m.getClickCount(); // might be 1,2,3 clicks or more You can also call at m.isPopupTrigger(). If it returns a true value, the user has asked for a pop-up menu. On a lot of window systems, the right mouse button is the trigger for pop-up menus. You can overload processMouseEvent for your component. public void processMouseEvent(MouseEvent e) { if (e.isPopupTrigger()) { // do what you want } else super.processMouseEvent(e); } The code above applies to JDK 1.1. You can also call java.awt.swing.SwingUtilities.isRightMouseButton(MouseEvent me). See also question 15.10. ------------------------------- 11. Swing 1. (Sect. 11) What is Swing? [*] Swing is a new GUI toolkit bundled with JDK 1.2, and available as an add-on extension library for JDK 1.1. Swing is part of the Java Foundation Classes and supports a GUI toolkit that lets developers create components that have a pluggable look-and-feel. From an architectural standpoint, the Swing component set extends - but does not completely replace - the Abstract Windowing Toolkit (AWT). Swing has many components that can be used in place of components in the AWT (e.g. JFrame instead of Frame, JButton instead of Button, JApplet instead of Applet, JPanel instead of Panel). It also has many components that don't exist in the AWT (e.g. tool tips, toolbars, and progress bars). However Swing relies on the underlying AWT being there. The Swing toolkit allows the creation of GUI's that are every bit as sophisticated as native code toolkits like MFC -- with the Java advantage that they run on every platform. The pluggable look and feel means that they can have the same appearance on every platform, or you can choose to have it look like Windows on a PC, like Motif on a Unix box, etc, just as the user chooses. Swing also supports the Accessiblity API. That API allows the adaptive software used by disabled computer users to directly query the Java VM and extract information about the running program, the usual purpose for this being to determine the UI components. Then the existing adaptive software can interpret it to the user (e.g. read the contents of a window, etc). Swing doesn't use native components, and the adaptive software taps into native components, so without the accessibility API has a real role in bringing the two together. The beauty of the Accessibility API is that developers need to do little work to support it, but they do need to be made aware of it if they add new components. With Swing, native window behavior is confined to external window frames (and their borders) and a few other things such as fonts and the buffers used to hold window contents. The composition, layout, and drawing of controls is now all handled by Java code. So identical code is executed to create and manage your user interface on every platform. Swing provides a much greater consistency of behavior across different platforms. Swing works with JDK 1.1 if you download the swing.jar file and add it to your path. Swing is built in to JDK 1.2, and Javasoft has just changed its 1.2 Swing package-naming strategy. It is now called javax.swing. 2. (Sect. 11) Should I use Swing or AWT to build my GUIs? [*] Use Swing to build your apps now instead of AWT components, wherever you have a choice. Swing is a GUI toolkit that is at least as good as other commercial GUI toolkits, and better in several respects. With Swing, it is easier to build an application that is portable between Mac, Solaris, Windows 95 and NT, than it is to use Win32 and build an application that just runs on Windows 95 and NT. 3. (Sect. 11) Where can I find a Swing tutorial? [*] There is a Swing tutorial at http://java.sun.com/docs/books/tutorial/ui/swing/index.html which is part of this tutorial: http://java.sun.com/docs/books/tutorial/ui/TOC.html There is also a Swing FAQ at http://www.drye.com/java/faq.html See also http://www.codeguru.com/java/Swing/index.shtml There is a Swing Developer Connection website with white papers and examples at http://www.theswingconnection.com/. Please let this FAQ maintainer know about other good Swing tutorials and online resources. 4. (Sect. 11) What is the Model/View/Controller paradigm? [*] Model/View/Controller is a design pattern or framework originally developed by Prof. Trygve Reenskaug at Xerox PARC in 1978/9. MVC was developed to allow Smalltalk to conveniently support GUIs. Model/View/Controller is a design pattern used extensively in Swing. Basically, the "model" contains your data, the "view" is the graphical representation, and the "controller" is responsible for the interaction between the other two. As an example, think of visually editing the Tree widget that represents a directory. The display is the view. Selecting a file, and dragging it to the trash can will delete the file. In order for the delete to happen, the controller must tell the model what just happened in the view. In practice, inter-communication between the view and the controller is complex, so the two are bundled together in one category in Swing. The model (data) is separate though. There's a reasonable white paper on MVC in Swing at http://java.sun.com:81/products/jfc/swingdoc-static/swing_arch.html . There is information on other OO design patterns at http://www.parallax.co.uk/cetus/oo_patterns.html. 5. (Sect. 11) When I run the Swing demo on Windows 95 I get an error "Out of environment space." [*] That's because you don't have enough space for your DOS environment. You can fix this with: o Right click your MS-DOS Prompt icon or window and choose Properties. o Choose "Memory" and on "Initial Environment", choose 4096 instead of "auto". o Run Swing again, you'll be OK. 6. (Sect. 11) How can I run Swing code in a browser? [*] Most current browsers have to be specifically set up to run Swing applets. Read the article at http://www.javasoft.com/products/jfc/swingdoc-current/applets.html for information about this. The article also contains a simple Swing example applet, so you can confirm that that's your problem. Another approach is to use the Java plug-in, which automatically gives a Swing-compatible Java in the browser. See http://java.sun.com/products/jfc/tsc/swingdoc-current/java_plug_in.html 7. (Sect. 11) Why is my menu showing up behind other components when I use Swing? [*] The answer relates to lightweight and heavyweight (peer-based) components. There is a good article about it at http://www.javasoft.com/products/jfc/swingdoc-current/mixing.html For those who want the quick fix, and will read the article later, adding the line: javax.swing.JPopupMenu.setDefaultLightWeightPopupEnabled(false); before you create any menus will probably fix it (even if you're using menus other than JPopupMenu). The summary answer is that a Lightweight component will not appear over a heavyweight component by default. 8. (Sect. 11) Why is there no JCanvas? How do I get a lightweight Canvas? [*] Use a JPanel as a Swing replacement for Canvas. All Swing components have a paint(Graphics) routine that you can override, just as you would have with Canvas, (but you probably want to override paintComponent(Graphics) instead, see next question). 9. (Sect. 11) Why don't the borders of my Swing components look right when I override paint(Graphics)? [*] Swing splits painting into several different routines: o paintComponent(Graphics), o paintBorder(Graphics), o paintChildren(Graphics) all of which are called from paint(Graphics). If you override paint(), unless you remember to do it, the paintBorder() and paintChildren() won't get done. In most cases, what you really want to do is override paintComponent() instead of paint(). 10. (Sect. 11) Why does my JFrame go away after I choose system close on the window? [*] Assume that you have a Swing JFrame component, and you handle the windowClosing event, but do nothing in the handler. You will see that the JFrame disappears anyway. The reason is that JFrame's have default handling of the system close operation, separate from the windowClosing event. You have to override that by calling: setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); on your JFrame. 11. (Sect. 11) Why can I run the Mac Look and Feel only on Mac OS? [*] (This answer comes from the Swing Connection, see http://java.sun.com/products/jfc/tsc/swingdoc-current/911.html). Sun has not determined that it has the right to deliver the Mac look and feel on platforms other than MacOS. If Apple were to confirm Sun's right to deliver this look and feel on other operating systems, Sun would be delighted to remove the lock. To date, Apple has declined to do this. Although you cannot use the new Mac L&F on non-Macintosh platforms, there is a way to examine the source code so developers can use it as an example of how to create a custom L&F. The Mac L&F is distributed in "stuffed-binhexed" format, which is standard for the Macintosh. If you develop on a MS-Windows platform and would like to examine the source code for the Mac L&F then you can do that by downloading and using a program called Aladdin Expander for Windows. You can download Aladdin Expander from this URL: http://www.aladdinsys.com/expander/index.html When you have downloaded Aladdin Expander, you can use it to decode the Mac L&F file posted on the JDC. A recent posting on comp.lang.java.gui suggested the following user workaround: import com.sun.java.swing.plaf.windows.WindowsLookAndFeel; class MyOwnWindowsLookAndFeel extends WindowsLookAndFeel { public isSupportedLookAndFeel() { return true; } } The desire on Sun's part to avoid infringing the Windows Look and Feel is also the reason why the JTree uses colored circles (and soon, little circles with a short line coming out of them) for the nodes to indicate whether they are open or not. The Swing team could have used the '+' and '-' as Windows does, or even the triangles that MacOS uses, but decided against it. 12. (Sect. 11) When I set the cursor to WAIT_CURSOR why does it only change when my cursor is over specific components? or How can I change the cursor to a WAIT_CURSOR over my entire window and all of its components, preventing any user action, while some other process is happening. (i.e. database access, opening another window, downloading an image, sorting some data, etc.) [*] In JDK 1.0.2 only the awt Frame could change its Cursor. With the advent of JDK 1.1 the Cursor manipulation has been move to the Component clss. Now all Components have access to the Cursor class. You could change your Cursor to a WAIT_CURSOR for each Component. This could be time-consuming. You could have a potentially large number of Components. With the advent of the JFC Swing, there is a mechanism to change the Cursor over the entire Window regardless of the number of components. The Swing component JFrame has a method: public void setGlassPane(Component glassPane) which sets an awt Component as the 'glassPane' for the JFrame. This Component will cover the entire JFrame's visible user accessible (when visible), area excluding the border set by the underlying windowing system. With the 'glassPane' Component you can set the 'WAIT_CURSOR' over an entire JFrame, prohibiting user input (the 'glassPane' Component gets all user input) and blocking the user until your 'other' processing is complete. NOTE: You must spawn a Thread to accomplish your 'other' work if you want to see the WAIT_CURSOR while the 'other' processing is happening. When the 'other' work is being accomplished, the 'glassPane' is visible with a WAIT_CURSOR and gobbling up all user input. When the 'other' work is finished, the Thread uses your waitCursor() method to hide your 'glassPane' until its needed again. 13. (Sect. 11) Why does the compiler complain that the javax.swing.ProgressMonitor method "isCancelled()" isn't found? [*] In American English there are two acceptable spellings: "canceled" and "cancelled". Note that the first one has one "el" and the second two "el's". Sun spells this "canceled" for ProgressMonitors but many of the secondary sources of documentation spell it "cancelled". To make matters worse, Sun spells it "cancelled" at other times, such as the method "isCancelled()" for PrinterJob. 14. (Sect. 11) Why doesn't pressing the Enter key activate the default button on a Swing dialog? [*] The default keymap for Swing text components (derived from JTextComponent) binds the Enter key (VK_ENTER) to the ActionEvent for text fields. This was done to be compatible with the behavior of java.awt.Textfield. To enable use of the Enter key to activate the default button, remove the Enter key binding from the default text component keymap as follows: static { KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0); Keymap map = JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP); map.removeKeyStrokeBinding(enter); } 15. (Sect. 11) How do I create non-rectangular Components? [*] Take a look at the following example that comes with the JDK: $JAVAHOME\demo\awt-1.1\lightweight\RoundButtons\example.html ------------------------------- 12. Browsers 1. (Sect. 12) When will my favorite browser support Java 1.1? [*] All popular browsers now have JDK 1.1 support. Netscape Communicator 4.04 plus patch "J" fully supports the features of Java 1.1. It was released in December 1997, and is only missing the JavaSoft support for applet signing (Netscape has gone its own way on this). See http://developer.netscape.com/support/faqs/champions/java.html#21 If you have Netscape 4.05, and the console says anything other than Java 1.1.5 then you do not have a fully 1.1 compliant Netscape. There is a special preview version available here: http://developer.netscape.com/software/jdk/download.html Netscape badly fumbled its Java support in 1997 as its market was seized by Microsoft. Microsoft is using IE as a strategic tool to deploy what Microsoft employees call "polluted Java". For both of these browsers, the Java Plug-in is currently a good approach. Sun's HotJava browser fully supports the JDK 1.1 features. People who are obliged to use a browser without standard Java support should use the Java Plug-In. The Java Plug-In substitutes a standard Java virtual machine for the one that shipped with the browser. It allows you to use RMI, JavaBeans components, and Java Foundation Classes in Internet Explorer 3.02, 4.0, and 4.01. The Java Plug-In also works flawlessly with Netscape browsers. You can download the Java Plug-In from http://java.sun.com/products/. Note that you need to change the HTML a little, to ensure that the plug-in JVM is invoked, not the browser JVM. A tool is included to do the changes automatically. 2. (Sect. 12) What applet routines get called in various browsers and the plug-in on different browsing actions (back, forward, load, etc)? [*] Java supporter Dave Postill did the work to get this answer. The life cycle of an applet is illustrated by logging calls to init(), start(), stop() and destroy(). Use caution when your applets have threads since in most sample applet code, the stop() method calls stop on any separate threads within the applet, and then sets them to null. This reckless threadicide is because most people think of the stop() method as something called only when the user leaves the page and wants to forget about it. But since Netscape calls stop() when you resize the window, your users would lose the applet's state when they thought they were only making a minor adjustment. See "Java Tip 8: Threads, Netscape, and the resize problem - How to deal with applet resizing in Netscape Navigator", JavaWorld http://www.javaworld.com/javatips/jw-javatip8.html. Sadly the JavaWorld workaround does not completely fix the problem, since it relies on start() being called soon after stop() to identify a resize. However if you minimise the browser it may send a stop() to the Applet and then may not send a start() until the Browser is either restored or maximised. In this case, using the workaround results in the Applet being destroyed following minimising of the Browser - unless the Browser gets un-minimised within the killThreads timeout. Netscape Netscape Applet- Internet Internet [4.04/JDK with Viewer Explorer 4 Explorer 1.1.4] Plug-In [JDK SP1 with Plug-In [4.05/JDK [4.05/ JDK 1.1.5] 4.72.3110.8 [5.00.0518.10 1.1.5] 1.1.5/ [JDK on NT 4.0 / Plugin 1.1] Plugin 1.1] 1.1.6] SP3 on NT 4.0 SP3 1. Clear browser nothing nothing nothing nothing nothing cache init(), 2. start() or Initial init(), init(), init(), init(), init(), load of start(), start() start() start() start() .html stop(), start() [1] 3. Back stop() stop(), [4] stop(), stop(), destroy() destroy() destroy() 4. init(), init(), init(), Forward start() start() [4] start() start() stop(), stop(), stop(), stop(), 5. Reloaddestroy(), destroy(), [4] destroy(), destroy(), init(), init(), init(), init(), start() start() start() start() 6. <shift> reload stop(), stop(), stop(), stop(), [NS], destroy(), destroy(), [4] destroy(), destroy(), <ctrl> init(), init(), init(), init(), reload start() start() start() start() [IE] 7. Resizestop(), [3] [3] [3] [3] start() 8. Minimize [2] [3] stop() [2] [3] 9. Restore [2] [3] start() [2] [3] 10. Exit stop(), stop(), stop(), stop(), stop(), destroy() destroy() destroy() destroy() destroy() Notes: [1] Results not repeatable. [2] Not tested. [3] Tested, and found that no logged methods are called. [4] Test not applicable. 3. (Sect. 12) Is it possible to set and retrieve cookies from Java, in a manner that is compatible with all browsers supporting cookies? [*] Short answer: no. Longer answer: probably no. Ultimate answer: A cookie is a morsel of tasty data that a server sends back to the client, and can retrieve on demand. It allows the server to retain some state information for each of its clients. The information is typically something like "what pages has the user seen?" or "is this a privileged user?". The DevEdge site on Netscape's home page has a Javascript-Java example on getting cookies. Also http://www.geocities.com/SiliconValley/Vista/1337 has info on connecting an applet with JavaScript functions. It's quite involved. Stick to just Java if you can. 4. (Sect. 12) I am developing an applet and testing it in Netscape Navigator. I find that after I recompile, I press reload, clear the caches, retype the URL of the HTML wrapper, and I still have the old version. Why is this? [*] Note: a reader reports that as of Netscape Communicator 4.05 it is possible to force the browser to reload the applet by holding down "control"+"shift" while clicking "Reload" In the past Netscape has completely failed to improve the defective code that does this monstrously wrong thing. It has been like this for many successive releases. Flushing the network cache will make no difference; that isn't where the caching is taking place. Although applets are sometimes "pruned" and their ClassLoaders garbage-collected, this doesn't happen predictably, so restarting Netscape is the only reliable work-around at the moment. A related question is "how do I make the browser reload from a URLConnection instead of just getting the content from the local cache?" The answer is to use java.net.URLConnection.setUseCaches(false) Browsers seem to vary in their conformance to this programmatic request. Netscape caching varies depending on whether a proxy server is in use, and which thread in the applet made the get request. Another approach is adding "?" to the URL, e.g. http://www.somesite.com/webcam/image.jpg?100 and increasing this number each time the Applet fetches the image. 5. (Sect. 12) Why didn't Netscape reload the applet when you pressed the Reload button? [*] For the applet to be reloaded, the new version would have to be loaded in a different ClassLoader. Navigator/Communicator's policy for assigning ClassLoaders to applets doesn't take into account whether a reload has been done (although there is no technical reason why it couldn't). Some versions of Netscape reload the Applet if you use Edit/Preferences/Advanced/Cache to Clear Memory Cache and Clear Disk Cache, then <Shift> while you click on reload. In Explorer, use View/Options/General/Delete Files, then <Control> 'Reload' button to reload the page containing the applet. Until they fix it, use the appletviewer to test applets. And send them mail - developers can only fix the bugs they know about. 6. (Sect. 12) Should I use Microsoft CAB files or Java JAR files? [*] The question contains its own answer. CAB format is a Microsoft-only format. So do not use it as it destroys software portability. JAR format is the Java standard format, based on PKZIP format including data compression. JARs were introduced with JDK 1.1. See http://www.ibm.com/java/community/viewarchive4.html for more information. You should use the Java standard format JAR (Java Archive) files, not a vendor-specific format. JAR files are not just a Java standard, they are in industry-standard PKZIP format. One reader comments that both formats can be used with this tag: <APPLET NAME=myapplet ARCHIVE="myzip.zip" CODE="com/nnnnn/nnnn/cccccccc.class" WIDTH=n HEIGHT=n> <PARAM NAME="cabbase" VALUE="mycab.cab"> </APPLET> IE3 does not support JAR IE4 supports compressed and uncompressed JAR, but not signed JAR 7. (Sect. 12) How can I tell the version of Java that my browser supports? [*] See http://java.rrzn.uni-hannover.de/insel/beispiele/vertest.html. This page tells you whether your browser supports JDK 1.1. See http://www.uni-kassel.de/~pfuetz/Properties.html This page tells you which classes you may expect to be present in the browser's runtime. 8. (Sect. 12) How can I tell the options/commands that Netscape's JVM takes? [*] You can open the Java Console and type a "?" to get a list of all the commands/options available to you in Netscape's built-in JVM. ------------------------------- 13. Applets 1. (Sect. 13) What is the difference between an application, an applet, and a servlet? [*] An applicationis a standalone program. An applet is a downloadable program that runs in a web browser. Typically an applet has restricted access to the client system for reasons of security. Other than that it is virtually no different from a regular Java program. A servlet is a Java program whose input comes from a server and whose output goes to a server. Other than that it is virtually no different from a regular Java program. Think of a servlet as an application, but one that (like an applet) requires a context in which to run, namely web server software. Servlets are used like CGI scripts, but take much less processor resources, and they allow the server end to be written in Java as well as the client. There is a page with much servlet information at: http://www.frontiernet.net/~imaging/servlets_intro.html There is a servlet tutorial at http://java.sun.com/docs/books/tutorial/servlets/index.html and another servlet tutorial at http://www.novocode.com/doc/servlet-essentials/ There is a servlet FAQ at http://www.saint-elie.com The web server starts up a servlet when the URL is referenced, and now your applets have something that they can talk to (via sockets) on the server that can write files, open connections to other servers, or whatever. There is also a software technology from IBM called an "Aglet". An aglet is a mobile agent that can go from machine to machine, performing tasks, serializing data collected, and "shipping itself" (code and data) to the next machine. It's too early to say if aglets are a flash in the pan or a dawning technology. Read about aglets at http://www.trl.ibm.co.jp/aglets/ Finally, there is the ticklet (Tcl/Tk) plugin for your browser (Netscape or Explorer) available at http://sunscript.sun.com/plugin/ Don't confuse Sun's JWS "Java Web Server" with JWS "Java Workshop". Java Web Server supports servlets, as does the lightweight and free server at Acme.com: http://www.acme.com/java/software/Acme.Serve.Serve.html 2. (Sect. 13) My applet works on my machine, but fails when I put it on our web server. Why? [*] It could be one of several reasons, and unfortunately the messages that you get in this situation aren't much help. In general, you can assume that either your applet's class files are corrupted somehow, or the web server can't find one or more of them when the browser needs them. Be careful of the following things: o Make sure you transfer the class files in binary mode, rather than text or ASCII mode. An error from the browser saying "cannot start applet ... bad magic number" usually means that one of the class files on the server is corrupted. Replace your class binary files on the web server, clean up the cache of your browser, and reload your applet. o Make sure you transfer all of the class files that are a part of your applet. Sometimes people are surprised by how many there are. There will be a class file for every class and interface you define, even if you define more than one in a single source file. If you use the Java 1.1 "inner classes" feature, there will be class files for each inner class as well. o Make sure you maintain the appropriate case distinctions in your filenames. If a class is called StUdLy, it must be found in a file called StUdLy.class. o Make sure you maintain the directory structure that matches your package structure. If you declare a class in package com.foo.util, the class either needs to be in a Jar file, or the class file needs to be in directory com/foo/util under the applet's codebase directory. Again, case distinctions are important for package/directory names, just as they are for class/file names. o Make sure that the web server process will have read access to the class files, and search access to the directories that the files are in. For example, if the web server runs on a Unix machine, use the command "chmod o+r filename" for the files, and "chmod o+x dirname" for the directories. 3. (Sect. 13) How do I load a webpage using an applet? [*] Use code like this, getAppletContext().showDocument( new URL("http://www.here.com") ); Or, to show the page in another window or frame, getAppletContext().showDocument( new URL("http://www.here.com"), "windowname" ); 4. (Sect. 13) How do I use an image as the background to my applet? How do I set the background color of my applet the same as the browser? [*] You can simply do a g.drawImage(yourImage, x, y, this) in the paint() routine of your applet. If the image isn't big enough to fill the entire background, tile it or scale it. Here is some code to tile it // The background image is named "bg". int w = 0, h = 0; while (w < size().width) { g.drawImage(bg, w, h, this); while ((h + bg.getHeight(this)) < size().height) { h += bg.getHeight(this); g.drawImage(bg, w, h, this); } h = 0; w += bg.getWidth(this); } Alternatively, the AWT can scale your background image to the size of the applet. The result quality will depend on the kind of image. Inside an applet class, you can use: drawImage(img, 0, 0, size().width, size().height, this); You can set the background color to match the background color of the browser by passing the value in as a parameter, like this: In the HTML applet tag: <param name=BrowserColor value=F1F1F1> (value should be the same hex as the HTML COLOR value). In the Applet init() method: String colparam = getParameter("BrowserColor"); int col = Integer.valueOf(colparam,16).intValue(); setBackground( new Color(col) ); An applet cannot override the size imposed by the HTML. If you make the applet larger, the browser will still clip to the original size. If you need more room, open up a new Frame, Window or Dialog to show your output. 5. (Sect. 13) How do you make the applet's background transparent? [*] There is no way to give an applet a transparent background that lets the web browser background show through. You can simulate it by giving the applet a background that matches the underlying browser background. (For a straight color, it will be the value of <BODY BGCOLOR=nnnnnn> in the HTML file). It doesn't produce satisfactory results with a patterned background because of problems aligning the edges. Lightweight components (new in JDK 1.1) have a transparent background, but that merely allows other components to show through. A lightweight component is always ultimately positioned in a heavyweight component. 6. (Sect. 13) How do you do file I/O from an applet? [*] Unsigned applets are simply not allowed to read or write files on the local file system (see answer to question 7.8). Unsigned applets can, however, read (but not write) non-class files bundled with your applet on the server, called resource files. See answer to question 7.8 and question 7.9. 7. (Sect. 13) How do I pull a non-class file, such as a .gif, out of a jar file? [*] [Question has been retired, in favor of question Q7.9] 8. (Sect. 13) How do I read a text file stored in a Jar? [*] [Question has been retired in favor of Q7.9] 9. (Sect. 13) How do you get a Menubar/Menu in an applet? [*] In your applet's init() method, create a Frame instance and then attach the Menus, Menubar etc to that frame. You cannot attach the Menu or a Menubar to an applet directly. Or get the parent Frame like this (doesn't work in all execution environments): Container parent = getParent(); while (! (parent instanceof Frame) ) parent = parent.getParent(); Frame theFrame = (Frame) parent; This second suggestion definitely doesn't work in the appletviewer, and probably won't work on Macs (where would the Menubar go?) or in some browsers. In JDK 1.1, just use a popup menu, which isn't attached to a Frame. 10. (Sect. 13) Can I get rid of the message "Warning:Applet Window" along the bottom of my popup windows in my Applet? [*] This is a security feature that prevents the applet programmer from popping up a window that looks like it came from the native OS and asking for passwords or credit card info (etc.). Users must always be aware of when they are talking to an unsigned applet. You can get rid of it by signing the applet, if the user accepts signed applets from you. In Netscape (only), using the Capabilities API to make the call PrivilegeManager.enablePrivilege("UniversalTopLevelWindow"); before creating the Frame eliminates the message, if the security manager passes it. 11. (Sect. 13) When I subclass Applet, why should I put setup code in the init() method? Why not just a constructor for my class? [*] The browser invokes your constructor, then setStub, then init(). Hence when your constructor is invoked, the AppletStub (and through it the AppletContext) is not yet available. Although in principle you can do things in the constructor that don't rely (even indirectly) on the AppletStub or AppletContext, it is less error-prone to simply defer all setup to the init() method. That way you know that anything that needs the stub/context will have it available. 12. (Sect. 13) I want to know about {applets,applications} but the lousy book I got just talks about {applications,applets}. What can I do? [*] The truth is that 95% of the material is the same, whichever your book chooses to focus on. Some people write their apps to work completely in a Panel, then depending on whether they're running stand-alone or in a browser the Panel is either added to a Frame or an Applet. The trick is that you need to add a listener to the application's Frame to handle the WINDOW_CLOSING (previously WINDOW_DESTROY) event yourself. If you fail to do this, when running as an application, the window won't close. See Question 15.7 for a sample of the right handler. In this scenario the following code will tell you which environment you're running in: public boolean isRunningInBrowser() { Component p = getParent(); while(p != null && !(p instanceof Frame)) { p = p.getParent(); } return (p == null); } 13. (Sect. 13) How do I print a page with an applet? [*] Browsers are starting to introduce support for this. Until they all have it, your best bet is to print a screendump. Using the browser to print the page may leave a blank where the applet is. Putting print support in the applet will print the applet only, not the rest of the browser page. Also in the FAQ: Q5.2. 14. (Sect. 13) How can I position my dialogs centered (not top left)? [*] Use some code like this: void center(Component parent) { pack(); Point p = parent.getLocation(); Dimension d = parent.getSize(); Dimension s = getSize(); p.translate((d.width - s.width) / 2, (d.height - s.height) / 2); setLocation(p); } 15. (Sect. 13) How can I get two applets on the same page to communicate with each other? [*] This is the purpose of the InfoBus protocol. See http://java.sun.com/beans/infobus/index.html The older way to do it was as follows. In your HTML page, give a NAME in the APPLET tag for the applet receiving the message, say <APPLET ... NAME=someName ...>. In the Java code of the other applet do Applet anotherApplet = getAppletContext.getApplet("someName"); Cast anotherApplet to the correct applet subclass, and you can call any methods in the applet subclass. Don't forget to use appropriate synchronization when two threads tweak variables. This only works when the applets are truly on the same page. If they are in different frames, it doesn't work. You can walk through all the applets on an HTML page using code like that below. However this appears to be broken in Communicator 4.04 on Win95. Applet otherApplet; AppletContext ac =getAppletContext; Enumeration applets = null; for (applets=ac.getApplets(); applets.hasMoreElements(); ) { otherApplet=(Applet)applets.nextElement(); if (otherApplet!=this) break; // do something with otherApplet, e.g. // if (otherApplet instanceof FooApplet) ... } Some people suggest using the static members of a common class to communicate information between the applets. This is not recommended as it relies on class-loading behavior that may change in future. Netscape changed it in one Beta so it didn't work, then changed it back again so it did. It doesn't work if you use the "mayscript" tag though. Inter-applet communication sometimes arises when you have a multi-screen type program and you don't want to force the user into downloading everything at once. One alternative is to make them into one applet with two GUIs. Try to avoid the need for applets to talk to each other. Also check the URL http://java.sun.com:81/products/hotjava/1.1/applet_environment.html which explains how it can be done in HotJava 1.1. Recommendation: avoid code which is browser-specific. 16. (Sect. 13) How can I resize an applet? [*] If you want resizing behavior from an applet, you should launch an external Frame that can be resized independently. One programmer suggests using percentages for the height/width parameters in an applet tag, like this: <APPLET CODE="lewinsky.class" WIDTH="100%" HEIGHT="100%"> You can't resize the applet directly, but it does get resized when you resize the browser window (tested with Netscape 3.04 and 4.04, but does not work with appletviewer). If you have nothing else on your HTML page and use 100% for your width and height, the browser window looks almost like a real application. For the extremely tricky: have the browser reload the page with the applet when the browser resizes using new values for width and height (probably not what you want most of the time). You would need Javascript to generate a page dynamically using document.write("...") when the browser resizes. Not recommended. Another possibility is to use the new SplitPane class in JFC. 17. (Sect. 13) How do I sign an applet? [*] The browser vendors have produced independent and different solutions for applet signature (alas). Here are some URLs on this topic. See the Java Signing FAQ at http://www.fastlane.net/~tlandry/javafaq.txt Read the basics of signing at: http://www.javareport.com/html/features/archive/9802/somers.shtml Be aware that the mechanism of signing and administering signed code changed significantly between Java 1.1 and Java 2. Netscape signing: http://developer.netscape.com/docs/manuals/signedobj/javadoc/netscape_security_Target.html https://certs.netscape.com/client.html http://developer.netscape.com/docs/manuals/signedobj/capabilities/contents.htm http://developer.netscape.com/docs/manuals/signedobj/targets/contents.htm Microsoft signing: http://www.microsoft.com/java/security/secfaq.htm http://www.microsoft.com/java/sdk/20/tools/signcode.htm ------------------------------- 14. Multi-Media 1. (Sect. 14) Are there any good Java Image libraries? [*] Yes. Try the Java Image Management Interface (JIMI), which offers a free trial period. JIMI is a toolkit that lets your Java programs read and write many graphics file formats (PNG, JPG, BMP, GIF etc). JIMI is written in 100% Java, and best of all, it's a breeze to get started with. See http://www.activated.com/jimi.html 2. (Sect. 14) Why won't my audio file play? [*] Java 1.1 and earlier releases use one audio format exclusively. The audio file must be in .au format, recorded at 8 KHz, mono, in mu-law encoding. If your audio clip is in a different format (e.g., .wav) or a different frequency it must be converted to the exact specifications above before Java can play it. Support for .wav and other formats is part of the Java Media Framework coming in JDK 1.2. Search at http://www.yahoo.com for GoldWave for Win 95, sox for Unix and similar conversion utilities for other systems. Other sites: o One conversion utility in Java is at http://saturn.math.uaa.alaska.edu/~hursha o The source of a Java class to play linear PCM .WAV files is at: http://www.shef.ac.uk/~cs1mjp/Java/WhiteBoard/WavePlayer.html. It can be used in any Java application or applet. 3. (Sect. 14) How can I do video streaming using Java? [*] That is the purpose of StreamBean. See http://www.streambean.com/streambean/ 4. (Sect. 14) Does Java support animated GIFs? [*] Java 1.0.2 and earlier releases use GIF and JPEG formats, and do not use the GIF89 animated GIF format. (An animated GIF is one that contains successive frames of an image, so when they are displayed in quick sequence the image appears to contain movement). When you display an animated GIF in Java 1.0.2, you will just get the first frame. There doesn't appear to be any easy way to get other frames from the image. The advantage of an animated GIF file is that there is only one file to download, and it is simple to do simple animations. The advantage of programmatic control over individual frames is that you control the rate and order of displaying them. Here's a surprise: JDK 1.1 supports the animated display of animated GIFs. For simple animations animated GIFs are a lot easier and lighter-weight than coding an animation explicitly. 5. (Sect. 14) How do I create animated GIFs? [*] Use GIFanimator from ULead (said to be the best) http://www.ulead.com, or GIF Construction Set from Alchemy Mindworks 6. (Sect. 14) How do I prevent animated GIFs from flashing while displaying? [*] The problem is most likely that in your paint method you have g.drawImage(img, ix, iy, this); You should change this to g.drawImage(img, ix, iy, getBackground(), this); This will change all the transparent regions of the image to the background color before painting to the screen. If you paint transparent images directly to the screen they flicker. If that does not solve it then check that imageUpdate is public boolean imageUpdate(Image img, int flags, int x, int y, int width, int height) { if ((flags & (FRAMEBITS|ALLBITS))!= 0) repaint(); return (flags & (ALLBITS|ABORT)) == 0; } update is public void update(Graphics g) { paint(g); } If you have a background Image behind the partly transparent animated GIF you will have to double buffer. You can crop the backgound image so you won't have to double buffer the full app and waste too much memory. 7. (Sect. 14) Does Java support transparent GIFs? GIF89a images with a transparent background show up as transparent without further filtering. This has been supported from 1.0 on. Java correctly displays both animated GIFs and transparent GIFs. Even better, you can fill the transparent pixels with a color (so they appear non-transparent in Java). Just pass the fill color explicitly: drawImage(img, x, y, w, h, fillcolor, this); Further, you can filter the pixels of an Image to turn any bits you wish transparent. However, the most you can do is reveal what is underneath the image. You cannot reveal what is underneath the applet (i.e. on the browser itself). By default applets have a plain grey background. 8. (Sect. 14) How do I play video in Java? [*] Use the Java Media Framework Player API. Other sites: o The Java Media Framework Player API spec can be found at http://java.sun.com/products/java-media/jmf/ o Intel has released a SDK for the Java Media Framework Player API. The SDK is for Windows 95 and Windows NT. For more information, see http://developer.intel.com/ial/jmedia o SGI has released an implementation of JMF for IRIX: See http://www.sgi.com/Products/motion/ 9. (Sect. 14) How can I play *.au files from an application? [*] A new static method was introduced in JDK1.2 in the class Applet: public final static AudioClip newAudioClip(URL url) { The method turns a URL (pointing to an audio file) into an AudioClip. Since the method is static it can be used without any objects of class Applet needing to exist, e.g. in an application. Once you have an AudioClip, you can play it with: MyAudioClip.play(); The Java Media Framework provides a richer API for playing sounds in an application. For code prior to JDK 1.2, you can use the AudioClip or AudioPlayer class in sun.audio http://www.javaworld.com/javaworld/javatips/jw-javatip24.html. If you do this your code is no longer 100% pure Java, as it relies on a vendor library. import sun.audio.*; URL url; ... AudioStream audiostream = new AudioStream(url.openStream()); AudioPlayer.player.start(audiostream); ... AudioPlayer.player.stop(audiostream); Also in the FAQ: Use the new Java Media Framework API, allowing a wide range of video and audio formats to be played back. See previous question. 10. (Sect. 14) How do I read in an image file, in an application? Use Image img = Toolkit.getDefaultToolkit().getImage(fname); 11. (Sect. 14) When I initialize a component,I call MyComponent.getImage() to get its image. createImage() returns null! I know the image works elsewhere. What's wrong? [*] A peer component needs to exist for your component before you can get its image. This is done by the method addNotify() (surely one of the most poorly named methods in all Java -- it doesn't mean "add a Notify". It means "Notify that the Component has been added to a Container". It tells the system, "you need to create the peer for this Component now"). addNotify will be called for you when you add your component to a container. Javasoft notes that most applications do not call addNotify() directly. It is called for you when you add the component to a container. If you have any code that requires peer resources, you can move it into a thread that is started from a conditional branch of the paint() or update() method. That way the peer will definitely exist when the code is executed. A common reason for seeming to require peer resources in a constructor, or alternatively in the getPreferredSize() method, (which is also usually before the peer is created) is to measure the area required for your window, in terms of font and image sizes. Font sizes may be obtained by calling Toolkit.getDefaultToolkit().getFontMetrics(somefont). This does not require a peer. Image sizes may be obtained by waiting for the relevant Image to load from the ImageProducer by using an ImageObserver, or a MediaTracker (see 8.15), also without requiring a peer. See 15.4 for more discussion of this problem. If you override addNotify(), don't forget to call super.addNotify() in your overriding version. 12. (Sect. 14) How can I force a reload a fresh version of an image into my applet? My image file is changed periodically, and I want the applet to go and retrieve it, not cache it. [*] You need to turn off caching for the URL. URL url = null; URLConnection con; try { url = new URL(getDocumentBase(),"image.jpg"); con = url.openConnection(); con.setUseCaches(false); } catch (MalformedURLException e1) { System.err.println(e1.getMessage());} catch (IOException e2) { System.err.println(e2.getMessage());} Note: Some programmers have reported that it caches anyway, even if they do this. That is a browser bug. One programmer reported that even after turning off caching and calling image.flush() before getImage(..), he was still seeing the same picture even though it had been changed on the server. He worked out a solution: access the image via a cgi script that returned a URL. This redirects the browser, and he put in an Expires: header as well to force the reload. Painful and laborious, but it got the result. 13. (Sect. 14) How can I save an Image file to disk in JPG or GIF format? [*] o If you have an Image and you want a JPG in a file, download James Weeks's code from http://www.obrador.com/essentialjpeg/ o Sean Breslin also wrote a program that compresses a Java Image into a JPEG file. http://www.afu.com/jpeg.txt o If you just want to convert some file, a non-Java solution is to use the standard IJG 'cjpeg' utility. It supports GIF, PPM, BMP, PNG and Targa input files. o If you have an Image and you want a GIF or PPM in a file, download Jef Poskanzer's abstract ImageEncoder class at http://www.acme.com/java/software/ Also try the Java Image Management Interface (JIMI), which is free for non-commercial use. JIMI is a toolkit that lets your Java programs read and write many graphics file formats (PNG, JPG, BMP, GIF etc). JIMI is written in 100% Java, and best of all, it's a breeze to get started with. See http://www.activated.com/jimi.html 14. (Sect. 14) What causes this problem: $ appletviewer m.html Premature end of JPEG file sun.awt.image.Im...Exception: JPEG datastream contains no image at sun.awt.image. ... .produceImage(JPEGImageDecoder.java:133) at sun.awt.image.Inpu...mageSource.doFetch( InputStreamImageSource.java:215) at sun.awt.image.ImageFetcher.run(ImageFetcher.java:98) [*] There's a known bug in early releases of the JDK which can cause the above failure when reading a JPEG across a slow connection. The failure only occurs if the JPEG contains a large application data block (APPn marker) - the problem is that the JPEG decoder is trying to skip over the APPn and failing if not all of the APPn has been received yet. The quoted error message is only one of several possible complaints, but they all stem from the same root. Photoshop is the most common source of JPEGs containing oversize APPn blocks. In particular, if you allow Photoshop 4 to save a thumbnail (preview) in a JPEG, the thumbnail plumps up Photoshop's private APPn marker to several K, which is usually enough to cause this problem. There are several possible workarounds: o Get a newer JDK - this problem is said to be fixed in 1.1. (If you are putting images up on the Web, this isn't much of a solution, because you can't assume visitors to your site have an up-to-date Java installation.) o When making JPEGs for Web use from Photoshop, make sure you have turned off the "save thumbnails" preference. (This is a good idea quite aside from bug workarounds, because the thumbnail is just a waste of download time as far as a Web browser is concerned.) You might still have a problem if you've got verbose comments or lots of paths being saved into the file, but 99% of the time, getting rid of the thumbnail will make Photoshop's APPn small enough to not trigger the Java bug. o Use a tool such as 'jpegtran' (from the Independent JPEG Group) to strip out the Photoshop APPn entirely without any loss of image quality. Recommended answer for the compulsive byte-trimmer. o (Last resort) Load and resave the image in a different image editor that won't insert any APPn or other overhead data. This implies a JPEG generational loss, so I don't recommend it if you are picky about image quality. Any large overhead marker will cause the same problem; 4K of comment text, say, in a COM marker. So Photoshop is not the only source of tickling this bug. 15. (Sect. 14) How can I convert between GIF and JPEG formats? [*] In a word: don't. There's hardly any overlap between the set of images that JPEG works well on and the set that GIF works well on. Sometimes, with enough care, you can get an acceptable conversion...but most of the time GIF<->JPEG conversion will just turn your image to mush. It's better to pick the right format in the first place. Other sites: o If you're determined to convert formats anyway, try the GBM (Generalized Bitmap Module). The package is GNU licensed, in C and is very good. Find it at http://www.interalpha.net/customer/nyangau/ GBM does a good job converting to JPEG, and 'lossiness' is adjustable to 0%. It also converts to/from about 20 other formats, does cropping, sizing, color mapping, gamma correction, halftoning, everything you could want. GBM source doesn't support JPEG directly, but utilizes JPEG source from IJG called jpeg-6a and found at ftp://sun2.urz.uni-heidelberg.de/pub/simtel/graphics/jpegsr6a.zip o For more info see the JPEG FAQ at http://www.faqs.org/faqs/jpeg-faq/ 16. (Sect. 14) If you have an InputStream (rather than a file) that contains an Image, how can you display it? [*] Use this method, and some adroit shuffling. Toolkit.getImage(URL url) Create a thread that pretends to be an http server. Make it listen to some port (8765 for example) for incoming requests. When the thread gets a request, it should simply whisk up the appropriate http headers and follow it by the InputStream. Thus the component that has the input stream and wants to do the getImage(url) can now invoke: Toolkit.getImage("localhost:8765/") The thread will act as a stream-to-url adapter, and send back the data It saves you from having to read 200K of JPEG data before you can begin drawing anything. 17. (Sect. 14) How can I record sounds in Java? [*] The Java Media Framework will eventually support this, but it does not yet. JMF 1.0.1 only supports playback. JMF 1.0.1 is bundled with JDK 1.2, and available as a separate download for JDK 1.1 and Netscape Communicator 4 with Java 1.1. Other sites: In the meantime, there is a package for Win95/NT available at http://www.scrawl.com/store/. It supports 8, 16-bit, stereo, mono, 11025, 22050, 44100 Hz record/play, load/save .WAV files. You could also interface to native code for your platform. 18. (Sect. 14) Does Java have any built-in support for displaying HTML? [*] JDK 1.1 supports rendering HTML using the unbundled JFC 1.1 package known as Swing. The Swing package is bundled in JDK 1.2. It has an elementary (graphics, tables, text) HTML bean that is good enough for simple rendering (help files, email, etc). Other sites: o JavaBrowser http://www.ii.uib.no/~alexey/jb/index.html Free source, free for use under GNU LGPL licence, HTML 2.0 (sort of). o ICE Browser - Java Bean Component http://www.icesoft.no/ICEBrowser/ Free binaries for use in free applications. Commercial licensing available including source - flat fee licence. Thin HTML client! Lightweight! HTML 3.2 o HotJava HTML Component - Java Bean Component http://www.javasoft.com/products/hotjava/bean/index.html $195 for private use binary licence. HTML 3.2 o HTML browser (free source) http://barium.tn.tudelft.nl/people/gool/java/html/Html.html o Web Window Browser http://www.opencube.com/example_wwb.htm $139 - no sources. o jHelp ($20-650) http://w3.nai.net/~rvdi/jhelp/jhelp2/jhelp.html jHelp is a HTML browser component written in Java, HTML 2.0 19. (Sect. 14) I loaded an Image file from a JPEG/GIF file using the Toolkit/Applet.createImage(URL/String) method, and (the height and width are -1 / it will not draw to the screen). What is wrong? [*] The behaviour of the AWT on creating images in this way is to do nothing at all. When the image is first drawn using Component.drawImage(), or its size is requested, the image begins to load in a different Thread. As the image loads, the ImageObserver specified in the drawImage()/getHeight() call is periodically notified of the loading status of the image, by calls to its imageUpdate() method. In the case of Component.drawImage() call, the default behavior of Component.imageUpdate() is to schedule *another* repaint() call when the image has fully loaded. This means that, in particular the following code will not work: class MyComponent extends Component { ... public void paint(Graphics g) { ImageFilter cropper=new CropImageFilter(0,0,16,16); Image cropped_image=createImage(new FilteredImageSource(image.getSource(),cropper)); g.drawImage(image,10,400,this); // this line works // this line doesn't - g.drawImage(cropped_image,400,15,this); } } The cropped_image will not be created in time to be painted, and when it is finally created, another call will be scheduled to paint, which will try to draw another one, etc. (Note also that creating objects like this in paint() methods is generally a very poor idea in Java, since they are called very frequently, and you will strongly offend the garbage collector. In order to get round this problem, you may i) add all such Images to a MediaTracker, and call the waitForAll() method. ii) implement your own ImageObserver interface, and wait for the imageUpdate() method to be called with the ALLBITS/FRAMEBITS value. i) is easier, but ii) is recommended, since there are reports of MediaTracker not working in some environments. Also in the FAQ: o See also Q13.12 o See Q6.4 for examples of how to reuse objects. 20. (Sect. 14) How can I record sound in an applet? [*] If you are using win95/nt, you could use SoundBite - Audio Recording in Applets. See http://www.scrawl.com/store/ It provides easy access to audio data in arrays: short[] left, right; 21. (Sect. 14) Does Java support PNG? Yes. PNG - Portable Network Graphics - provides a patent-free replacement for GIF and TIFF. If you save a GIF, don't forget to pay the royalty to Unisys - see Unisys's web page at http://www.unisys.com/LeadStory/lzwfaq.html. That patent is why GIFs are a poor choice for internet images. The PNG format is specified in RFCs 1950, 1951, and 2083, and is unencumbered by licenses or patents. See also the PNG-1.1 specification at ftp://swrinde.nde.swri.edu/pub/png/documents. The PNG format is supported by the Java Advanced Imaging API which is part of the 1.2 media APIs. ------------------------------- 15. Networking and Distributed Objects RMI Issues Note that there is an RMI FAQ at http://java.sun.com/products/jdk/rmi/faq.html 1. (Sect. 15) Should I use CORBA in preference to RMI? Or DCOM? Or what? [*] If your distributed programs are all in Java, then RMI provides a simpler mechanism that allows the transfer of code, pass-by-value of real Java objects, and automatic garbage collection of remote objects. If you need to connect to C++ (or other language) systems or you need CORBA-specific services, then CORBA is your choice. In July 1997, Sun announced that it was aligning RMI to work more closely with CORBA. Sun is simply adding an IIOP transport layer to RMI to support interoperability with CORBA. Java programs can then use RMI to access CORBA-based objects through IIOP, the OMG's CORBA-based protocol. This is very good news for those building heterogenous Enterprise systems, although it will take some additions to IIOP to support the pieces that RMI uses. In 1998 Microsoft spokespeople tried to promote DCOM by spreading misinformation that RMI is changing or being dropped. That is totally wrong. The RMI API continues unchanged in its current form. Using DCOM restricts your code to only ever run on Microsoft platforms using Intel hardware, and negates the "write once, run anywhere" Java philosophy. You would have to recompile your DCOM code to run it on other Microsoft platforms like Compaq's (formerly DEC's) alpha computer. Non-portable, single vendor code should be avoided. DCOM/DNA has limitations for use in the enterprise. Other sites: http://www.javaworld.com/javaworld/jw-10-1997/jw-10-corbajava.html has a good intro to CORBA in the Java world. http://www.objenv.com/cetus has a CORBA/RMI comparison. 2. (Sect. 15) How do I do RMI into a different domain?" [*] Similar to the proxy answer in a section below; you must tell the program where to find the server. In this case start up the client with this commandline option: -Djava.rmi.server.hostname=hostname.domainname 3. (Sect. 15) RMI seems to have stopped working for me in JDK 1.1. Why is this? [*] The rules for where the client looks for a stub class seem to have changed making it necessary to reset your class path on the client after starting the RMI registry. In particular, it looks like rmic was not updated to the new "don't need $CLASSPATH for current dir" convention as the compiler was. You are best off setting classpath explicitly. Other sites: There are several very good sources available from Sun which cover many simple and advanced RMI problems. o The documentation, of course: http://java.sun.com/products/jdk/1.1/docs/guide/rmi/index.html o Dedicated FAQs on RMI and Object Serialization http://java.sun.com/products/jdk/rmi/faq.html o Mailing list RMI-USERS@JAVASOFT.COM with archive at http://chatsubo.javasoft.com/email/rmi-users/ Visit the archive! 4. (Sect. 15) After a number of RMI client to server connections (55 on my system), subsequent RMI clients trying to connect fail. Why? [*] You are hitting the default limit of 64 open file descriptors. Try increasing the limit in your OS. In addition there is currently a practical RMI connection limit imposed by the scalability of the VM and the performance of object serialization. This is addressed in JDK 1.2. The actual number of active clients you will be able to support will depend on the workload mix you have (i.e. the number of clients, how often they talk to the server, and how much work must be done per call). 5. (Sect. 15) I'm using RMI on Win95, and the Naming.lookup() call is taking a long time, even for localhost. How do I fix it? [*] (See also the first answer in next section below, and note that this Windows workaround has never worked for some people). Try adding a definition for the machine in your "hosts" file. Typically, this file will be named c:\windows\hosts (if it doesn't exist, there should be a file called c:\windows\hosts.sam). The hosts file is searched by your TCP/IP stack before it resorts to DNS, so adding an entry in this file can speed up your lookups considerably. The hosts file is used to map IP addresses to symbolic addresses. To enter the name "localhost" with address 127.0.0.1 (the IP loopback address), enter the following line in your hosts file. 127.0.0.1 localhost Windows Networking 6. (Sect. 15) Why does < Windows RMI/my java debugger/IDE/other> hang for a couple of minutes if my Windows PC is not dialed up to the Internet? [*] Java has networking support built in. When the Java program starts the Winsock DLL automatically gets loaded. The first thing this does is to try to resolve the fully qualified domain name for your machine under the name "localhost". If your system doesn't have this name mapped, it will try to query a nameserver on the internet, which is typically (on a PC) your dialup ISP. So it either prompts you to connect to the ISP, or waits till the attempt times out. Some people say you can avoid the Win95 problem by giving your system another way to resolve DNS names. This tip has never worked for me. Edit the hosts file for your system so that localhost and the full domain name are both mentioned. On Windows 95 systems the hosts file is: %windir%\HOSTS (for example, C:\WINDOWS\HOSTS). On Windows NT systems the hosts file is: %windir%\System32\DRIVERS\ETC\HOSTS (for example, C:\WINNT\System32\DRIVERS\ETC\HOSTS). One gotcha under Win95 is that if the last entry in the hosts file is not concluded with a carriage-return/line-feed then the hosts file will not be read at all. So if my system is called goober.best.com change the hosts file from 127.0.0.1 localhost to 127.0.0.1 goober.best.com localhost Showing more of the file: # Hosts file 127.0.0.1 localhost 129.146.77.177 goober Another alternative is to dial up with a PPP connection to your ISP whenever you want to run networking programs. Fundamentally the experience of some people has been that networking is not completely satisfactory on Windows95 using Winsock 1.1, and is subject to sporadic unexplained failures. You could try downloading Winsock 2.0. To get Winsock 2.0, you need to drag in all the other junk from Microsoft Windows Sockets 2.0 Software Development Kit. This free software can be downloaded from the following addresses: http://www.microsoft.com/win32dev/netwrk/winsock2/ws295sdk.html or ftp://ftp.microsoft.com/bussys/WinSock/winsock2/ The patches needed to improve Win95 networking are already in Win98. Other Networking Issues 7. (Sect. 15) If I call the InetAddress.getByName() method with an IP-address-string argument, like "192.168.0.1", get an UnknownHostException on some platforms, but not others. Code like Socket sock = new Socket("155.152.5.1", 23); triggers the exception. Why? [*] This is a platform difference that arises out of different semantics in the underlying network libraries, and is [said to be, but subject to confirmation] fixed in JDK 1.1. On Solaris and Windows NT, the IP address string only works for IP addresses that have an associated hostname. On Linux and Windows 95, the IP address string works in all cases. When InetAddress is instantiated with an IP address, a reverse DNS lookup is done. If the IP address is not associated with a valid hostname, the instantiation will fail. This is part of anti DNS-spoofing, and in JDK 1.1 works because the reverse lookup will not occur until the hostname is asked for. So in JDK 1.1, InetAddress in = InetAddress.getByName("155.152.5.1"); [Note: this info is still to be confirmed. Net gurus?] Other sites: Microsoft has several network-related patches at its site http://www.microsoft.com/ 8. (Sect. 15) I want to pass a class file to willing recipients who are using my applet. Any ideas how? [*] You could use a trick: put your .class file(s) in a .zip archive and use showDocument() on the URL. A person accessing this will get a dialog box put up asking them about saving the file to their local hard disk. Other sites: You can see this in action and try it out yourself at: http://www.best.com/~rmlynch/saveit.html 9. (Sect. 15) How do I get a URLConnection to work through proxy firewalls? I.e. How do you get your Java application to do its web accesses through a proxy? [*] This is typically needed for any net access to another domain. Tell the run time system what you are trying to do, by using these commandline arguments when you start the program. java -DproxySet=true -DproxyHost=SOMEHOST -DproxyPort=SOMENUM code.java Note proxyPort is optional and it defaults to 80. Without this, you will see an exception like java.net.UnknownHostException or java.net.NoRouteToHostException The proxy settings work for both java.net.URLConnection, and for java.net.Sockets. Netscape's and IE's JVMs (at least in versions 4.x+) take the proxy settings for applets from the browser's proxy configuration. You can also do URL proxies in applications (not applets) with the following code // set up to use proxy System.getProperties().put("proxySet", "true"); System.getProperties().put("proxyHost", "myproxy.server.name"); System.getProperties().put("proxyPort", "80"); But how do I know the name of the proxy server? This code just tells you how you can get a URL connection to the outside. Since it is your proxy server, you are expected to know the name of it. There isn't any code that you can write that will allow arbitrary URL connections to be initiated from outside the firewall. Think about it! If there were, the firewall would not be doing its job. Also note there are corresponding socksProxyPort and socksProxyHost for when socks is used instead of proxy. The default socks port is 1080. 10. (Sect. 15) What is "swizzle", as in "Swizzle this object?" [*] It means serialize. To swizzle an object is to recursively serialize or flatten composed objects. 11. (Sect. 15) I have been using the Serializing capabilities in 1.1 to save some objects to disk. I added a new field to one of my objects that get serialized and now deserializing my old data no longer works. I get this exception: java.io.InvalidClassException: MacroData; Local class not compatible [*] You need to add a declaration such as static final long serialVersionUID = 4021215565287364875L; in the modified class. The actual value of this long is supplied by the "serialver" utilitity suppied with the JDK. Any versions of a class other than the first version require this static to be defined in the class. This is how versioning is achieved. 12. (Sect. 15) My socket code looks good, but is broken! [*] When using sockets you typically open both inward and outward streams. A TCP connection is full duplex, but either the send or receive side may be closed independently. By default, the remote end will take the close as indicating that the connection has simply been closed, and will close its end as well. Check whether this is happening for you, by adding the matched pair. Use tcpdump to check this. 13. (Sect. 15) How do I map between IP address and hostname? [*] In Java 1.1 (earlier releases were buggy) use: String host = InetAddress.getByName("211.10.2.119").getHostName(); 14. (Sect. 15) How do I embed an anchor in a URL? Just putting it as part of the string in the constructor doesn't work. [*] Like this: URL url = new URL("http://www.my_domain.com/my_page.html"); URL anchor = new URL(url, "#section2"); this.getAppletContext().showDocument(anchor); 15. (Sect. 15) How do I POST to a CGI script from an applet? [*] Let's start by noting that this is more troublesome than it might seem at first, and that GET is preferred. For an untrusted applet, the CGI script can only be on the server that served the applet. POSTing to the server involves sending key/value pairs, not just a message. Also values must be encoded. To send "words to the server" you might try: StringBuffer sb = new StringBuffer(); String str="words to the server"; sb.append("message="); sb.append(java.net.URLEncoder.encode(str)); URLConnection cn = url.openConnection(); // set properties cn.setDoOutput(true); cn.setUseCaches(false); cn.setAllowUserInteraction(false); cn.setRequestProperty("content-type","application/x-www-form-urlencoded"); // send parameters PrintWriter out = new PrintWriter(cn.getOutputStream()); out.print(sb.toString()); out.close(); // read stuff BufferedReader in = new BufferedReader( new InputStreamReader( cn.getInputStream())); sb = new StringBuffer(); String inputLine; while ((inputLine = in.readLine()) != null){ sb.append(inputLine); sb.append("\n"); } in.close(); uresp = new URL(getDocumentBase(),"respond.html"); getAppletContext().showDocument(uresp); } The CGI has to write its output to respond.html so that it can be displayed by the browser. But it may still fail, because respond.html could be overwritten by a subsequent request to the same CGI before the results of the first POST are read back. To get an acceptable solution takes quite a lot of effort. In general you should prefer GET to POST for CGI access from Java. As it says on the Javaworld page, the answers to the question are really: you can't, don't POST (use GET), use a bean, or cheat. Note, if you request a URL via the URLConnection/HttpURLConnection, the server sets the content type, and your applet can use URLConnection.getContentType() to get the type. Alternatively, use setRequestProperty to set it, like this: url = new URL(cgiUrl); urlc = url.openConnection(); urlc.setRequestProperty( "Content-type", "application/x-www-form-urlencoded"); Other sites: There's a pretty good explanation at http://www.javaworld.com/javaworld/javatips/jw-javatip41.html See also the Marty Hall book Core Web Programming (Prentice Hall ISBN: 0-13-625666-X). It has comprehensive coverage of writing Java programs that interface to CGI scripts. Better still, use servlets, write everything in Java, and discard your CGI code. 16. (Sect. 15) How can I write CGI programs in Java? [*] CGI (the Common Gateway Interface for web servers) is an API for writing programs that use the web as its user interface. By far, the most popular language for this task is Perl, because of its powerful text handling capabilities, and excellent resources available for making the jobs of CGI programmers easier. CGI programs can be written in any language, including Java. Unfortunately, the interface between the web server and the CGI program uses environment variables extensively. Use of environment variables has always been deprecated in Java, because of portability issues (not all systems have environment variables). The way to get around this is to write a "wrapper" for the Java program in a language that supports environment variables, and can then invoke the Java program with the appropriate environment data passed in as Java properties. Because the Java runtime environment is not a lightweight process, it might take a moment for the CGI program to get started before anything happens. This is particularly true on operating systems, like NT, that have a large overhead to spawning new processes. In preference to using Java for CGI on the server, you might consider using the Java servlet API in Netscape's Enterprise Server. This allows you to develop server-side programs in Java without suffering the same performance restrictions and other limitations of the CGI API. Other sites: See http://search.netscape.com/comprod/server_central/ query/eval_guide/enterprise/advantage.html for more details. 17. (Sect. 15) How can I write the "ping" program in Java? [*] You can't do it directly. Quoting from the Java Networking FAQ, Ping requires ICMP packets. These packets can only be created via a socket of the SOCK_RAW type. Currently, Java only allows SOCK_STREAM (TCP) and SOCK_DGRAM (UDP) sockets. It seems unlikely that this will be added very soon, since many Unix versions only allow SOCK_RAW sockets to be created by root, and winsock does not address ICMP packets (win32 includes an unsupported and undocumented ICMP.DLL). You could write a program that handshakes with a remote system, to simulate ping, or you could use native code for the raw socket. Other sites: You can find the Java Networking FAQ at http://www.io.com/~maus/JavaNetworkingFAQ.html There is an additional Java Networking FAQ (which is being modified and reposted regularly) at http://www.davidreilly.com/java/java_network_programming/ 18. (Sect. 15) Why, when I make a call to DatagramPacket.getlength() does it returns the wrong size? [*] You are probably reusing a Datagram packet, and it has no way to grow its buffer if a longer packet comes in. Take care of it by calling setLength(max) before reuse. Failing to do this is a very common mistake. 19. (Sect. 15) Why do my networking programs freeze on the Mac? [*] You shouldn't println to a socket. This is the subject of Apple Technical Note 1157 at http://developer.apple.com/technotes/tn/tn1157.html The problem is that many socket protocols expect CR+LF to terminate a string, but println delivers a platform-specific EOL mark. On the Mac, it is just CR. Therefore the server hangs waiting for the Mac to send a LF. It never does. But the program works fine on platforms that send CR+LF. 20. (Sect. 15) How do I "timeout" a socket read, as the "select" function in Unix does? [*] There are two timeouts at issue here. Use the ServerSocket.setSoTimeout(int millis) for timing out your 'accept()' calls. For a select() like mechanism, you can poll InputStreams of your connections for available() > 0 URLConnection doesn't have a method for this, but you can do it by using multiple threads. Create a timer thread that would just track time and close the connection after your specified timeout period. Check the URLConnection to see if it's got any data flowing through it (calling URLConnection.connected() is probably a sufficient test). The URLConnection should be in a separate thread. ------------------------------- 16. Security 1. (Sect. 16) What is a "trusted applet"? [*] JDK 1.1 introduced the notion of a "trusted applet" which is one that has been cryptographically signed to guarantee its origin and make it tamper-resistant. Trusted applets can be granted more system access privileges than untrusted applets. You preconfigure your browser with a list of whose X.509 certificate you trust, and then applets arrive with X.509's attesting to their keys. It's easier than it sounds. 2. (Sect. 16) What is the story with Java and viruses? What is the blackwidow virus? [*] Java was designed with security in mind. The security features make it very difficult, probably impossible, to attach a virus (self-copying code) to a Java applet. There has never been a Java virus carried from system to system by applets. There has been mention of a "Java virus" called "BlackWidow" in the media (it was mentioned in Unigram in late 1996, and obliquely on the RISKS newsletter in February 1997). A request to the editor of Unigram for more information brought the answer that there was no more information, it was just a report of a rumor. As far as is known, this story exists only as rumors reported on by the press. There is no actual Java virus or blackwidow virus (there was a legitimate commercial product of that name, since renamed). In spring 1998 there were press reports of a "Java applet" called White Ghost. It turns out that it relies on security flaws in ActiveX, and the only susceptible systems are Microsoft's Active Desktop. If anyone has a URL for a copy of this code, and an analysis of it, please contact the FAQ author. In August 1998, Symantec had some information about a Java program (application) that could append itself to some other Java program. They termed it "Strange Brew". That is just normal file processing, no different to a program written in C, C++, Fortran, COBOL, etc. What makes PC viruses dangerous is when they have a hidden means of travelling between places, such as being attached to code that is automatically executed, like boot sector code, or Word macro initialization files. No one has yet produced a virus that does this in Java. In March 1999, reports surfaced of a virus called BeanHive. Again this was not Java-related, but relied on the browser user explicitly accepting an unknown certificate as trusted when prompted. If the user allowed that, then any code from that source will be uploaded and run without further input from the user. Don't remove security for untrusted code simply because it asks for it, is the lesson here. If anyone has more concrete information about a virus that can attack a Java applet (again, this is thought to be impossible), please contact the FAQ author. 3. (Sect. 16) Why do I get the warning string "Unsigned Java Applet Window" at the bottom of popup windows in my applets? [*] This is a security feature, to make certain that users can always tell that a window asking for their password and credit card details (or whatever) is from an applet. There should be no way for an untrusted applet to work around this message. Also in the FAQ: See also the answer to Q12.7. 4. (Sect. 16) Where can I find information on signing applets? [*] Please take a look at the "Code Signing for Java Applets" page at http://www.suitable.com/Doc_CodeSigning.shtml. The page explains how to sign your Java applet so that it can be used in both Navigator/Communicator and Internet Explorer. 5. (Sect. 16) Where can I find crypto libraries for Java? [*] Cryptographic libraries are not part of the Java release because US Government policy classifies strong cryptography under the same rules as munitions. Its export is regulated under the International Traffic in Arms Regulations. Many people regard this as a Kafka-esque (and futile) attempt to stem the use of cryptography inside the US. Other sites: o The comprehensive and free "Cryptix" crypto library written in Java is at: http://www.cryptix.org See also http://www.hi.is/~logir/logi.crypto/ o Another free crypto library for Java is at: http://www.acme.com/java/software/Package-Acme.Crypto.html It includes Blowfish, CRC16, CRC32, DES, DES3, IDEA, RC4, ROT13 (can they really call that "crypto"?), and more. o Another pure Java Cryptography toolkit is at http://www.freestylesoft.com/products/crypto/avalanche.html (free for personal use). o One commercial Java encryption source (from Ireland) is: http://www.baltimore.ie/jcrypto.htm o A complete crypto API for Java (with HTML documentation) at: http://www.geocities.com/SiliconValley/Heights/8298 The library provides comprehensive and complete range of crypto library and functions covering DES, 3DES, IDEA, Blowfish ...and RSA, DH, DSA and PGP access to Java programmers. The crypto functions are based on the C cryptlib, by Peter Gutmann. It would be illegal to export this under current US government rules, but the author of the code is outside the US, and not subject to US export regulations. Download it today before it becomes illegal. o Some Java crypto available with source under GPL is at http://www.aba.net.au/solutions/crypto/jce.html http://www.geocities.com/SiliconValley/1394/ o Also, data about Sun's Java Cryptography Extension (JCE) is available at: http://developer.java.sun.com/developer/earlyAccess/jdk12/jce.html (This may not be exported outside the USA and Canada). o An actual port of PGP v2.6.3i to Java is at: http://tassun.math.nsc.ru o A list of free crypto libraries, not necessarily in Java, and of course the FBI will be all over you like hair on an ape if you try to export any of these, is at: http://www.homeport.org/~adam/crypto/ 6. (Sect. 16) How do I find out what these terms mean? [*] Read Bruce Schneier's excellent book "Applied Cryptography 2nd Ed." for more info on what these terms mean. Read David Kahn's excellent (and exhaustive) book "The Codebreakers" for more info on the history and background of encryption. 7. (Sect. 16) Where is Javasoft's Security FAQ? [*] Javasoft's security FAQ can be found at: http://java.sun.com/sfaq/index.html Other sites: http://java.sun.com/products/jdk/1.1/docs/guide/security/ 8. (Sect. 16) Where is that online book on Java Security? [*] Gary McGraw and Ed Felten's book Securing Java can be found on the web at http://www.securingjava.com/ ------------------------------- 17. For C and C++ Afficionados 1. (Sect. 17) How do I translate C/C++ into Java or vice-versa? [*] In general it is not simple to translate C/C++ into Java, as Java lacks the arbitrary pointer arithmetic of those languages. If your C code does not use pointer arithmetic, automatic translation gets a lot simpler. Try these URLs: http://www.ist.co.uk (search for X-Designer 4.6: Java edition). http://members.aol.com/laffra/c2j.html http://www.ilog.com/ Going the other way there are currently three freely-available tools to translate Java into C. It seems that these have been done for hacking value, rather than practical purposes. o j2c from Japan, http://www.webcity.co.jp/info/andoh/java/j2c.html o Toba from the Sumatra research project, translates 1.0.2 .class files into .c source code http://www.cs.arizona.edu/sumatra/toba o JCC from Nik Shaylor. http://www.geocities.com/CapeCanaveral/Hangar/4040/ None of them support the AWT yet, and both j2c and JCC have additional restrictions. There's a product to convert Visual Basic to Java. Details at http://www.blackdirt.com and http://www.javadelphi.com (also a Delphi-to-Java source converter) and http://www.tvobjects.com There's a product to translate COBOL source to Java source, see http://www.Synkronix.com/ This program dumps info about the class file: http://www.professionals.com/~cmcmanis/java/dump/index.html Chuck McManis was one of Sun's original Java implementors. 2. (Sect. 17) How are finalizers different from C++ destructors? [*] Java objects are not explicitly deleted and do not have destructors. Instead they are implicitly garbage collected when the JVM realizes your program can no longer access them. Typically this technology is _not_ based on reference counting and _will_ cope with circular references. Every object has a routine called finalize() which will be called before the object is collected. This is Java's nearest equivalent to C++'s destructor. However, it is not a good idea to rely on finalization for the timely freeing of resources. This is because garbage collection and hence finalization may be arbitrarily delayed, and may never happen at all if the program terminates before it runs out of memory. You should instead provide your objects with methods similar to Graphics.dispose() to free resources, and call the dispose() method explicitly when you have finished using them - typically within the "finally" clause of a "try/catch" block. You may then call your dispose() method from within your finalize() method as a last-ditch attempt to free the resource if someone forgets. Alas, all this means the C++ idiom of "object construction is resource aquisition" does not translate well to Java. However, note that 90% of destructors in C++ are there to free memory, and the GC means you don't need to do that in Java. As well as fixing an important source of bugs, the GC is essential to Java's security model; without it you could forge object references by preserving the reference after the object has been deleted. If your program appears to be crashing due to running out of some system resource (like File, Window or Graphics handles), it probably because the system is running out of handles before it has run out of memory. Check that you have called the dispose() method (or equivalent) on every object that uses system resources. You can help the GC a little bit more by explicitly NULLing out references that you've finished with. 3. (Sect. 17) What's the Java equivalent of sizeof()? [*] There isn't one. sizeof() in C and C++ is used in three main places: 1. To check on the size of a primitive type. In Java, the sizes of primitive types are fixed in the language specification (a short is _always_ 16 bits; an int is _always_ 32 bits, etc), so this is no longer necessary. 2. In memory allocation (i.e. malloc (32 * (sizeof(int));) In Java you always allocate a specific type of object, rather than a block of raw memory that you will fill as you like. The system always knows the size of the kind of objects you are allocating. So sizeof is not needed. 3. In pointer arithmetic (i.e. p += sizeof (int)) Pointer arithmetic of this type is not allowed in Java, so this isn't necessary, either. For all these reasons, there is no need for a Java sizeof() operator. by having the object serialize itself to a ByteArrayOutputStream, and looking at the bytearray.length. That won't work because a lot of additional data is written when an object is serialized. The additional data includes a description of the class, any objects referenced by the serialized object, null references (written as a single byte), etc. If you write another instance of the same class, the amount of data written can differ dramatically. And if you serialize the same object again, it isn't written at all -- even if its data fields have changed! Instead, a one byte token and a four byte "sequence number" that refer to the first writing are output. Using Object Serialization to determine the size of an object does not (except by coincidence) give the right answer. 4. (Sect. 17) Does Java have the equivalent of "const" arguments in C and C++? [*] Java 1.1 adds the ability to use the "final" keyword to make arguments constant. When used to qualify a reference type, however, this keyword indicates that the reference is constant, not that the object or array referred to is constant. For example, the following Java code: void foo(final MyClass c, final int a[]) { c.field = 7; // allowed a[0] = 7; // allowed c = new MyClass(); // final means this is NOT allowed a = new int[13]; // final means this is NOT allowed } is roughly equivalent to the following C/C++ code: void foo(MyClass * const c, int * const a) { c->field = 7; // allowed a[0] = 7; // allowed c = new MyClass(); // const means this is NOT allowed a = new int[13]; // const means this is NOT allowed } Java does not have any equivalent to the following C/C++ function declarations: void foo(const MyClass *c); // a pointer to a const class void foo(const int *a); // a pointer to a const int void foo(const int a[]); // a pointer to an array of const ints 5. (Sect. 17) Are there any hacks around this? [*] Certainly! There are always hacks around stuff. One way of enforcing constant values is to have two interfaces, a constant one and a non-constant one, e.g. public interface ConstFoo { int getValue(); } public interface Foo extends ConstFoo { int getValue(); void setValue(int i); } Then when you want to receive a parameter that cannot be modified you have: void noChange(ConstFoo foo); For a parameter that can be modified void change(Foo foo); 6. (Sect. 17) How can I write C/C++ style assertions in Java? [*] The two classes shown below provide an assertion facility in Java. Set Assert.enabled to true to enable the assertions, and to false to disable assertions in production code. The AssertionException is not meant to be caught--instead, let it print a trace. Since the exception is not meant to be caught, we just extend Error instead of RuntimeException. As with RuntimeException, a method does not need to declare that it throws Error. In addition programmers are less likely to write "catch(Error) ..." than "catch(RuntimeException)". With a good optimizing compiler there will be no run time overhead for many uses of these assertions when Assert.enabled is set to false. However, if the condition in the assertion may have side effects, the condition code cannot be optimized away. For example, in the assertion Assert.assert(size() <= maxSize, "Maximum size exceeded"); the call to size() cannot be optimized away unless the compiler can see that the call has no side effects. C and C++ use the preprocessor to guarantee that assertions will never cause overhead in production code. Without a preprocessor, it seems the best we can do in Java is to write Assert.assert(Assert.enabled && size() <= maxSize, "Too big"); Alternatively, use if (Assert.enabled) Assert.assert( size() <= maxSize, "Too big" ); In this case, when Assert.enabled is false, the method call can always be optimized away totally, even if it has side effects. The relevant sections of the JLS are Section 13.4.8, final Fields and Constants and Section 14.19, Unreachable Statements. 13.4.8 requires that primitive constants ("a field that is static, final, and initialized with a compile-time constant expression") be inlined. So everywhere Assert.enabled is refered it is replaced at compile time with its value. Writing: if (Assert.enabled) Assert.assert(size() <= maxSize, "Too big"); is exactly the same as writing: if (false) Assert.assert(size() <= maxSize, "Too big"); ... assuming Assert.enabled is false at compile time. Section 14.19 discusses compiling away such dead code. To sum up: the inlining of the primitive constant is required by the spec. The subsequent optimization of not generating code masked by (what turns into) an "if (false) ..." is not required but is implemented by many existing Java compilers. public class AssertionException extends Error { public AssertionException(String s) { super(s); } } public final class Assert { public static final boolean enabled = true; public static final void assert(boolean b, String s) { if (enabled && !b) throw new AssertionException(s); } } 7. (Sect. 17) How do I do stuff like scanf and sscanf in C/C++? And how do I do stuff like sprintf, e.g. float x = 12345.6789; printf("%6.3f/n", x); [*] You can break a string like "5 loaves 2 fishes" into its parts by using java.util.StringTokenizer. This is the Java equivalent of sscanf(). StreamTokenizer does a similar thing on a file or any stream (i.e, what scanf() and fscanf() do in C). To do formatted character output, create a format string, and then use that to format your binary value, e.g. import java.text.*; float fi = 1234.56789F; DecimalFormat mydf = new DecimalFormat( "###0.000" ); mydf.setMinimumIntegerDigits(3); // for example System.out.println( mydf.format(fi) ); gives: 1234.567 If you want to see a float print out as "0.0000001" instead of "1E-7", use: java.text.DecimalFormat myFmt = new java.text.DecimalFormat("#,###,###,###.############"); System.out.println(myFmt.format(myFloat)); There are lots of different characters you can feed to the DecimalFormat constructor, not just "0" and "#". See $JAVAHOME/src/java/text/DecimalFormat.java source for details. The always excellent Acme site has an sprintf() package written in Java See http://www.acme.com. 8. (Sect. 17) What is the Java equivalent of C++'s "friend"? [*] The keyword "friend" in C++ is a hack to allow a piece of code to access the private member declarations of another class. In Java, you would do this by labelling, not the friend, but the private members. Instead of making them private, make them either protected or package (no keyword) or public. The four different Java protection levels are: private, package, protected, and public. o private members can only be accessed by the containing class and internal classes. o package (specified by omitting other keywords) is the default level of protection; members are accessible from any class within the package of the containing class. o protected is package-level-access plus access to sub-classes of the containing class. So "protected" is less protected than the default. o public fields in public classes are accessible from all classes. 9. (Sect. 17) Does anything like the C++ Standard Template Library exist for Java? [*] Yes, only it's better and simpler to use in Java. It's called the Java Generic Library. This library (JGL) is freely downloadable from http://www.objectspace.com/ It includes about a dozen nice data structures (including sets and bags) and algorithms like unions, searching, and sorting. It has over 100,000 users and 11 OEM distributors. [Some Java vendors are bundling it with their next release] 10. (Sect. 17) What happens to post-increment when an exception is thrown? [*] If you have the code: array[i++] = foo(); and foo() throws an exception, i will be incremented anyway. This can cause problems if sometimes foo() throws an exception and you don't want i incremented in cases when it does. This is a consequence of JLS 15.25.1 and 15.6.1 "the left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated." (assignment is taken as a binary operator). Note that this is not how C++ behaves. ------------------------------- 18. Java Idioms See also the list of Java Design Patterns at http://c2.com/cgi/wiki?JavaIdioms 1. (Sect. 18) What are the naming conventions in Java? [*] The naming conventions are straightforward: o Package names are guaranteed uniqueness by using the Internet domain name in reverse order: com.javasoft.jag - the "com" or "edu" (etc.) part used to be in upper case, but now lower case is the recommendation. o Class and interface names are descriptive nouns, with the first letter of each word capitalized: PolarCoords. Interfaces are often called "something-able", e.g. "Observable", "Runnable", "Sortable". o Object and data (field) names are nouns/noun phrases, with the first letter lowercase, and the first letter of subsequent words capitalized: currentLimit. o Method names are verbs/verb phrases, with the first letter lowercase, and the first letter of subsequent words capitalized: calculateCurrentLimit. o Constant (final) names are in caps: UPPER_LIMIT. Other sites: o Check out the section "Naming Conventions" in the language specification: http://java.sun.com/docs/books/jls/html/6.doc.html#11186 o Also take a look at Doug Lea's draft coding standard: http://gee.cs.oswego.edu/dl/html/javaCodingStd.html 2. (Sect. 18) How do I convert a String to an int? [*] There are several ways. The most straightforward is: String mystring = numString.trim(); int i = Integer.parseInt(myString); long l = Long.parseLong(myString) or String mystring = numString.trim(); i = Integer.parseInt(myString,myIntRadix); Note 1: There is a gotcha with parseInt - it will throw a NumberFormatException for String values in the range "80000000" to "ffffffff". You might expect it to interpret them as negative, but it does not. The values have to be "-80000000" .. "-ffffffff" to be properly recognized as negative values. This is true for all radixes. According to Bug Parade bug report 4068580, the proper way to generate negative-valued hex Strings for eventual use by parseInt() is with Integer.toString(i, 16). Once that high "sign bit" is on, without the accompanying character, parseInt() says "too big". Note 2: There are similar methods for Byte, Short, and Long. Use myString.trim() to get rid of unwanted spaces before the conversion. Some of the parse methods can cope with spaces, others can't. They were written by two different people. int i = Integer.valueOf(my_str).intValue(); also works but involves the creation of an extra object. Note: the pre-FCS JDK 1.2 documentation at one point said that parseDouble and parseFloat methods were to be introduced, but this does not seem to be the case (see bug 4160672). JDK 1.2. float f = Float.valueOf(my_str).floatValue(); double d = Double.valueOf(my_str).doubleValue(); 3. (Sect. 18) How do I convert an int to a string? [*] Try any of these: String s = String.valueOf(i); or String s = Integer.toString(i); or String s = Integer.toString(i, radix); or // briefer but may result in extra object allocation. String s = "" + i; Note: There are similar classes for Double, Float, Long, etc. 4. (Sect. 18) How do I print the hex value of an int? [*] You can print the hex equivalent of an int with: int i = 0xf1; System.out.println("i is hex " + Integer.toHexString(i) ); OK, how do I read a hex string into an int? int i = Integer.valueOf(myHexString, 16).intValue(); 5. (Sect. 18) How can you send a function pointer as an argument? [*] Simple answer: use a "callback". Make the parameter an interface and pass an argument instance that implements that interface. public interface CallShow { public void Show( ); } public class ShowOff implements CallShow { public void Show( ) { .... } public class ShowOff2 implements CallShow { public void Show( ) { .... } public class UseShow { CallShow savecallthis; UseShow( CallShow withthis ) { savecallthis = withthis; } void ReadyToShow( ) { savecallthis.Show( ); } } // in some other class that uses all this stuff: UseShow use_1 = new UseShow( new ShowOff() ); UseShow use_2 = new UseShow( new Showoff2() ); and then the ReadyToShow() method on use_1 or use_2 will call the appropriate method, as if you had stored a pointer to the method. 6. (Sect. 18) How do I execute a command from Java? [*] Use Runtime.getRuntime().exec( myCommandString ) where myCommandString is something like "/full/pathname/command". An applet will need to be signed in order to allow this. Note, there is a gotcha associated with reading output from commands. When the runtime exec's the process, it passes to it 3 streams, for stdin, stdout, and stderr; the out and err are buffered but the buffer size isn't very big. When your process runs, it reads (if needed) from in, and writes to out and err. If it doesn't write more than the buffer-size, it can run to completion. But if it tries to write more data to one or the other stream than the buffer can hold, the write blocks, and your process hangs, waiting for you to empty the buffer so it can write some more. So after the exec call, get the streams, and read from them in a loop until they both hit end-of-stream (don't block on either one, just read whatever is available from each, each loop iteration). Then when the streams have ended, call the process.waitFor() method to let it finish dying. 7. (Sect. 18) How do I do I/O redirection in Java using exec()? [*] This solution works on Unix platforms using either JDK 1.0.2, or JDK 1.1. The trick is to use an array of Strings for the command line: String[] command = {"/bin/sh", "-c", "/bin/ls > out.dat"}; If you don't do this, and simply use a single string, the shell will see the -c and /bin/ls and ignore everything else after that. It only expects a single argument after the -c. import java.io.*; import java.util.*; class IoRedirect { public static void main(String Argv[]) { try { String[] command = {"/bin/sh", "-c", "/bin/ls > out.dat"}; Process p = Runtime.getRuntime().exec(command); p.waitFor(); System.out.println("return code: "+ p.exitValue()); } catch (IOException e) { System.err.println("IO error: " + e); } catch (InterruptedException e1) { System.err.println("Exception: " + e1.getMessage()); } } } 8. (Sect. 18) So why can't I exec common DOS commands this way (as in 18.7)? [*] The reason is that many of the DOS commands are not individual programs, but merely "functions" of command.com. There is no DIR.EXE or COPY.EXE for example. Instead, one executes the command processor (shell) explicitly with a request to perform the built-in command, like so: Runtime.getRuntime().exec("command.com /c dir") for example. On NT, the command interpreter is "cmd.exe", so the statement would be Runtime.getRuntime().exec("cmd /c dir") And you could bring the command output into the program with code like: Process p = runtime.exec ("cmd /c dir"); DataInputStream procIn = new DataInputStream(p.getInputStream()); while ( true ) { String line = procIn.readLine(); if ( line == null ) break; // do something with lin } This situation occurs on any OS where some commands are actually interpreted directly by the shell. 9. (Sect. 18) OK, how do I read the output of a command? [*] As above (18.6, 18.7), adjusted like this: BufferedReader pOut= new BufferedReader( new InputStreamReader(p.getInputStream())); try { String s = pOut.readLine(); while (s != null) { System.out.println(s); s = pOut.readLine(); } } catch (IOException e) { } Another possibility is to read chunks of whatever length as they come in: ... p = r.exec(cmd); InputStream is = p.getInputStream(); int len; byte buf[] = new byte[1000]; try { while( (len = is.read(buf)) != -1 ) { String str = new String(buf,0,0,len); System.out.println( "Process out: " + str ); } } catch( java.io.EOFException eof ) { ... } catch( java.io.IOException ioe ) { ... } However, you cannot read output from some DOS commands on Windows 95/98. This is bug 4211683 at Sun, but it is actually a Microsoft bug/poor design. Windows programs that explicitly use a handle to the console ("CON" or "CON:") instead of stdin and stdout cannot be used as subprocesses to Java. The Win95 FTP program is an example of such a program. Windows provides no convenient way for Java to redirect the input and output of such processes from the console to input and output pipes. The only workaround is to use a different implementation of the program that does not use the console directly. Microsoft documents a difference in DOS Console stream handling between 95 and NT: see http://support.microsoft.com/support/kb/articles/q150/9/56.asp So capturing output from GNU ls on Win95 works, but the output from "command.com /c dir" is not captured. 10. (Sect. 18) How do I compile code which has a cyclic dependency, i.e class pkg1.X contains a reference to class pkg2.Y ? [*] You throw both classes at the compiler at the same time. javac pkg1/X.java pkg2/Y.java 11. (Sect. 18) What is the point of creating the temporary reference to this.layoutMgr? [*] This code is from the 1.0 AWT, and the programmer was probably pretty skilled. public synchronized void layout() { LayoutManager layoutMgr = this.layoutMgr; if (layoutMgr != null) { layoutMgr.layoutContainer(this); } } The code makes a local copy of a global variable for one or both of two reasons. The first reason is that accessing local variables can be faster than accessing (non final) member variables. It's good for loops or where there are many references in the source. The second reason is so that even if other threads update the global, this.layoutMgr = someOtherLayoutMgr; This method will still have a pointer to the original layoutMgr. If the local variable were omitted, and another thread used the setLayout() method to change layoutMgr to null between when the layout method checked for null and when it invoked layoutMgr's layoutContainer method, a NullPointerException would result. Note that the synchronized keyword on the layout method doesn't help any, since setLayout (which could make such a dire change) isn't synchronized. Synchronized methods only lock out other synchronized methods on this object. (The unhelpful synchronized keyword on the layout method is gone in JDK 1.1.) There are two alternative solutions. One would be to make setLayout synchronized and make layoutMgr private, so that it can't be set other ways. This provides a stronger form of thread serialization, in that you would never be able to see an old layout manager being used after it had been replaced. However, it is slower. Another option that provides no increase in thread serialization over the original would be to catch the NullPointerException. Threaded programming is hard! This idiom was probably put in place by someone who got really bitten by this in the past. 12. (Sect. 18) What is the difference between "a & b" and "a && b" ? [*] "a & b" takes two boolean operands, or two integer operands. It always evaluates both operands. For booleans, it ANDs both operands together producing a boolean result. For integer types, it bitwise ANDs both operands together, producing a result that is the promoted type of the operands (i.e. long, or int). "|" is the corresponding bitwise OR operation. "^" is the corresponding bitwise XOR operation. "a && b" is a "conditional AND" which only takes boolean operands. It always avoids evaluating its second operand if possible. If a is evaluated to false, the AND result must be "false" and the b operand is not evaluated. This is sometimes called "short-circuited" evaluation. "||" is the corresponding short-circuited OR operation. Possible mnemonic: The longer operators "&&" or "||" try to shorten themselves by not evaluating the second operator if they can. 13. (Sect. 18) If I create a thread, and then null out the reference to it, what happens to the thread? Does it get interrupted or what? [*] The code looks like this: Thread t = new Thread( my_runnable_obj ); t.start(); ... t = null; // what happens to the thread? The answer is that you may no longer have a reference to the thread, but the JVM still does. Once a thread is started, and as long as it keeps running, it is a root object. Root objects are the starting points for "things in use" that the garbage collector uses. 14. (Sect. 18) How can a Java program determine the level of JDK support given by the underlying VM? I.e. is it running in a JDK 1.0.2 or 1.1 VM? [*] Look at the java.version system property with: String ver = System.getProperty("java.version"); There isn't a lot of standardization on the string contents however. Another possibility is to try { ... } to load a class that is unique to one release, like this: boolean isJDK1_1 = true; try { // java.awt.Cursor is available only in the 1.1.x JDK Class cls = Class.forName("java.awt.Cursor"); } catch (Exception e) { // we should have written 'ClassNotFoundException e', // but Communicator generates security exception instead. isJDK1_1 = false; } This approach has the advantage that it can be compiled by any version compiler. 15. (Sect. 18) How can I set a system property? [*] JDK 1.2 has System.setProperty( "property", "new value" ); Until then, you can get all the properties, and set just the one you want with code like this: System.getProperties().put("property", "new value" ); 16. (Sect. 18) How can I clone using serialization? [*] Look at the code below, submitted by expert programmer John Dumas. It uses serialization to write an object into a byte array, and reads it back to reconstitute a fresh copy. This is a clever hack! import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.ObjectOutputStream; import java.io.ObjectInputStream; public class Cloner { private Cloner() {} public static Object cloneObject(Object o) throws Exception { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bOut); out.writeObject(o); ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray()); ObjectInputStream in = new ObjectInputStream(bIn); return(in.readObject()); } public static void main(String args[]) throws Exception { java.util.Vector v = new java.util.Vector(); v.addElement(new StringBuffer("Hello")); java.util.Vector vClone = (java.util.Vector)Cloner.cloneObject(v); // Changing the StringBuffer int the cloned vector has no // effect on the original StringBuffer object -- // demonstrating that we have indeed done a deep copy ((StringBuffer)vClone.elementAt(0)).append(" world"); StringBuffer sb = (StringBuffer)v.elementAt(0); System.out.println(sb.toString()); sb = (StringBuffer)vClone.elementAt(0); System.out.println(sb.toString()); int array[] = { 1, 2, 3, 4, 5 }; int arrayClone[] = (int [])Cloner.cloneObject(array); // Again, changes to an element in the cloned array do not // have any effect on the original arrayClone[0]++; System.out.println(array[0]); System.out.println(arrayClone[0]); } } The main() routine is just a driver. All the cleverness is in the very brief cloneObject(). It does a "deep" clone, which is what you usually want (though Java gives you a "shallow" clone by default). ------------------------------- 19. Java GOTCHA'S 1. (Sect. 19) What is a "GOTCHA" (for non-English native speakers)? [*] It is an abbreviation of "Got you!" It is the triumphant exclamation that a bug or programming idiom makes as it traps the unwary programmer. This section details some of the popular "gotcha's" of Java. See also the list of Java Gotcha's at http://mindprod.com/gloss.html 2. (Sect. 19) Why can't I filter filenames with the accept() method? [*] It's a known bug. FileDialog doesn't call FilenameFilter.accept(). The bug id is 4031440, and it can be seen at the Java Developer Connection. There is no way to implement FilenameFilter support with the current reliance on the Win32 common file dialog. To support FilenameFilter, the FileDialog needs to issue a callback for each file it wants to display, which the FilenameFilter can veto. But the Win32 common FileDialog doesn't have any way to issue callbacks. Instead it accepts simple wildcard patterns for choosing files which match a certain pattern. That's a reasonable alternative to FilenameFilters, but that model isn't supported by the current Java API. JFC has a JFileChooser class that is a better bet for you to use for file dialogs. It works fine. 3. (Sect. 19) I changed a final value, and recompiled just the file that it was in, and the entire rest of the program used the old value! [*] This is the "expected" behavior. If you have this in one file class Flags { final static boolean debug = true; } and you change it to, and recompile just this file: class Flags { final static boolean debug = false; } Then the rest of your Java .class files will still see it as "true". When you declare a "static final int" (or any other primitive), the compiler turns that into a compile time constant whose value can be substituted wherever it is used in your program. If you update the value in the source file, you'll need to recompile every class that uses it. See Java Language Specification, section 13.4.8 "final Fields and Constants": "We call a field that is static, final, and initialized with a compile-time constant expression a primitive constant. If a field is a primitive constant, then deleting the keyword final or changing its value will not break compatibility with pre-existing binaries by causing them not to run, but they will not see any new value for the constant unless they are recompiled." 4. (Sect. 19) What is the "substring trap"? [*] The "substring trap" is the name for a mistake that is all too easy to make when using the substring() method of class String. The method signature is: public String substring(int beginIndex, int endIndex) The name "endIndex" suggests that is the index where the Substring ends. But in fact, the substring extends only to the character at position (endIndex-1)! It seems to be done this way so that s.substring(0,s.length()) is equal to s. If so, the name of the second parameter should be something like endInxLessOne or Length. But not the confusing and misleading endIndex. Beware the substring trap. 5. (Sect. 19) Why does getGraphics() return null on my offscreen image? [*] The following code class MyFrame extends Frame { MyFrame() { Image offscreen = createImage(100,100); Graphics offg = offscreen.getGraphics(); } ... } will usually not work, since the peer will not exist at this time. Without the peer for the Frame, you cannot succeed in creating offscreen Images. (There's no problem creating Produced Images without a peer. Trying to draw them, of course, is another matter). One "standard" form of offscreen code looks like this: (note the reuse of the Graphics and Image objects for as long as possible) class Gumble extends java.awt.Something { private Image offi; private Graphics offg; public void update(Graphics g) { if (g == null) return; // Paranoia Dimension size = size(); if ( offi == null || offi.getWidth()!=size.width || offi.getHeight()!=size.height ) { if (offg!=null) offg.dispose(); offi = createImage(size.width, size.height); offg = offi.getGraphics(); // Regenerate offi here... } // If you use getClipBounds() here, // check that for being null, too! // several implementations have been known to pass them.... g.drawImage(offi); } public void paint(Graphics g) { update(g); } } See also Question 8.7 6. (Sect. 19) The dynamic type of a method argument doesn't seem to be used to choose an overridden method at runtime. [*] Correct. Generally, if you invoke a method on an object, the object's actual runtime type, not the type of the reference that you used to reference it, determines which method is invoked. This is regular polymorphism. It's not the same for object parameters: the compiler decides at compile time, depending on the types of the parameter expressions, which method signature to use, and this is "hardwired" into the bytecode. The compiler does not look at the object argument at runtime and say "ah, this is a derived type, so I will choose the method that takes the derived type as an argument." This is best seen in a code example: class Base { } class Derived extends Base { } public class foo { public static void method(Base b) { System.out.println("In the base method..."); } public static void method(Derived d) { System.out.println("In the derived method..."); } public static void test(Base b) { if (b instanceof Derived) System.out.print("Derived: "); else System.out.print("Base: "); method(b); // which method? method(base) or method(derived)? } public static void main(String args[]) { Base b = new Base(); Derived d = new Derived(); System.out.println("test calls."); test(b); test(d); } } Running the program gives an output of test calls. Base: In the base method... Derived: In the base method... See JLS section 15.11.4.4 and 15.11.3: "If class S contains a declaration for a method named m with the same descriptor (same number of parameters, the same parameter types, and the same return type) required by the method invocation as determined at compile time then this is the method to be invoked." 7. (Sect. 19) Why did I lose my updates when I changed data fields in a graph that I was serializing? [*] Quoting from the object serialization specification at: http://www.javasoft.com/products/jdk/1.1/docs/ guide/serialization/spec/serial-arch.doc.html#4176 The writeObject method serializes the specified object and traverses its references to other objects in the object graph recursively to create a complete serialized representation of the graph. Within a stream, the first reference to any object results in the object being serialized or externalized and the assignment of a handle for that object. Subsequent references to that object are encoded as the handle. In other words, changing an object and then writing it again does not really write it twice. Instead it just writes a reference back to the first occurrence, losing any fields that have changed in the meantime. There are three ways around this: (1) (inefficient) Reset (or close and reopen) the stream, and start again by writing the new value of the object. This is drastic -- you are throwing away all the serialization that you have already done. (2) (kludgey) Create a new object and write that. (3) (could be a lot of work) Write your own protocol for object serialization. Have something like a data stream where the contents of an object are marked by special identifiers. Each "end" of the stream can decide whether it will use a new object each time or reuse an existing object. 8. (Sect. 19) When I click on a Java window frame, it doesn't close! [*] You need to add the code to listen for a window closing event, and take the appropriate action (hide the window, exit the program if the top level frame, etc). The window closing event handler is simple: Frame mf = new Frame("binky"); mf.addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent we) { System.exit(0); // or setVisible(false); etc. } }); This really should be the default behavior of an AWT Frame. So you'll be delighted to hear that JavaSoft has "made it so" for the JFrame Swing component. That leads to a slightly different problem. See Question 4.3.3. See also Question 13.9. 9. (Sect. 19) What's the deal with "super"? How far back into parent classes can I go? [*] The most common use of super is the call "super()" to invoke a constructor in the superclass. The keyword "super" is also used to access fields of any superclass (not just the immediate superclass) that are hidden by an identically named feature in the current class. However there is no way to "chain" several super's together, and reach back higher into the parent class hierarchy. E.g. do not think that "super.x" means the "x of parent" and "super.super.x" means the "x of grandparent". This is a very common mistake. There is no "super.super.x". Looking at the generated byte code, if you have class Parent { } class Child extends Parent { } then, in Child "super.someParentMethod();" means "invokespecial X.someParentMethod()" in the JVM, not "invokevirtual". Invokespecial means "call the exact method I am telling you." Invokevirtual means "call the right method for whatever object this is". 10. (Sect. 19) When I change some component (e.g. a new label on a button) I don't see the change on the screen immediately even if I repaint(). [*] You need to add a call to the paintImmediately(x,y,w,h) method of JComponent. That repaints the component completely before continuing execution. On pre-JDK 1.2 systems, use: invalidate(); validate(); They cause the component hierarchy to be marked as needing to be laid out again, and the validate causes that to be done. It may be expensive, but is a way of getting the peers to recalculate size and to do what is needed to bring the display up to date. It has limitations: it doesn't cause an immediate screen update when invoked from an event handler, where paintImmediately() does. 11. (Sect. 19) Why aren't popup menus working cross-platform for me? [*] On Windows, the pop-up trigger is a mouse release (except in certain programs like Netscape Communicator). On Unix, the pop-up trigger is a mouse press. Therefore you need to ask the question isPopupTrigger() in both the mousePressed() and mouseReleased() methods when implementing the MouseListener interface. Alternatively override Component's processMouseEvent as a central place for handling mouse input. 12. (Sect. 19) Why aren't newlines working cross-platform for me? [*] Code like this: if (c == '\n') fin = true; is not cross-platform. On Unix the line terminator is "\n", on Windows, it is frequently "\r\n", on the Mac it is "\r". The call System.getProperty("line.separator") will return a string containing the platform-specific line separator character(s), and you then need to compare it according to how your data is formatted (e.g. compare 2 characters or one). There is also a property for the separator character in file pathnames, and other values too. This can screw-up your networking programs too. Most ASCII based protocols like HTTP expect \r\n to terminate a request. They will hang on a request from a Mac that only sends \r. 13. (Sect. 19) Why didn't my text display in my GUI? Is the Inset wrong? [*] The most common Inset problem is not an Inset problem at all, but rather that people just assume the x,y location of a Graphics.drawString() actually refers to the top left part of the string image. In fact it refers to the baseline. So you'll need to take g.drawString("Hello World",0,getFontMetrics(getFont()).getAscent()); 14. (Sect. 19) Why did my polygon come out the wrong shape? [*] This question and answer comes directly off comp.lang.java.programmer, and deserves to be immortalized for posterity. When I use fillPolygon with the following points I get two inverted triangles instead of a rectangle. Why? int xPoints[] = {71, 78, 71, 78}; int yPoints[] = {147, 147, 130, 130}; g.fillPolygon(xPoints, ypoints, xPoints.length); Developer Felix Pahl supplied the answer in limerick form: o A developer (for details bored her) didn't follow the polygon's border so instead of right angles she got two triangles 'cause the endpoints were in the wrong order! You must put the points in the order you would encounter them in if you went round the polygon's border. The filling algorithm is doing the right thing! Try drawing the points on paper to see: 71,130 78,130 O--------O | | | | | | o--------o 71,147 78,147 Under JDK1.1, the two endpoints are connected automatically and you would order the array elements as: int xPoints[] = { 71, 78, 78, 71}; int yPoints[] = {130, 130, 147, 147}; Under JDK1.0.2, you have to explicitly connect the two endpoints, and you would write the array elements as: int xPoints[] = { 71, 78, 78, 71, 71}; int yPoints[] = {130, 130, 147, 147, 130}; 15. (Sect. 19) Why can't I see all the components I added to a Frame? [*] If you have code like: Frame myframe = new Frame("Child Frame"); myframe.resize(512,384); myframe.add(new Label("Child")); myframe.show(); The default layout manager for Frame is BorderLayout. Components positioned with a BorderLayout should include a positioning constant to be correct. If you don't include one, "-1" is assumed, which causes the component to go to the end of the list, and possibly be buried (in terms of z-order) under any other components you add. So, change the add to myframe.add("Center", new Label("Child")); and all will be well. 16. (Sect. 19) Why do I get the wrong results when I compare two Strings together? if (s1 == s2) is giving me funny results. [*] The comparison using "==" on objects, like Strings, is asking the question "do these two objects have the same reference?". That is, do they have the same address, and hence are not two object but one? What you most probably meant is "do these two Strings have the same contents?" which you can express this way: if ( s1.equals(s2) ) This is a very, very easy mistake to make and impossible to spot until you have had it explained to you. People talk about "interning" a String. That means calling the intern() method on a String. This places the String in the runtime constant pool if it was not already there. The compiler is required to intern() all literal Strings. If you intern() all your Strings as well then all duplicates are shared and comparisons can be done by the (much faster) address comparison rather than content comparison. It's a performance optimization. See also Q3.22. Note that this comparison error also occurs with other objects, not just Strings. The code: if (getBackground() == Color.black) is a test for object identity, rather than content identity. It will work if you originally setBackground(Color.black). To avoid difficult debugging in the future, you almost certainly want to say if (getBackground().equals( Color.black ) ) or even (in this visual case) compare the darkness of the RGB values of the pixels. 17. (Sect. 19) Why doesn't final prevent my object from changing? [*] You have code like this final StringBuffer s = new StringBuffer("don't change me"); // ... s.append(", but I did"); System.out.println(s); And the new value of s is "don't change me, but I did". The reason is that the "final" modifier makes the reference variable (here, s) final, not the object that s points to. It means that the reference variable cannot be changed to point to some other StringBuffer. The state of the StringBuffer can still be modified by calling methods on it or directly assigning to its public fields. The right way to think about final is that it prevents you assigning to that particular variable. The only way to make the fields of an object constant (unchanging) is to make all its data fields private, and not provide any set methods for them, only get methods. Even that won't stop other objects of the same class adjusting it. 18. (Sect. 19) Why can't the compiler find my package? [*] When trying to compile a file in a package you get a compiler error like: DBTest.java:10: Class database.Table not found in type declaration. The file Table.java and DBTest.java are in the same directory. They both have "package database;" at the top of the file. The current directory is included in the classpath. The reason is that when compiling packages, you have to be at the 'top' of the directory/package hierarchy. So to compile both Table.java and DBTest.java, you have to be in the directory that contains the database directory (i.e. where the package hierarchy starts), and just: javac database/Table.java javac database/DBTest.java and it should all compile fine. 19. (Sect. 19) I have a program with keyboard input and a button. When the user hits the space bar, the button gets pressed as it is in focus! [*] The VM sets the focus on the first traversible object in the UI. If you want the button not to be assigned focus by default, you must subclass the button and override the isFocusTraversable() method to return false. Another approach is to manually set the focus on some other component (say the Frame) when you show the window. To do so you have to jump through hoops to outsmart the VM that is trying to set it on the button. One approach is to listen for the windowActivated event and set a Swing Timer to do a requestFocus() on the frame about 0.1 seconds after the activated message. This seems convoluted, but it is the only thing found that consistently works cross platform. Another reader suggests that if the frame normally gets the focus first, you can override its gotFocus() event and set the focus to the component you want. Don't forget to return true! 20. (Sect. 19) What's the hidden size limitation of String serialization? [*] If you wish to Serialize a string, be alert to the restriction that: The size of the String, when UTF-encoded, must be < 64Kb So for robust code you have to examine the String once to ensure that it will be less than 64Kb after encoding, and then have the JVM effectively repeat that work in the process of encoding, when you write it to an ObjectOutputStream. A possible workaround that is to strip the string down to "byte[]" and pass it around in RMI that way. The code with this restriction is in DataOutputStream public final void writeUTF(String str) ... [perform the size-after-conversion-to-UTF computation] ... if (utflen > 65535) throw new UTFDataFormatException(); ... RMI relies on serialization, so RMI has the same String size limitation. 21. (Sect. 19) When I change a field in just one object in my array, that field changes in all the objects in my array! [*] Here the problem is probably that you have initialized the array with N references to the same one object. This is easy to overlook, because arrays in Java only contain references to objects, not objects. (Or they can contain primitives). 22. (Sect. 19) Do DrawRect and FillRect work on rectangles of the same size? [*] No. java.awt.Graphics.drawRect draws a rectangle that's 1 pixel wider and 1 pixel taller than a rectangle drawn by fillRect. 23. (Sect. 19) My executable Jar files don't work! [*] It is possible to exactly follow the instructions given in the documentation and yet still get the following error message when attempting to run the .jar file: "Failed to load Main-Class manifest attribute from myapp.jar" There has to be a carriage return after the Main-Class definition in the manifest file, otherwise it does not work! Example, in a file called manifest.txt: Main-Class: MyClass // does not work Main-Class: MyClass // does work Then, when the manifest file is merged into the jar file like this: jar cmfv manifest.txt myapp.jar *.class it works fine. 24. (Sect. 19) Why do I get the error message "Wrong number of arguments in constructor" [*] Almost certainly, you have written your constructor with a return type or void or something. I.e. you have written: public MyClass Myclass() { ...} instead of: public Myclass() { ...} Giving a constructor a return type makes it into a regular method that happens to have the same name as the class. The language should ideally outlaw this, but it doesn't. ------------------------------- 20. Further Resources 1. (Sect. 20) Will Java ever be fast enough for games like Quake? [*] Some people originally thought not. Please see the site http://fragisland.fragzone.se/ which has the Frag Island game (a quake-style game) written in 100% Java. You play it as an applet, by browsing the above site. Watch out -- it's noisy! 2. (Sect. 20) Are there any commercial/shareware/free Java libraries? [*] Take a look at the Java Collection Framework, a group of classes that are part of Java 1.2. These classes implement general-purpose data structures, and they will become widely used. The documentation for JDK 1.2 explains that the Collection Framework defines three kinds of things: o Standard interfaces representing data structures of various kinds for you to implement. Since these are interfaces, you can use them in your code before you have implemented them. o Partial implementations of those interfaces, saving you some work. o Complete implementations, ready to use for data in your programs. The standard interfaces are Collection, Set, List and Map, plus the more specialised SortedSet and SortedMap. Lists have duplicate elements whereas Sets do not. Finer distinctions such as immutability are defined in the implementor classes, enforced by throwing runtime exceptions. See the JDK 1.2 documentation for a full discussion. For more about sorting prior to JDK 1.2, look at the class SortDemo in the demo directory of the JDK. Alternatively, use one of the several classic sorts available from Roedy Green. They are supplied free with heavily commented Java source code. See "QuickSort", "HeapSort" and "RadixSort" in the Java glossary at http://mindprod.com/index.html. Also, try the Java Generic Library. This library (JGL) is freely downloadable from http://www.objectspace.com/ Also Visual Engineering has JChart at: http://www.ve.com. No licensing fees. Visual Numerics has its Java Numeric Library available for download at http://www.vni.com/products/wpd/jnl/jnl_1_0.html. They offer the JNL as a proposed standard library for numerical functions missing from Java. 3. (Sect. 20) Why doesn't somebody write a shell in Java? Then they could use it on all platforms! [*] Somebody has done just that. Look at http://www.jsh.net/ 4. (Sect. 20) Are there any URLs for other libraries? [*] Indeed, there are. The Java3D Repository http://java3d.sdsc.edu/ 5. (Sect. 20) Are there any URLs for regular expression handlers in Java? [*] There is one from ORO Inc. They dissolved as a corporation, but one of the founders maintains the software at http://www.oroinc.com/. For other sources, see http://www.meurrens.org/ip-Links/Java/regex/index.html And don't forget to check out Lava -- a set of Java classes designed to support programmers who develop console-mode applications and/or C programmers who are converting to Java. The first release of Lava has printf and other text formatting, encryption, parsing and miscellaneous I/O. Lava can be downloaded from http://www.newbie.net/sharky/lava/ Also consider the Java version of the Unix find command. It offers Regex filename matching, mindepth, maxdepth, symlink follow / no follow, file type matching all cross-platform. The package is at http://www.rule-of-eight.com/en/components/ 6. (Sect. 20) Are there any installers for Java? Preferably platform-neutral ones. [*] There are several possibilities. o InstallAnywhere 2 from ZeroG software. See http://www.zerog.com/html/installanywhere_2.html They have a free version for shareware authors. o InstallShield makes a Java version of their installation package. See http://www.installshield.com/java/default.asp o IBM offers a comprehensive Java installer through its alphaworks site http//www.alphaworks.ibm.com/formula/installtoolkit o Denova offers the J'Express installer. There is a free trial version available for download at http://www.denova.com Freeware authors can receive a completely free license to J'Express Standard. Simply fill in the application at http://www.denova.com/JExpress/freeware.html. 7. (Sect. 20) What is "Jazilla"? [*] Jazilla is Mozilla (Netscape Communicator free source) ported to Java. In other words, a free source browser that supports Java and Javascript, written in Java! You can get more information, and volunteer to help with the project at http://www.jazilla.org/ 8. (Sect. 20) Where can I get Java for my Palm Pilot PDA? [*] There is a translator allowing you to compile Java programs for the Palm Pilot PDA! This is an astonishing piece of work as the Pilot has such a small memory footprint. The translator is in an early stage of development, but is available at: http://www.cs.washington.edu/homes/mcdirmid/ghost Try it, or even better, volunteer to help with the project. Details at the website above. There is a Java-PalmPilot Project called "jSyncManager" which allows PalmPilot synchronization and jConduit development in pure Java. See http://yaztromo.idirect.com/java-pilot.html. If you can run Java 1.1 and Sun's Communications API, you can run jSyncManager. 9. (Sect. 20) What is "Dippy Bird" and where can I get it? [*] Dippy Bird is Java documentation in WinHelp format, which can be used directly on Windows desktops, and has a searching utility. The developer of the Dippybird project, Bill Bercik, has stopped further work on the project due to lack of time and funds. Instead you can use http://www.confluent.fr/javadoc/JavadocE.htm which has a more up to date Java WinHelp doc. You can get still get the Dippy Bird download at http://www.dippybird.com/jdk111.exe (JDK 1.1). Note that on NT 4.0 you need to change the generated shortcut to point to NT's 32-bit WinHelp. 10. (Sect. 20) Are there any Java graphing tools? [*] Take a look at GraphMaker -- a complete full-featured Java application for creating and searching graphs. It is available under GPL with source, and uses the latest Swing JFC features. See http://home.earthlink.net/~nfiedler/graph/ 11. (Sect. 20) Where can I get icons for use with Java? [*] Public spirited programmer and Java supporter Dean S. Jones has created a collection of over 100 icons for use in Java freeware. They are available on the Java Lobby site at http://webart.javalobby.org/jlicons/. 12. (Sect. 20) What is "UML"? [*] UML is the Unified Modeling Language. It is unified in the sense that it draws together ideas from a couple of earlier software design languages. UML is an emerging standard for diagrams of object-oriented classes. It was devised by Grady Booch, Ivar Jacobsen, and James Rumbaugh, and it unifies several popular existing notations. A UML product is available from Rational Software, who also offer a tutorial CD for free. See http://www.rational.com/uml/index.jtmpl There are some whitepapers too, but there don't seem to be any free online tutorials. See http://www.togetherj.com/ for information on Together/J. That is a platform-independent UML product that supports round-trip engineering for Java. Whiteboard version is free. 13. (Sect. 20) Where can I get info on Java college courses? [*] The JCampus site at http://www.jcampus.org has links and connections to Java CS Dept. courses, assignments, academic papers and Java-related events. JCampus is a non-profit, online Community for CS Dept. professors, students and staff who are teaching, learning and using the Java programming language. 14. (Sect. 20) What is the Java IFAQ? [*] It is the Java list of Infrequently Answered Questions, a FAQ maintained by Peter Norvig, author of the book "Artificial Intelligence - A Modern Approach". Take a look at the Java IFAQ at http://www.norvig.com/java-iaq.html There's a lot of good information in that document. 15. (Sect. 20) Are there any Java tools for PDF? [*] PDF (Portable Document Format) is the text publishing format defined by Adobe. Acrobat is the technology to display and print PDF files. Abode supplies the client (document reading) software for free. There is a PDF toolkit written in Java at http://www.etymon.com. Even better it is GPL'd. It is more a toolkit for programmers embedding PDF in their products, than an end-user technology though. It doesn't have a GUI for displaying PDF for example. 16. (Sect. 20) Are there any Java info search tools? [*] IBM has a very good search engine for java developers http://www.ibm.com/java 17. (Sect. 20) What other languages compile to bytecode? [*] Quite a lot of languages compile to Java bytecode, more than 60 at the last count. See the webpage http://grunge.cs.tu-berlin.de/~tolk/vmlanguages.html 18. (Sect. 20) Has anyone written a Java-to-RPC interface, to talk to legacy code? [*] See www.distinct.com. It implements a subset of RPC, and is a commercial, supported product. You can review RFCs 1831 and 1832 for information on the full protocol. Java uses the same endianness as RPC's external data representation (network byte order), so all the Java file reads/writes can be used directly. Netbula recently released Java RPC, a fully compatible port of ONC RPC to Java. The binary package can be downloaded for evaluation from http://netbula.com/javarpc/ The specifications are in RFC 1831 (the RPC protocol spec) and RFP 1832 (the XDR spec). 19. (Sect. 20) Are there any automated tools for Javadoc? [*] Yes. See http://www.mindspring.com/~chroma/docwiz/docwizApplet.html for a Java development tool called DocWiz. It is the easiest way to add JavaDoc comments to your Java code. 20. (Sect. 20) Is there any information on XML and Java? [*] Yes. See http://developerlife.com It shows you how to use: o the Sun parser (Sun ProjectX EA2) o the DOM (org.w3c.dom.*) interfaces o JFC/Swing with XML o Servlets with XML and more. 21. (Sect. 20) How can I find the format of a .class file/a JPG/a PNG file/any file? [*] There is a great website that maintains descriptions and links to descriptions of hundreds of file formats. The site is at: http://www.wotsit.org/ It shows you how the files are structured, and makes it a lot simpler for you to write code that creates/decodes such a file. 22. (Sect. 20) Why not start up one copy of the JVM and share it among many Java programs? [*] If the JVM takes about 15MB (say) in overhead, and a program takes 3MB, then starting up a fresh JVM for each program is slow and wasteful. If a single copy of the JVM and libraries could instead be shared among multiple Java applications there would be less overhead and everything would run faster. That observation was the guiding force behind the echidna project to support a JVM that could run multiple applications. See the site http://www.javagroup.org/echidna/ for more details. 23. (Sect. 20) How can I edit sound files? [*] The JaWavedit java code lets you edit .wav and .au files. It can be found at http://www.bome.com/JaWavedit/. It's free to use. If you are inspired to write freeware like this yourself, many file formats are explained and described at http://www.wotsit.org ------------------------------- 21. Acknowledgements A jolly little song that explains how to solve commonly-encountered problems in Java. The FAQ Melody by Antranig Basman. On the First Day of Christmas, my true-love said to me: Read the F-A-Q. On the Second Day of Christmas, my true-love said to me: My Image isn't drawing; Read the F-A-Q. On the Third Day of Christmas, my true-love said to me: My Pixels are not grabbing, My Image isn't drawing, Read the F-A-Q. On the Fourth Day of Christmas, my true-love said to me: My Layout is not laying, Pixels are not grabbing, Image isn't drawing, Read the F-A-Q. On the Fifth Day of Christmas, my true-love said to me: Null - Pointer - Exception! My Layout is not laying, Pixels are not grabbing, Image isn't drawing, Read the F-A-Q. On the Sixth Day of Christmas, my true-love said to me: Netscape will not run it, Null - Pointer - Exception! Layout is not laying, Pixels are not grabbing, Image isn't drawing, Read the F-A-Q. On the Seventh Day of Christmas, my true-love said to me: J++ don't mind it, Netscape will not run it, Null - Pointer - Exception! Layout is not laying, Pixels are not grabbing, Image isn't drawing, Read the F-A-Q. On the Eighth Day of Christmas, my true-love said to me: Threads they are a-blocking, J++ don't mind it, Netscape will not run it, Null - Pointer - Exception! Layout is not laying, Pixels are not grabbing, Image isn't drawing, Read the F-A-Q. On the Ninth Day of Christmas, my true-love said to me: Dialogs-a-hanging, Threads they are a-blocking, J++ don't mind it, Netscape will not run it, Null - Pointer - Exception! Layout is not laying, Pixels are not grabbing, Image isn't drawing, Read the F-A-Q. On the Tenth Day of Christmas, my true-love said to me: Time-zone's in Pacific, Dialogs-a-hanging, Threads they are a-blocking, J++ don't mind it, Netscape will not run it, Null - Pointer - Exception! Layout is not laying, Pixels are not grabbing, Image isn't drawing, Read the F-A-Q. On the Eleventh Day of Christmas, my true-love said to me: Docs are not specific, Time-zone's in Pacific, Dialogs-a-hanging, Threads they are a-blocking, J++ don't mind it, Netscape will not run it, Null - Pointer - Exception! Layout is not laying, Pixels are not grabbing, Image isn't drawing, Read the F-A-Q. On the Twelfth Day of Christmas, my true-love said to me: File I/O's horrific, Docs are not specific, Time-zone's in Pacific, Dialogs-a-hanging, Threads they are a-blocking, J++ don't mind it, Netscape will not run it, Null - Pointer - Exception! Layout is not laying, Pixels are not grabbing, Image isn't drawing; You Should Read The-e F-A-Q! FAQ copyright 1997, 1998, 1999 by Peter van der Linden. Contributions and help from: Matt Kennel, Patric Jonsson, Brad Van Tighem, Tony Hursh, Glenn L Vanderburg, Peter Jones, John McDowall, Jim Driscoll, Uday, Dave Harris, Bill Wilkinson, Tom Valesky, Dan Drake, Giles Thomas, Mitch Baltuch, Guy Ruth Hammond, Gordon Keith, Jason Brome, Shani Kerr, Steve Chapel, Timothy Wolters, Robert Lynch, Jake Cormier, Sean C Sullivan, Joseph A. Millar, Jim Frost, Jim Balter, Jeff Bauer, John Kochmar, Carl Burke, William Stubbs, Mark Smith, Volker Turau, Real Gagnon, Russell Gold, Max Hailperin, Bill Tschumy, Marco Nijdam, Marc Pawlowsky, Laurence Vanhelsuwe, Ian Macgregor, Mike Faulkner, Rich Koch, Will Clark, Govind Seshadri, Rich Simkin, Ian Stiles, Kieren, Darren Christie, Tom Lane, Michael Jungmann, Rob Mayoff, George Ruban, Tom McCann, David Hopwood, Thomas Phan, Kai Stuke, Rolf Howarth, Derek Snider, David Boydston, Andy Godwin, John F. Dumas, Doug Bell, David J. Biesack, Tiger Quimpo, Martin Hugh Rogers, Brian Krahmer, Ian Burrell, Nikki Locke, Bin Li, Jackson Thompson, Steve Odendahl, Greg Smith, Jeffrey C. Ollie, Mark Halvin, Jeremy Cook, Lak Ming Lam, Peter S. Morris, Mark Halvin, Juergen Keil, Alex Stewart, Mike Abney, Rodney Stephenson, Mark Gritter, Satish Talim, Tamminen Eero, Alexander Gridnev, Eric Hodges, Jamey Graham, Will Lockhart, Scott Plante, Tom Sanfilippo, Jan Newmarch, Sean Breslin, Stuart D. Gathman, rhino@wwdc.com, C Matthew Curtin, Tor Iver Wilhelmsen, A.N.Pryke, Phil Race, David Holmes, David Rodal, Dominique Plante, Trent Jarvi, Ingrid Biery, Gopal Unni Krishnan, Grant Lewis, Tov Are Jacobsen, Gary McGath, Marty Hall, Will Forster, Colin Mummery, Darin McBride, Mayank Shah, Jens Alfke, Glen Stampoultzis, Philip Brown, Peter Steiner, Kurt Spaugh, Rasmus Ekman, Jonathan Revusky, Ken Kalish, Dave Sanders, Bill Hyden, James Cloughley, Philip "diodes" Gustafson, Paul Kinnucan, Juan ValdИz, Antranig Basman, Felix Pahl, David N. Still, Simon Arthur, Mark Hammond, Dan Kegel, Thomas Weidenfeller, Pavel Shvartsman, Christen Monberg, George Reese, Ian Macgregor, John Sublett, David Zimmerman, Tony Dahlman, Druid, Chris Kelly, Patricia Shanahan, Paul Hill, Lyne Lamoureux, Don Kennedy, Alec Muffett, Andrew Mickish, Pavel Shvartsman, Neil of Parkway Consultants, Chris Thiessen, David Michaels, Bob Sutherland, Michael Allen Latta, Joshy, Eric Albert, Wes Isberg, Lisa Retief, Michael Park, Dave Postill, Thomas Weidenfeller, Konstantin Laufer, HЕkan Gustavsson, James Stauffer, Reuben Firmin, David Lim, Eamonn Maher, Craig West, Pavel Shvartsman, Jay Dunning, Kevin Swan, Grant Gainey, Dan Schmitt, Benjamin Goldberger, Jake Hamby, Yaakov Itzhaki, Robert Lynch, Laura Werner, Tomm Hoeft, King Dale, Joe Halpin, Daniel M. Pomerantz, Kevin Kelley, misnomer@earthling.net, Peter Seibel, Werner Zsolt, Hank Stuck, David M. Karr, John J. Bartholdi, III, Garry Turkington, John Bokma, Frank McCreedy, Nat Pryce, Jeff Luszcz, Brent Callaghan, Neil Allen, Joe Preston, Tim Bell, Rajesh, Jeffrey Galyan, Nick Matsakis, Larry Hamel, David Lamb, Mr Tines, Bill McHardy, Phillip Lord, Jon K. Hellan ------------------------------------------------------------------------ I am maintaining a FAQ list to address specifically programming issues (not a general tutorial on Java). Please mail suggested FAQ entries including answer to faqidea on the site afu.com. Question with answer gets you a credit in the FAQ. Peter van der Linden, Sun Certified Java Programmer. ------------------------------------------------------------------------ Cross references Most cross reference links inside this document are still to be filled in after the great FAQ re-org. If you'd like to contribute a few, send me the new text for the NAME= and the HREF=, and I'll fold them in as time permits. Look at the FAQ source for the style to follow. Copyright Copyright (c), 1997,1998,1999 Peter van der Linden. Permission to copy all or part of this work is granted for individual use, and for copies within a scholastic or academic setting. Copies may not be made or distributed for resale. The no warranty, and copyright notice must be retained verbatim and be displayed conspicuously. You need written authorization before you can include this FAQ in a book and/or a CDROM archive, and/or make a translation, and/or publish/mirror on a website (scholastic and academic use excepted). If anyone needs other permissions that aren't covered by the above, please contact the author. No Warranty This work is provided on an "as is" basis. The copyright holder makes no warranty whatsoever, either express or implied, regarding the work, including warranties with respect to merchantability or fitness for any purpose. Furthermore the author has been known to wear socks that don't match his pants, and to commit other egregious lapses of good fashion sense. ------------------------------------------------------------------------
Закладки на сайте Проследить за страницей |
Created 1996-2024 by Maxim Chirkov Добавить, Поддержать, Вебмастеру |