These items below are listed pretty much in the order that they were troubling my java development efforts. It's said that smart people can learn from their own errors, but a genius can learn from the mistakes of others. Here's you chance to exercise your genius and learn from my errors.
When I have encountered and solved a java puzzle, I write up the problem and its solution here. May this list save you a bit of time, I've got quite a few hours in figuring out how to do these things!
To ameliorate the disorderliness of the entries, use your browser's find function to search for whatever's bothering you.
Compiling java code.
I have found that it's nice to have all of your classes in a single directory
during development. Once you deliver to a customer, you of course should
package everything nicely into a jar file, but while you're putting things
together, it's nice to take advantage of Java's ability to put everything into a
single directory:
javac -d /my/class/directory/ myJavaSource.java
The above command places the myJavaSource.class file into the
/my/class/directory/ directory. All you then need to do is have
/my/class/directory/ in your CLASSPATH environmental variable, and java will
have no trouble finding it.
As an aside, most current Java IDEs will handle these details for you, and if
you're stuck with nothing better than a Windows system to work on, you should
take advantage of the IDE. Unix, however, is its own IDE, and most IDE
functions are contained within its many commands.
To position an initial window in Swing:
JFrame frame = new JFrame("SwingApplication");
frame.setBounds(100,100,200,200);
// This places the window at 100,100 on the screen, and makes it
// 200x200 pixels in size.
The setPreferredSize method seems to have no effect.
To display an integer as hex:
int exponent;
String exp;
exp = Integer.toHexString(exponent).toUpperCase();
System.out.println("The exponent is " + exp); To capture keyboard input:
// The following snippet reads a byte (single keystroke) from the keyboard:
import java.io.*;
class myClass
{
public int myMethod() throws IOException
{
java.io.BufferedReader in =
new java.io.BufferedReader(new InputStreamReader(System.in));
String s = in.readLine();
}
}Where is servlet.jar?
Your java server pages (JSPs) and servlets will not work without J2EE's
servlet.jar and jsp.jar. When you download the latest versions of J2EE (sun
now calls it Java EE), these jars are nowhere to be found.
Sun has renamed them to servlet-api.jar and jsp-api.jar. I use the
ones in my Tomcat distribution, which are in
/usr/local/tomcat/common/lib/servlet-api.jar and
/usr/local/tomcat/common/lib/jsp-api.jar
on my server.
When running a project, all references to executables
must contain the fully qualifed project URL, e.g.:
java myProject.Class
java Class
javac MyClass.java
java myPackage/MyClassDebugging an applet
To debug an applet, run it under appletviewer, not a browser. Any run time errors will be reported by appletviewer, whereas the browser is generally silent.
Configuring JFrame
When configuring a JFrame, many properties must be set by using:
f = new JFrame();
f.getContentPane().setLayout(new GridBagLayout());
f.getContentPane().setBackground(Color.BLUE);
f.setLayout(new GridBagLayout());
f.setBackground(Color.BLUE);
Importing jar files
When using classes from a jar file, first do a jar -tf jarFile.jar, and ascertain the path in each of the classes that you need to use. This, and not the jar file itself, is the import statement used at the beginning of your .java file to use the class.
Invisible components
If a component (e.g. JLabel) does not show up when properly added to a frame or panel, call the setOpaque method and set it to true: myLabel.setOpaque(true);
Null pointer to a Graphics object:
Before you can get the Graphics object of a component, it must be installed into the panel where it will live, and that panel must be set visible, or the Graphics object will be null.
Setting up a $CLASSPATH:
Each directory specified must end in a slash.
/myJava/classes won't work, while /myJava/classes/ will.
Jar files must be spelled out explicitly.
/myJava/classes/ won't pick up the jar files in the directory.
You must use:
/myJava/classes/myJarFile.jar.
Jar files are not followed by a slash.Setting up multidimensional arrays of objects:
It's not enough to declare and size the array:
Item[][] myItems = new Item[5][5];
You must initialize them, too:
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
myItems[i][j] = new Item();
}
}
Using objects instantiated in try/catch blocks outside of the block.
Declare the object outside of the try/catch, and set
it to "null" (set Strings to""). The
instantiated object can then be used outside of the try/catch block.
Regular expressions in java
When escaping meta characters in java, you need 2 (count'em: two)
backslashes before the meta character for the pattern compilier to
correctly recognise the character, e.g.: to find a question mark:
Pattern p = Pattern.compile("\\?");
A FileInputStream anomaly.
The read(byte[] b, int off, int len) method is a bit of a misnomer. As written, one would expect it to read len bytes into byte array b starting at byte off in the file you're reading.This is not the case.
What really occurs is that len bytes are read into array b at location off in the byte array, not the file. Use RandomAccessFile instead.
Bit busting in Java.
Java's lack of unsigned integers makes bit busting in the language a real
pain. Here's how you read in floating point numbers, say from the output
of a C program, and translate them into Java floats:
byte note[] = new byte[sizeOfBuffer];
int tc;
...
for (i = 0; i < 4; i++)
{
if (note[i] < 0)
{
byte b = (byte) ((int) note[i] & 127);
tc += b << (i * 8);
tc |= (1 << ((i * 8) + 7));
}
else { tc += note[i] << (i * 8); }
}
float a = Float.intBitsToFloat(tc);
Accessing variables in main, anonymous classes, etc.
Main and most anonymous classes will not access variables outside of their
boundaries.
This is one royal pain until you learn the trick, which is all too often
obfscutated as it is so apparent to those in the know that they forget
to mention it.
Use accessor methods. To get the value of variable bozo, your class has
an accessor method for bozo:
public int getBozo() { return bozo; }
This can be called by your internal classes to get the variable.
BTW this technique is the reason that all Java beans require accessors
for all variables that might ever be used by a calling method.
Hashtables must have Objects as their
keys and values. Primitives, like int and double, won't work.
Jars
To list the contents of a jar file: jar tf jelly.jar To extract the contents of a jar file: jar tx jelly.jar
A cross-platform line end token.
The end-of-line marker is 10 in unix, 13/10 in windows, and 13 in the world of mac. How do you get text to reflect this in Java?
String end = System.getProperty("line.seperator");
Use this string instead of the usual "\n", and the JRE will figure out which line end to use on the platform the code is running on.
A bit busting bug.
Using java's bitwise functions produces erratic results:
return (buffer[i + 1] << 8) | buffer[i];
Using its arithemetic functions produces the correct results:
return (buffer[i + 1] * 256) + buffer[i];
If you're doing a lot of bit busting, you should really be using C, perhaps
with native methods to interface it to a larger java procedure. Java just
doesn't do this very well.
Drawing to a specific component
To draw in a component, build a drawComponent (Graphics g) method in a
class which extends the component's class. This can be the only method
in this class, but it allows Java's drawing routine to identify which
component to paint.Getting the graphics environment, for later drawing.
A graphics object, such as a JFrame or JPanel needs to be made visible *before*
you try and access it. This code:
g = jpnl.getGraphics();
f.pack();
f.setLocation(50,50);
f.setSize(winSize, (winSize + (winSize / 8)));
f.setVisible(true);
Will result in g being a null pointer. Instead, put the getGraphics call after
setting visible to true:
f.pack();
f.setLocation(50,50);
f.setSize(winSize, (winSize + (winSize / 8)));
f.setVisible(true);
g = jpnl.getGraphics();
Note. Setting the size of a component must also be done *AFTER* the component
has been rendered visible, just like the getGraphics command.
Here jpnl is a JPanel within a JFrame f, and G, of course, is a Graphics
environment object.
A collection anomaly
So far, this one has only been verified on ListArrays, but I suspect that it
might be just as nasty for the other collections that allow you to have several
identical members.
MyObject mo = new MyObject();
ListArray la = new ListArray();
...
for (int i = 0; i < numItems; i++) {
...
la.add(mo);
}
The above code won't work as expected. Everytime you add your object, mo,
every item in you list, la, is set to the last item you added. You need to add
another line:
for (int i = 0; i < numItems; i++) {
...
la.add(mo);
mo = new MyObject();
}
This fixes the problem, as mo is assigned a new address and Java's hidden
pointer that references your objects in ListArray is changed, allowing your
multiple entries to be the ones you expect, instead of the last one added.
Displaying graphics in an application at startup.
This one was subtle, and more than one Java Guru went down in flames trying to solve it, and I spent more than a year, off and on, before I found a solution.
The following code snippet attempts to set up a Java window, but all it produces is a blank frame.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Blank {
JPanel p;
public Blank() {
JFrame f = new JFrame("BlankFrame");
Dimension d = new Dimension(200, 200);
p = new JPanel();
p.setOpaque(true);
f.getContentPane().add(p);
f.setLocation(50,50);
f.setSize(d);
f.setVisible(true);
}
/* This is never even called.*/
public void paintComponent(Graphics g) {
g.setColor(Color.white);
g.fillRect(0, 0, 200, 200);
g.setColor(Color.black);
g.drawLine(0, 0, 190, 170);
g.drawLine(0, 170, 190, 0);
System.out.println("Lines drawn.");
}
public static void main(String s[]) {
Blank b = new Blank();
}
}
What is needed is a class that extends JPanel (or whatever component you
want the use) which has the
public paintComponent(Graphics g)
method overidden. The new paintComponent does your drawing for you. The
default, in JComponent, just blanks the panel. Because class Blank does not
have the paintComponent method in it's ancestry, (it's a simple object), this
is not called, but the paintComponent for JPanel is, blanking the frame. Here's
the same code, "refactored" a bit to display the graphics:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Plot {
public Plot() {
JFrame f = new JFrame("GraphicsDemo");
Dimension d = new Dimension(200, 200);
Pad p = new Pad();
f.getContentPane().add(p);
f.setLocation(50,50);
f.setSize(d);
f.setVisible(true);
}
public static void main(String s[]) {
Plot q = new Plot();
}
}
/* The drawing has to occur in a separate class. */
class Pad extends JPanel {
public Pad() {
Dimension d = new Dimension(200, 200);
setPreferredSize(d);
}
// Note this is called 3 times as the frame is set up.
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.black);
g.drawLine(0, 0, 190, 170);
g.drawLine(0, 170, 190, 0);
System.out.println("Lines drawn."); //TEST
}
}
Embedding an applet in an HTML page.
If you want your applet to appear as if it was part of an HTML page,
utilize the fact that Applet (and JApplet) inherit from Panel. Instantiate the
page in Panel, as opposed to placing it into a Frame (or JFrame). If you place
it into the frame, the applet will come up in a separate window, which might not
be what you wanted.
Finding the size of your screen.
By screen I mean the monitor/terminal you're running on. Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
String pattern matching foolishness
The boolean String method matches("Your regular expression here")
ONLY returns true if the ENTIRE string is matched.
A real comedown from perl's superb regular expression engine.
Importing a package
In specifying a package, the fully qualified class name must be used. This is the group of subdirectories off of a node of your $CLASSPATH. Having :. as the last node of the $CLASSPATH does not seem to help.
Constructors do not have return types.
// This will confuse the compiler:
class public myClass
{
public void myClass
{
// Here we construct myClass.
}
}
// This is correct:
class public myClass
{
myClass
{
// Here we construct myClass.
}
} Java packaging:
Each file should have only ONE public class in it.
The package name and directory name must be identical.
All classes in a given package must be in that directory.
All these classes have, as their first executable statement:
package Package_Name;
(Package_Name is the name of the package.)
Write all of the classes, compile and test them before introducing the
"package Package_Name;" statement at the top of each file. The compiler
gets confused when non members try to access package members.
Unless the Java program which accesses the methods in a package is
a member of the package, you'll have to import it just as you would any
other package:
import Package_Name;
If you have a package named:
myJava.mySource
that is kept in directory /home/myRoot/myJava/mySource,
and class myClass (original names, don't you think?)
Your class path should have /home/myRoot/ in it, but /home/myRoot/myJava/
or /home/myRoot/myJava/mySource/ will not find your class. This can be
quite puzzling, until you figure out Java's arcane way of directory
specification.
Iterating over an ArrayList, and changing the contents of
some of the list members
This should be easier and more general. If you know of a cleaner, more
general way, please email it to me!
import java.util.*;
public class IterateOverCollection {
ArrayList al;
public IterateOverCollection() {
al = new ArrayList();
for (int i = 0; i < 10; i++) {
Integer j = new Integer(i);
al.add(j);
}
}
void changeMembers() {
Iterator i = al.iterator();
while (i.hasNext()) {
Integer j = i.next();
int k = j.intValue();
int h = al.indexOf(j);
k += 10;
j = al.set(h, k);
}
}
void printMembers() {
Iterator i = al.iterator();
while (i.hasNext()) {
Integer j = i.next();
System.out.print(j.intValue() + " ");
}
System.out.print("\n");
}
public static void main(String[] args) {
IterateOverCollection ioc = new IterateOverCollection();
ioc.printMembers();
ioc.changeMembers();
ioc.printMembers();
}
}
JTextArea (and other similar components)
Simply creating a JTextArea object and adding it to a panel or frame is not enough. You need to size the object as well for it to display:
JTextArea ta = new JTextArea("Some Text");
ta.setEditable(false);
ta.setSize(800, 800);
Regular expressions with capture.
Regular expressions in Java are a nice addition to the language. They are
poorly documented (but so are everyone elses) and akward (compared to Perl) but
they are, as I just said, a welcome addition. Examples, especially with
capturing part of the expression, are hard to come by, so I include one here:
import java.util.regex.*;
public class RegexDemo {
public static void main(String[] s) {
Pattern p = Pattern.compile("\\w+(ing)");
// Parse through the input strings.
for (int i = 0; i < s.length; i++) {
Matcher m = p.matcher(s[i]);
if (m.find()) {
System.out.println("The " + m.group(1) + " word " +
s[i] + " was found.");
} else {
System.out.println(s[i] + " does not have \"ing\" in it.");
}
}
}
}
When you run it, you should get something like this:Iterating through an array of collection, new style.
This is so much nicer than having to set up an iterator or enumerator and calling hasNext and next until you're done...
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for (int numeral : numbers) {
System.out.print(numeral + " ");
}
System.out.println("");
Initizalition of components in a JFrame.
This is a weird one. In a window with a number of components such as JLabels, JButtons, etc, I initialized a class I built from a JPanel last. The class never displayed itself. When I instead, initialized it first, up it came. I seems that Java, once it has initialized on of its "built in" classes tends to ignore the others. I had set layout to null in both the JFrame and class derrived from JPanel.