This section outlines the basic rules of Java syntax and gives a brief introduction to Java concepts useful for the WebLogic Workshop developer. If you are familiar with another high-level programming language, such as C, C++, Visual Basic, or even JavaScript, you should have no trouble learning Java quickly. If you want a more detailed and thorough introduction to Java, there are a number of excellent books and courses available to you.
The following sections cover some some of the basics of Java syntax.
In Java, you must declare a variable before you use it, providing both its name and type. While this may seem like more work up front than simply using the variable when you need it, the extra bit of effort pays off, because the compiler can check and enforce type restrictions. This can save you debugging time later on.
For example, you can declare a new variable to store an integer as follows:
int x;
The following declares a new variable to hold a text string:
String strName;
After you’ve declared the variable, you can assign a value to it:
x = 5;
or
strName = "Carl";
The prefix str in the variable above makes it easy for the developer to remember that it is a variable of type String.
Java provides several primitive types that handle most kinds of basic data. The primitive types are:
In Java, you use primitive types to handle basic values and Java objects to store more complex data. Every Java object is derived from a basic Object class. A class is a template for creating an object; you can think of a class as a cookie cutter, and the objects created from it as the cookies.
It is important to keep in mind the difference between a primitive type and an object. An Integer object is different from an int, even though both store an integer value. A method that accepts one as an argument will not accept the other unless it has been specifically defined to do so. Also, Java objects always have methods which you use to work with them; a primitive type cannot have a method.
Note that in Java, the memory size of the primitive types is well-defined. An int, for example, is always a 32-bit value.
Java Tip: Many useful classes in Java that store and manage collections of objects (lists, trees, arrays, etc.) cannot operate on primitive types, because the primitive types are not derived from the basic Java Object class. However, Java includes wrapper classes for the primitive types, which you can use to temporarily create an object. You can then use that object in the desired operation. The wrapper classes have similar names to the primitive types, but with an uppercase first letter:
It is easy to create a wrapper class object from a primitive value, as shown below for Integer and int:
int myInt;
Integer myInteger = new Integer(myInt);
The primitive value can then be retrieved from the wrapper object as follows:
myInt = myInteger.intValue();
A statement is a logical line of code. A statement may assign a value to a variable or call a function. A statement is the basic building block of your Java program. For example, the following statement assigns the value 5 to the variable x:
x = 5;
This statement calls a function:
calculateIT(x);
As you may notice above, statements must end in a semicolon. Exceptions to this rule are statements that begin new blocks of code-–that is, sections of code enclosed in curly braces ({}).
Curly braces ({}) are used to enclose blocks, as shown below:
for( i=0; i< 100; i++) { <one or more statements> }
The position of lines breaks is not important. The following example is logically equivalent to that above:
for(i=0; i<100; i++) { <one or more statements> }
However, most programmers would consider the latter example to be poor style since it hampers readability.
Blocks group a set of statements together. In the above example, using a block here indicates that all the statements in the block should be executed in turn as part of the for loop.
The following section discusses some of the operators you need to understand to write Java code.
To use an object in Java, you must follow a two-step process. First, you must declare an object variable, providing its name and type; second, you must create a new instance of the object’s class. The second step creates a new object for you in memory and assigns it to the variable you’ve declared. You use the new keyword to create a new instance of a class, together with a class constructor.
A Java class always has one or more constructors, which are methods that return a new instance of the class. Every Java class provides a basic constructor method that takes no arguments. Consider the following example:
class MyClass { int firstElement; float secondElement; } MyClass myClassInstance; // at this point, myClassInstance is null myClassInstance = new MyClass(); // now myClassInstance refers to an object
A Java class may also have constructor methods that take several arguments; these constructors are generally provided as a convenience for the programmer using the object. You decide which one to use based on how you want to store data in the object.
The . (dot) operator is used to access information or to call an object’s methods. For example, given the class definition and variable declaration above, the members of myClassInstance object can be accessed as follows:
myClassInstance.firstElement = 1; myClassInstance.secondElement = 5.0f;
In Java, arrays are accessed by integer array indices. Indices for arrays begin with zero (0). Each element of an array can be accessed by its index using the [] (array) operator.
For example, to store an array of six names, you can declare an array as follows:
String strNames[5];
You can then set the value of first element in the array by assigning an appropriate value:
strNames[0] = "Carl";
The following section explains collections and iterators.
Java defines a set of classes known as collection classes. These classes are defined in the java.util package (see more on packages below). The most commonly used collection classes are:
Objects created from these classes provide convenient management of sets of other objects. An advantage of a collection over an array is that you don’t need to know the eventual size of the collection in order to add objects to it. The disadvantage of a collection is that it is generally larger than an array of the same size. For example, you can create a LinkedList object to manage a set of objects of unknown size by saying:
LinkedList li = new LinkedList(); li.add("Bob"); li.add("Mary"); li.add("Jane"); …
Note that in versions of Java before 1.2, the Vector and Hashtable classes were often used to manage collections of objects. These classes, however, are synchronized, meaning they are safe for multi-threaded use. Synchronization has performance implications. If you do not require synchronization behavior, you will achieve better performance by using the newer ArrayList and HashMap classes.
Some collection classes provide built-in iterators to make it easy to traverse their contents. The built-in iterator is derived from the java.util.Iterator class. This class enables you to walk a collection of objects, operating on each object in turn. Remember when using an iterators that it contains a snapshot of the collection at the time the iterator was obtained. It’s best not to modify the contents of the collection while you are iterating through it.
Java provides convenient string manipulation capabilities via the java.lang.String and java.lang.StringBuffer classes. One of the most common performance-impacting errors new Java programmers make is performing string manipulation operations on String objects instead of StringBuffer objects.
String objects are immutable, meaning their value cannot be changed once they are created. So operations like concatenation that appear to modify the String object actually create a new String object with the modified contents of the original String object. Performing many operations on String objects can become computationally expensive.
The StringBuffer class provides similar string manipulation methods to those offered by String, but the StringBuffer objects are mutable, meaning they can be modified in place.
Java defines a mechanism for attaching information to program elements and allowing automatic extraction of that information. The mechanism, called Javadoc, was originally intended to attach specially formatted comments to classes, methods and variables so that documentation for the classes could be generated automatically. This is how the standard Java API documentation is produced.
Javadoc requires a special opening to Javadoc comments: they must start with /** instead of /*.
Java Tip: While the comment may contain arbitrary text before the first Javadoc annotation in the comment, all text after the first Javadoc annotation must be part of an annotation value. You cannot include free comment text after Javadoc annotations; doing so will cause compilation errors.
In addition to the special opening of the comment, Javadoc defines several Javadoc annotations that are used to annotate parts of the code. Javadoc annotations always start with the @ character. Examples of standard Javadoc annotations are:
Although originally intended to produce documentation, Javadoc annotations have now found other uses, as they are a convenient and systematic way to attach information to program elements that may be automatically extracted.
WebLogic Workshop uses Javadoc annotations to associate special meaning with program elements. For example, the @common:control annotation on a member variable of the class in a JWS file tells WebLogic Workshop to treat the annotated member variable as a WebLogic Workshop control.
Java defines a common strategy for dealing with unexpected program conditions. An exception is a signal that something unexpected has occurred in the code. A method throws an exception when it encounters the unexpected condition. When you call a method that throws an exception, the Java compiler will force you to handle the exception by placing the method call within a try-catch block (see below).
An exception is a Java object, which makes it easy to get information about the exception by calling its methods. Most Java exception objects inherit from the basic java.lang.Exception class. Specific exception classes contain information pertinent to the particular condition encountered. For example, a SQLException object provides information about a SQL error that occurred.
You use try-catch-finally blocks to handle exceptions. The try-catch-finally block allows you to group error handling code in a single place, near to but not intermingled with the program logic.
The following example demonstrates a try-catch-finally block. It assumes that method doSomething() declares that it throws the BadThingHappenedException:
public void callingMethod() { try { doSomething(); } catch (BadThingHappenedException ex) { <examine exception and report or attempt recovery> } finally { <clean up any work that may have been accomplished in the try block> } return; }
If doSomething() completes normally, program execution continues at the finally block.
If doSomething()throws the BadThingHappenedException, it will be caught by the catch block. Within the catch block, you can perform whatever action is necessary to deal with the unexpected condition. After the code in the catch block executes, program execution continues at the finally block.
Notice that the finally clause is always executed, whether or not an exception occurred in the try block. You can use the finally clause to clean up any partial work that needs to be performed, regardless of whether an error occurred. For example, if a file is opened in the try block, the finally block should include code to close the file, such that the file is closed regardless of whether or not an exception occurred.
Unlike its predecessor compiled languages like C and C++, Java is never compiled all the way to machine code that is specific to the processor architecture on which it is running. Java code is instead compiled into Java byte code, which is machine code for the Java Virtual Machine (JVM). This is the feature that gives Java its inherent portability across different operating systems.
Since all Java code is run in the JVM, the JVM can include capabilities that would be difficult to implement in a traditional programming language. One of the features the JVM provides is garbage collection.
The JVM keeps track of all references to each object that exists. When the last reference to an object is removed, the object is no longer of any use (since no one can reference it, no one can use it). Periodically, or when memory resources are running low, the JVM runs the garbage collector, which destroys all unreferenced objects and reclaims their memory.
For the programmer, this means that you don't have to keep track of memory allocations or remember when to free objects; the JVM does it for you. While Java includes the new keyword, which is analogous to the malloc function in C/C++ and the new operator in C++, Java does not include a free() function or a delete keyword. It is still possible to leak memory in Java, but it is less likely than in other high-level languages.
The following sections explain Java packages and their relationship to Java classes.
All Java code exists within what is know as the package namespace. The package namespace exists to alleviate conflicts that might occur when multiple entities are given the same name. If the entities exist in different portions of the namespace, they are unique and do not conflict.
A package statement may optionally be included at the top of every Java source file. If a file does not specifically declare a package, the contents of the file are assigned to the default package.
Every class and object has both a simple name and a fully qualified name. For example, the Java class String has the simple name String and fully qualified name java.lang.String, because the String class is declared in the java.lang package.
There is a relationship between the package names and the directory hierarchy within which the files exist. A file containing the statement
package security.application;
must reside in the directory security/application or the Java compiler will emit an error.
Note that packages allow the same class or object name to exist in multiple locations in the package hierarchy, as long as the fully qualified names are unique. This is how the standard Java packages can contain a List class in both the java.util and java.awt packages.
If a file includes a package statement, the package statement must be the first non-comment item in the file.
Before you can refer to classes or objects in other packages, you must import the package or the specific entities within the package to which you want to refer. To import all classes and objects in the package from the previous example, include the following statement in your file:
import security.application.*;
Note that the following statement imports only the classes and objects that are declared to be in the security package; it does not import the security.application package or its contents.
import security.*;
If UserCredentials is a class within the security.application package and it is the only class or object in the package to which you want to refer, you may refer to it specifically with the following statement:
import security.application.UserCredentials;
If you are only importing a few classes from a large package, you should use the specific form instead of importing the entire package.
Import statements must be the first non-comment items in the file after the optional package statement.