java7新特性之Simplified varargs method invocation

java7新特性之Simplified varargs method invocation

This is one of the simplest changes of all—it moves a warning about type information

for a very specific case where varargs combines with generics in a method signature.

Put another way, unless you’re in the habit of writing code that takes as arguments

a variable number of references of type T and does something to make a collection

out of them, you can move on to the next section. On the other hand, if this bit of

code looks like something you might write, you should read on:

public static <T> Collection<T> doSomething(T... entries) {
...
}

Still here? Good. So what’s this all about?

As you probably know, a varargs method is one that takes a variable number of

parameters (all of the same type) at the end of the argument list. What you may not

know is how varargs is implemented; basically, all of the variable parameters at the end

are put into an array (which the compiler automatically creates for you) and they’re

passed as a single parameter.

This is all well and good, but here we run into one of the admitted weaknesses of

Java’s generics—you aren’t normally allowed to create an array of a known generic

type. For example, this won’t compile:

HashMap<String, String>[] arrayHm = new HashMap<>[2];

You can’t make arrays of a specified generic type. Instead, you have to do this:

HashMap<String, String>[] warnHm = new HashMap[2];

This gives a warning that has to be ignored. Notice that you can define the type of

warnHm to be an array of HashMap<String, String>—you just can’t create any instances

of that type, and instead have to hold your nose (or at least, suppress the warning) and

force an instance of the raw type (which is array of HashMap) into warnHm.

These two features—varargs methods working on compiler-generated arrays, and

arrays of known generic types not being an instantiable type—come together to cause

a slight headache. Consider this bit of code:

HashMap<String, String> hm1 = new HashMap<>();

HashMap<String, String> hm2 = new HashMap<>();

Collection<HashMap<String, String>> coll = doSomething(hm1, hm2);

The compiler will attempt to create an array to contain hm1 and hm2, but the type of

the array should strictly be one of the forbidden array types. Faced with this dilemma,

the compiler cheats and breaks its own rule about the forbidden array of generic type.

It creates the array instance, but grumbles about it, producing a compiler warning

that mutters darkly about “unchecked or unsafe operations.”

From the point of view of the type system, this is fair enough. But the poor developer just wanted to use what seemed like a perfectly sensible API, and there are scarysounding warnings for no adequately explained reason.

WHERE DID THE WARNING GO IN JAVA 7?

The new feature in Java 7 changes the emphasis of the warning. After all, there is a

potential for violating type safety in these types of constructions, and somebody
had better be informed about them. There’s not much that the users of these types of APIs

can really do, though. Either the code inside doSomething() is evil and violates type

safety, or it doesn’t. In any case, it’s out of the API user’s hands.

The person who should really be warned about this issue is the person who wrote

doSomething()—the API producer, rather than the consumer. So that’s where the

warning goes—it’s moved from where the API is used to where the API was defined.

The warning once was triggered when code that used the API was compiled.

Instead, it’s now triggered when an API that has the potential to trigger this kind of

type safety violation is written. The compiler warns the coder implementing the API,

and it’s up to that developer to pay proper attention to the type system.

To make things easier for API developers, Java 7 also provides a new annotation

type, java.lang.SafeVarargs. This can be applied to an API method (or constructor)

that would otherwise produce a warning of the type discussed. By annotating the

method with @SafeVarargs, the developer essentially asserts that the method doesn’t

perform any unsafe operations. In this case, the compiler will suppress the warning.

CHANGES TO THE TYPE SYSTEM

That’s an awful lot of words to describe a very small change—moving a warning from

one place to another is hardly a game-changing language feature, but it does serve to

illustrate one very important point. Earlier in this chapter we mentioned that Project

Coin encouraged contributors to mostly stay away from the type system when proposing changes. This example shows how much care is needed when figuring out how different features of the type system interact, and how that interaction will alter when a

change to the language is implemented. This isn’t even a particularly complex

change—larger changes would be far, far more involved, with potentially dozens of

subtle ramifications.

This final example illustrates how intricate the effect of small changes can be.

Although they represent mostly small syntactic changes, they can have a positive impact

on your code that is out of proportion with the size of the changes. Once you’ve started

using them, you’ll likely find that they offer real benefit to your programs.

读书笔记:The Well-Grounded Java Develope

时间: 2024-10-04 21:00:57

java7新特性之Simplified varargs method invocation的相关文章

java7新特性之Try-with-resources (TWR)

java7新特性之Try-with-resources (TWR) This change is easy to explain, but it has proved to have hidden subtleties, which made it much less easy to implement than originally hoped. The basic idea is to allow a resource (for example, a file or something a

java7新特性之Diamond syntax

java7新特性之Diamond syntax Java 7 also introduces a change that means less typing for you when dealing with generics. One of the problems with generics is that the definitions and setup of instances can be really verbose. Let's suppose that you have som

java7新特性

1 package com.test; 2 3 import java.io.BufferedReader; 4 import java.io.FileReader; 5 import java.io.IOException; 6 import java.sql.Connection; 7 import java.sql.DriverManager; 8 import java.sql.PreparedStatement; 9 import java.sql.ResultSet; 10 impo

小菜修炼之道——Java7新特性

1.TWR 自动关闭资源 自动关闭资源必须要注意书写规范,所有需要关闭的资源必须使用一个变量声明出来并且写在try的小括号块中,不是大括号.如下代码: try(  InputStream is = new FileInputStream(new File(path))    ){ // 可能发生异常的代码 }catch(Exception e){ // 异常信息捕获 }finally{ // 自动关闭资源,无需手动处理 is } 2.switch 新增字符串支持 在java7之前switch只是

java7新特性(简述八大新特性)

1.switch中添加对String类型的支持 public String generate(String name, String gender) { String title = ""; switch (gender) { case "男": title = name + " 先生"; break; case "女": title = name + " 女士"; break; default: titl

Java之Java7新特性之try资源句式

一.原来写法: 1 static String readFirstLineFromFile(String path) throws IOException { 2 BufferedReader br = null; 3 try { 4 br = new BufferedReader(new FileReader(path)); 5 } catch (Exception ex) { 6 //do exception action 7 } finally { 8 if (br != null) {

java7 新特性 总结版

http://www.zhuke.com/user/zkuser57546968?p6=123.baidu.com=&lvhttp://www.zhuke.com/user/zkuser59918842?p6=123.baidu.com=&lvhttp://www.zhuke.com/user/zkuser56775905?p6=123.baidu.com=&lvhttp://www.zhuke.com/user/zkuser71200347?p6=123.baidu.com=&a

java7和java8新特性

以下来至网址: http://blog.csdn.net/samjustin1/article/details/52268004 Java7 新特性 1.switch中可以使用字符串了 String s = "test"; switch (s) { case "test" : System.out.println("test"); case "test1" : System.out.println("test1&qu

java5、java6、java7、java8的新特性

Java5: 1.泛型 Generics:        引用泛型之后,允许指定集合里元素的类型,免去了强制类型转换,并且能在编译时刻进行类型检查的好处. Parameterized Type作为参数和返回值,Generic是vararg.annotation.enumeration.collection的基石. A.类型安全 抛弃List.Map,使用List<T>.Map<K,V>给它们添加元素或者使用Iterator<T>遍历时,编译期就可以给你检查出类型错误 B