You can get 'Just Java' at Amazon.com You can get 'Not Just Java' at Amazon.com
Go to the Index


15. Networking and Distributed Objects

    RMI Issues

    Note that there is an RMI FAQ at http://java.sun.com/products/jdk/1.2/docs/guide/rmi/faq.html

  1. (Sect. 15) Should I use CORBA in preference to RMI? Or DCOM? Or what?

    * If your distributed programs are wholly written in the Java programming language, then RMI provides a simpler mechanism that allows the transfer of code, pass-by-value of 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 Java 1.3 Sun has aligned RMI to work more closely with CORBA. Sun has simply added an IIOP transport layer to RMI to support interoperability with CORBA. Java technology-enabled programs can now 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.
    Microsoft spokespeople have 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 would restrict 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:

  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.

  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 want to use JDK 1.2 at one end of my RMI system, and JDK 1.1 at the other end.

    * You're getting an error message about version compatability, right? The RMI Compiler has a -v1.1 option for generating 1.1 compatible stubs and skeletons. It should work with that .

  6. (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

  7. (Sect. 15) Why does < Microsoft Windows RMI/my java debugger/IDE/other> hang for a couple of minutes if my PC is not dialed up to the Internet?

    * The Java language has networking support built in. When the 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 has intermittent 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

  8. (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:

  9. (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:

  10. (Sect. 15) How do I get a URLConnection to work through proxy firewalls? I.e. How do you get your 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  classname
    
    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 java.net.URLConnection, but apparently not for java.net.Sockets. Update! The proxyHost and proxyPort systems properties (from 1.0.2) are deprecated, you should use http.proxyHost and http.proxyPort. They are for HTTP proxies only. If you are using java.net.Socket you are not using the URL classes, and cannot get the proxy behavior.

    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.

  11. (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.

  12. (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.

  13. (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.

  14. (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();
         

  15. (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);
         

  16. (Sect. 15) How do I POST to a CGI script from an applet?

    * POST passes the form data to the next page as part of the HTTP headers, while GET sends the data appended to the URL as a querystring. in the manner of http://www.someurl.com/page.htm?varname=value. POST and GET are different ways of transmitting form data to a server-side application. GET is limited to a small amount of text data that can be appended to the address. POST handles larger amounts of text and binary data and does not show up in the address URL.

    Why have two access methods if the only difference is in syntax? The real difference is that GET is "idempotent", meaning that you can call it again and again with absolutely no side-effects for the retrieval of the page. If you do GET on the same page twice, the page may legally be sent to you from your browser cache, a proxy cache, or the webserver itself.

    If you do a POST the browser knows the page must always be retrieved by going through all the layers to the server and extracting the data again. If it is a webpage that is being fetched this doesn't matter, but if you're calling a script (CGI, servlet, or similar) then the difference is huge. If the script has side-effects that should be done on each access of the webpage (such as access control, or making the user pay something) you will definitely want to invoke the script each time it is called. See http://www.rfc-editor.org/rfc.html for RFC 1945 (HTTP/1.0) or RFC 2068 (HTTP/1.1) to get the absolute formal meanings of the difference between GET and POST.

    When you do a GET, since the data is actually added onto the end of the URL string, the user can actually bookmark it, and submit the same info later by going to the bookmarked site. This is why search engines often use GET.

    Note that (in Java) POST 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();
        

    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:

    See also the Marty Hall book Core Web Programming (Prentice Hall ISBN: 0-13-625666-X). It has comprehensive coverage of writing Java technology-based programs that interface to CGI scripts. Better still, use servlets, write everything in the Java programming language, and discard your CGI code.

  17. (Sect. 15) How can I write CGI programs in the Java programing language?

    * 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 programming langauge, 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 technology-enabled 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 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.

  18. (Sect. 15) How can I write the "ping" program?

    * 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:

  19. (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.

  20. (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.

  21. (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.

    That approach will be inefficient for a large number of streams. A lower overhead implementation would be to create a thread to do a blocking read for the stream in that thread and then process it asynchronously. See http://www-ast.man.external.lmco.com/lm-tds/kqml/ for an example.


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?

    * The technology 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 an 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?

    * Cryptographic libraries are not part of the 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.
    Late in 2000, the US government relaxed the "crypto software" export regulations somewhat, permitting certain formerly forbidden products to be exported. Other sites:

  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:

  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/

  9. (Sect. 16) How can I accept a password from the console without echo?

    * When you want to pick up a password from the console, you don't want to have the characters echoed as the user types them.

    There is no way to accomplish this in Java using console I/O. You have an easy approach and a hard approach. The easy approach is to use the AWT (Textfield) or Swing (JPasswordField). The harder approach is to write native code to disable and enable echoing to the console.

    Note that the obvious use of Process process = runtime.exec("stty -echo"); will not work because it turns off echo in the spawned child process not the process running the JVM.


17. For C and C++ Fans

  1. (Sect. 17) How do I translate C/C++ into Java programming langauge or vice-versa?

    * In general it is not simple to translate C/C++ into Java programming language, 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:

    Going the other way there are currently three freely-available tools to translate Java programming language into C. It seems that these have been done for hacking value, rather than practical purposes.

    None of them support the AWT yet, and both j2c and JCC have additional restrictions.

    There are several products to convert Visual Basic to Java. Details at

    There's a product to translate COBOL source to Java source, see
    http://www.Synkronix.com/

    This program dumps info about the class file:

    Chuck McManis was one of Sun's original Java implementors.

  2. (Sect. 17) How are finalizers different from C++ destructors?

    * Java programming language 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. 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 the 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 the Java programming language. However, note that 90% of destructors in C++ are there to free memory, and the GC means you don't need to do that. 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 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. Some people have suggested that you can find out the size of an object 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:

    is roughly equivalent to the following C/C++ code:

    Java does not have any equivalent to the following C/C++ function declarations:

  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.

    Then when you want to receive a parameter that cannot be modified you have:

    For a parameter that can be modified

  6. (Sect. 17) How can I write C/C++ style assertions?

    * The two classes shown below provide an assertion facility. 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

    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 the Java programming language is to write

    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.

  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 programming langauge 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.

    gives:

    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.
    See also "Henrik Bengtsson's Java printf, sprintf and fprintf" library which is downloadable from http://www.braju.com.

  8. (Sect. 17) What is the 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 the Java programming language, 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 protection levels are: private, package, protected, and public.

  9. (Sect. 17) Does anything like the C++ Standard Template Library exist?

    * Yes, only it's better and simpler to use. 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 Programming Language Idioms

    See also the list of Java Design Patterns at
    http://c2.com/cgi/wiki?JavaIdioms

  1. (Sect. 18) What are the naming conventions?

    * The naming conventions are straightforward:

    Other sites:

  2. (Sect. 18) Do I really need to use new String(...) to create a new String?

    * No. A String constant such as "" or "hello" is already a String, so there's no need to write code like:

    
          String s = new String("");
        
    You can instead write the simpler
    
          String s = "";
        
    Note that Strings are immutable (unchangeable), so there is no danger of accidentally modifying a String that is pointed to by another reference.

  3. (Sect. 18) Why can't I get String mutator methods to work?

    * Code like this seems to show that the calls don't work!

    
          String s = "  hello  ";
          s.trim();
          s.toUpperCase();
        
    Note again that Strings are immutable. This means that once a String has been initialized, its contents won't change. In the code above, the method calls return a different String with the desired alterations. But this new String is not assigned to anything, so the results are discarded. To see the changes, assign the results of the method call to the original String or to another String.
    
          String s = "  hello  ";
          s = s.trim();
          s = s.toUpperCase();
        

  4. (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 parseDouble and parseFloat methods were introduced in JDK 1.2.
    
        float f = Float.valueOf(my_str).floatValue();
        double d = Double.valueOf(my_str).doubleValue();
        

  5. (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.

  6. (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();
        

  7. (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.

  8. (Sect. 18) How do I execute a command in my program?

    * 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. If the pathname contains spaces, e.g. "c:\program files\windows\notepad", then enclose it in quotes within the quoted string.

    From JDK1.3 there are two new overloaded Runtime.exec() methods. These allow you to specify starting directory for the child process.

    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.

  9. (Sect. 18) How do I do I/O redirection 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());
            }
        }
        } 
        

  10. (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.

  11. (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.

  12. (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

    A better approach is to remove the cyclic dependency by redesigning the class structure, or using interfaces.

  13. (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.

  14. (Sect. 18) How do I manipulate bits in Java?

    * Use bytes, shorts, chars, ints or longs if you need to manipulate no more than 64 bits at once. Use ~ for NOT, & for AND, | for OR, and ^ for XOR. Beware that the precedence for & | and ^ is not intuitive; they have lower precedence than == and !=, so you must write:

          if ((a & 1) == 1)
    
    rather than:
          if (a & 1 == 1)
    
    You can also shift bits with the <<, >> and >>> operators; >> is a signed shift and >>> is an unsigned shift. If you use bytes or shorts, beware that they will be sign extended to ints when they're used in operations. Thus, in the code
          byte b = (byte) 0x80;
          short s = (short) (b | 1);
    
    the result in s is 0xFF81 instead of the expected 0x0081. The easiest way to convert a byte or a short to an without sign extension is to AND with 0xFF or 0xFFFF. If you need to manipulate more than 64 bits, you can use arrays of booleans, ints, or longs. Beware that arrays of booleans are inefficient, as they take one byte of storage per bit. Alternatively, you can use the java.util.BitSet class.

  15. (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.

  16. (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 and it keeps running. 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 will skip over.

  17. (Sect. 18) How can a 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.

  18. (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" );
        

  19. (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).

  20. (Sect. 18) How can I get a globally unique ID in Java?

    * The only way in pure Java to create globally unique ids is to set up a server, accessible by all interested parties, which supplies the ids.

    There are classes in Java which may supply 'probably' unique ids, with varying levels of reliability --- but a dual processor machine with two JVMs running could easily generate duplicate ids.

    Note that a global server issuing a token (and periodic "are you still using it" messages) is a pretty good way to do cooperative file locking too.


19. Java Technology 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 the Java programming language.

    See also the list of 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 API.

    JFC has a JFileChooser class that is a better bet for you to use for file dialogs.

  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)!
    Example: the substring of 'xabcdef' from 1..3 is 'ab'
    Char 'a' is at position 1 in the String, and 'b' is at 2, which is 3-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 endIndxPlusOne. But not the confusing and misleading endIndex. Beware of 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 the question about "When I initialize a component,I call MyComponent.getImage() to get its image, but createImage() returns null!"

  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

    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 technology-enabled window frame, it doesn't close!

    * This happens with a java.awt.Frame. The best answer is to use a javax.swing.JFrame where closing is the default behavior. If you have to stick with Frame, 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 the font metrics into account:

    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:

    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, "Center" is assumed. You could change the add to

    myframe.add( new Label("Child"), "Center" );
    

    to be explicit.

  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 [JLS section 3.10.5 "String literals - or, more generally, strings that are the values of constant expressions (§15.27) - are "interned" so as to share unique instances, using the method String.intern (§20.12.47).]

    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 (pre-JDK 1.3)?

    * If you wish to Serialize a string, be alert to the restriction that:

    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. This limitation was removed in JDK 1.3

  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.

  25. (Sect. 19) What resources must be explicitly managed?

    * Although Java will automatically manage your memory use, there are certain non-memory resources which you need to explicitly manage. In particular, if you do not keep track of the following OS resources, and free them up when no-longer in use, your program may well slow down or stop.

    These need to be close()'d or dispose()'d as soon as they are no longer in use. There is the same rule as for C memory management: whenever you allocate one of these, you must also write the matching deallocation statement or you have created a resource leak. The Graphic object is particularly prone to not having a matching dispose() written.

    There are also dispose methods for ComponentPeer and MenuComponentPeer, but you only need worry about those if your code allocates them.


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://hem.passagen.se/carebear/fraggame.htm 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. If you do it at work, 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:

    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.tardis.ed.ac.uk/~skx/java/Shell/

  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.quateams.com/oro.
    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 programming langauge 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 technology? Preferably platform-neutral ones.

    * There are several possibilities.

  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 programming language and Javascript, written in the Java programming language!

    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 programming language for my Palm Pilot PDA?

    * In the June 1999 JavaOne conference, Palm Pilot V's were available with a small JVM known as KJava installed on them. KJava was an early access release, and is expected to become generally available later in 1999. This is an astonishing piece of work as the Pilot has such a small memory footprint.

    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 technology 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 are the biggest people behind UML, and 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 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 technology 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. Adobe supplies the client (document reading) software for free. There is a PDF toolkit written in the Java programming language 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 search tools?

    * IBM has a very good search engine for 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 programming language uses the same endianness as RPC's external data representation (network byte order), so all the Java technology file reads/writes can be used directly.

    Netbula recently released Java RPC, a fully compatible port of ONC RPC to Java technology. The binary package can be downloaded for evaluation from http://netbula.com/javarpc/

    See also http://www.nc-labs.com

    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 code.

  20. (Sect. 20) Is there any information on XML and Java programming language?

    * Yes. See http://developerlife.com
    It shows you how to use:

    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

  24. (Sect. 20) Are there any Java tools for improving source reading?

    * Java programmer Jason Shattu has released Java2HTML Tool which is a simple-to-use tool which converts Java Source Code into colorized and browsable HTML. You can find the details at http://www.vaegar.f9.co.uk/java2html.html

    The Java2HTML tool has many features, and was JARS rated in the top 25%. Take a look and check it out for yourself!

  25. (Sect. 20) Where can I find the Macintosh Java FAQ?

    * The FAQ for Java on the Apple Mac is at http://www.outlawcafe.org/MRJ-FAQ/


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!

Entire document is copyright 1997, 1998, 1999 by Peter van der Linden.


I am maintaining a FAQ list to address specifically programming issues
(not a general tutorial on the Java programming language). 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,2000 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.


Go to the Index