Java 7 的7个新特性.docx
《Java 7 的7个新特性.docx》由会员分享,可在线阅读,更多相关《Java 7 的7个新特性.docx(9页珍藏版)》请在冰豆网上搜索。
Java7的7个新特性
Java7的7个新特性
1.对集合类的语言支持;
2.自动资源管理;
3.改进的通用实例创建类型推断;
4.数字字面量下划线支持;
5.switch中使用string;
6.二进制字面量;
7.简化可变参数方法调用。
1.对集合类的语言支持
Java将包含对创建集合类的第一类语言支持。
这意味着集合类的创建可以像Ruby和Perl那样了。
原本需要怎样:
1Listlist=newArrayList();
2list.add("item");
3Stringitem=list.get(0);
4
5Setset=newHashSet();
6set.add("item");
7Mapmap=newHashMap();
8map.put("key",1);
9intvalue=map.get("key");
现在只需这样:
(这些集合是不可变的...)
1Listlist=["item"];
2Stringitem=list[0];
3
4Setset={"item"};
5
6Mapmap={"key":
1};
7intvalue=map["key"];
2.自动资源管理
Java中某些资源是需要手动关闭的,如InputStream,Writes,Sockets,Sqlclasses等。
这个新的语言特性允许try语句本身申请更多的资源,这些资源作用于try代码块,并自动关闭。
以前的写法:
1BufferedReaderbr=newBufferedReader(newFileReader(path));
2try{
3returnbr.readLine();
4}finally{
5br.close();
6}
现在可以:
(有点像C#)
1try(BufferedReaderbr=newBufferedReader(newFileReader(path)){
2returnbr.readLine();
3}
3.改进的通用实例创建类型推断;
类型推断是一个特殊的烦恼,如下面的代码:
1Map>anagrams=newHashMap>();
通过类型推断后变成:
1Map>anagrams=newHashMap<>();
注:
这个<>被叫做diamond(钻石)运算符,Java7后这个运算符从引用的声明中推断类型。
4.数字字面量下划线支持
很长的数字可读性不好,在Java7中可以使用下划线分隔长int以及long了。
如:
intone_million=1_000_000;
这样子还真看不惯。
。
。
不过的确是可读性好了。
5.switch中使用string
这个问题是我在Java中不喜欢用switch的原因之一,以前在switch中只能使用number或enum。
现在可以使用string了,哈哈,不错,赞个!
1Strings=...
2switch(s){
3case"quux":
4processQuux(s);
5//fall-through
6case"foo":
7case"bar":
8processFooOrBar(s);
9break;
10case"baz":
11processBaz(s);
12//fall-through
13default:
14processDefault(s);
15break;
16}
6.二进制字面量
由于继承C语言,Java代码在传统上迫使程序员只能使用十进制,八进制或十六进制来表示数(numbers)。
由于很少的域是以bit导向的,这种限制可能导致错误。
你现在可以使用0b前缀创建二进制字面量:
1intbinary=0b1001_1001;
现在,可以使用二进制字面量这种表示方式,并且使用非常简短的代码,可将二进制字符转换为数据类型,如在byte或short。
1byteaByte=(byte)0b001;
2shortaShort=(short)0b010;
7.简化可变参数方法调用。
当程序员试图使用一个不可具体化的可变参数并调用一个*varargs*(可变)方法时,编辑器会生成一个“非安全操作”的警告。
JDK7将警告从call转移到了方法声明(methorddeclaration)的过程中。
这样API设计者就可以使用vararg,因为警告的数量大大减少了。
Java7的新特性
在switch语句中使用String
在JDK7发布版本中,开发人员可以在switch表达是中,使用String对象:
publicStringgetTypeOfDayWithSwitchStatement(StringdayOfWeekArg){
StringtypeOfDay;
switch(dayOfWeekArg){
case"Monday":
typeOfDay="Startofworkweek";
break;
case"Tuesday":
case"Wednesday":
case"Thursday":
typeOfDay="Midweek";
break;
case"Friday":
typeOfDay="Endofworkweek";
break;
case"Saturday":
case"Sunday":
typeOfDay="Weekend";
break;
default:
thrownewIllegalArgumentException("Invaliddayoftheweek:
"+dayOfWeekArg);
}
returntypeOfDay;
}
这次switch的增强,避免了遇到判断多个String对象时,使用多个if-else的表达式。
try-with-resources语句
try-with-resources语句是指在try语句中,描述了一个或多个资源资源的语句块,资源是指当程序结束后,必须关闭的资源对象。
与try语句连用,确保接程序结束之前,每一个资源都被释放或关闭。
任何实现了java.lang.AutoCloseable接口的可以作为一个资源使用。
例如java.io.InputStream,OutputStream,Reader,Writer,java.sql.Connection,Statement,和ResultSet,都实现了AutoCloseable接口,所有实现了这些接口的类都可以使用try-with-resources语句。
考虑下面的例子,从文件中读取第一行。
它会使用一个BufferReader的实例来从文件中读取数据。
BufferReader是一个资源,当程序结束之前,必须确保被关闭,下面的例子中,不管try语句中,是否出现异常,使用finally语句块来确保BufferReader的实例被正常关闭。
staticStringreadFirstLineFromFile(Stringpath)throwsIOException{
BufferedReaderbr=newBufferedReader(newFileReader(path));
try{
returnbr.readLine();
}finally{
br.close();
}
}
在使用JAVASE7后,可以使用下面的方式来完成同样的功能。
staticStringreadFirstLineFromFile(Stringpath)throwsIOException{
try (BufferedReaderbr=newBufferedReader(newFileReader(path)){
returnbr.readLine();
}
}
我们在try-with-resources语句中,可以定义多个资源文件。
下面的例子是一个拷贝文件的静态方法。
这个例子展示了在先前JavaSE版本中如何释放两个资源:
staticvoidcopy(Stringsrc,Stringdest)throwsIOException{
InputStreamin=newFileInputStream(src);
try{
OutputStreamout=newFileOutputStream(dest);
try{
byte[]buf=newbyte[8*1024];
intn;
while((n=in.read(buf))>=0)
out.write(buf,0,n);
}finally{
out.close();
}
}finally{
in.close();
}
}
下面的例子通过使用try-with-resources语句实现了同样的功能。
Thefollowingexamplehasthesamefunctionalityasthepreviousexample,exceptitusesatry-with-resourcesstatement:
staticvoidcopy(Stringsrc,Stringdest)throwsIOException{
try (InputStreamin=newFileInputStream(src);
OutputStreamout=newFileOutputStream(dest)){
byte[]buf=newbyte[8192];
intn;
while((n=in.read(buf))>=0)
out.write(buf,0,n);
}
}
在例子中,包含了两个资源,可以看出处理起来相当繁琐,需要嵌套的使用try语句才可以完成。
下面再给出使用try-with-resources语句自动关闭java.sql.Statement对象的例子:
publicstaticvoidviewTable(Connectioncon)throwsSQLException{
Stringquery="selectCOF_NAME,SUP_ID,PRICE,SALES,TOTALfromCOFFEES";
try(Statementstmt=con.createStatement()) {
ResultSetrs=stmt.executeQuery(query);
while(rs.next()){
StringcoffeeName=rs.getString("COF_NAME");
intsupplierID=rs.getInt("SUP_ID");
floatprice=rs.getFloat("PRICE");
intsales=rs.getInt("SALES");
inttotal=rs.getInt("TOTAL");
System.out.println(coffeeName+","+supplierID+","+price+
","+sales+","+total);
}
}catch(SQLExceptione){
JDBCTutorialUtilities.printSQLException(e);
}
}
泛型接口的使用
看下面一个泛型变量的例子:
Map>myMap=newHashMap>();
在JavaSE7,可以使用不带任何泛型参数的方式来构造一个泛型变量,例如:
Map>myMap=newHashMap<>();
再看一个错误使用的例子,下面的例子编译时会出错
Listlist=newArrayList<>();
list.add("A");
list.addAll(newArrayList<>());
原因是因为list定义的泛型是String,addAll方法指能接受addAllArrayList的实例。
捕获多个异常类型,使用改进的类型检查重新抛出异常
处理多个异常类型
在JavaSE第7和更高的版本,一个catch块可以处理多个类型的异常。
此功能可以降低代码重复,并减少捕捉异常过于宽泛的缺陷。
请考虑下面的示例中,在每一个catch块中,都包含了重复的代码:
catch(IOExceptionex){
logger.log(ex);
throwex;
catch(SQLExceptionex){
logger.log(ex);
throwex;
}
在JavaSE7之前的版本,很难通过一个通用的方法消除重复的代码,因为变量前ex都有不同的异常类型。
下面的示例中,在JavaSE7及更高版本中是可以使用的,可以消除重复的代码:
catch(IOException|SQLExceptionex){
logger.log(ex);
throwex;
}
catch子句指定了需要捕获的所有异常类型,每种异常类型之间用(|)隔开。
注:
如果catch块处理多个异常类型时,参会会被隐式的标记为final,在上面的例子中,ex捕获参数是隐式的标记为final的,因此在catch块中,不能对ex重新赋值。
编译可以处理多个异常类型的catch块,比编译许多catch块生成的字节码较小,而且性能更好,编译的字节码中,也不会有重复代码。
用兼容性更强的类型检查重新抛出异常
JavaSE7编译器对于重新抛出异常的处理上,比早期版本的JavaSE有更精确的分析。
这使您能够在throws代码块中,指定更加具体的异常类型。
考虑下面的例子
staticclassFirstExceptionextendsException{}
staticclassSecondExceptionextendsException{}
publicvoidrethrowException(StringexceptionName)throwsException{
try{
if(exceptionName.equals("First")){
thrownewFirstException();
}else{
thrownewSecondException();
}
}catch(Exceptione){
throwe;
}
}
此示例的try块可能抛出FirstException或SecondException。
假设您想要的rethrowException方法声明throw块中指定这些异常类型。
在JavaSE7之前的版本,是不能这样做的。
因为catch块的参数e,是Exception类型的,catch块再次抛出的异常的参数e、只能通过在rethrowException方法中指定throws块为Exception类型的异常。
然而,在JavaSE7中,你可以在throws子句中,指定FirstException和SecondException的异常类型。
JavaSE7编译器能判断出是最终抛出FirstException还是SecondException。
即使异常参数e是Exception类型的:
publicvoidrethrowException(StringexceptionName)
throwsFirstException,SecondException{
try{
//...
}
catch(Exceptione){
throwe;
}
}
在数字定义中使用下划线
在JavaSE第7和更高的版本,可以数字的任何位置可以使用任意个的下划线字符(_)。
,可以提高代码的可读性。
例如,如果您的代码中包含很多位数的数字,你可以使用下划线分隔,类似于在句子中,使用都标点符号作为分隔符。
下面的示例显示在数字中使用下划线的方法:
longcreditCardNumber=1234_5678_9012_3456L;
longsocialSecurityNumber=999_99_9999L;
floatpi=3.14_15F;
longhexBytes=0xFF_EC_DE_5E;
longhexWords=0xCAFE_BABE;
longmaxLong=0x7fff_ffff_ffff_ffffL;
bytenybbles=0b0010_0101;
longbytes=0b11010010_01101001_10010100_10010010;
你只能将下划线放在数字之间的位置,你不能将下划线放在下面几个地方
•在数字开发不能放
•在小数点傍边不能使用下划线
•不能放在F或L后缀之前
•本该是非数字字符的位置上不能使用下划线。
下面是一些非法和合法的例子
floatpi1=3_.1415F;//Invalid;cannotputunderscoresadjacenttoadecimalpoint
floatpi2=3._1415F;//Invalid;cannotputunderscoresadjacenttoadecimalpoint
longsocialSecurityNumber1
=999_99_9999_L;//Invalid;cannotputunderscorespriortoanLsuffix
intx1=_52;//Thisisanidentifier,notanumericliteral
intx2=5_2;//OK(decimalliteral)
intx3=52_;//Invalid;cannotputunderscoresattheendofaliteral
intx4=5_______2;//OK(decimalliteral)
intx5=0_x52;//Invalid;cannotputunderscoresinthe0xradixprefix
intx6=0x_52;//Invalid;cannotputunderscoresatthebeginningofanumber
intx7=0x5_2;//OK(hexadecimalliteral)
intx8=0x52_;//Invalid;cannotputunderscoresattheendofanumber
intx9=0_52;//OK(octalliteral)
intx10=05_2;//OK(octalliteral)
intx11=052_;//Invalid;cannotputunderscoresattheendofanumber