站内搜索: 请输入搜索关键词

当前页面: 开发资料首页J2SE 专题Part of aspects in J2SE 1.5

Part of aspects in J2SE 1.5

摘要: Part of aspects in J2SE 1.5

Nearly three years ago the design of one of the most significant updates to the Java platform in its history was planned. So what has happened in those three years? J2SE 1.5 ("Tiger") has been developed through the Java Community Process (JCP), and in addition to the 18 experts on the J2SE 1.5 JSR (JSR 176) there are an additional 15 component JSRs (see Table 1), each with their own domain experts. In addition to Java luminaries such as James Gosling and Graham Hamilton, over 160 Java experts worldwide have contributed to its design. The common goal was to make Java the best developer platform available, and I trust you will agree that we have listened very carefully to what the Java community wanted. Let's take a look at the information you need to get up to speed with J2SE 1.5, including code examples that you can run with the beta release that is available currently.

Although there are over 100 major features, the release is focused along certain key themes, namely, quality, ease of development, monitoring and manageability, performance and scalability, and desktop client. There are a few features that didn't fit neatly into the themes, and we'll look at those later.

Note that even if you do not change a single line of your existing application there are many features in J2SE 1.5 that you can take advantage of by just migrating to the new release. Be sure to try out the new beta, run your existing code, and then try some of the great new language features.

Language Changes and More
Perhaps the most talked about features in this release are the new Java language changes. Some of these changes have been covered in detail in several recent Java Pro articles. However, the ease of development theme covers much more than the Java language updates. There are other changes to make it easier for developer tools to work with the Java platform and also a whole new locking and threading framework.

The javac compiler uses the 1.5 language features by default. To use any of the examples you see here with the beta 1 release, you will need to add the option -source 1.5 when using the javac compiler:

javac -source 1.5 Hello.java

The primary ease of development changes and the respective JSR in which they were developed are shown in Table 2. Arguably, the most significant language change delivered with J2SE 1.5 is the introduction of Generic types. Generic types provide the ability for API designers to create common code that can be used with any Java reference type and yet can be checked for type safety at compile time. The Collections API is a good example of an API that can benefit from Generic types and has already been updated in the 1.5 release. In addition, any APIs that call the Collection API inside the core platform have also been retrofitted with a Generic signature, along with the Class API. To see Generics types in action, consider this ArrayList example that uses the 1.4.2 release:

ArrayList list =  new ArrayList();list.add(0, "User1"); String firstuser= (String)list.get(0);

The last statement casts the object returned from the ArrayList to a String. This cast is required because the Collections API stores the ArrayList elements as Java objects. However, if somewhere in our application we also made a call to list.add(0, new StringBuffer()), the compiler will accept this type as it is a valid Java object. Only when the program is run, the error is detected. The call to return the first element would retrieve a StringBuffer object instead, and this mis-mismatch would generate a ClassCastException at runtime. The same example with the generified Collections library is written:

ArrayList list =  new ArrayList();list.add(0, "User1");String firstuser = list.get(0);

To use an API that has been generified requires supplying the type using the <> notation to both sides of the declaration as shown for ArrayList and then removing any casts. If we now try to compile the same example and supply the faulty code, list.add(0, new StringBuffer()) the javac compiler will now generate an error.

Unlike C++ templates, the javac compiler only needs to create one generic class to represent any type used; C++ on the other hand creates one file per type used. It does this by removing the type information when storing the new generic class, called type erasure. This feature provides compatibility with previous APIs. However, the downside is that mixing and matching nongeneric and generic code has to be done very carefully; otherwise, the nongeneric mode is used. To generify your own APIs, check the Generics tutorial or look through the Collections API source (see Resources).

Convert Primitive Types
The Java language contains a small number of types like int and float that are not objects. One of the primary reasons these primitive types exist is for improved performance. However, when using an object-centric API like the Collections API, the onus is on the developer to convert the primitive type to an object and then convert it back again.

Autoboxing – With the new autoboxing feature the javac compiler generates the extra code necessary to convert from the primitive type, and with auto-unboxing converts the object back into its primitive type. This example shows an Integer object being stored using the generic Collections API, first with the 1.4.2 libraries:

Vector v= new Vector();v.add(new Integer(7));int first =((Integer)v.get(0)).intValue();

And then with the 1.5 release:

Vector v= new Vector();v.add(7);int first =v.get(0);

Enhanced for loop – The enhanced for loop feature reduces the extra coding required when stepping through a Collection. Stepping through a Collection often requires the use of an Iterator. The 1.4.2 version again is first, and it should look very familiar to Collection API users:

Vector v= new Vector();for (Iterator i =v.iterator(); i.hasNext() ;) {Integer value=(Integer)i.next();System.out.println("value="+value);}

The enhanced for loop uses the : character to identify that this is a special for statement. The element is retrieved from the Collection without us needing to declare an Iterator, as the javac compiler does the work behind the scenes. The same example using J2SE 1.5 and with Generic types is:

Vector v = new Vector();for (Integer value : v) {System.out.println("value="+value);}

Enumerated types – The enum keyword uses a special class to represent enumerated types. The new enumerated type is type safe, which means values outside that set are rejected at compile time. This example creates a type called Medal that only accepts values of Gold, Silver, and Bronze. It would reject a Medal of value 4, something that is difficult to prevent when using static final constants:

public enum Medal { Gold, Silver, Bronze }Medal winner;switch (winner) {case Gold: System.out.println("play anthem"); }

Static import – The static import feature enables you to refer to static constants from a class or interface without needing to inherit from it. Instead of BorderLayout.CENTER, each time we add a component you can simply refer to CENTER:

import static java.awt.BorderLayout.*;getContentPane().add(new JPanel(), CENTER);

There is another smaller ease of development change in this release as you no longer need to repeatedly call getContentPane() with Swing components. That line can be written simply as:

add(new JPanel(), CENTER);

Metadata – The metadata feature in J2SE 1.5 provides the ability to associate additional data alongside Java packages, classes, interfaces, methods, and fields. The javac compiler or other tools can read this additional data, or annotations, and depending on configuration can also be stored in the class file and discovered at runtime using the Java reflection API.

It is anticipated that Metadata will be used to reduce the amount of repetitive or boilerplate coding, and also provide assistance in using deployment descriptors. For most developers the exposure to Metadata will only be through predefined Metadata tags; development and deployment tools will do the processing.

Metadata IDs
APT, the annotation processing tool available in beta 2 provides a framework for identification and processing of metadata tags. The code example in Listing 1 creates a Metadata annotation to store release information that is then simply displayed at runtime.

Now let's look at an example of the type of code generation that could be achieved using metadata processing tools. The interface source in this JAX-RPC server could be generated automatically by a metadata processing tool that has a rule for the tag @remote without metadata:

public interface HelloIF extends Remote {public String sayHello(String s) throws RemoteException;}public class HelloImpl implements HelloIF {public String sayHello(String s) {return "Hello " + s;}}

or reduced code with metadata:

public class HelloImpl {public @remote String sayHello(String s) {return "Hello " + s;}}

When porting legacy code to the Java platform, one of the more laborious changes is to convert printf style output to the println concatenation style of output. Developers now have the option of using printf-type functionality to generate formatted output. When porting code, the C-style format strings should work the same with the printf formatter; however, even though using the \n character is supported on Unix platforms for true cross-platform newline support, the %n character should be used:

System.out.printf("User %-8s score %d%n","duke", 10);

The scanner API provides basic input functionality. To read simple input from standard input or any other stream requires calling a next() method from the Scanner API. The action for next() is to block if no data is available. There are also some complex pattern matching algorithms:

Scanner s=Scanner.create(System.in);int i = sc.nextInt(); // Read an // integertry {String s1 = s.next(Pattern.compile("[Yy]")); // only match Y or y} catch (InputMismatchException e){System.out.println("Expected Y or y");}s.close();

Varargs allows multiple arguments to be passed as parameters to methods. It requires the simple ... notation and internally is used to implement the flexible number of arguments required for printf:

void argtest(String ... vargs) {for (int i=0;i 

The concurrency utility library is based on a popular package from Doug Lea that has been standardized in JSR 166. It provides many useful APIs and tools for writing safer multithreaded code. The APIs include a thread executor task that can be used for managing threads, as well as a range of locks, like the Semaphore; timers; and other synchronization primitives. The JSR also delivers a nanosecond timer, java.lang.System.nanoTime(), for platforms that support that granularity.

A simple example is the atomic lock, which guarantees that when retrieving a value and setting it-sometimes called test and set-the value does not change in the meantime. This example uses the new AtomicInteger class that protects the balance value when updating it:

AtomicInteger balance=new AtomicInteger(10);System.out.println(balance.getAndAdd(10));

At Your Request
One of the most requested features I hear from the Java community is to improve startup time. Along with the streamlined class loading and reducing startup bottlenecks, this release also introduces class-data sharing in the Hotspot Java Virtual Machine (JVM). This technology shares read-only class data between multiple running JVMs, which not only can reduce the memory footprint of multiple JVMs but also improves startup time as core JVM classes are prepacked.

Performance ergonomics are a new feature in J2SE 1.5, which means that if you have been using specialized JVM run-time options in previous releases it may be worth re-validating your application performance with no or minimal options.

Another popular feature request for J2SE 1.5 is to improve the monitoring and manageability of the JVM, and in particular, the ability to detect low-memory conditions. Internal data from the JVM, like thread information and memory, is available for publication through the JMX API (JSR 003) interface. The published data is also available through the JMX remote interface (JSR 160) and can be monitored using the SNMP protocol. Not only can you view this information, but the framework provides a way to also manage or set values-for example, changing the logging level dynamically. Probably the most useful property to monitor is the low-memory threshold. The threshold can be customized for each JVM, and an SNMP trap or JMX notification can be sent when the threshold is exceeded, allowing an administrator to bring more machines online to share the load.

To enable a JVM to be monitored using the standard SNMP ports in the beta 2 release, modify the management.properties file, or supply these options at runtime:

java -Dcom.sun.management.snmp.acl=false -Dcom.sun.management.snmp.port=161 -Dcom.sun.management.snmp.trap=162 -Dcom.sun.management.snmp.acl=false -jar Java2Demo.jar

You can enable the JMX MBeanServer in a similar manner:

java -Dcom.sun.management.jmxremote.authenticate=alse -Dcom.sun.management.jmxremote.port=5001 -Dcom.sun.management.jmxremote.ssl=false -jar Java2Demo.jar

Most of the native monitoring functionality has been implemented using jvmti. This API has been specified through JSR 163, enables improved performance analysis, and will replace jvmpi. The API also provides the ability to use bytecode instrumentation to enable tools to add additional profiling only where it is needed, including at runtime. Although it is possible to write your own jvmti server, the main benefit will be enhanced developer tools.

Generating a stack trace from an embedded JVM or from a JVM that doesn't have a console has never been easy. You can now call Thread.getAllStackTraces() to generate a list of all stack frames from within your application. Alternatively, you can request a stack trace of the current thread and parse each element in sequence:

StackTraceElement e[]=Thread.currentThread().getStackTrace();for (int i=0; i 

In the rare case that the JVM aborts you can configure it to call your own error handler program:

-XX:OnError="command" optional %p used as process id-XX:OnError="pmap %p" -XX:OnError="gdb %p" 

In addition, by using the JDI serviceability bridge you can even attach a java debugger tool, such as jdb, to a core file or hung JVM process. To connect to a core file on Linux and debug Java methods, use:

jdb -server -connect sun.jvm.hotspot.jdi.SACoreAttachingConnector:javaExecutable=/usr/java/j2sdk1.5.0/bin/java

Look and Feel
The Java Desktop client is one of the key themes of the release and has been the subject of many improvements in this release. I mentioned improved startup time and memory footprint earlier. Desktop developers also asked for updates to the cross-platform Look and Feel, and the release includes the fresh new Ocean Look and Feel (see Figure 1) and further improvements in the native GTK skinnable Look and Feel and Windows XP Look and Feel.

If you have the latest OpenGL drivers, you can now use native hardware acceleration for any Swing application by using this run-time property:

java -Dsun.java2d.opengl=true -jar Java2D.jar

The Linux release now uses a new windowing toolkit based on X11 instead of motif. This toolkit is faster and also provides better drag and drop and clipboard interoperability. To enable this toolkit on Solaris, set the toolkit system property:

java -Dawt.toolkit=sun.awt.X11.XToolkit -jar Notepad.jar

J2SE 1.5 provides the foundation XML support to J2EE and also the Java Web Services Developer Pack. JAXP 1.3 (JSR 206) introduces XML 1.1 along with SAX 2.0.2, XLST and DOM Level3. In addition to tracking the latest W3C specifications these updates bring faster XML processing.

Unicode 4.0 support includes 32-bit surrogate character support. Surrogate characters are encoded as a special pair of UTF16 values to generate a different character, or codepoint. A surrogate pair is a combination of a high UTF16 value and a following low UTF16 value.

The approach taken by the Unicode organization to support these additional characters lends itself to a similar approach taken by the Supplementary Character API (JSR 204). As the Java char is also 16 bits, the core APIs have been updated to handle two chars together. In a few cases an additional method that takes an int type has been added for methods that only took a char as an argument. However, for most users the change will be transparent.

JSR 200 introduces a JAR file compression technology that can be used to dramatically shrink JAR files for network transmission. This compression and inflation can be achieved programmatically by using the javax.pack.Pack200 class. In addition, for simple downloads, you can use the stand-alone tools pack200 and unpack200. The pack200 command creates a compressed JAR file called charsets.pack.gz from charsets.jar. As part of the compression process the JAR file is deconstructed and reassembled; for this reason signed JARs should be initially prepared with the -repack option. In this example, the charset.jar file is repackaged and gzip compressed into the file charsets.pack.gz:

pack200 -v charsets.pack.gz charsets.jar

To unpack the transferred charsets.pack.gz back into the charsets.jar file, use the unpack200 command with the arguments in the same order:

unpack200 charsets.pack.gz charsets.jar

In this case the original JAR file, which is available in the JRE, is originally 8.61 MB, and using a normal compression tool would reduce the size to 4.19 MB. With the new pack tool this size can be further reduced by default to 1.69 MB, which is 80 percent smaller than the original size.

Finally, JDBC rowsets were originally introduced in J2SE 1.4, and J2SE 1.5 introduces a disconnected CachedRowSet and WebRowSet implementations. The CachedRowSet contains an in-memory collection of rows retrieved from the database. The connection to the database is managed by the RowSet API and simply needs information about the datasource or database connection details. The rowset can then be updated without tying up database connection resources, and then it can be resynced at a later time. The WebRowSet is an extension to the CachedRowSet that can also import and export an XML representation of the database rowSet (see Listing 2).

We've only covered some of the larger features in the J2SE 1.5 beta release here. There are over 100 features, but there are many smaller updates and bug fixes. Try the beta release with your own applications, and see the improvements firsthand.




↑返回目录
前一篇: J2SE新功能
后一篇: 学习J2SE过程中的30个基本概念[转]