`
kaka2008
  • 浏览: 91601 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java 7 新特性 -- 实战篇

阅读更多
   “举世瞩目”的java 7近日发布,oracle网站上列出了java 语言的新特性 http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html,最近出差,晚上闲来无事,将这些java语言的新特性试了下,very cool。
    下面介绍了java 7的一些新特性,翻译自oracle网站,结合自己的实战。对Java 7研究不深,以下内容有对有错,欢迎大家批评指正,共同学习!

    环境: ubuntu 11.04+eclipse 3.8
    本来是用netbeans7.0.1,可是非常难用(不习惯 netBeans),加之用了几天之后,eclipse3.8推出,也支持java7,就切换到了更熟悉的eclipse下。顺便说一句,ubuntu11.04界面做的挺不错的,非常喜欢(附图是win 7下的无缝模式)。

    eclipse 3.8下载: http://download.eclipse.org/eclipse/downloads/drops/S-3.8M1-201108031800/
    Netbeans 7.0.1 下载:[url] http://netbeans.org/downloads/start.html?platform=linux&lang=zh_CN&option=javaee[/url]


    特性1:二进制字面值(Binary Literals)

    在java7里,整形(byte,short,int,long)类型的值可以用二进制类型来表示了,在使用二进制的值时,需要在前面加上ob或oB,看代码
   
        //b 大小写都可以
	int a = 0b01111_00000_11111_00000_10101_01010_10;
	short b = (short)0b01100_00000_11111_0;
	byte c = (byte)0B0000_0001;
    


    其次,二进制同十进制和十六进制相比,可以一目了然的看出数据间的关系。例如下面这个数组中展示了每次移动一位后数字的变化。
   
  public static final int[] phases = {
     0b00110001,
     0b01100010,
     0b11000100,
     0b10001001,
     0b00010011,
     0b00100110,
     0b01001100,
     0b10011000
  }

如果用十六进制来表示的,它们之间的关系就无法一眼看出来了。
   public static final int[] phases = {
    0x31, 0x62, 0xC4, 0x89, 0x13, 0x26, 0x4C, 0x98
   }


    特性2:数字变量对下划线_的支持

    你可以在数值类型的变量里添加下滑线,除了以下的几个地方不能添加:
      数字的开头和结尾
      小数点前后
      F或者L前
      需要出现string类型值的地方(针对用0x或0b表示十六进制和二进制,参考第一点),比如0x101,不能用0_x101
   
      int num = 1234_5678_9;
      float num2 = 222_33F;
      long num3 = 123_000_111L;
      
      //下面的不行
      //数字开头和结尾
      int nu = _123;
      int nu = 123_;
      //小数点前后
      float f = 123_.12;
      float f = 123._12;
      //F或者L前
      long l = 123_L;
      float f = 123_F;
      //需要出现String的地方
      int num = 0_b123;
      float f = 0_x123F;
    


    这个,我个人觉得没什么实际作用,只是可以提升代码的可读性。

    特性3:switch 对String的支持

    这个大家期待很久了,switch终于支持String了
   
    public static void first() {
        //项目状态
        String status = "approval";
        //我们之前经常根据项目状态不同来进行不同的操作
        //目前已经换成enum类型
        
        switch (status) {
            case "shouli":
                System.out.println("状态是受理");
                break;
            case "approval":
                System.out.println("状态是审批");
                break;
            case "finish":
                System.out.println("状态是结束");
                break;
            default:
                System.out.println("状态未知");
        }
    }


    每个case是使用String的equals方法来进行比较的,对大小写敏感。

    和一连串的if-else-then想比,使用switch来计较String,Java编译器会生成更加有效的字节码,写一个例子测试一下。

  public static void second() {
        String status = "approval";
        if ("shouli".equals(status)) {
            System.out.println("状态是受理");
        } else if ("approval".equals(status)) {
            System.out.println("状态是审批");
        } else if ("finish".equals(status)) {
            System.out.println("状态是结束");
        } else {
            System.out.println("状态未知");
        }
  }

使用javap之后,生成字节码如下:
switch
public static void first();
    Code:
       0: ldc           #2                  // String approval
       2: astore_0      
       3: aload_0       
       4: astore_1      
       5: iconst_m1     
       6: istore_2      
       7: aload_1       
       8: invokevirtual #3                  // Method java/lang/String.hashCode:()I
      11: lookupswitch  { // 3
           -1274442605: 72
            -903146056: 44
            1185244739: 58
               default: 83
          }
      44: aload_1       
      45: ldc           #4                  // String shouli
      47: invokevirtual #5                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      50: ifeq          83
      53: iconst_0      
      54: istore_2      
      55: goto          83
      58: aload_1       
      59: ldc           #2                  // String approval
      61: invokevirtual #5                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      64: ifeq          83
      67: iconst_1      
      68: istore_2      
      69: goto          83
      72: aload_1       
      73: ldc           #6                  // String finish
      75: invokevirtual #5                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      78: ifeq          83
      81: iconst_2      
      82: istore_2      
      83: iload_2       
      84: tableswitch   { // 0 to 2
                     0: 112
                     1: 123
                     2: 134
               default: 145
          }
     112: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
     115: ldc           #8                  
     117: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     120: goto          153
     123: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
     126: ldc           #10                 
     128: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     131: goto          153
     134: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
     137: ldc           #11                 
     139: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     142: goto          153
     145: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
     148: ldc           #12                
     150: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     153: return  


   用if-else串生成的字节码
  
       public static void second();
    Code:
       0: ldc           #2                  // String approval
       2: astore_0      
       3: ldc           #4                  // String shouli
       5: aload_0       
       6: invokevirtual #5                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z
       9: ifeq          23
      12: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
      15: ldc           #8                  
      17: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      20: goto          71
      23: ldc           #2                  // String approval
      25: aload_0       
      26: invokevirtual #5                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      29: ifeq          43
      32: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
      35: ldc           #10                 
      37: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      40: goto          71
      43: ldc           #6                  // String finish
      45: aload_0       
      46: invokevirtual #5                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      49: ifeq          63
      52: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
      55: ldc   
      57: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      60: goto          71
      63: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
      66: ldc           #12                 
      68: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      71: return 
   

   网上说,用switch之后比用if-else生成的字节码更有效一些,不过目前至少从长度上来说,switch还是长一些
  

   特性4:try-with-resources 声明

   try-with-resources 是一个定义了一个或多个资源的try 声明,这个资源是指程序处理完它之后需要关闭它的对象。try-with-resources 确保每一个资源在处理完成后都会被关闭。
可以使用try-with-resources的资源有:
任何实现了java.lang.AutoCloseable 接口和java.io.Closeable 接口的对象。

来看例子:
  public static String readFirstLineFromFile(String path) throws IOException {
     try (BufferedReader br = new BufferedReader(new FileReader(path))) {
       return br.readLine();
     }
}

   在java 7 以及以后的版本里,BufferedReader实现了java.lang.AutoCloseable接口。
  
        try (Closeable obj = new Closeable() {
	       @Override
	       public void close() throws IOException {
		  // do something
	        }
	}) {
	// do something
	}

	try (AutoCloseable obj = new AutoCloseable() {
	        @Override
		public void close() throws IOException {
		   // do something
		}
	}) {
   	   // do something
	} 
   

  
   由于BufferedReader定义在try-with-resources 声明里,无论try语句正常还是异常的结束,它都会自动的关掉。而在java7以前,你需要使用finally块来关掉这个对象。
 
  public static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
     BufferedReader br = new BufferedReader(new FileReader(path));
     try {
        return br.readLine();
     } finally {
        if (br != null) br.close();
     }
   }
 


   然而,如果 readLine() 和 close() 这两个方法都抛出异常,那么readFirstLineFromFileWithFinallyBlock 方法只会抛出后面部分也就是finally块中的内容,try块中的异常就被抑制了,对于我们的程序来说,这显然不是一种好的方式。
   而在java 7中,无论是try块还是try-with-resource中抛出异常,readFirstLineFromFile会捕捉到try块的异常,try-with-resources中中异常被禁止了。在java 7 中,你能捕捉到被禁止的异常。后面会介绍。
 
   另外,一个try-with-resourcse声明了可以包含多个对象的声明,用分号隔开,和声明一个对象相同,会在结束后自动调用close方法,调用顺序和生命顺序相反。
  
    try (
      java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName);
      java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
    ) {
      // do something
    }
   

 
  此外,try-with-resources 可以跟catch和finally,catch和finally的是在try-with-resources里声明的对象关闭之后才执行的。


   特性5:捕获多种异常并用改进后的类型检查来重新抛出异常
  
   1、捕获多种异常

   在Java SE7里,一个catch可以捕获多个异常,这样可以减少重复代码。每个异常之间用 | 隔开。
  
     public static void first(){
         try {
	    BufferedReader reader = new BufferedReader(new FileReader(""));
	    Connection con = null;
	    Statement stmt = con.createStatement();
         } catch (IOException | SQLException e) {
	    //捕获多个异常,e就是final类型的
	    e.printStackTrace();
         }
     }
   

   而在Java SE6以前,需要这样写
  
       public static void second() {
		try {
			BufferedReader reader = new BufferedReader(new FileReader(""));
			Connection con = null;
			Statement stmt = con.createStatement();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
   

   注意,如果一个catch处理了多个异常,那么这个catch的参数默认就是final的,你不能在catch块里修改它的值。
   另外,用一个catch处理多个异常,比用多个catch每个处理一个异常生成的字节码要更小更高效。

   使用一个catch生成的字节码
  
     public static void first();
    Code:
       0: new           #2                  // class java/io/BufferedReader
       3: dup           
       4: new           #3                  // class java/io/FileReader
       7: dup           
       8: ldc           #4                  // String 
      10: invokespecial #5                  // Method java/io/FileReader."<init>":(Ljava/lang/String;)V
      13: invokespecial #6                  // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;)V
      16: astore_0      
      17: aconst_null   
      18: astore_1      
      19: aload_1       
      20: invokeinterface #7,  1            // InterfaceMethod java/sql/Connection.createStatement:()Ljava/sql/Statement;
      25: astore_2      
      26: goto          34
      29: astore_0      
      30: aload_0       
      31: invokevirtual #10                 // Method java/lang/Exception.printStackTrace:()V
      34: return        
    Exception table:
       from    to  target type
           0    26    29   Class java/io/IOException
           0    26    29   Class java/sql/SQLException
   


   使用两个catch生成的字节码
  
     public static void second();
    Code:
       0: new           #2                  // class java/io/BufferedReader
       3: dup           
       4: new           #3                  // class java/io/FileReader
       7: dup           
       8: ldc           #4                  // String 
      10: invokespecial #5                  // Method java/io/FileReader."<init>":(Ljava/lang/String;)V
      13: invokespecial #6                  // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;)V
      16: astore_0      
      17: aconst_null   
      18: astore_1      
      19: aload_1       
      20: invokeinterface #7,  1            // InterfaceMethod java/sql/Connection.createStatement:()Ljava/sql/Statement;
      25: astore_2      
      26: goto          42
      29: astore_0      
      30: aload_0       
      31: invokevirtual #11                 // Method java/io/IOException.printStackTrace:()V
      34: goto          42
      37: astore_0      
      38: aload_0       
      39: invokevirtual #12                 // Method java/sql/SQLException.printStackTrace:()V
      42: return        
    Exception table:
       from    to  target type
           0    26    29   Class java/io/IOException
           0    26    37   Class java/sql/SQLException
   

  
   switch那里生成的字节码不太明显看出来优化在哪里,这个很明显。首先,字节码长度变少 其次,从最后可以看出,target type都指向29行,两个catch会指向不同的行~

   2、用更包容性的类型检查来重新抛出异常

   在方法的声明上,使用throws语句时,你可以指定更加详细的异常类型。
  
  
   static class FirstException extends Exception { }
   static class SecondException extends Exception { }

   public void rethrowException(String exceptionName) throws Exception {
     try {
        if (exceptionName.equals("First")) {
            throw new FirstException();
        } else {
            throw new SecondException();
        }
     } catch (Exception e) {
      throw e;
     }
    }
   


   这个例子,try块中只能抛出两种异常,但是因为catch里的类型是 Exception,在java SE7以前的版本中,在方法声明中throws 只能写Exception,但是在java SE7及以后的版本中,可以在throws后面写 FirstException和SecondException——编译器能判断出throw e语句抛出的异常一定来自try块,并且try块只能抛出FirstException和SecondException。
  
     public static void reThrowException(String exceptionName)
			throws FirstException, SecondException{
	try {
	    if ("first".equals(exceptionName))
		throw new FirstException();
	    else
		throw new SecondException();
	    } catch (Exception e) {
		throw e;
	    }
        }
   

  
    所以尽管catch里的异常类型是Exception,编译器仍然能够知道它是FirstException和 SecondException的实例。怎么样,编译器变得更智能了吧。

    但是,如果在catch里对异常重新赋值了,在方法的throws后无法再向上面那样写成FirstException和SecondException了,而需要写成 Exception。

    具体来说,在Java SE 7及以后版本中,当你在catch语句里声明了一个或多个异常类型,并且在catch块里重新抛出了这些异常,编译器根据下面几个条件来去核实异常的类型:
    
- Try块里抛出它
- 前面没有catch块处理它
- 它是catch里一个异常类型的父类或子类。


    特性6:创建泛型对象时类型推断

    只要编译器可以从上下文中推断出类型参数,你就可以用一对空着的尖括号<>来代替泛型参数。这对括号私下被称为菱形(diamond)。

    在Java SE 7之前,你声明泛型对象时要这样
   
      List<String> list = new ArrayList<String>();
    


    而在Java SE7以后,你可以这样
   
      List<String> list = new ArrayList<>();
    

  
     因为编译器可以从前面(List)推断出推断出类型参数,所以后面的ArrayList之后可以不用写泛型参数了,只用一对空着的尖括号就行。当然,你必须带着”菱形”<>,否则会有警告的。
  
     Java SE7 只支持有限的类型推断:只有构造器的参数化类型在上下文中被显著的声明了,你才可以使用类型推断,否则不行。
    
     List<String> list = new ArrayList<>();
     list.add("A");

     //这个不行
     list.addAll(new ArrayList<>());

     // 这个可以
     List<? extends String> list2 = new ArrayList<>();
     list.addAll(list2);
     


     注意:菱形<>主要用在变量声明里。
 
     类里也可以使用类型推断
    


    准备返京,未完待续~


    Java 7 从呼之欲出到千呼万唤使出来,经历了好几年,期间sun也易主,真是不容易。
   
    不过想要马上大规模的使用还不现实,Java 6从推出到大规模的使用花了两三年的时间吧(这里我不太清楚)甚至更久,到现在还有好多大公司使用 java5或4呢,所以这也是我为什么把java 7装到虚拟机上的缘故,毕竟商业的东西,还是以稳定为主。
    以上介绍了些皮毛,未来还要靠大家自己多多努力,争取两年后,java 7正式商用了,大家也能对java 7掌握的更熟练写,更好的应用,提高自己的工作效率。
   
        
    
   

  • 大小: 260.7 KB
分享到:
评论
2 楼 linweibin 2012-11-28  
真是佩服死了~~
1 楼 yk0025 2011-10-31  







支持

相关推荐

    Struts2实战.pdf

    《Struts 2实战》结合实例介绍了Struts 2框架,主要内容包括Action、Result、Interceptor等框架组件,基于注解的配置选项等新特征,Struts 2插件 FreeMarker,如何从Struts 1和WebWork 2迁移到Struts 2,Ajax标签、...

    Java数据库技术详解 DOC简版

    第一篇 数据库基础篇 第1章 Java和数据库 1.1 Java概述 1.2 Java的开发和运行环境 1.3 数据库概述 1.4 数据持久层 ...第6章 JDBC的高级特性 ...第7章 JDBC结合Servlet...第六篇 项目实战篇 第19章 学籍管理系统

    Java开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

    书名:《Java开发实战1200例(第I卷)》(清华大学出版社.李钟尉,陈丹丹) PDF格式扫描版,全书分为24章,共817页。2011年1月出版。 全书压缩打包成4部分,这是第3部分 注:本系列图书的第I、II卷再版时均相应改名为...

    java后端学习推荐书籍清单

    《深入理解Java虚拟机:JVM高级特性与最佳实践》 《深入理解计算机系统(原书第三版》《Netty权威指南 第2版》 《Netty 4核心原理与手写RPC框架实战》 《MyBatis技术原理与实战》 《大话设计模式》 《高性能MySQL》 ...

    学通Java的24堂课

    第1部分 基础篇 第1堂课 java概述 3 视频讲解:31分钟 ...第4部分 实战篇 第22堂课 进销存管理系统 647 第23堂课 企业内部通讯管理系统 729 第24堂课 图书馆管理系统 737 附录a java程序编码规范 749

    Java SE实践教程 源代码 下载

    1.2.3 J2SE 5.0新特性实践 26 1.3 小结 35 第2章 对象无处不在——面向对象的基本概念 37 2.1 讲解 38 2.1.1 什么是面向对象 38 2.1.2 面向对象的基本概念 38 2.1.3 Java对面向对象的支持 41 2.2 练习 42 ...

    Java典型模块

    第7篇 项目案例实战 第29章 人员信息管理项目 (接口设计模式+MySQL数据库) 29.1 人员信息管理原理 29.1.1 项目结构框架分析 29.1.2 项目功能业务分析 29.2 人员信息管理项目前期准备 29.2.1 设计数据库 29.2.2 ...

    Java并发编程实战 03互斥锁 解决原子性问题

    在第一篇文章01并发编程的Bug源头当中,讲到了把一个或者多个操作在 CPU 执行的过程中不被中断的特性称为原子性,那么原子性的问题该如何解决。 同一时刻只有一个线程执行这个条件非常重要,我们称为互斥,如果能...

    R的极客理想:工具篇,完整扫描版

    书中内容涉及计算机、互联网、数据库、大数据、统计、金融等领域,详细总结了R语言与Java、MySQL、Redis、MongoDB、Cassandra、Hadoop、Hive、Hbase等技术的综合运用的解决方案,具有实战性,可操作性强。...

    Spring3.x企业应用开发实战(完整版) part1

     Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架、REST风格的Web编程模型等。这些新功能实用性强、易用性高,可大幅降低Java应用,特别是JavaWeb应用开发的难度,同时有效提升...

    Spring.3.x企业应用开发实战(完整版).part2

     Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架、REST风格的Web编程模型等。这些新功能实用性强、易用性高,可大幅降低Java应用,特别是JavaWeb应用开发的难度,同时有效提升...

    集群好书《高性能Linux服务器构建实战》 试读章节下载

    1.8 实战Nginx与Perl、Java的安装与配置 1.8.1 Perl(FastCGI)的安装 1.8.2 为Nginx添加FCGI支持 1.8.3 测试Nginx +Perl(FastCGI) 1.8.4 搭建Nginx+Java环境 1.9 本章小结 第2章 高性能HTTP加速器...

    Java开发技术大全 电子版

    第1篇Java基础知识入门. 第1章Java的开发运行环境2 1.1Java的运行环境与虚拟机2 1.2Java的开发环境4 1.2.1JDK的安装4 1.2.2如何设置系统环境变量6 1.2.3编译命令的使用8 1.2.4解释执行命令的使用10 1.2.5...

    struts2 in action

    《Struts 2实战》结合实例介绍了Struts 2框架,主要内容包括Action、Result、Interceptor等框架组件,基于注解的配置选项等新特征,Struts 2插件 FreeMarker,如何从Struts 1和WebWork 2迁移到Struts 2,Ajax标签、...

    Spring4.x企业应用开发 有书签,很方便查找

    Spring+4.x企业应用开发实战 ...1.6 Spring 4.0新特性 8 1.6.1 全面支持Java 8.0 9 1.6.2 核心容器的增强 11 1.6.3 支持用Groovy定义Bean 12 1.6.4 Web的增强 12 1.6.5 支持WebSocket 12 1.6.6 测试的增强 13

Global site tag (gtag.js) - Google Analytics