Go to java5.0 New Features

Source: Internet
Author: User
Tags deprecated
Java 5.0 has been released, and many people will begin to use some new features of this JDK version. From an enhanced for loop to more complex features such as generic (generic), it will soon appear in your code. We have just completed a large Java 5.0-based task, and this article will introduce our experience with these new features. This article is not an introductory article, but an in-depth introduction to these features and their impact. It also provides some tips for using these features more effectively in projects.
Introduction

In the beta phase of JDK 1.5, we developed a Java 5 compiler for Bea's Java IDE. Because we have implemented many new features, people start to use them in new ways. Some usage is clever, and some usage should obviously be included in the disabled list. The compiler itself uses new language features, so we also have a direct experience using these features to maintain code. This article describes many of the features and experience of using them.

We assume that you are familiar with these new features, so we will not fully introduce each feature. Instead, we will talk about interesting, but probably less obvious content and usage. These skills come from our practical experience and are categorized by language features.

We will gradually transition from the simplest features to advanced features. Generics are rich in content, so they are half the length of this article.

Enhanced for Loop

To iterate collections and arrays, the enhanced for loop provides a simple and compatible syntax. There are two points worth mentioning:

Init expression

In a loop, the initialization expression is calculated only once. This means that you can usually remove a variable declaration. In this example, we must create an integer array to save the computenumbers () result to prevent this method from being recalculated for each loop. As you can see, the following code is cleaner than the above Code, and the variable numbers is not leaked:

Unreinforced:
Int sum = 0;
Integer [] numbers = computenumbers ();
For (INT I = 0; I <numbers. length; I ++)
Sum + = numbers [I];
Enhanced:
Int sum = 0;

For (INT number: computenumbers ())
Sum + = number; Limitations

Sometimes you need to access the iterator or subscript during the iteration. It seems that the enhanced for loop should allow this operation, but in fact it is not like this. Please refer to the following example:
For (INT I = 0; I <numbers. length; I ++ ){
If (I! = 0) system. Out. Print (",");
System. Out. Print (numbers [I]);
} We want to print the values in the array into a comma-separated list. We need to know whether it is the first item so as to determine whether a comma should be printed. This information cannot be obtained using an enhanced for loop. We need to keep a subscript or a Boolean value to indicate whether the first item has passed. This is another example:

For (iterator It = n. iterator (); it. hasnext ();)
If (it. Next () <0)
It. Remove (); in this example, we want to delete negative items from the Integer Set. Therefore, we need to call a method for the iterator, but when using an enhanced for loop, the iterator is invisible to us. Therefore, we can only use the iteration method of Java 5 or earlier versions. By the way, note that iterator is declared as an iterator because it is generic. . Many people forget this and use the original iterator format.

Note

Annotation processing is a big topic. Because this article only focuses on the core language features, we do not intend to cover all its possible forms and traps. We will discuss the built-in annotations (suppresswarnings, deprecated and override) and the limitations of General annotation processing.
Suppress warnings

This annotation disables the class or method-level compiler warning. Sometimes you know more clearly than the compiler that the Code must use a rejected method or execute some actions that cannot be statically determined to be type-safe, and use:

@ Suppresswarnings ("deprecation ")
Public static void selfdestruct (){
Thread. currentthread (). Stop ();
} This may be the most useful place for built-in annotations. Unfortunately, javac 1.5.0 _ 04 does not support it. But 1.6 supports it, and sun is trying to port it back to 1.5.
Eclipse 3.1 supports this annotation, and other ides may also support it. This allows you to completely free code from warnings. If a warning occurs during compilation, you can confirm that you just added it to help you view the code that may be insecure. With the addition of generics, it will be easier to use.

Deprecated

Unfortunately, deprecated is not that useful. It was originally intended to replace the @ deprecated javadoc tag, but because it does not contain any fields, there is no way to recommend what the deprecated class or method users should use as a substitute. In most usage cases, the javadoc tag and the annotation are required at the same time. Override
Override indicates that the methods annotated by it should override the methods with the same signature in the superclass:

@ Override
Public int hashcode (){
...
} Looking at the example above, if "C" is not capitalized in hashcode, there will be no errors during compilation, but this method cannot be called as expected at runtime. By adding the override tag, the compiler will prompt whether it actually executes the rewrite.

This is also helpful when the superclass changes. If a new parameter is added to the method and the method itself is renamed, The subclass cannot be compiled because it no longer overwrites anything of the superclass.

Other annotations

Annotations are useful in other scenarios. Annotations run very well in frameworks such as EJB and web services, especially when you add sample code, instead of directly modifying the behavior but enhancing the behavior.
Annotations cannot be used as pre-processors. Sun's design specifically prevents modifying the class bytecode completely due to comments. In this way, you can correctly understand the results of the language, and tools such as IDE can also perform in-depth code analysis, refactoring, and other functions.

Note is not a silver bullet. At the first time, people tried various techniques. See the following suggestions from others:

Public class Foo {

@ Property
Private int bar;

} The idea is to automatically create the getter and setter methods for the private field bar. Unfortunately, this idea has two failures: 1) It cannot run, 2) It makes the code hard to read and process. It cannot be implemented, because Sun has previously mentioned that it is particularly blocked from modifying the classes with comments.

Even if possible, it is not a good idea because it makes the code less readable. The person who saw this code for the first time will not know how the annotation was created. In addition, annotations are useless if you need to perform some operations within these methods in the future.

In short, do not try to use comments to do things that can be done by conventional code.

Enumeration

Enum is very similar to the public static final int statement, which has been used as the enumerated value for many years. The biggest and most obvious improvement to Int Is type security-you cannot mistakenly use one type of enumeration to replace another type, which is different from Int, all int values are the same for the compiler. Except for a few exceptions, Enum instances should be used to replace all enumerated int structures.

Enumeration provides some additional features. The two classification classes enummap and enumset are specifically implemented for the standard set of enumeration optimization. If you know that the set only contains enumeration types, you should use these special sets to replace has hmap or hashset.

In most cases, you can use Enum to insert and replace all public static final int values in the code. They are comparable and can be imported statically, so references to them seem equivalent, even for internal classes (or internal enumeration types ). Note: When comparing enumeration types, the statements that declare them indicate their sequential values.

"Hidden" static method

The two static methods appear in all Enumeration type declarations. Because they are static methods on enumeration subclasses, rather than the enum method, they are not found in javadoc of Java. Lang. enum.

The first is values (), which returns an array of all possible values of the enumeration type.

The second is valueof (), which returns an enumeration type for the provided string. This enumeration type must exactly match the source code declaration.

Method

One of our favorite aspects about enumeration types is that it can have methods. In the past, you may need to write some code to convert public static final int and convert it from database type to jdbc url. Now, we can add a code sorting method to the enumeration type. The following is an example, which includes an abstract method of the databasetype Enumeration type and the implementation provided in each enumeration instance:

Public Enum databasetype {
Oracle {
Public String getjdbcurl (){...}
},
MySQL {
Public String getjdbcurl (){...}
};
Public abstract string getjdbcurl ();
} The Enumeration type can provide its practical method directly. For example:

Databasetype dbtype = ...;
String jdbcurl = dbtype. getjdbcurl ();

To obtain a URL, you must know in advance where the practical method is.
Variable Parameter (vararg)

Correct use of variable parameters can indeed clear some junk code. A typical example is a log method with variable number of string parameters:

Log. Log (string code)
Log. Log (string code, string Arg)
Log. Log (string code, string arg1, string arg2)
Log. Log (string code, string [] ARGs)

When talking about variable parameters, it is interesting that if you replace the first four examples with the new variable parameters, they will be compatible:

Log. Log (string code, string... ARGs)

All variable parameters are source compatible-that is to say, if you re-compile all the calling programs of the log () method, you can directly replace all four methods. However, if you need backward binary compatibility, you need to remove the first three methods. Only the method with the last string array parameter is equivalent to the variable parameter version, so it can be replaced by the variable parameter version.

Type forced conversion

If you want the caller to know which type of parameters should be used, you should avoid forced type conversion with variable parameters. Let's take a look at the example below. The first item is string, and the second item is exception:

Log. Log (object... objects ){
String message = (string) objects [0];
If (objects. length> 1 ){
Exception E = (exception) objects [1];
// Do something with the exception
}
} The method signature should be as follows, and the variable parameters should be declared using string and exception respectively:

Log. Log (string message, exception E, object... objects ){...}

Do not use variable parameters to destroy the type system. It can be used only when it is strongly typed. For this rule, printstream. printf () is an interesting exception: it provides type information as its first parameter so that it can accept those types later.

Covariant return

The basic usage of covariant return is to avoid forced type conversion when the returned type of an implementation is known to be more specific than the API. In the following example, there is a zoo interface that returns the animal object. Our implementation returns an animalimpl object, but before JDK 1.5, an animal object must be declared. :

Public interface zoo {
Public animal getanimal ();
}
Public class zooimpl implements zoo {
Public animal getanimal (){
Return new animalimpl ();
}
} Three reverse modes are replaced by the return value of the covariant:

Direct field access. To avoid API restrictions, some implementations expose the subclass as a field: zooimpl. _ animal

Another form is to execute the following downward conversion in the calling program when you know that the implementation is actually a specific subclass: (animalimpl) zooimpl. getanimal ()). implmethod ();

The last form I see is a specific method, which is used to avoid the problem caused by a completely different signature: zooimpl. _ getanimal ();

These three models have their own problems and limitations. Either it is not neat enough or it exposes unnecessary implementation details.

Covariant

The covariant return mode is neat, secure, and easy to maintain, and does not require type forced conversion or specific methods or fields:

Public animalimpl getanimal (){
Return new animalimpl ();
}

Result:
Zooimpl. getanimal (). implmethod ();

Use generic

We will understand generics from two perspectives: Using Generics and constructing generics. We will not discuss the obvious usage of list, set, and map. It is enough to know that the generic set is powerful and should be used frequently.

We will discuss how to use generic methods and how compilers deduce types. Generally, there will be no problems, but when there is a problem, the error information will be very confusing, so you need to know how to fix these problems.

Generic Method

In addition to generic types, Java 5 also introduces generic methods. In this example from Java. util. Collections, a single element list is constructed. The element type of the new list is inferred based on the object type of the input method:
Static List Collections. singletonlist (t o)
Example usage:
Public list Getlistofone (){
Return collections. singletonlist (1 );
} In the example, an int is input. Therefore, the return type of the method is list. . The compiler infers t to integer. This is different from the generic type because you do not need to explicitly specify the type parameter.
This also shows the interaction between automatic packing and generics. The type parameter must be of the reference type: that is why we get the list Instead of list .

Generic method without Parameters

The emptylist () method is introduced with generics as a safe replacement of the empty_list field type in Java. util. Collections:
Static List Collections. emptylist ()
Example usage:
Public list Getnointegers (){
Return collections. emptylist ();
} Unlike the previous example, this method has no parameters. How does the compiler infer the T type? Basically, it will try to use the parameter once. If it does not work, it tries to use the return or value type again. In this example, the returned list is So T is inferred to be integer.

What if the generic method is called outside the return statement or value assignment statement? Then the compiler will not be able to execute the second transfer of type inference. In the following example, emptylist () is called from the condition OPERATOR:

Public list Getnointegers (){
Return X? Collections. emptylist (): NULL;
} Because the compiler does not see the returned context and cannot infer t, it abandons and uses the object. You will see an error message, such as: "list cannot be converted to list ."
To fix this error, type parameters should be passed explicitly to the method call. In this way, the compiler will not try to deduce the type parameter, so it can get the correct result:

Return X? Collections. Emptylist (): NULL; this often happens in method calls. If a method includes a list Parameter, and you need to call the passed emptylist () for that parameter, you also need to use this syntax.

Outside the set

There are three examples of generic types. They are not a set, but they are used in a novel way. All three examples come from the standard Java Library:
Class
The class is parameterized on the class type. This makes it possible to construct a newinstance without forced type conversion.
Comparable
Comparable is parameterized by the actual comparison type. This provides stronger typing for compareto () calls. For example, string implements comparable . Calling compareto () for anything except string will fail during compilation.
Enum >
Enum is parameterized by Enumeration type. An Enumeration type named color will extend the Enum
. The getdeclaringclass () method returns class objects of the enumeration type. In this example, it is a color object. Unlike getclass (), the latter may return an unknown class.
Wildcard

The most complex part of generics is the understanding of wildcards. We will discuss three types of wildcards and their usage.

First, let's take a look at how arrays work. You can assign a value to a number [] from an integer. If you try to write a float to number [], you can compile it, but it will fail during runtime, and an arraystoreexception will appear:
Integer [] IA = new integer [5];
Number [] NA = IA;
Na [0] = 0.5; // compiles, but fails at runtime
If you try to convert this example to a generic type, the compilation will fail, because the assignment is not allowed:
List Ilist = new arraylist ();
List NLIST = ilist; // not allowed
NLIST. Add (0.5); if you use generics, you will not encounter classcastexception when the code is compiled without warning.

Upper Limit wildcard

What we want is a list of unknown exact element types, which is different from the array.

List Is a list whose element type is number.
List extends number> is a list of unknown element types. It is a number or its subtype.

Upper Limit

If we update the initial example and assign the value to list extends number>, the assignment will be successful now:

List Ilist = new arraylist ();
List extends number> NLIST = ilist;
Number N = NLIST. Get (0 );
NLIST. add (0.5); // not allowed we can get the number from the list, because no matter what the exact element type of the List is (float, integer, or number ), we can assign a value to number.

We still cannot insert the floating point type into the list. This will fail during compilation, because we cannot prove that this is safe. If we want to add a floating point type to the list, it will destroy the initial type security of ilist -- it only stores integer.

Wildcards give us more expressive power than arrays.

Why do I use wildcards?

In the following example, wildcards are used to hide type information from API users. Internally, set is stored as customerimpl. API users only know that they are acquiring a set from which they can read the customer.
Wildcards are required because To set Assignment:
Public class customerfactory {
Private set _ MERs MERS;
Public set extends customer> getcustomers (){
Return _ MERs MERS;
}
} Wildcard and collaborative return

Another common usage of wildcard is to use it together with the coordinated return. Rules with the same value assignment can be applied to the covariant return. If you want to return a more specific generic type in the override method, the declared method must use wildcards:

Public interface numbergenerator {
Public list extends number> Generate ();
}
Public class fibonaccigenerator extends numbergenerator {
Public list Generate (){
...
}
} To use an array, the interface can return number [], while the implementation can return integer [].

Lower limit

We are talking about the upper limit wildcard. There is also a lower limit wildcard. List super number> is a list that is unknown for the exact "element type", but may be a mnumber or a super-type of number. So it may be a list Or a list.

Lower-limit Wildcards are far less common than upper-limit wildcards, but they are required when they are needed.

Lower limit and Upper Limit

List extends number> readlist = new arraylist ();
Number N = readlist. Get (0 );

List super number> writelist = new arraylist ();
Writelist. Add (New INTEGER (5); the first one is a list of readings from it.
The second is a list of numbers that can be written.

Unbounded wildcard

Finally, the content of List> list can be of any type, and it is almost the same as list extends Object>. You can read objects at any time, but cannot write content to the list. Wildcards in public APIs
In short, as mentioned above, wildcards are very important in hiding implementation details from the caller, but even if the lower-limit wildcard seems to provide read-only access, since remove (INT position) and other non-generic methods. If you want a truly unchanged set, you can use methods on java. util. Collection, such as unmodifiablelist ().

Remember the wildcard when writing an API. In general, you should try to use wildcards when passing generic types. It allows more calling programs to access APIs.

By receiving list extends number> instead of list , The following method can be called by many different types of lists:

Void removenegatives (list extends number> list); construct a generic type

Now we will discuss how to construct your own generic type. We will show some examples, in which the use of generics can improve the type security, we will also discuss some common problems when implementing generic types.

Collection-like functions
The first example of a generic class is a collection style example. Pair has two types of parameters, and the fields are type instances:

Public final class pair {
Public final a first;
Public final B second;

Public pair (a first, B Second ){
This. First = first;
This. Second = second;
}
} This makes it possible to return two items from the method without writing a dedicated class for each combination of the two types. Another method is to return object [], which is insecure or untidy.

In the following usage, a file and a Boolean are returned from the method. The client of the method can directly use fields without forced type conversion:

Public pair Getfileandwritestatus (string path ){
// Create File and status
Return new pair (File, status );
}

Pair Result = getfileandwritestatus ("...");
File F = result. first;
Boolean writeable = result. Second; outside the set

In the following example, generics are used for additional compilation security. By setting the dbfactory class parameter to the created peer type, you actually force the factory subclass to return a specific child type of the Peer:

Public abstract class dbfactory {
Protected abstract t createemptypeer ();
Public list Get (string constraint ){
List Peers = new arraylist ();
// Database magic
Return peers;
}
}
Dbfactory , Customerfactory must return a customer from createemptypeer:
Public class customerfactory extends dbfactory {

Public customer createemptypeer (){
Return new customer ();
}
} Generic Method

Whether you want to impose constraints on generic types between parameters or between parameters and return types, you can use the generic method:

For example, if a reverse function is written to reverse the position, you may not need a generic method. However, if you want to reversely return a new list, you may want the element type of the new list to be the same as that of the imported list. In this case, a generic method is required:

List Reverse (list List)
Concrete

When implementing a generic class, you may want to construct an array T []. This is not allowed because generics are implemented through erasure.

You can try to forcibly convert object [] to T []. But this is not safe.

Specific Solution

According to the general practice of the generic tutorial, the solution uses a "type token" and adds a class to the constructor. You can force the client to provide the correct class object for the class type parameter:
Public class arrayexample {
Private class Clazz;

Public arrayexample (Class Clazz ){
This. clazz = clazz;
}

Public T [] getarray (INT size ){
Return (T []) array. newinstance (clazz, size );
}
} To construct arrayexample The client must pass string. class to the constructor, because the string. class type is class. .

Having class objects makes it possible to construct an array with the correct element type.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.