I spoke on this topic in 1997-11 at the Colorado Summit Conference and again in 1999-11.
Inconsistent Extensions | ||
---|---|---|
Where | Extension Mandatory? | Example |
compiling | mandatory | CD \MyDir javac.exe -classpath . HelloWorld.java |
executing | must exclude | CD \MyDir java.exe -classpath . HelloWorld |
Applet | mandatory | <applet code="HelloWorld.class" width="230" height="240"> <img src="image/NoJava4U.jpg"> </applet> |
C/C++ programmers will attempt to write code like
if ( width ) { widen( width ); } if ( myDog ) { myDog.bark(); }You need to spell these out longhand in Java :
if ( width != 0 ) { widen( width ); } if ( myDog != null ) { myDog.bark(); }
However, for
if ( tooWide ) { widen( width ); }
Beware, you
if ( tooWide = true ) { widen( width ); }Note: that the = above is an assignment operator, not an == comparison operator. The if is always true.
C programmers are familiar with this, but those coming from languages designed by Professor Wirth will gasp in astonishment
switch ( k ) { case 1: out.println( "hello" ); case 2: out.println( "hi" ); }When k is 1, the program will print out both hello and hi. Case clauses fall though by default. You won’t get a syntax error or even a warning if you leave out the break after each case.
Because the syntax for defining cases and labels is so similar, it is easy to make an error like this: The programmer left out a space and, instead of handling n == 3, he defined a goto label called case3 in his switch statement.
In Java version 1.4 or later you can use the javac.exe -Xswitchcheck to get the compiler to warn you if you do this. However, there is no syntax to tell Java when you meant to do it deliberately, e. g. a break case or fallthru keyword.// String.replace produces a new String. It does not modify the original. // Since String is immutable, no method can modify the original. String aa = "peal"; String bb = aa.replace( 'a', 'e' ); out.println ( aa + " " + bb ); // Prints "peal peel" not "peel peel" // Newbies often expect String aa to be changed too.String. replace does not modify the input String. It could not, even if it wanted to, since Strings are immutable. Further, the Javadocs for replace explain that replace creates a new String.
// OOPS, DON'T DO THIS! component.setFont( new Font( "Dialog", 12, Font.BOLD )); // do this instead: component.setFont( new Font( "Dialog", Font.BOLD, 12 ));
Font.createFont produces a font 1 point high, too tiny to see. You must use Font. deriveFont before you can use it.
You need to treat primitives as objects for another purpose — so that you can put them into containers such as ArrayLists or Vectors. In Java, you must manually wrap your primitive up in an object. Sun provides a set of immutable object wrapper classes called: Byte, Short, Character (not Char), Integer (not Int), Float and Double, the very same classes that house your static methods for fiddling with primitives! It might have been clearer had they called these classes names like ImmutableByte or ByteWrapper, but they didn’t. You can’t change the value of the primitive inside any of these wrapper objects. All you can do is create a new object with a new immutable primitive sitting inside.
To make matters all the more confusing, the Double class then has double duty, to deal with both double primitives and Double wrapper objects. The instance methods for Double manipulate Double objects and the static methods for Double manipulate double primitives. These methods naturally have similar if not identical names! The same problem occurs for all the other primitive/class pairs, but most newbies seem to trip over it first with
double d; /* double primitive */ Double dd; /* Double wrapper */ String g; g = Double.toString( d ); /* double primitive */ g = dd.toString(); /* Double wrapper */See the conversion for help in interconverting the various primitives and wrappers.
With the default toString, you just get the class name and hashCode of the object, which looks like gibberish, e.g. [C@ad3ba4.
char[] c = { 'a' , 'b' , 'c'}; out.println( c.toString() );will print out the address of c, not the characters that compose it. You must use newString ( char[] ) to convert a char array to a String.
Label.toString() is not an alias for Label.getText(). It will print out a summary of the Label fields like this: java.awt.Label[label0,0,0,0x0,invalid,align=left,text=def]
How then do you convert to String? With a hodgepodge of techniques that rival French verbs for irregularity.
String x = "foo" + 's';In Java version 1.6 or later, x is foos. In early Java version 1.2 it is foo115, but was fixed for the release version.
Even though a constructor is similar to static method that returns a new object, you may not declare the constructor static. It is not static, since it works on specific default object. this is defined in the constructor.
If you do any of these things, the compiler will think your constructor is just an ordinary method. You will be baffled by the compiler’s complaints that you have not defined a suitable constructor to match the arguments you provide.
It may help if you realise that new allocates/creates the object and the constructor initializes it. Therefore the constructor has no need to return an object.
If you don’t provide any constructors at all, Java will automatically provide you with a default constructor
public MyClass() { super(); }However, if you get ambitious and write an extra constructor, say like this:
private MyClass( int fudgicles ) { this.fudgicles = fudgicles; }The default constructor will disappear! You have to then provide it yourself explicitly.
You will most likely come across this problem when you see the following error message:
In English, it means you are missing the default public constructor for your Applet. See constructor.
The new hex Unicode technique \u003f has a catch. It is not suitable for encoding control characters. It is evaluated in a pre-processor pass and converted to a character, then the code is compiled. If for example you wrote \u000a, this gets converted to:
" "Since the \u000a gets converted to a newline character. It definitely won’t work for Cr and Lf. It might work for some of the other control chars in some compilers. I suggest using the octal forms for safety.
Every
double x = 90; double y = sin( x ); double z = tan( x + PI );And stares and stares at it wondering why it won’t work. You need to write it this way:
// converting degrees to radians, manually. static final double CONVERT_DEGREES_TO_RADIANS = Math.PI / 180; double x = 90 * CONVERT_DEGREES_TO_RADIANS; double y = Math.sin( x ); double z = Math.tan( x + Math.PI );There are three places to trip up:
// built-in radians <-> degrees methods. public static double toDegrees ( double angleInRadians ); public static double toRadians ( double angleInDegrees );
Further, every time you do a floating point calculation you loose a little precision. It all adds up.
In Java 5.0 you no longer need the Math. in Math. sin() so long as you add an import like this:
import static java.lang.Math;
// beep on the PC speaker by sending a BEL character to the console out.print ( "\007" ); out.flush();It ignores '\a' in console output, though you can use \007 to get the BEL.
You can make a simple beep with Toolkit.getDefaultToolkit().beep() . I have seen reports that beep does not work properly on some platforms.
// beep via the console out.print ( "\007" ); out.flush(); // beep via toolkit Toolkit.getDefaultToolkit().beep();You can also play AU, wav, midi and aiff files with AudioClip.play.
You might look a long time through java.io.* trying to find the directory operations, before you find them hiding in the File class e.g. list a directory to find out the files
File dir = new File( "C:\\" ); String[] files = dir.list();
won’t
File dir = new File( "C:\\." ); String[] files =dir.list();Be aware that \ in Java Strings has to be written as \\.
This makes reading Strings representing filenames confusing. Unix systems use the / path separator character instead of \. Macintoshes use : and have interesting twists like :: for up instead of /../ as in Unix. To write platform independent code, you should use the system properties file.separator and path.separator, or use the File methods that construct filenames for you from parts.
Then
File[] roots = File.listRoots();
for : pronounced for each is a shorthand extension to the regular for. It lets you iterate over Iterators, Collections and arrays with a terse syntax. However, it will not let you iterate over the characters of a String or let you access the index the way you do with a regular for, just the values. Look at the following example to see what I mean:
for ( long i=Long.MAX_VALUE -2; i<=Long.MAX_VALUE; i++ ) { /* ...*/ }How many times will that for loop execute? Until you kill the process! It will loop endlessly because i can never get bigger than Long.MAX_VALUE to terminate the loop. There are similar problems with Integer.MAX_VALUE, Long.MIN_VALUE and Integer.MIN_VALUE. You get used to thinking of the upper limit as the logical stopping point, where canonical for loops actually stop on one past that value. The reason the loop does not terminate is Java integer arithmetic allows overflow as normal. The reason for this is most hardware behaves this way and much bit fiddling would be overly complicated if overflow threw exceptions. You can handle detection of numbers getting too big with an assert, which catches the problem long before they get close to overflowing 32 or 64 bits.
You might inadvertently try writing some code like this:
String lower = String.toLowerCase( upper ); // should be String lower = upper.toLowerCase();
The compiler will complain about incompatibility with the Locale type. What is going on? You have inadvertently used the String.toLowerCase( Locale locale ) method. What you meant to use was String.toLowerCase(). String. was taken to mean this.
Take a look at the source of java.lang.String.toUpperCase(). You might expect it to contain
if ( 'a' <= theChar && theChar <= 'z' ) theChar -= ('a' -'A' );However, you will discover the code is quite elaborate. For example, it tests if the current locale is Turkish to call special code to cope with the dotless i. It tests for the German ß and converts it to a pair of letters SS ! If you are only working with English, you might want to roll your own more streamlined version. If you take a string to lower case then back to upper case then back to lower case, you won’t necessarily end up where you started.
In other languages, to extract a substring, you give an offset where the string starts and a length in characters. In Java, you provide two zero-based offsets. The first points to the start of the string as you might expect and
"abcdefg".substring( 3, 5 ) gives "de". "abcdefg".substring( 3, 7 ) gives "defg". "abcdefg".substring( 3, 8 ) gives StringIndexOutOfBoundsException.
If you specify offsets that are outside the span of the string, you don’t get a truncated or null string; you raise a StringIndexOutOfBoundsException. One way to remember the way it works is that you specify the first character to include and the first character to exclude. But not quite. You are allowed to be just barely past the end.
"emptiness".substring( 9 )returns "" (an empty string)
"emptiness".substring( 10 )gives a StringIndexOutOfBoundsException
Why do it this way?
Then:
s = "APPLE".substring( 1, 4 ); // gives "PPL". s = "APPLE".substring( 3, 3 ); // gives "". s = "APPLE".substring( 0, 5 ); // gives "APPLE".Beware of using substring with only one argument.
String tail = x.substring( endindex );
gets you the tail end of a string starting at endindex. It does not get you the beginning
head = x.substring( 0, length );gets you the first part of the string, the first length characters.
When you divide by zero with double, take the square root of a negative number, overflow the maximum representable value etc. the result is a magic number called Double.NaN, Double.POSITIVE_INFINITY or Double.NEGATIVE_INFINITY. You
if ( Double.isNaN( d ) )
or with Double.isInfinite . You can’t test
if ( d == Double.NaN )
Because there are two different flavours of NAN, Double.POSITIVE_INFINITY and Double.NEGATIVE_INFINITY You can’t directly compare == Double.NAN to check for NAN. However, you can directly compare == Double.NAN; However, you can use Double.isNaN or == to compare with Double.POSITIVE_INFINITY. There is a corresponding Float.NaN and Float.isNaN The theory is making NaN not equal to itself allows a quick and dirty way to test for a calculation going haywire.
if ( result != result ) { out.println( "oops" ); }
Beware
The problem is StringBuffer.equals checks if two references point to the same StringBuffer, something you almost never want to do. StringBuilder has the same gotcha.int[] intArray = null; String.valueOf( intArray ); // produces the String "null" char[] charArray = null; String.valueOf( charArray ); // throws NullPointerException
final Thing thing = new Thing( 7 ); thing = otherThing; // generates a compiler error thing.setSize( 10 ); // ok thing.girth = 6; // okThis also applies to parameters declared final.
Watch
IBM (International Business Machines) ’s BigDecimal and Arcimath BigDecimal have provisions for detecting overflow and generating an exception. You can roll your own with code like this in standard Java.
or
If you know both values are positive, you can use a simpler overflow check. You could check if the sum is less than 0 or less than one of the two operands. I’m not sure if this catches all overflows, however.
Floating point arithmetic uses the IEEE (Institute of Electrical & Electronics Engineers) error propagating scheme similar to that used in a spreadsheet to propagate invalid value flags to cells that depend on invalid values. In Java, though there is no overflow interrupt or notification, there is a good chance you will eventually find out about an overflow error when you see a java.lang.Double.POSITIVE_INFINITY, java.lang.Double.NEGATIVE_INFINITY or java.lang.Double.NaN showing up in one of your double variables. You can’t use == to test for NaN , you must use java.lang.Double.isNan().
Back when the earth was still molten, when characters still had only 7 bits, somebody thought it would be a good idea if characters were signed. This caused a schism in the C world when 8-bit characters later appeared. Java added unsigned 16-bit Unicode characters, but decided to support only signed 8-bit characters, known as bytes. Perhaps Java’s designers wanted to encourage migration to Unicode by making handling unsigned bytes awkward. In any case, you most often want unsigned 8-bit characters, not signed.
int i1 = b2 & 0xff; byte b2 = (byte)( b2 + 1 ); byte b3 = b2;
You cannot say:
since Comparable is only an interface. The run time needs a specific class to construct an Object. An interface does not have a constructor.
However, you can say:
All that gets constructed is an block of 10 null pointers. No Objects with the Comparable interface are constructed.
However, you cannot say:
Because of the cheesy way Java implemented generics, they are incompatible with arrays. The excuse is it has no way to record the generic information associated with array.
Floored division is what you normally want when trying to figure out which bin an item belongs in. You can
For computing how many fixed-size bins you need to contain N items, you want ceiled division, also known as the covered quotient. You can compute the covered quotient as:
Inconsistent Signs | ||
---|---|---|
Signs | Division | Modulus |
+ + | +7/+4=+1 | +7%+4=+3 |
- + | -7/+4=-1 | -7%+4=-3 |
+ - | +7/-4=-1 | +7%-4=+3 |
- - | -7/-4=+1 | -7%-4=-3 |
static { calcPriceTab();}Newbies just stick such code anywhere inside the class { } sandwich and are baffled by the misleading error messages.
The order of your variables that are statically initialised matters. Consider this little program:
The output with Java 1.4.1 was no compile error and 61 0 61, YMMV (Your Mileage May Vary)The order of those three static finals is crucial to the results! You must put them in the order you want the calculations done. Java is not smart like a spreadsheet to do natural order recalcs for you. It will notice and either handle or reject such forward references when only literals and simple variables are involved, but as soon as you do things inside methods, it throws up its hands and says on your own head be it.
The advantage of putting it on the declaration is that you need to specify it only once, not once for each constructor. This means there is less likelihood of error if its value is ever changed. The other safe approach is to put all your initialisation code in one method or one constructor and have all the constructors call it.
However, there is one particularly tricky problem with initialisation order. In general you must avoid calling any non-final methods in a constructor. The problem is that instance initialisers / variable initialisation in the derived class is performed after the constructor of the base class. This can cause a problem if the base class constructor calls a method polymorphically, since that method will be presuming its derived class fields have all been initialised when they have not.
So base class constructors can safely call private or final methods of the base class provided those methods directly or indirectly call only private or final methods of the base class. If you call methods in your constructor polymorphically, the compiler will not stop or warn you of the initialisation pitfalls awaiting.
There are four sorts of cast:
byte b = -42; int i = (int)b;This cast is nugatory, though you might want to use the cast as a documentation aid. It does some conversion work — sign extension.
int i = -16411; byte b = (byte)i;
This style of cast actually may do some real conversion work — zeroing out high order bits.
Dog myDog = (Dog)aDalmatian;This cast is nugatory, though you might want to use the case as a documentation aid. All Dalmatians automatically have all the Dog fields, so this cast has no run-time overhead.
Dalmatian myDalmatian = (Dalmatian)aDog;At run time, this cast actually checks that aDog truly is already a Dalmatian, and raises a ClassCastException if it does not. It does not make any attempt to convert a Dog to a Dalmatian.
You might logically presume that casts are for converting one type into another. You might attempt code like
String s1 = (String) i; int i = (int) s2; String s3 = (String) myDalmatian;Yet casting only works for two primitives. When there is a primitive and an object involved, there is a system of conversion functions with about as much regularity as French verbs.
Cat c = null; Object o = c; Dalmatian d = (Dalmatian)o;In other words, there is one universal representation for null, not a special one for each class.
In contrast if ( null instanceof Dog ) is always false. instanceof does filter out nulls.
Dog fido = new Dalmatian(); int spots = (Dalmatian)fido.spotCount();Hint: What are you trying to cast to Dalmatian, the Dog fido or the int result of the spotCount method? When you are casting, you often need a forest of parentheses. This is what you should have written:
Dog fido = new Dalmatian(); int spots = ((Dalmatian)fido).spotCount();
(B)( ( (A)va.get( 0 )).b ).c = x;What does that mean? Get the first element of vector va (an Object), cast it to an A object which then, using field b, points to another object. Cast that object to class B. In that object is a String reference c that you want set to x.
That would be so much easier to read as:
In getting those ()((()()))) right, count +1 for each ( and -1 for each ). You should get back to 0 at the end and any place you think you should be outside all (). You should never go negative. In that case above you count:
The problem is the infernal mix of prefix, postfix and infix operators that Java inherited from C. (At least the goofiness of String x [] is sort of gone).
In a language with postfix casts and flatter precedence that might read:
Java uses the + operator to mean both addition and concatenation. Parsers can unambiguously figure out which your intent is from the context, but humans can be easily fooled. For example:
out.println(" x+y " + x+y ); out.println( x+y + " x+y " );
Which + are addition? Which are concatenation?
The way you most commonly get caught is code like this where the last + is treated as concatenation.
out.println( "value: " + v + 1 );
The concatenation operator has the magic power of being able to
implicitly coerce an int into a
String by automatically invoking the
static String Integer. toString(int)
method, however, oddly, you can’t do the same thing
explicitly with a (String) cast.
out.println( 'A' ); out.println( 'A' + 'B' );You might naïvely expect: A AB, or perhaps 65 131, however, the answer is: A 131.
The problem is Java’s design blunder of using + to mean both addition and concatenation. Addition also promotes to int, which println displays differently from char.
I really want this fixed. Concatenation should get a new operator symbol and using + for concatenation should be deprecated. The current scheme leads to code too easy to misread. + with int can mean either addition or concatenation. Deciding which depends too much on subtle context clues.
The symptoms of this gotcha are getting two ChangeEvents triggered where you would expect only one, or using removeChangeListener and events continue to arrive. The catch is you must call addChangeListener only once. If you call it twice with the same delegate, you will set up two Listeners each receiving a copy of each ChangeEvent. addChangeListener adds a second ChangeListener even if it is already added. Similarly, removeChangeListener just removes the first matching ChangeListener it finds, not the duplicates too. This applies to all types of Listener.
There are 10 common character handling types in Java
Ten Character Handling Types | ||||
---|---|---|---|---|
Type | mutable? | size in bits | signed? | Description |
String | immutable | 16 | unsigned | Unicode |
StringBuffer | Mutable both in value and size | 16 | unsigned | Unicode |
StringBuilder | Mutable both in value and size. Faster than StringBuffer, but only available in Java version 1.5 or later | 16 | unsigned | Unicode |
FastCat | Mutable both in value and size. Faster than StringBuilder when concatenating Strings rather than characters. Easier to estimate the size. | 16 | unsigned | Unicode |
char | mutable value | 16 | unsigned | individual Unicode character. |
Character | immutable | 16 | unsigned | Unicode character object. |
char[] | mutable value | 16 | unsigned | array of Unicode characters. |
byte | mutable value | 8 | signed | individual ASCII (American Standard Code for Information Interchange) char. |
Byte | immutable | 8 | signed | ASCII char object. |
byte[] | mutable value | 8 | signed | array of ASCII chars. |
UTF (Unicode Transformation unit) | immutable | 8/16 | unsigned | 16-bit length, 7-bit chars, multibyte codes for 16-bit chars with high bit on. |
Finally can be confusing. The finally keyword is Java’s answer to C++ destructors. In C++, when automatic objects go out of scope (even as a result of a thrown exception), the objects’ destructors are called in a well-defined order. Java has garbage collection and no destructors, so there needs to be some way to ensure that certain things happen before exiting the scope. finally lets you achieve this, but if you put certain kinds of statements in finally blocks, you can confuse yourself. The following
Also, the behavior of exceptions thrown from within finally blocks is not obvious.A rule of thumb is: never assume that JDK (Java Development Kit) objects are thread safe. Do not think, "Oh, I bet I can guess the implementation and it must be thread safe." For example, java.util.SimpleDateFormat is not thread safe, so things like this will cause strange formatting errors
For greater efficiency, you can often use a long or int and keep track of the scaling yourself and inserting a decorative decimal point on output.
BigDecimal is a travesty and deserves raspberries just like Date. Briefly, it is slow, it is difficult to use, it uses native methods and it quietly drops off significant digits during conversion.
Also, java.text.DecimalFormat. parse returns either a Long or a Double. There is no built-in way to define custom number formatting for BigDecimalor BigInteger objects.
Fortunately, IBM has made available its proposed replacement for Oracle’s class, which is 23 times faster, smaller, uses no native methods and implements standard ANSI (American National Standards Institute) X3.274 floating arithmetic. For the spec see: IBM’s Decimal Arithmetic For Java and AlphaWorks. Dirk Bosmans has implemented the IBM spec as ArciMath. Another implementation is PSPDec.
java.awt.Graphics.drawRect( int x, int y , int width , int height )
draws a rectangle one pixel bigger than the specified width and height. I am told if you understand the abstract drawing model the AWT (Advanced Windowing Toolkit) uses, it turns out this extra pixel is deliberate and unavoidable. The rationale is that you specify the path of an idealised box drawn with infinitely thin lines and the pen hangs down and to the right, at least one pixel thick.
All graphics routines expect x,y to represent the upper left corner of a bounding box. However, for Graphics.drawString() x,y refers to the to the baseline (which is distinct yet again from the lower left corner). This inconsistency is traditional in drawing packages. You need to
g.drawString( "Hello World" , 0, getFontMetrics(getFont()).getAscent() );
GridBagLayout will generate goofy layouts when components provide incorrect numbers for minimum and preferred size. For example TextFields don’t take into consideration setColumns or the size of the current font. All you can do is fudge using the ipadx and ipady parameters to inflate the minimum size.
GridBayLayout does not mind if you have a row or column with nothing in it. It will take no space. You might consider leaving some empty rows and columns in your layouts for future expansion.
weightx and weighty control where the extra space goes if the container is expanded. Think of them as percentages that don’t have to add up to 100%. They are automatically normalised. To figure out which column should get the most space, GridBagLayout examines each component in the column and looks at its weightx. It saves the biggest weightx of all the components in that column as the weight for the entire column. It does not average them, or add them. Then it proportionately assigns the extra space based on the column weights. The component with a lot of weight does not necessarily grow, just the column that component is in. Giving equal but non-zero weight to columns tends to equalize their size.
GridBagLayout does the same thing allocating extra space to rows by using weighty.
The Insets(top, left, bottom, right) can be used to build a border around a component. The four numbers are measured in pixels.
If you want to fix the size of some element, you must use all three methods: setMinimumSize, setMaxiumSize and setPreferredSize.
Make sure you supply some non-zero x and y weights in your GridBag. Otherwise when you squeeze the frame down too small the components will act as if they had infinite space and will scoot madly offscreen to the right.
If you use GridBagConstraints.BOTH, forcing fill, that will override any setMaximumSize you may have specified on your panel.
setVisible() calls the deprecated show(), the reverse of that you might expect. You would think the deprecated method should bear the speed penalty of another layer of indirection. Yet consider what happens if you write a new setVisible() method to override one of the built-in ones. Users of the original show() method will be unaffected. They will continue to use the old code. Only those who directly call setVisible() will use your new routine. Now, consider what happens if you write a new deprecated show() method to override one of the built-in ones. All works properly; everyone will use your new method. You are thus stuck writing new deprecated methods if you want your code to work properly.
Let us say the AWT were redesigned so that instead show() called setVisible(). Then old code that used the deprecated methods would suddenly stop working.
This problem is general and applies to all deprecated methods. Let us hope Sun will soon get rid of the deprecated methods entirely, then this problem will go away. Most of the deprecated names are just name changes to fit the JavaBeans get/set conventions. Such deprecations could be handled as pure aliases by translation to the new names inside the compiler and do away with the old classes entirely. However, that would cause a political problem of JDK 1.0.2 code no longer running under Java version 1.6 or later without recompilation or some translation process. You could not then have code that would run both under JDK 1.02 and 1.1. We would need to support the translation process in the JVM (Java Virtual Machine) to have old code automatically use the new names. Sun is very reluctant to make any changes to the JVM .
The JDK 1.0.2 event handling routines are also deprecated. It is quite a bit bigger job to convert those. They could not be handled by a simple alias.
int BufferedInputStream.read( byte[] m, int offset, int len )is advertised to block until some input is available. It returns the number of bytes read, or -1 for EOF (End Of File). You might erroneouslypresume that it blocks either:
int BufferedReader.read ( char[] m, int offset, int len )has a similar gotcha. You must use java.io.DataInputStream.readFully if you want to get all the bytes you asked for.
The read routine has another problem. It traps and ignores IOExceptions rather than passing them on to you. To get around both the above problems, you can use your own read routine like this:
For more elaborate code to deal with the problem download the com.mindprod.http package and download the com.mindprod.filetransfer package. You can also view some of the code at the http entry.I know of no method that will let you hide a component, that does not invalidate, thus leaving its space reserved, with no shuffling of sibling components.
The Dialog background gets reset when the dialog is being prepared for display, so your call to setBackground (or setForeground) in the constructor won’t have an
public void addNotify() { super.addNotify(); setBackground( Color.red ); }Add notify creates the peer object. You are hooking your code in right after the peer gets created.
You also need to explicitly control the background of each component. Inheriting it from the Dialog will just give gray.
One further warning. In JDK 1.0, the modal feature of dialogs does not work.
Until nio, there was no select() like functionality in sockets (or to be more flexible, in InputStreams) and there was no timeout in the InputStream.read() method. This makes it impossible to program a Socket server having a number of threads less than the number of users. However, I am told that if you use the available() method cleverly you can fudge it.
You have some control over timeouts with the networking system properties.
If you use an include for boilerplate headers and footers then you may get a ClassNotFoundException if the included JSP uses a custom class.
ASP (Active Server Page) developers are used to source code being dropped in by the ASP preprocessor and interpreted as one big file. According to this logic an import statement would be expected to appear at the top of the page, where most ppl declare variables and define functions are in ASP . However, in JSP, things tend to be split up and stay split up into many small files. You must thus make sure the import goes in each file that uses it, not just at the beginning.
See the table of error messages, now a separate document.
Unfortunately, the email addresses below are not clickable. Further, you cannot copy/paste them into your email program. You must manually re-type them. The email addresses are graphic *.png images created by Masker. I inconvenience you this way to discourage spammers from harvesting email addresses from the website with automated website spidering.
Contributors | |
---|---|
Tov Are | |
Paul van Keep | |
Mike Cowlishaw | |
Pierre Baillargeon | |
Bill Wilkinson | |
Patricia Shanahan | |
Joseph Bowbeer | |
Charles Thomas | |
Joel Crisp | |
Eric Nagler | |
Daniel Leuck | |
William Brogden | |
Yves Bossu | |
Chad Loder | |
Savas Alparslan | |
Simon Gibbs | |
Laurence Vanhelsuwé | |
Norman Paterson | |
Jonathan Finn |
recommend book⇒Java ™ Puzzlers: Traps, Pitfalls and Corner Cases | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
by | Joshua J. Bloch, Neal Gafter | 978-0-321-33678-1 | paperback | |||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
birth | 1961-08-28 age:56 | B001U5VJVS | kindle | |||||||||||||||||||||||||||||||||||||||||||||||||||||
publisher | Addison-Wesley | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
published | 2005-07-04 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
A set of 95 short programs that give astonishing results. When you understand them, you understand the quirkier features of Java. Bloch wrote much of the JDK class library. He also wrote the Effective Java Programming Language Guide | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Greyed out stores probably do not have the item in stock. Try looking for it with a bookfinder. |
This page is posted |
http://mindprod.com/jgloss/gotchas.html | |
Optional Replicator mirror
|
J:\mindprod\jgloss\gotchas.html | |
Please read the feedback from other visitors,
or send your own feedback about the site. Contact Roedy. Please feel free to link to this page without explicit permission. | ||
Canadian
Mind
Products
IP:[65.110.21.43] Your face IP:[3.135.200.121] |
| |
Feedback |
You are visitor number | |