虽然是英文,还能看得懂,感觉变化了很大,用起来也简单多了!
Improved Type Inference
i. Constructors
The addition of generics to the language greatly improved compile time type checking and largely eliminated the need for casting. Unfortunately it also increased the verbosity of declarations, for example:
Map<String, List<String>> anagrams = new HashMap<String, List<String>>();
As a result, generic declarations often require multiple lines. It would be nice if you could omit the second occurrence of the type parameters (<String, List<String>>) and let the compiler figure it out ("constructor type inference "). This would remove the redundancy from the declaration, geatly enhancing readability and ease-of-use:
Map<String, List<String>> anagrams = new HashMap<>();//这个有意思!
See also http://gafter.blogspot.com/2007/07/constructor-type-inference.html
ii. Argument Positions
The result of a generic method, such as:
public <E> Set<E> emptySet() { ... }
may be used on the right-hand side of an assignment:
Set<Person> honestPoliticians = Collections.emptySet();
The compiler's type-inference mechanism figures out that the type parameter to the emptySet invocation is Person . It seems reasonable that the compiler should be able to infer the type when the result of such a generic method invocation is passed to another method:
void timeWaitsFor(Set<Man> people) { ... }
...
timeWaitsFor(Collections.emptySet()); // * Won't compile!
Sadly, this is not allowed. The specification currently requires an explicit type argument under these circumstances:
timeWaitsFor(Collections.<Man> emptySet());
Not only are explicit type arguments awkward, but many programmers are unfamiliar with them and unable to cope when the compiler requires them. With inference in argument positions, the explicit type argument is rarely required and the starred method invocation above becomes legal.
See also http://lampwww.epfl.ch/~odersky/ftp/local-ti.ps and http://www.javac.info/Inference.html
Enum Comparison
Enum constants can safely be compared for equality use the == operator. All enum types implement Comparable, so it stands to reason that it should be possible to compare constants of an enumerated type for order using the <, >, <=, and >= operators. Unfortunately, it isn't, so programmers are forced to litter their code with calls to the compareTo method:
enum Size { SMALL, MEDIUM, LARGE }
if (mySize.compareTo(yourSize) >= 0)
System.out.println("You can wear my shirt.");
If the <, >, <=, and >= operators worked for enums, this code could be replaced by the clearer:
if (mySize >= yourSize)
System.out.println("You can wear my shirt.");
See also http://www.javac.info/EnumCompare.html
String Switch
Information often comes into programs in string form, and some action (often translation into another form) takes place depending on the string value. For example, the following method translates strings to boolean values:
static boolean booleanFromString(String s) {
if (s.equals("true")) {
return true;
} else if (s.equals("false")) {
return false;
} else {
throw new IllegalArgumentException(s);
}
}
This code is not pretty, and somewhat bug-prone. If it were possible to switch on string values, this code could be replaced by the prettier and safer:
//这个也比较爽!
static boolean booleanFromString(String s) {
switch(s) {
case "true":
return true;
case "false":
return false;
}
throw new IllegalArgumentException(s);
}
See also http://yost.com/computers/java/string-switch/index.html
Chained Invocations
Some mutation-based APIs have a number of methods that return void. This is common in the factory pattern:
class Factory {
void setSomething(Something something) { ... }
void setOther(Other other) { ... }
Thing result() { ... }
}
Using such a class can be awkward
Factory fac = new Factory();
fac.setSomething(something);
fac.setOther(other);With chained invocations, you can reuse the receiver of the previous invocation and chain the calls together:
//这个更加爽!
Thing thing = new Factory()
.setSomething(something)
.setOther(other)
.result();
With this language support, it is much easier to define "fluent" APIs.
See also http://docs.google.com/View?docid=dg8rbgp8_0gnjwr2
Extension methods
Existing interfaces cannot be extended with additional methods without breaking some clients. Instead, functionality is typically "added to an interface" by static methods in a separate utility class. Using them is somewhat awkward:
List<String> list = ...;
Collections.sort(list);
With extension methods, client can designate utility methods to act as if they were members of the interface (or class)
import static java.util.Collections.sort;
list.sort();
Improved Catch Clauses
i. Catching Multiple Exception Types
It is often necessary to do the same thing when one of several exceptions occurs. Currently the only way to do this is to duplicate code in multiple catch clauses:
try {
return klass.newInstance();
} catch (InstantiationException e) {
throw new AssertionError(e);
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
It may be tempting to replace several catch clauses with one for the class that is the "least common ancestor" of the each of the exception types in question:
// Broken - catches exceptions that should be allowed to propagate!
try {
return klass.newInstance();
} catch (Exception e) {
throw new AssertionError(e);
}
Unfortunatley this does not have the correct semantics. In the case of this example, it erroneously wraps unchecked exceptions in assertion errors. To solve this problem, we propose that it be possible to catch two or more exception types in a single catch clause:
try {
return klass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new AssertionError(e);
}
See also http://www.javac.info/Multicatch.html
ii. Improved Checking for Rethrown Exceptions
It is not uncommon that you want to catch an exception, perform some action, and rethrow the exception:
try {
doable.doIt(); // Specified to throw several different exceptions
} catch (Throwable ex) {
logger.log(ex);
throw ex; // Won't compile unless method is specified to throw Throwable!
}
Unfortunately, it is not generally possible to do this, as the resulting catch clause throws the type of exception that was caught, which the enclosing method is typically not specified to throw. To get around this, programmers often wrap the exception prior to rethrowing it:
try {
doable.doIt();
} catch (Throwable ex) {
logger.log(ex);
throw new WrappedException(ex); // Obscures exception type!
}
If a caught exception is declared final, it is safe to rethrow any caught exception:
try {
doable.doIt();
} catch (final Throwable ex) {
logger.log(ex);
throw ex;
}
Because the catch parameter is final, it can only hold exceptions that are thrown from the try block. Exception checking should take advantage of that fact: the compiler should treat this rethrown exception as if it can throw only checked exceptions that occur in the try block.
还有其他的希望大家补充!!