This page is offered as a service of Bristle Software, Inc. New tips are sent to an associated mailing list when they are posted here. Please send comments, corrections, any tips you'd like to contribute, or requests to be added to the mailing list, to tips@bristle.com.
Last Updated: 9/5/2000
Applies to: Java 1.0+
Here are some of the differences between Java and C++:
| boolean | (Size not specified, but only 2 values supported: true, false) |
| char | 16 (Unicode) |
| byte | 8 |
| short | 16 |
| int | 32 |
| long | 64 |
| float | 32 |
| double | 64 |
| void | N/A |
for (i = 1, j = 1; i < 10; i++, j++) {...}
{
int i = 1;
{
int i = 2;
}
}
Java does not allow this. However, it does allow the following where the inner variable goes out of scope before the outer variable is declared:
{
{
int i = 2;
}
int i = 1;
}
ParentClass.method1()
ChildClass.method1()
In C++, these 2 calls would invoke different
implementations of method1 if it was not defined as a virtual method, and was implemented
by both classes.
MyParent::member1
Java uses the keyword super for this as:
super.member1
class MySubClass : public MyBaseClass
{
MySubClass (char* s) : MyBaseClass(s)
{
...
}
};
In Java, you call the base class constructor via the super keyword as:
class MySubClass extends MyBaseClass
{
MySubClass (String s)
{
super (s);
...
}
}
The call to super must be the very first thing
in the subclass constructor. It can't even be nested inside a try
block to catch exceptions.
class MySubClass : public MyBaseClass1,
public MyBaseClass2
{ ... };
Java allows implementation inheritance from only one base class:
class MySubClass extends MyBaseClass { ... }
However, you can accomplish a similar effect via
inner classes, as described in Multiple
Implementation Inheritance.
class MyBaseClass { ... }
interface Interface1 { ... }
interface Interface2 { ... }
interface Interface3 { ... }
class MySubClass extends MyBaseClass
implements Interface1,
Interface2,
Interface3
{ ... }
In this case, MySubClass automatically inherits
the implementation of the methods in MyBaseClass. However, it inherits only the
interfaces of Interface1, Interface2, and Interface3 -- it must explicitly provide an
implementation of each method declared in Interface1, Interface2, and Interface3, though
these implementations can also be inherited from MyBaseClass.
interface Interface1 { ... }
interface Interface2 { ... }
interface Interface3 { ... }
interface MyInterface extends Interface1,
Interface2,
Interface3
{ ... }
In this case, MyInterface is still an interface,
and so provides no implementation of any methods. However, any class that inherits
MyInterface is required to provide implementations of all methods from Interface1,
Interface2, and Interface3.
class MySubClass : public MyBaseClass { ... }
class MySubClass : private MyBaseClass { ... }
class MySubClass : protected MyBaseClass { ... }
Java offers only public inheritance. The syntax is:
class MySubClass extends MyBaseClass { ... }
public class Colors
{
public final static int RED = 1;
public final static int GREEN = 2;
public final static int BLUE = 3;
}
Note: An earlier version of this tip
recommended using an interface instead of a class.
This requires less typing, since all data members of an interface are automatically
public, final, and static. However, as Ken Swanson and Alex Blakemore pointed out,
you can't declare variables of an interface type. Therefore, the class approach is
better.
In Java, all member variables of classes and all elements of arrays are
automatically initialized to empty values like zero (numeric), false (boolean), etc. when
allocated. Local variables (declared inside a method) are not initialized, but any
attempt to use an uninitialized variable is caught at runtime.
class MyClass
{
int i = 0;
MyObject obj = new MyObject(57);
}
C++ does not allow this. It requires you
to initialize the variable with a separate statement in the class constructor, which is
typically in a different file from the class declaration.
For cases where the initial value is not so simple, Java allows you to embed an explicit block of initialization code among your member variable declarations, as:
int i = 0;
int j = 29;
int k;
{
if (i < j) k = j;
else k = i;
}
This code is executed for each instance of the class before the constructor is executed. C++ does not offer such a feature. Such code would have to occur in the class constructor.
static int i = 0;
static MyObject obj = new MyObject(57);
C++ does not allow this. It requires you to use a "static member initializer" statement. Such a statement cannot occur inside the class declaration, or the class constructor or any other method. It is typically in a separate file with the bodies of the constructors and other methods of the class. For example, the C++ static data member declarations in the .H file might look like:
class MyClass
{
static int i;
static MyObject obj;
}
and the separate static member initializer statements in the .CPP file might look like:
int MyClass::i = 0;
MyObject MyClass::obj = new MyObject(57);
As with non-static data members, Java allows you to embed an explicit block of initialization code among your static member variable declarations, as:
static int i = 0;
static int j = 29;
static int k;
static
{
if (i < j) k = j;
else k = i;
}
As with the static data member initialization clauses, this code is executed once for the entire class, not once per instance. It executes before any instance of the class is created and before the static data member is accessed.
C++ does not offer such a feature. Such code would have to occur in a separate
function called by the C++ "static member initializer" statement. Putting
such code in the C++ constructor doesn't work because the constructor can be called too
often (once per instance), too late (after the static data member is accessed), or not at
all (if the static members and methods of a class are used, but no instance is ever
created). The Java technique deals with all of these possibilities.
try
{
SetMousePointer();
DoSomeRiskyStuff();
}
catch (Exception e)
{
DealWithErrors();
}
finally
{
ResetMousePointer();
}
The code in the finally clause
is guaranteed to be executed. If the code in the try block runs to
completion, it executes after the code in the try block. If the try
block contains a return statement, it executes just before control is
returned to the caller. If an exception occurs in the try block, it executes after
the local handler (if any) that catches the exception. If an unhandled exception
occurs, or a handled exception is re-thrown, it executes just before the exception is
propagated to the caller. It can be used with or without a catch
clause, but requires a try block.
--Fred
Last Updated: 2/22/2007
Applies to: Java 6.0+
Java SE 6.0 was released in December 2006. For a summary of new features, see:
http://java.sun.com/developer/technicalArticles/J2SE/Desktop/javase6/beta2.html
An article by Danny Coward, the lead developer.
http://java.sun.com/javase/6/features.jsp
The key features list at the Sun Web site.
http://jcp.org/aboutJava/communityprocess/final/jsr270/index.html
The official specification of the final release
contents.
--Fred
Last Updated: 10/13/2000
Applies to: Java 1.0+
Here is a simple Java console application:
class App1
{
public static void main(String[] args)
{
System.out.println("Hello World!");
}
}
It must reside in a file named exactly App1.java (case sensitive) to match the class name. It can be compiled (using the Sun JDK compiler, available for free download at http://java.sun.com) as:
javac App1.java
and invoked from the command line as:
java App1
Like C/C++ programs, Java console applications always begin with the main() method. They can accept command line arguments, read from standard input, write to standard output, return a status code to the command line processor, read/write files, etc.
--Fred
Original Version: 10/13/2000
Last Updated: 2/5/2006
Applies to: Java 1.0+
A Java applet is a Java class that runs in the context of an applet container (typically a Web Browser). Here is a simple Java applet:
import java.applet.Applet;
import java.awt.Graphics;
public class Applet1 extends Applet
{
public void paint(Graphics g)
{
g.drawString("Hello world!", 50, 25);
}
}
It must be a subclass of Applet and must reside in a file named exactly Applet1.java (case sensitive) to match the class name. It can be compiled (using the Sun JDK compiler, available for free download at http://java.sun.com) as:
javac Applet1.java
It can't be invoked directly from the command line because it has no main() method.
Java applets can contain several methods that are invoked at various times by the applet container. This example contains only a paint() method, but a more typical applet might contain the following:
| init() | Called to initialize the applet. |
| start() | Called when the applet becomes visible (a good place to start an animation). |
| stop() | Called when the applet moves out of sight of the user (may as well stop any animation here to save CPU time). |
| destroy() | Called when the applet is unloaded from the container. |
| paint() | Called when the applet should re-draw itself. |
Typically applets are run in the context of a Web Browser, but the Sun JDK includes a tool (a simple applet container) called appletviewer that can also be used to run an applet. In either case, you run them as part of an HTML page, like the one below:
<html> <body> Here is the output of my program: <applet code="Applet1.class" width="150" height="25"> </applet> </body> </html>
To run the applet, load this HTML page into a Web Browser. To run it via appletviewer, specify the name of the HTML file as the command line argument, as:
appletviewer Page1.html
There are lots of restrictions on applets, mostly due to security concerns. Applets typically reside on a Web server, but are downloaded automatically as part of the Web page, and executed by the Web Browser. Therefore, they are not permitted to do things that might be dangerous to the computer running the Web Browser, like reading/writing/deleting files, etc. However, you can get around these restrictions with signed, trusted applets.
--Fred
Original Version:
10/14/2000
Last Updated: 2/5/2006
Applies to: Java 1.1+
A Java servlet is a Java class that runs in the context of a servlet container (typically a Web Server). Here is a simple Java servlet:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Servlet1 extends HttpServlet
{
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println(" <body>");
out.println(" <h1>Hello World!</h1>");
out.println(" </body>");
out.println("</html>");
}
}
It must implement the Servlet interface (typically by being a subclass of HttpServlet) and must reside in a file named exactly Servlet1.java (case sensitive) to match the class name.
To compile the servlet, you must have access to a Java compiler (the Sun JDK compiler is available for free download at http://java.sun.com) and the standard Java servlet classes (javax.servlet.* used in the import statements above). If your Web Server supports servlets (most do) it should include a .JAR or .ZIP file that contains these classes. Otherwise, you can download "Tomcat", the official reference implementation of a servlet container for free from http://jakarta.apache.org/tomcat.
Tomcat is easy to download, unzip, and run. No installation required. Its servlet.jar file contains the servlet classes. You can compile the servlet (using the Sun SDK Java compiler and the Tomcat servlet.jar file) as:
javac -classpath c:\tomcat\lib\servlet.jar Servlet1.java
The servlet can't be invoked directly from the command line because it has no main() method. Before you run it as a servlet, you must register it with a servlet container. With Tomcat, there are configuration files you can edit to register locations of servlets, but the easiest way to get started is to simply copy the Servlet1.class file (created by the compile command above) into an existing subdirectory of the Tomcat tree. For example, copy it to:
c:\tomcat\webapps\examples\WEB-INF\classes
Once the servlet is registered, start Tomcat by running the "startup.bat" (Windows) or "startup.sh" (Unix) file. You can then run the servlet by loading the following URL into your Web Browser:
http://localhost:8080/examples/servlet/Servlet1
Note that, by default, the Tomcat server listens on port 8080. You can change this by editing the server.xml configuration file.
Java servlets can contain several methods that are invoked at various times by the servlet container. This example contains only a doGet() method, but the following are also defined:
| init() | Called to initialize the servlet. |
| doGet() | Called to handle all GET requests from an HTTP client. |
| doPost() | Called to handle all POST requests from an HTTP client. |
| service() | Called to handle all requests from an HTTP client. |
| destroy() | Called when the servlet is unloaded from the container. |
This servlet simply writes a hardcoded stream of HTML to the Web Browser. A more typical servlet would accept parameters (passed as part of the URL and accessed via the request parameter to the servlet's method), access a relational database or other data source, perform some computation, perhaps read and write files on the Web Server, and write a stream or HTML or XML to the Web Browser.
For more information, see the O'Reilly Java Servlet Programming book.
--Fred
Original Version: 10/14/2000
Last Updated: 12/12/2006
Applies to: Java 1.1+
JavaServer Pages (JSPs) are similar to Microsoft "Active Server Pages" (ASPs). They simplify the job of writing a servlet when the primary purpose of the servlet is to generate an HTML page. Such a servlet would otherwise consist of a sequence of println() calls to print out the HTML, intermixed with occasional other Java statements. The bulk of the file would be HTML, but all of the HTML would be wrapped in double quotes to make it into Java string literals, making it more difficult to use quotes in the HTML itself. For example, the following is a valid Java servlet:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Servlet1 extends HttpServlet
{
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println(" <body>");
out.println(" <p><font color=\"red\">" +
"The Web Server is running Java version " +
System.getProperty("java.version") +
"</font></p>");
out.println(" </body>");
out.println("</html>");
}
}
The corresponding JSP page consists of a sequence of HTML with occasional embedded Java code:
<html>
<body>
<p><font color="red">"
The Web Server is running Java
version <%= System.getProperty("java.version") %>
</font></p>
</body>
</html>
The <% and %> delimiters are used to enclose the Java code. The rest of the lines are wrapped automatically in Java println() calls as shown in the servlet above. When a client requests a JSP page, the server automatically calls the JSP compiler to translate the JSP page into a servlet source file, then calls the Java compiler to compile it, then executes the servlet. Unnecessary steps are skipped based on the last modification date/time of the JSP file, .java file and .class file.
By default, all of the JSP code ends up in the service() method of the generated servlet. However, you can exercise more control over the generated code via JSP directives and JSP declarations.
The above describes the use of "scriptlets" in JSP pages, which is how many JSP programmers get started. However, the real power of JSP is the use of custom tags, like the Struts tag library, the JSTL tag library, JavaServer Faces libraries, and even your own homegrown tag libraries.
For more info, see:
--Fred
Original Version: 2/5/2006
Last Updated: 5/19/2007
Applies to: Java 1.0+
Unlike Java applets and Java servlets, Java beans are not required to implement any particular interface or inherit from any particular class. Being a Java bean is accomplished by adhering to a design pattern, a coding convention.
The basic requirement is that Java beans have a public "default constructor" (a constructor with no parameters) and make their properties available via pairs of "accessor" methods known as "getters" and "setters" using the prefixes:
"set" for setters
For example, the following is a valid (but not very useful) Java bean:
public class BeanWithNoProperties
{
}
The following is a simple contrived example that is slightly more useful:
public class Rectangle
{
private Integer width;
private Integer height;
private String name;
public void setWidth(Integer value) { width = value; }
public Integer getWidth() { return width; }
public Integer getHeight() { return height; }
public void setSquare(boolean square) { height = (square ? width : null); }
public boolean isSquare() { return width == height; }
public void setName(String newname) { name = newname; }
}
Notes:
- Public constructor exists by default.
- Standard getters and/or setters are defined for zero or more of the properties.
- Internal property values are declared "private" to prevent bypassing the accessor methods.
- Each property may have a getter, a setter, both or neither.
- Getters and setters may compute values instead of mapping directly to internal variables.
- Names of the arguments for getters and setters are irrelevant.
- Setters must return "void".
- Getters must take no arguments.
Common uses of Java beans are:
- As UI components, where a drag/drop UI builder uses "reflection" to determine what properties are defined for a bean so that it can offer them to the user in a property sheet.
- As simple data objects that are pluggable into a wide variety of frameworks. For example, "backing beans" for JavaServer Faces applications.
- As "Enterprise Java Beans" (EJBs), which use the basic Java bean interface, but have additional requirements in order to support features for remote access, concurrency, scalability, data access, etc.
Other features/requirements of Java beans are:
- Must be persistable which the above is by default. Technically it should implement one of the interfaces:
java.io.Serializable
java.io.Externalizable
but neither of these requires any methods, and many applications requiring Java beans do not require them.- Must support "introspection" which all Java objects do via "reflection", but a bean can choose to explicitly use the BeanInfo class instead.
- Can register with other beans of interest as a "listener" to be informed of "events" that occur to those beans.
- Can support custom "property editors" for use in property sheets of an enclosing application.
For more info, see:
--Fred
Original Version: 2/5/2006
Last Updated: 5/19/2007
Applies to: Java 1.0+
JDBC (Java Database Connectivity) is the Java equivalent of ODBC. It provides access to a relational database. Here is a simple Java application using JDBC:
import java.sql.*; public class JDBCSample { public static void main(String[] args) throws ClassNotFoundException, SQLException { String url = "jdbc:oracle:thin:@my_server.com:1521:DBSID"; String user = "my_username"; String pw = "my_password"; Class.forName("oracle.jdbc.driver.OracleDriver"); Connection conn = DriverManager.getConnection(url, user, pw); Statement st = conn.createStatement(); ResultSet rs = st.executeQuery("select * from table1"); while (rs.next()) { String col1 = rs.getString(1); int col2 = rs.getInt(2); } rs.close(); st.close(); conn.close(); } }
You can compile it like any Java application, using any Java compiler. The java.sql classes are included in the standard runtime library.
To run it, you must have access to a JDBC driver. In this case, you'll need the Oracle JDBC driver, which is available for free download at http://www.oracle.com /technology /software /tech /java /sqlj_jdbc /index.html). It's a simple Java JAR file (though older versions were JAR files named with a .ZIP extension), so just copy it to your Java classpath.
Of course, you'll also need access to a relational database (in this case Oracle), running at the specified host ("my_server.com"), listening on the specified port (1521), and named with the specified database SID ("DBSID"). And it should have a table named "table1".
This example is pretty simple. It just selects from a single table and examines the String and int values of the first 2 columns in the resultset.
However, you can get fancier, using the typical ODBC syntax to call a procedure or function with input and output "bind variables":
CallableStatement st = conn.prepareCall ("{? = call my_function(?, ?, ?)}"); st.registerOutParameter(1, Types.VARCHAR); st.setInt (2, 57); st.setString (3, "a string value"); st.registerOutParameter(4, Types.INTEGER); st.execute(); String returnVal = st.getString(1); int outParam = st.getInt(4);
You can also:
- Call conn.setAutoCommit(false), and explicitly call conn.commit() or conn.rollback().
- Prepare statements (for faster repeated execution) via conn.prepareStatement().
- Call st.registerOutParameter(n, oracle.jdbc.driver.OracleTypes.CURSOR) to return resultsets as output params or function return values.
- Specify resultSetType values on the call to createStatement(), prepareCall(), or prepareStatement():
ResultSet.TYPE_FORWARD_ONLY
ResultSet.TYPE_SCROLL_INSENSITIVE
ResultSet.TYPE_SCROLL_SENSITIVE- Specify resultSetConcurrency values on the call to createStatement(), prepareCall(), or prepareStatement():
ResultSet.CONCUR_READ_ONLY
ResultSet.CONCUR_UPDATABLE- Get connections from a connection pool, instead of creating a new one for each query.
- etc.
Thanks to John Moore for pointing out a typo in this tip!
--Fred
Last Updated: 11/23/2003
Applies to: Java 1.0+
The Java JDK (Java Developer's Kit) from Sun includes a standard tool called "javadoc". It scans your Java code and automatically produces API documentation as a set of linked Web pages. To run it against a bunch of Java source files, simply type:
javadoc *.java
For a typical set of such documentation, see:
http://bristle.com/Tips/javadocs/index.html
For more info, see:
--Fred
Last Updated: 10/13/2000
Applies to: Java 1.0+
Coming soon...
--Fred
Last Updated: 5/21/2000
Applies to: Java 1.0+
| = | assignment, shallow copy for objects |
| == | comparison Shallow compare for objects. Use equals() for deep compare. |
| != | comparison Shallow compare for objects. Use equals() for deep compare. |
| < | |
| <= | |
| > | |
| >= | |
| +, += | unary and binary |
| -, -= | unary and binary |
| *, *= | |
| /, /= | |
| %, %= | modulus |
| ++ | prefix and postfix |
| -- | prefix and postfix |
| && | Logical AND Short circuit like C++ |
| || | Logical OR Short circuit like C++ |
| ! | Logical NOT |
| &, &= | Bitwise AND |
| |, |= | Bitwise OR |
| ~ | Bitwise NOT |
| ^, ^= | Bitwise XOR |
| <<, <<= | Left shift |
| >>, >>= | Right arithmetic shift (sign extended) |
| >>>, >>>= | Right logical shift (zero extended) |
| ? : | Ternary if-then-else |
| , | Used only in for loop |
--Fred
Last Updated: 11/13/2000
Applies to: Java 1.0+
| 123 | decimal int (32-bit) |
| 123.4 | decimal double (64-bit) |
| 0177 | octal int (32-bit) |
| 0x1FF, 0X1FF, 0x1ff, 0X1ff | hex int (32-bit) |
| 123L, 123l | long (64-bit) |
| 123F, 123f | float (32-bit) |
| 123D, 123d | double (64-bit) |
| 1.23e-9 | scientific notation |
Thanks to John Haibach for pointing out some additions to the original version of this tip!
--Fred
Last Updated: 7/17/2000
Applies to: Java 1.0+
Java executes your code magically (without an apparent call to the code) in the following situations:
| constructor | Class constructor called whenever a class is
created via new(). Note, however, that there are no destructors. |
| parent constructor | Default constructor of parent class called automatically from the constructor of a child class, unless the child constructor explicitly calls super() as the first line of code. |
| finalize() | finalize() method called by garbage collector before reclaiming the storage used for the class. |
| finally clause | Statements in the finally clause of a block are run when control passes out of the block. |
| toString() | toString() method called when a class instance is mentioned in a context that requires a string. |
--Fred
Last Updated: 1/27/2006
Applies to: Java 1.4.2+
To see the command line options supported by the Java Virtual Machine (java.exe), type:
java -?
java -X
For Java 1.4.2, the output is of java -? is:
Usage: java [-options] class [args...]
(to execute a class)
or java [-options] -jar jarfile [args...]
(to execute a jar file)
where options include:
-client to select the "client" VM
-server to select the "server" VM
-hotspot is a synonym for the "client" VM [deprecated]
The default VM is client.
-cp <class search path of directories and zip/jar files>
-classpath <class search path of directories and zip/jar files>
A ; separated list of directories, JAR archives,
and ZIP archives to search for class files.
-D<name>=<value>
set a system property
-verbose[:class|gc|jni]
enable verbose output
-version print product version and exit
-version:<value>
require the specified version to run
-showversion print product version and continue
-jre-restrict-search | -jre-no-restrict-search
include/exclude user private JREs in the version search
-? -help print this help message
-X print help on non-standard options
-ea[:<packagename>...|:<classname>]
-enableassertions[:<packagename>...|:<classname>]
enable assertions
-da[:<packagename>...|:<classname>]
-disableassertions[:<packagename>...|:<classname>]
disable assertions
-esa | -enablesystemassertions
enable system assertions
-dsa | -disablesystemassertions
disable system assertions
and the output is of java -X is:
-Xmixed mixed mode execution (default)
-Xint interpreted mode execution only
-Xbootclasspath:<directories and zip/jar files separated by ;>
set search path for bootstrap classes and resources
-Xbootclasspath/a:<directories and zip/jar files separated by ;>
append to end of bootstrap class path
-Xbootclasspath/p:<directories and zip/jar files separated by ;>
prepend in front of bootstrap class path
-Xnoclassgc disable class garbage collection
-Xincgc enable incremental garbage collection
-Xloggc:<file> log GC status to a file with time stamps
-Xbatch disable background compilation
-Xms<size> set initial Java heap size
-Xmx<size> set maximum Java heap size
-Xss<size> set java thread stack size
-Xprof output cpu profiling data
-Xrunhprof[:help]|[:<option>=<value>, ...]
perform JVMPI heap, cpu, or monitor profiling
-Xdebug enable remote debugging
-Xfuture enable strictest checks, anticipating future default
-Xrs reduce use of OS signals by Java/VM (see documentation)
-Xcheck:jni perform additional checks for JNI functions
The -X options are non-standard and subject to change without notice.
Thanks to Michel van der List for pointing out that there is an incredibly extensive list of options, for various versions of the JVM, at:
http://blogs.sun.com/roller/resources/watt/jvm-options-list.html
Thanks also to James Higgins for pointing out that Sun has excellent technical documents on using these options to tune the performance of JVM garbage collection, for various versions of the JVM, at:
http://java.sun.com/docs/hotspot
--Fred
Last Updated: 6/5/2000
Applies to: Java 1.0+
Casts can be done between any of the primitive types except boolean (byte, char, short, int, long, float, double). Casting to a wider data type can be done implicitly and preserves the signed value (sign-extending the bit pattern for integral types). Casting to a narrower date must be done explicitly and discards the high order bits. For example:
int int1 = -1; // -1 (FFFF FFFF hex) long long1 = (long)int1; // -1 (sign extended to FFFF FFFF FFFF FFFF) int1 = (int)long1; // FFFF FFFF (low order bits -- happens to be -1) long1 = 0x300000000L; // 3 0000 0000 int1 = (int)long1; // 0 (low order bits = 0000 0000) long1 = 0x00000000FFFFFFFFL; // 0000 0000 FFFF FFFF int1 = (int)long1; // -1 (low order bits = FFFF FFFF)
Casting from a float or double to an integral type discards the fractional portion of the value.
--Fred
Last Updated: 6/5/2000
Applies to: Java 1.0+
Java does not treat numeric overfow as an error. For example:
int int1 = 0x7FFFFFFF; System.out.println(int1); // 2147483647 int1 *= 4; System.out.println(int1); // -4
--Fred
Last Updated: 6/25/2000
Applies to: Java 1.0+
Here are some of the differences between arrays and containers:
--Fred
Last Updated: 7/7/2000
Applies to: Java 1.0+
You can create a type-specific container. Create a class that contains a member
of a standard container type (ArrayList, HashSet, etc). Offer the standard methods
(add, remove, clear, get, size, etc.), but declare the method parameters as the specific
type of object you wish to contain. From each of your methods, call the
corresponding method of the standard container. VB programmers may recognize this
technique as a "collection class".
Note 1: There is an advantage to encapsulating the standard
container like this, rather than inheriting from it. With inheritance, your
type-specific methods would overload (but not hide) the standard methods (which take
Object parameters). Therefore, it would still be possible for the user of your class
to add any object to the container. By encapsulating the standard container, you
hide its methods from your user.
Note 2: If you add an implements clause to your type-specific container, so that it officially implements one of the standard container interfaces (List, Set, etc.), your users can use your class wherever a standard container class is expected. However, this forces you to add more methods to your class, specifically the ones that you avoided by not using inheritance -- the ones that take Object as parameters and make it possible for your users to add any object to the container.
--Fred
Last Updated: 7/7/2000
Applies to: Java 2+
When using inheritance to create your own containers, use inherits (implementation inheritance) with the standard abstract classes (AbstractList, AbstractSet, AbstractMap, etc.) rather than using implements (interface inheritance) with the standard interfaces (List, Set, Map, etc.). This allows you to inherit the implementation of much of the boilerplate code, rather than having to write it all yourself.
--Fred
Last Updated: 7/7/2000
Applies to: Java 2+
When using creating a class to be used as a key in a HashMap or HashSet, be sure to override both hashCode() and equals(). Override hashCode() so you can use the "value" of the class (whatever you decide that means) as the hash value, not the address of the class which the default Object.hashCode() method would return. Override equals() so you can compare the value of the class with other keys, rather than comparing the address via Object.equals().
--Fred
Last Updated: 7/7/2000
Applies to: Java 1.0+
Java 1.0 included a standard library of containers (Vector, Stack, HashTable, etc.). In Java 2, these are still supported, but deprecated in favor of a new container library (ArrayList, HashSet, HashMap, etc.). Here are some notes about the old and new libraries:
| Java 1.0 | Java 2 |
| Vector | ArrayList |
| Stack | LinkedList |
| HashTable | HashMap |
--Fred
Last Updated: 6/16/2000
Applies to: Java 1.0+
Java classes in a package can have public or "package" access, but not protected or private. This makes sense since they are nested inside a package, not another class. However, you can also nest a class inside another class, in which case you can make it protected or private. Such a class is called an "inner class". You can also declare an inner class inside a method or inside an unnamed block of code. You can also declare an anonymous inner class (a class with no name) in an expression, inheriting from a named class. An inner class can be static, in which case an instance of it can exist without requiring an instance of the enclosing class. A static inner class can be nested inside an interface.
--Fred
Last Updated: 6/25/2000
Applies to: Java 1.0+
Unlike C++, Java doesn't directly support multiple implementation inheritance. However, with a little work, you can accomplish the same effect -- inheriting the implementation of multiple base classes with the ability for the subclass to selectively override methods of each base class.
Approach 0: The C++ approach.
The C++ approach (expressed in Java syntax) would look like:
class Base1
{
private String myName = "Base1";
public void method1a ()
{ System.out.println ("method1a of " + myName); }
public void method1b ()
{ System.out.println ("method1b of " + myName); }
}
class Base2
{
private String myName = "Base2";
public void method2a ()
{ System.out.println ("method2a of " + myName); }
public void method2b ()
{ System.out.println ("method2b of " + myName); }
}
class SubClass extends Base1, Base2 // *** Illegal!
{
private String myName = "SubClass";
public void method1b ()
{ System.out.println ("overridden method1b of " + myName); }
public void method2b ()
{ System.out.println ("overridden method2b of " + myName); }
}
public class MI
{
static void call1a(Base1 base1) { base1.method1a (); }
static void call1b(Base1 base1) { base1.method1b (); }
static void call2a(Base2 base2) { base2.method2a (); }
static void call2b(Base2 base2) { base2.method2b (); }
public static void main(String[] args)
{
SubClass s = new SubClass();
call1a(s);
call1b(s);
call2a(s);
call2b(s);
}
}
However, this is not supported in Java. You can't put 2 class names after the keyword "extends".
Approach 1: Interface Inheritance
The standard Java approach is to use interfaces for any additional base classes beyond the first one, as:
class Base1
{
private String myName = "Base1";
public void method1a ()
{ System.out.println ("method1a of " + myName); }
public void method1b ()
{ System.out.println ("method1b of " + myName); }
}
interface Base2
{
String myName = "Base2";
public void method2a ();
public void method2b ();
}
class SubClass extends Base1
implements Base2
{
private String myName = "SubClass";
public void method1b ()
{ System.out.println ("overridden method1b of " + myName); }
public void method2a ()
{ System.out.println ("required method2a of " + myName); }
public void method2b ()
{ System.out.println ("required method2b of " + myName); }
}
public class MI
{
static void call1a(Base1 base1) { base1.method1a (); }
static void call1b(Base1 base1) { base1.method1b (); }
static void call2a(Base2 base2) { base2.method2a (); }
static void call2b(Base2 base2) { base2.method2b (); }
public static void main(String[] args)
{
SubClass s = new SubClass();
call1a(s);
call1b(s);
call2a(s);
call2b(s);
}
}
However, this requires SubClass to provide the complete implementation of Base2. All it inherits from Base2 is an interface -- a requirement to implement the methods itself, not an existing implementation of the methods.
Approach 2: Composition
Another alternative is to use composition instead of inheritance, as:
class Base1
{
private String myName = "Base1";
public void method1a ()
{ System.out.println ("method1a of " + myName); }
public void method1b ()
{ System.out.println ("method1b of " + myName); }
}
class Base2
{
private String myName = "Base2";
public void method2a ()
{ System.out.println ("method2a of " + myName); }
public void method2b ()
{ System.out.println ("method2b of " + myName); }
}
class SubClass extends Base1
{
private String myName = "SubClass";
public void method1b ()
{ System.out.println ("overridden method1b of " + myName); }
public Base2 base2 = new Base2();
public Base2 getBase2() { return base2; }
}
public class MI
{
static void call1a(Base1 base1) { base1.method1a (); }
static void call1b(Base1 base1) { base1.method1b (); }
static void call2a(Base2 base2) { base2.method2a (); }
static void call2b(Base2 base2) { base2.method2b (); }
public static void main(String[] args)
{
SubClass s = new SubClass();
call1a(s);
call1b(s);
call2a(s.getBase2());
call2b(s.getBase2());
}
}
This allows SubClass to use the implementation of both base classes. However, it has lost the ability to override the behavior of any of the methods of Base2. The advantage is that it is not required to implement all of the Base2 methods, but the disadvantage is that it is not permitted to implement any of them. It can only offer the default Base2 behavior to its clients. Also, the code using the subclass must "cast" the subclass to the right type by calling the getBase2 method when using SubClass as a Base2, but not when using it as a Base1.
Approach 3: Inner Classes
A better alternative is to use inner classes, as:
class Base1
{
private String myName = "Base1";
public void method1a ()
{ System.out.println ("method1a of " + myName); }
public void method1b ()
{ System.out.println ("method1b of " + myName); }
}
class Base2
{
private String myName = "Base2";
public void method2a ()
{ System.out.println ("method2a of " + myName); }
public void method2b ()
{ System.out.println ("method2b of " + myName); }
}
class SubClass extends Base1
{
private String myName = "SubClass";
public void method1b ()
{ System.out.println ("overridden method1b of " + myName); }
public class Inner2 extends Base2
{
public void method2b ()
{
System.out.println ("overridden method2b of " + myName);
}
}
public Base2 getBase2() { return new Inner2(); }
}
public class MI
{
static void call1a(Base1 base1) { base1.method1a (); }
static void call1b(Base1 base1) { base1.method1b (); }
static void call2a(Base2 base2) { base2.method2a (); }
static void call2b(Base2 base2) { base2.method2b (); }
public static void main(String[] args)
{
SubClass s = new SubClass();
call1a(s);
call1b(s);
call2a(s.getBase2());
call2b(s.getBase2());
}
}
This allows SubClass to use the implementation of both base classes, and to selectively override the behavior of any of the methods of either base class.
Note: The code using the subclass must still "cast" the subclass to the right type by calling the getBase2 method. This seems to be unavoidable.
Approach 4: Anonymous Inner Classes
A slightly shorter, but stranger-looking alternative is to make the inner class anonymous, as:
class Base1
{
private String myName = "Base1";
public void method1a ()
{ System.out.println ("method1a of " + myName); }
public void method1b ()
{ System.out.println ("method1b of " + myName); }
}
class Base2
{
private String myName = "Base2";
public void method2a ()
{ System.out.println ("method2a of " + myName); }
public void method2b ()
{ System.out.println ("method2b of " + myName); }
}
class SubClass extends Base1
{
private String myName = "SubClass";
public void method1b ()
{ System.out.println ("overridden method1b of " + myName); }
public Base2 getBase2()
{
return new Base2()
{
public void method2b ()
{
System.out.println ("overridden method2b of " + myName);
}
};
}
}
public class MI
{
static void call1a(Base1 base1) { base1.method1a (); }
static void call1b(Base1 base1) { base1.method1b (); }
static void call2a(Base2 base2) { base2.method2a (); }
static void call2b(Base2 base2) { base2.method2b (); }
public static void main(String[] args)
{
SubClass s = new SubClass();
call1a(s);
call1b(s);
call2a(s.getBase2());
call2b(s.getBase2());
}
}
Here the inner class previous named Inner2 is defined without a name, as part of the return statement. An inner class can be defined within another class, or within any method of another class, or even within any expression in a method of another class. This case defines the inner class, including its override of method2b, within the expression returned by the return statement. No name is given to the inner class. Only its parent (Base2), methods (method2b) and instance variables (none) are specified.
For more details of this and other techniques using inner classes, see the excellent
discussion of inner classes in Chapter 8 "Interfaces and Inner Classes" of [Eckel00], and also the "Choosing Between Lists" section of
Chapter 9 "Holding Your Objects", which uses an array of anonymous inner classes
as a set of tests in a small benchmark program, and also the "Anonymous inner
classes" section of the "A directory lister" section of Chapter 11
"The Java I/O System" which shows how to use an anonymous inner class as a
FilenameFilter when iterating over files in a directory.
Last Updated: 7/16/2000
Applies to: Java 1.0+
To declare an exception:
class Exception1 extends Exception
{
public Exception1() {}
public Exception1(String msg) { super(msg); }
}
Or, if you don't intend to ever pass a details string as part of the exception:
class Exception1 extends Exception {}
--Fred
Last Updated: 12/6/1998
Applies to: Java 1.0+
To catch all exceptions, even if you don't know which ones might be thrown, use the syntax:
catch (Throwable t)
This is the Java equivalent of the C++ syntax:
catch (...)
--Fred
Last Updated: 7/16/2000
Applies to: Java 1.0+
After catching an exception, you can query information about it like any other Java Object via getClass(). You can also use methods of the Throwable class (of which Exception is a subclass). You can get the string message, if any, thrown with the exception via getMessage(). You can get a string containing the name and the message via toString(). Finally, you can print all this info plus a complete stack trace to the console or a file via printStackTrace().For example:
try
{
sub1();
}
catch (Exception e)
{
System.out.println ("getName():" + e.getClass().getName());
System.out.println ("getMessage():" + e.getMessage());
System.out.println ("toString():" + e.toString());
System.out.println ("printStackTrace():");
e.printStackTrace();
}
Here, printStackTrace is called with no parameter, so it prints to standard error, but you can also call it with a stream parameter (and thus capture the output in a file or string). See Propagating and Re-Throwing Exceptions for a more complete sample.
--Fred
Last Updated: 7/16/2000
Applies to: Java 1.0+
Once you've caught an exception, you can deal with the problem (correcting it, and re-trying the same operation that originally failed, trying an alternative approach, skipping the operation, etc.), and continue normally.
If you don't catch an exception, it propagates to the caller, carrying along the detailed message, if any, that was specified at the point where it was thrown, any other instance variables of the exception that you may have declared, and a full stack trace to the point where it was thrown. See example sub1 below.
Alternatively, you can catch the exception, take some local corrective action, and then re-throw it without disturbing the error details, stack trace, etc. See example sub1a below.
You can even re-throw the same exception with an updated stack trace to show the error as having been originally thrown from your error handler, via fillInStackTrace(). This is useful to hide the details of lower level components used by your component. See example sub1b below.
You can go one step further, updating not only the stack trace, but also the detailed message and all instance variables, by allocating a new exception object of the same type and throwing it instead of the one you caught. See example sub1c below.
Finally, of course, you can throw an entirely different exception from your exception handler. Here is a complete sample:
// Test case to show propagation, handling, re-throwing, and reporting
// of exceptions.
class Exception1 extends Exception
{
public Exception1() {}
public Exception1(String msg) { super(msg); }
}
public class Thrower
{
//
// Nested calls that allow the exception to propagate.
//
public int sub1() throws Exception1
{
return sub2();
}
public int sub2() throws Exception1
{
return sub3();
}
public int sub3() throws Exception1
{
throw new Exception1("This is the detail info.");
}
//
// Nested calls with one that catches and re-throws the same exception.
//
public int sub1a() throws Exception1
{
return sub2a();
}
public int sub2a() throws Exception1
{
try
{
return sub3a();
}
catch (Exception1 e)
{
// Take some cleanup action here, but we still want to
// report the original location of the exception.
// ...
throw e;
}
}
public int sub3a() throws Exception1
{
throw new Exception1("This is the detail info.");
}
//
// Nested calls with one that catches the exception, updates the
// stack trace info, and re-throws it.
//
public int sub1b() throws Exception1
{
return sub2b();
}
public int sub2b() throws Exception1
{
try
{
return sub3b();
}
catch (Exception1 e)
{
// Take some cleanup action here, then re-throw the
// exception with the original details string, but
// updating the stack info to report this as the original
// throw of the exception, hiding the fact that sub3b was
// ever involved.
// ...
throw (Exception1) e.fillInStackTrace();
}
}
public int sub3b() throws Exception1
{
throw new Exception1("This is the detail info.");
}
//
// Nested calls with one that catches the exception, and throws a
// different one of the same type.
//
public int sub1c() throws Exception1
{
return sub2c();
}
public int sub2c() throws Exception1
{
try
{
return sub3c();
}
catch (Exception1 e)
{
// Take some cleanup action here, then re-throw the
// exception with a new details string, and updating
// the stack info to report this as the original throw
// of the exception, hiding the fact that sub3b was
// ever involved.
// ...
throw new Exception1("This is different detail info.");
}
}
public int sub3c() throws Exception1
{
throw new Exception1("This is the detail info.");
}
public static class Tester
{
public static void main(String[] args)
{
Thrower t = new Thrower();
System.out.println ("Begin tests of " +
t.getClass().getName() + "...");
//
// Prints stack trace as expected.
//
System.out.println ("\nTest sub1:");
try
{
t.sub1();
}
catch (Exception e)
{
System.out.println ("getName(): " + e.getClass().getName());
System.out.println ("getMessage(): " + e.getMessage());
System.out.println ("toString(): " + e.toString());
System.out.println ("printStackTrace():");
e.printStackTrace();
}
//
// Prints stack trace as expected. Note that the sub2a line
// number shows the call to Sub3a that originally raised the
// exception, not the line that re-throws it.
//
System.out.println ("\nTest sub1a:");
try
{
t.sub1a();
}
catch (Exception e)
{
System.out.println ("getName(): " + e.getClass().getName());
System.out.println ("getMessage(): " + e.getMessage());
System.out.println ("toString(): " + e.toString());
System.out.println ("printStackTrace():");
e.printStackTrace();
}
//
// Prints stack trace as expected. Note that the sub2b line
// number shows the line that re-throws the exception, and that
// the call to Sub3b is not mentioned in the stack trace.
//
System.out.println ("\nTest sub1b:");
try
{
t.sub1b();
}
catch (Exception e)
{
System.out.println ("getName(): &