Early Java Discoveries
Every language has its own idiosyncrasies -- ways that this
language behaves differently from expected. It is either through repeatedly making
the same mistake or scrounging through documentation that these lessons are learned and
internalized. This is my own list of discoveries that I made in the first few months
of using Java.
GENERAL SYNTAX
- spaces: java is generally forgiving about including zero, one or more
spaces around operators
- case: java is very specific about case:
- language keywords/data types (e.g. if, for, int, boolean, extends, implements) are all
lowercase
- Objects (e.g. System, String) are mixed case
- java lets you name (and use) two methods or two variables that only differ by case (e.g.
calcAmount and CalcAmount can take the same parameters but would be considered two
different methods)
- semi-colon: strange error messages can result when ";" is
missing (sometimes the compiler clearly identifies its absence, other times the error
message is very misleading)
LANGUAGE CONSTRUCTS
IF Statement
- compiler flags a = b as a problem (helps when remembering to use ==)
- outer brackets are mandatory around the full IF expression (same for while, etc.)
- using && (instead of &) causes short-circuit evaluation (i.e. if left
operand is true, right operand is not evaluated)
- using || (instead of |) causes short-circuit evaluation (i.e. if left operand is false,
right operand is not evaluated)
- ^ is the operator for XOR evaluation
SWITCH Statement
- if the break is omitted at the end of a case clause, execution continues in the next
case statement (until a break or the end of the switch statement is reached)
Switch does not support strings operands (with strings, the only choice is to use long
IF/ELSE/IF sequences)
VARIABLES
General
- Java has no global variables. All variables must be at the class or method level. To
deal with application-level constants (the usual justifiable exception to the "no
globals" rules), you will have a create a public class to hold your application
constants.
- Variables may be defined partway through the script (i.e. after the first executable
statement). It is common to see Java code that does this.
Local (method) variables do not have default initialization. They must be
initialized before being used (the compiler wont even create bytecode if it sees a
local variable is referenced before it is initialized).
Class variables have a default initialization: zero for numbers, false
for booleans and null for String and other objects.
String
- when declaring a variable, "String" must start with uppercase "S"
followed by all lowercase (this is because String is a Class with its own methods, instead
of a plain variable type)
- Special characters useful when creating strings are: \t for tab, \n for newline, \r for
carriage return. Some primitive tools, like Notepad, require \r\n to both be
included (instead of just \n) to move to the next line so be careful when interpreting the
correctness of output with Notepad.
When comparing two strings using x == y, results can become unpredictable. The
x==y comparison checks whether the two strings refer to the same memory locaiton (and due
to compiler optimizations with immutable Strings, two different variables may point to the
same memory location and so the comparison may seem to work correctly). However, if
the two string values originate from different places (e.g. one from HTML and the other
from within Java), it is likely that x == y will yield false even if their values are
equal. The solution is to always remember to use the equals
function for string comparison. x.equals(y) will yield the expected
result, without the unpredictable side-effects of the == comparison (with String
operands).
Numerics
- Undefined operations such as division by zero do not generate exceptions for
float/double but do generate exceptions for integer/long. For float/double, special values
are assigned (more on this in the next point).
- the following values: positive infinity (inf), negative infinity, negative zero and
not-a-number (NaN) can be obtained by unexpected arithmetic operations like
divide-by-zero, divide-by-negative-zero, zero-divide-by-zero, etc.
- Not a Number (NaN) is not equal to
anything (even to NaN) so yields false in any comparison. Checking against NaN can be done
using the isNaN() method.
JavaScript has a looser definition of a number than Java. For
example, the following are valid JavaScript integers "+5" "2." "
8 " (return False to isNaN() JS function) but all of these will fail a
string-to-integer data conversion in Java. This would be a problem if you are
submitting HTML page elements to a JSP or Servlet. One simple solution is to have
JavaScript multiply the value by 1 before submission so the extraneous characters (+,
space, etc.) that bother Java are removed. Including the following code in
pre-submission logic will solve the problem:if (!isNaN(document.formMain.txtNum.value)) { // valid number
document.formMain.txtNum.value = document.formMain.txtNum.value * 1;
} else {
// appropriate error (non-numeric in numeric field)
}
NULL HANDLING
- Null is the default value for an uninitialized class-level object variable. It can
be tested for being uninitialized:
if (NewCustomerThread == null) ...
Method-level object variables cannot be referred to while still
uninitialized (the compiler will give an error if it sees the referenced String/Object has
not been assigned a value before the line it is referenced).
Of the basic / (near-basic) data types, only a String (not number or
boolean) can be assigned null; (x = null;), because String is really an object. It can
later be compared to null if (x == null)
strings with a value of null can be compared and get a sensible result (i.e. null ==
null, "" != null, etc.) This is preferable to the PowerBuilder or PL/SQL
behaviour where the else clause is automatically executed if either value in the
comparison is Null.
concatenating a variable equal to "bob" with variable equal to null results in
a string of length 7 that is output as "nullbob".
Using normal primitives is problematic when working in a database-oriented application
where the value of data elements (including primitive variables) can legitimately be null.
If you have a number and you need to distinguish between a value of 0 and a value
of null (i.e. unknown or not-specified), then a different approach is required: all values
that can be stored in the database should be defined using the corresponding class:
Integer instead of int, Long instead of long, Boolean instead of boolean, etc. In
this way, the variable can represent all the potential numeric values as well as the null
value.
CLASSES
- the case of the classname has to exactly match the case of the filename which holds the
source code
- if you inadvertently invoke a function, prefixing by the classname (instead of an
instance of that class), then you will get an error being told that you "can't make
static reference". The reason: it is only valid to call a static function
directly at the class level; a regular function must be invoked at an instance of that
class.
... back to Java Topics
Copyright © 1997-2010, Woodger Computing Inc.