AL MA TE RI Key Java Language Features and Libraries TE D The past two major releases of the JDK have seen some significant changes. JDK 5 introduced new features at the language level, something that has not happened since Java was first released. Some of the most significant features added to the language are generics (parameterized types), enumerations, and metadata.
Part I: Thinking Like a Java Developer Using Derby As mentioned, Derby is automatically installed as part of the JDK. Derby provides a command-line tool called ij, which is an abbreviation for interactive JDBC scripting tool. This tool provides a way to connect to and manipulate Derby databases. You must have the following JAR files in your classpath before using this tool. The derby.jar file contains the JDBC drivers, and derbytools.jar contains the ij tool itself: c:\Program Files\Java\jdk1.6.
Chapter 1: Key Java Language Features and Libraries The database name (in this case, DerbyTestDB) is created as a subdirectory of the directory where you started the ij tool. The database appears on disk in the directory C:\DerbyTestDB. Exploring this directory is strictly for curiosity’s sake — you should never have to modify any file in this directory, including the service.properties file that may seem tempting to play with. The creation of a database also creates a derby.
Part I: Thinking Like a Java Developer The showZipCodes method actually opens the connection and performs the query. The driver used is org.apache.derby.jdbc.EmbeddedDriver. Derby also includes a ClientDriver for connecting to Derby in network mode, where Derby runs a network server providing for a client/server approach to using Derby: public void showZipCodes() { try { String driver = “org.apache.derby.jdbc.EmbeddedDriver”; Class.forName(driver).newInstance(); Connection conn = null; conn = DriverManager.
Chapter 1: Key Java Language Features and Libraries Language Features Added in Java 5 Several useful syntactic elements were introduced in Java 5.
Part I: Thinking Like a Java Developer Generics are also known as parameterized types where a type is the parameter. As can be seen in the previous example, String is the formal type parameter. This same parameterized type must be used when instantiating the parameterized type. Because one of the goals of the new language features in Java 5 was to not change the Java instruction set, generics are, basically, syntactic sugar.
Chapter 1: Key Java Language Features and Libraries The compiler issues the following error: ErasureExample.java:23: cannot find symbol symbol : method draw() location: class java.lang.Object shape.draw(); ^ 1 error If you replace the drawShape method with the following, the compiler is now happy to compile the program: public static void drawShape(T shape) { System.out.println(“Hashcode: “ + shape.hashCode()); } Why this discrepancy? It’s the result of type erasure.
Part I: Thinking Like a Java Developer objectHolder.putItem(str); str2 = stringHolder.getItem(); //str2 = objectHolder.getItem(); } Look at the last two lines. Retrieving an element from stringHolder and assigning it to a string is fine. However, if you uncomment the second line, which tries to access the same string in the objectHolder, you get the following compiler error. c:\>javac CustomHolder.java CustomHolder.java:28: incompatible types found : java.lang.Object required: java.lang.
Chapter 1: Key Java Language Features and Libraries oldVector = intVector; // This causes an unchecked warning intVector = oldVector; // This is permitted ue.processIntVector(intVector); // This causes an unchecked warning ue.processIntVector(oldVector); } } Attempting to compile the previous code leads to the following compiler warnings: UncheckedExample.java:16: warning: unchecked assignment: java.util.Vector to java.util.Vector
Part I: Thinking Like a Java Developer } public static void main(String args[]) { CustomHolder2 stringHolder = new CustomHolder2(); CustomHolder2
Chapter 1: Key Java Language Features and Libraries } class Square implements Shape { public void draw() { System.out.println(“Drawing square”); } } class Circle implements Shape { public void draw() { System.out.println(“Drawing circle”); } } Now define a PaintProgram class to demonstrate bounds. If you add a drawShape method that defines a type parameter, this won’t work: public static void drawShape(S shape) { shape.
Part I: Thinking Like a Java Developer By constraining the T type parameter, invoking draw is acceptable because Java knows it’s a Shape. If you want to specify multiple interfaces/classes to use as a bound, separate them with the ampersand (&). Also note that extends is used to specify bounds regardless of whether the type parameter is bounded by an interface or a class. Using Generics It is straightforward to create objects of a generic type. Any parameters must match the bounds specified.
Chapter 1: Key Java Language Features and Libraries Generic Methods In addition to the generic mechanism for classes, generic methods are introduced. The angle brackets for the parameters appear after all method modifiers but before the return type of the method.
Part I: Thinking Like a Java Developer The specific type of exception is specified when an instance of the Executor class is created inside main. The execute method throws an arbitrary exception that it is unaware of until a concrete instance of the Executor interface is created. Enhanced for Loop The for loop has been modified to provide a cleaner way to process an iterator.
Chapter 1: Key Java Language Features and Libraries However, the compiler expands the array version to code slightly longer than the collection version: String[] $strArray = stringArray; for(int $i = 0; $i < $strArray.length; $i++) { String strObject = $strArray[$i]; // ... statements here ... } The compiler this time uses two temporary and unique variables during the expansion. The first is an alias to the array, and the second is the loop counter.
Part I: Thinking Like a Java Developer The introduction of this interface prevents dependency on the java.util interfaces. The change in the for loop syntax is at the language level and it makes sense to ensure that any support needed in the class library is located in the java.lang branch. Variable Arguments C and C++ are a couple of the languages that support variable length argument lists for functions. Java decided to introduce this aspect into the language.
Chapter 1: Key Java Language Features and Libraries } public static void main(String args[]) { VarArgsExample va = new VarArgsExample(); int sum=0; sum = va.sumArrays(new int[]{1,2,3}, new int[]{4,5,6}, new int[]{10,16}); System.out.println(“The sum of the numbers is: “ + sum); } } This code follows the established approach to defining and using a variable argument. The ellipsis comes after the square brackets (that is, after the variable argument’s type).
Part I: Thinking Like a Java Developer The need to create an Integer object to place an int into the collection is no longer needed. The boxing conversion happens such that the resulting reference type’s value() method (such as intValue() for Integer) equals the original primitive type’s value. Consult the following table for all valid boxing conversions. If there is any other type, the boxing conversion becomes an identity conversion (converting the type to its own type).
Chapter 1: Key Java Language Features and Libraries Valid Contexts for Boxing and Unboxing Conversions Because the boxing and unboxing operations are conversions, they happen automatically with no specific instruction by the programmer (unlike casting, which is an explicit operation). There are several contexts in which boxing and unboxing conversions can happen. Assignments An assignment conversion happens when the value of an expression is assigned to a variable.
Part I: Thinking Like a Java Developer This mechanism also prevents the dangerous coding practice of placing a set of static attributes into an interface, and then in each class that needs to use the attributes, implementing that interface.
Chapter 1: Key Java Language Features and Libraries You cannot statically import data from a class that is inside the default package. The class must be located inside a named package. Also, static attributes and methods can conflict. For example, following are two classes (located in Colors.java and Fruits.
Part I: Thinking Like a Java Developer Enumerations Java introduces enumeration support at the language level in the JDK 5 release. An enumeration is an ordered list of items wrapped into a single entity. An instance of an enumeration can take on the value of any single item in the enumeration’s list of items.
Chapter 1: Key Java Language Features and Libraries case linux: System.out.println(“You chose Linux!”); break; case macintosh: System.out.println(“You chose Macintosh!”); break; default: System.out.println(“I don’t know your OS.”); break; } } } The java.lang.Enum class implements the Comparable and Serializable interfaces. The details of comparing enumerations and serializing them to a data source are already handled inside the class.
Part I: Thinking Like a Java Developer { ProgramFlags flag = ProgramFlags.showErrors; System.out.println(“Flag selected is: “ + flag.ordinal() + “ which is “ + flag.name()); } } The ordinal() method returns the position of the constant in the list. The value of showErrors is 0 because it comes first in the list, and the ordinal values are 0-based. The name() method can be used to get the name of the constant, which provides for getting more information about enumerations.
Chapter 1: Key Java Language Features and Libraries Several types of annotations are defined in this package. These are listed in the following table. Each of these annotations inherits from the Annotation interface, which defines an equals method and a toString method. Annotation Class Name Description Target Specifies to which program elements an annotation type is applicable. Each program element can appear only once.
Part I: Thinking Like a Java Developer The Retention is set to SOURCE, which means this annotation is not available during compile time and runtime. The doclet API is used to access source level annotations. The Target is set to TYPE (for classes/interfaces/enums) and METHOD for methods. A compiler error is generated if the CodeTag annotation is applied to any other source code element. The first two annotation elements are authorName and lastModificationDate, both of which are mandatory.
Chapter 1: Key Java Language Features and Libraries The start method takes a RootDoc as a parameter, which is automatically passed in by the javadoc tool. The RootDoc provides the starting point to obtain access to all elements inside the source code, and also information on the command line such as additional packages and classes. The interfaces added to the doclet API for annotations are AnnotationDesc, AnnotationDesc .ElementValuePair, AnnotationTypeDoc, AnnotationTypeElementDoc, and AnnotationValue.
Part I: Thinking Like a Java Developer AnnotationTypeElementDoc This interface represents an element of an annotation type. Method Description AnnotationValue defaultValue() Returns the default value associated with this annotation type, or null if there is no default value. AnnotationValue This interface represents the value of an annotation type element. Method Description String toString() Returns a string representation of the value. Object value() Returns the value.
Chapter 1: Key Java Language Features and Libraries process(cls.annotations()); System.out.println(); for(MethodDoc m : cls.methods()) { System.out.println(“Annotations for method [“ + m + “]”); process(m.annotations()); System.out.println(); } } static void process(AnnotationDesc[] anns) { for (AnnotationDesc ad : anns) { AnnotationDesc.ElementValuePair evp[] = ad.elementValues(); for(AnnotationDesc.ElementValuePair e : evp) { System.out.println(“ NAME: “ + e.element() + “, VALUE=” + e.
Part I: Thinking Like a Java Developer Method Description T getAnnotation(Class annotationType) Returns the annotation associated with the specified type, or null if none exists. Annotation[] getAnnotations() Returns an array of all annotations on the current element, or a zero-length array if no annotations are present.
Chapter 1: Key Java Language Features and Libraries } public boolean testConcat() { String s1 = “test”; String s2 = “ 123”; return(concat(s1,s2).equals(“test 123”)); } public boolean testSubstring() { String str = “The cat landed on its feet”; return(substring(str, 4, 7).equals(“cat”)); } } Following is an example implementation of the testing framework.
Part I: Thinking Like a Java Developer String result = “PASSED”; try { m.invoke(o); } catch(Exception ex) { System.out.println(“Exception: “ + ex + “\n” + ex.getCause()); result = “FAILED”; } return(result); } public static void main(String [] args) { if(args.length == 0) { System.out.
Chapter 1: Key Java Language Features and Libraries Each library is designed for flexibility of usage. Familiarity with these libraries is vital when developing solutions in Java. The more tools on your belt as a developer, the better equipped you are. Java Logging Java has a well-designed set of classes to control, format, and publish messages through the logging system. It is important for a program to log error and status messages.
Part I: Thinking Like a Java Developer hierarchy. The names of the Logger objects, going down the tree, are dot-separated. Therefore, java .util is the parent Logger of java.util.ArrayList. You can name the loggers any arbitrary string, but keeping with the dot-separated convention helps with clarity. The simplest use of the logging system creates a Logger and uses all system defaults (defined in a properties file) for the logging system.
Chapter 1: Key Java Language Features and Libraries The LogManager Class The LogManager class contains methods to configure the current instance of the logging system through a number of configuration methods, tracks loggers and provides access to these loggers, and handles certain logging events. These methods are listed in the following tables. Configuration The methods listed in the following table relate to storage and retrieval of configuration information in the LogManager.
Part I: Thinking Like a Java Developer Events The methods listed in the following table provide a way to add and remove references to listeners that should be notified when properties are changed on the LogManager. Method Description void addPropertyChangeListener (PropertyChangeListener l) Adds a property change listener to the list of listeners that want notification of when a property has changed. The same listener can be added multiple times.
Chapter 1: Key Java Language Features and Libraries Logger Methods The Logger is the main class used in code that utilizes the logging system. Methods are provided to obtain a named or anonymous logger, configure and get information about the logger, and log messages. Obtaining a Logger The following methods allow you to retrieve a handle to a Logger. These are static methods and provide an easy way to obtain a Logger without going through a LogManager.
Part I: Thinking Like a Java Developer Method Description void setParent(Logger parent) Sets the parent for this logger. This should not be called by application code, because it is intended for use only by the logging system. void setUseParentHandlers(boolean useParentHandlers) Specifies true if log messages should be passed to their parent loggers, or false to prevent the log messages from passing to their parent.
Chapter 1: Key Java Language Features and Libraries Method Description void config(String msg) The Logger class contains a number of convenience methods for logging messages. For quickly logging a message of a specified level, one method for each logging level is defined.
Part I: Thinking Like a Java Developer Method Description void logp(Level level, String sourceClass, String sourceMethod, String msg) Take source class and source method names in addition to the other information. All this is put into a LogRecord object and sent into the system.
Chapter 1: Key Java Language Features and Libraries LogRecord Methods The LogRecord contains a number of methods to examine and manipulate properties on a log record, such as message origination, the log record’s level, when it was sent into the system, and any related resource bundles. Method Description Level getLevel() Returns the log record’s level. String getMessage() Returns the unformatted version of the log message, before formatting/localization.
Part I: Thinking Like a Java Developer Method Description void setThreadID (int threadID) Sets the identifier of the thread where the log message is originating. void setThrown (Throwable thrown) Sets a Throwable to associate with the log message. Can be null. Resource Bundle Methods The following methods allow you to retrieve and configure a resource bundle for use with the log message. Resource bundles are used for localizing log messages.
Chapter 1: Key Java Language Features and Libraries Method Description void setSequenceNumber(long seq) Sets the sequence number of the log message. This method shouldn’t usually be called, because the constructor assigns a unique number to each log message. The Level Class The Level class defines the entire set of logging levels, and also objects of this class represent a specific logging level that is then used by loggers, handlers, and so on.
Part I: Thinking Like a Java Developer Method Description static Level parse(String name) Returns a Level object representing the name of the level that is passed in. The string name can be one of the logging levels, such as SEVERE or CONFIG. An arbitrary number, between Integer.MIN_VALUE and Integer.MAX_VALUE can also be passed in (as a string). If the number represents one of the existing level values, that level is returned. Otherwise, a new Level is returned corresponding to the passed in value.
Chapter 1: Key Java Language Features and Libraries Method Description abstract void close() Should perform a flush() and then free any resources used by the handler. After close() is called, the Handler should no longer be used. abstract void flush() Flushes any buffered output to ensure it is saved to the associated resource. abstract void publish(LogRecord record) Takes a log message forwarded by a logger and then writes it to the associated resource.
Part I: Thinking Like a Java Developer Stock Handlers The java.util.logging package includes a number of predefined handlers to write log messages to common destinations. These classes include the ConsoleHandler, FileHandler, MemoryHandler, SocketHandler, and StreamHandler. These classes provide a specific implementation of the abstract methods in the Handler class. All the property key names in the tables are prefixed with java.util .logging in the actual properties file.
Chapter 1: Key Java Language Features and Libraries Property Name Description Default Value ConsoleHandler.level Log level for the handler Level.INFO ConsoleHandler.filter Filter to use Undefined ConsoleHandler.formatter Formatter to use java.util.logging .SimpleFormatter ConsoleHandler.encoding Character set encoding to use Default platform encoding The SocketHandler writes log messages to the network over a specified TCP port.
Part I: Thinking Like a Java Developer Property Name Description Default Value FileHandler.count Specifies how many output files to cycle through. 1 FileHandler.pattern Pattern used to generate output filenames. %h/java%u.log FileHandler.append Boolean value specifying whether to append to an existing file or overwrite it. false The FileHandler class supports filename patterns, allowing the substitution of paths such as the user’s home directory or the system’s temporary directory.
Chapter 1: Key Java Language Features and Libraries The properties on the MemoryHandler are listed in the following table. Property Name Description Default Value MemoryHandler.level Log level for the handler Level.INFO MemoryHandler.filter Filter to use undefined MemoryHandler.size Size of the circular buffer (in bytes) 1,000 MemoryHandler.push Defines the push level — the minimum level that will cause messages to be sent to the target handler Level.SEVERE MemoryHandler.
Part I: Thinking Like a Java Developer The Formatter Class The Formatter class is used to perform some custom processing on a log record. This formatting might be localization, adding additional program information (such as adding the time and date to log records), or any other processing needed. The Formatter returns a string that is the processed log record. The Formatter class also has support for head and tail strings that come before and after all log records.
Chapter 1: Key Java Language Features and Libraries getTail() methods are used to output the start and end of the XML file, the parts that aren’t repeated for each log record but are necessary to create a valid XML file. Example output from the XMLFormatter follows:
Part I: Thinking Like a Java Developer