您的位置:首页 > 编程语言 > Java开发

JDK7新特性详细说明及代码示例

2015-06-17 10:04 369 查看
在2011年7月28日,Oracle发布了JDK7的正式版。最近我从网上搜集了一些资料,把文字说明和代码示例结合起来,方便我们的学习。 下面我们来看看JDK7比6多了哪些新特性

1、访问文件系统

与之前的JDK中通过java.io.File访问文件的方式不同,JDK7将通过java.nio.file包中的类完成。JDK7会使用java.nio.file.Path类来操作任何文件系统中的文件。(这里说的任何文件系统指的是可以使用任何文件存储方式的文件系统)

示例:

Java7之前
File file = new File(“some_file”);
使用Java7
Path path = Paths.get(“some_file”);
在File类中加入了新的方法toPath(),可以方便的转换File到Path
Path path = new File(“some_file”).toPath();


2、Socket通道绑定和配置

在JDK7中面向通道的网络编程也得以更新!JDK7中可以直接绑定通道的socket和直接操作socket属性。JDK7提供了平台socket属性和指定实现的socket属性。•JDK7加入了一个新的字节通道类,SeekableByteChannel

•NetworkChannel是面向网络通道编程模块中的又一个新的超接口。利用它可以方便的绑定通道socket,并且方便设置和获取socket的属性。

•MulticastChannel接口方便创建IP协议多播。多播实现直接绑定到本地的多播设备。

3、I/O

可以通过真正的异步I/O,在不同的线程中运行数以万计的流操作!JKD7提供了对文件和socket的异步操作。一些JDK7中的新通道:•AsynchronousFileChannel:异步文件通道可以完成对文件的异步读写操作。

•AsynchronouseSocketChannel:Socket中的一个简单异步通道,方法是异步的并且支持超时。

•AsynchronousServerSocketChannel:异步的ServerSocket

•AsynchronousDatagramChannel:基于数据包的异步socket

4、Java语言的改进

OpenJDK项目的创造(JSR334)的主旨是对Java语言进行一些小的改进来提高每天的Java开发人员的工作。这些改进包括:

•Switch语句允许使用String类型

public static String getTypeOfDayWithSwitchStatement(String dayOfWeekArg) {  
         String typeOfDay;  
         switch (dayOfWeekArg) {  
             case "Monday": typeOfDay = "Start of work week";  break;  
             case "Tuesday":  
             case "Wednesday":  
             case "Thursday":  typeOfDay = "Midweek";  break;  
             case "Friday":   typeOfDay = "End of work week";  break;  
             case "Saturday":  
             case "Sunday":  typeOfDay = "Weekend";  break;  
             default:  throw new IllegalArgumentException("Invalid day of the week: " + dayOfWeekArg);  
         }  
         return typeOfDay;  
    }


•支持二进制常量和数字常量中可以使用下划线

// 二进制变量的表示,支持将整数类型用二进制来表示,用0b开头。  
    // 所有整数 int, short,long,byte都可以用二进制表示  
    // An 8-bit 'byte' value:  
    byte aByte = (byte) 0b00100001;  
    // A 16-bit 'short' value:  
    short aShort = (short) 0b1010000101000101;  
    // Some 32-bit 'int' values:  
    intanInt1 = 0b10100001010001011010000101000101;  
    intanInt2 = 0b101;  
    intanInt3 = 0B101; // The B can be upper or lower case.  
    // A 64-bit 'long' value. Note the "L" suffix:  
    long aLong = 0b1010000101000101101000010100010110100001010001011010000101000101L;  
    // 二进制在数组等的使用  
    final int[] phases = { 0b00110001, 0b01100010, 0b11000100, 0b10001001,  
    0b00010011, 0b00100110, 0b01001100, 0b10011000 };


// 数字类型的下划线表示 更友好的表示方式,不过要注意下划线添加的一些标准,可以参考下面的示例  
    long creditCardNumber = 1234_5678_9012_3456L;  
    long socialSecurityNumber = 999_99_9999L;  
    float pi = 3.14_15F;  
    long hexBytes = 0xFF_EC_DE_5E;  
    long hexWords = 0xCAFE_BABE;  
    long maxLong = 0x7fff_ffff_ffff_ffffL;  
    byte nybbles = 0b0010_0101;  
    long bytes = 0b11010010_01101001_10010100_10010010;   
    //float pi1 = 3_.1415F;      // Invalid; cannot put underscores adjacent to a decimal point  
    //float pi2 = 3._1415F;      // Invalid; cannot put underscores adjacent to a decimal point  
    //long socialSecurityNumber1= 999_99_9999_L;         // Invalid; cannot put underscores prior to an L suffix   
    //int x1 = _52;              // This is an identifier, not a numeric literal  
    int x2 = 5_2;              // OK (decimal literal)  
    //int x3 = 52_;              // Invalid; cannot put underscores at the end of a literal  
    int x4 = 5_______2;        // OK (decimal literal)   
    //int x5 = 0_x52;            // Invalid; cannot put underscores in the 0x radix prefix  
    //int x6 = 0x_52;            // Invalid; cannot put underscores at the beginning of a number  
    int x7 = 0x5_2;            // OK (hexadecimal literal)  
    //int x8 = 0x52_;            // Invalid; cannot put underscores at the end of a number   
    int x9 = 0_52;             // OK (octal literal)  
    int x10 = 05_2;            // OK (octal literal)  
    //int x11 = 052_;            // Invalid; cannot put underscores at the end of a number


•使用一个catch语言来处理多种异常类型

// Catch异常类型为final; 生成Bytecode 会比多个catch小; Rethrow时保持异常类型
 public static void main(String[] args) throws Exception {  
    try {  
          testthrows();  
        } catch (IOException | SQLException ex) {  
       throw ex;  
        }  
    }  
    public static void testthrows() throws IOException, SQLException {  
    }


•泛型实例的创建可以通过类型推断来简化 可以去掉后面new部分的泛型类型,只用<>就可以了

//使用泛型前   
    List strList = new ArrayList();   
    List<String> strList4 = new ArrayList<String>();   
    List<Map<String, List<String>>> strList5 =  new ArrayList<Map<String, List<String>>>();  
    //编译器使用尖括号 (<>) 推断类型   
    List<String> strList0 = new ArrayList<String>();   
    List<Map<String, List<String>>> strList1 =  new ArrayList<Map<String, List<String>>>();   
    List<String> strList2 = new ArrayList<>();   
    List<Map<String, List<String>>> strList3 = new ArrayList<>();  
    List<String> list = new ArrayList<>();  
    list.add("A");  
    // The following statement should fail since addAll expects  
    // Collection<? extends String>  
    //list.addAll(new ArrayList<>());


•在可变参数方法中传递非具体化参数,改进编译警告和错误

List l = new ArrayList<Number>();
    List<String> ls = l;       // unchecked warning
    l.add(0, new Integer(42)); // another unchecked warning
    String s = ls.get(0);      // ClassCastException is thrown
    Jdk7:
    public static <T> void addToList (List<T> listArg, T... elements) {
       for (T x : elements) {
         listArg.add(x);
       }
    }
    你会得到一个warning
    warning: [varargs] Possible heap pollution from parameterized vararg type
    要消除警告,可以有三种方式
    1.加 annotation @SafeVarargs 
    2.加 annotation @SuppressWarnings({"unchecked", "varargs"})
    3.使用编译器参数 –Xlint:varargs;


•Try-with-resources语句来自动关闭资源

这个所谓的try-with-resources,是个语法糖。实际上就是自动调用资源的close()函数。和Python里的with语句差不多。

例如:

static String readFirstLineFromFile(String path) throws IOException {
    try (BufferedReader br = new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}


可以看到try语句多了个括号,而在括号里初始化了一个BufferedReader。

这种在try后面加个括号,再初始化对象的语法就叫try-with-resources。

实际上,相当于下面的代码(其实略有不同,下面会说明):

static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        if (br != null) br.close();
    }
}


很容易可以猜想到,这是编绎器自动在try-with-resources后面增加了判断对象是否为null,如果不为null,则调用close()函数的的字节码。

只有实现了java.lang.AutoCloseable接口,或者java.io.Closable(实际上继随自java.lang.AutoCloseable)接口的对象,才会自动调用其close()函数。

有点不同的是java.io.Closable要求一实现者保证close函数可以被重复调用。而AutoCloseable的close()函数则不要求是幂等的。具体可以参考Javadoc

•ThreadLocalRandom 并发下随机数生成类,保证并发下的随机数生成的线程安全,实际上就是使用threadlocal

final int MAX = 100000;
    ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
    long start = System.nanoTime();
    for (int i = 0; i < MAX; i++) {
    threadLocalRandom.nextDouble();
    }
    long end = System.nanoTime() - start;
    System.out.println("use time1 : " + end);
    long start2 = System.nanoTime();
    for (int i = 0; i < MAX; i++) {
    Math.random();
    }
    long end2 = System.nanoTime() - start2;
    System.out.println("use time2 : " + end2);


•Networking增强

新增URLClassLoader close方法,可以及时关闭资源,后续重新加载class文件时不会导致资源被占用或者无法释放问题

URLClassLoader.newInstance(new URL[]{}).close();

新增Sockets Direct Protocol

绕过操作系统的数据拷贝,将数据从一台机器的内存数据通过网络直接传输到另外一台机器的内存中

•解决并发下加载class可能导致的死锁问题,这个是jdk1.6的一些新版本就解决了,jdk7也做了一些优化。有兴趣可以仔细从官方文档详细了解

jdk7前:

    Class Hierarchy:            
      class A extends B
      class C extends D
    ClassLoader Delegation Hierarchy:
    Custom Classloader CL1:
      directly loads class A 
      delegates to custom ClassLoader CL2 for class B
    Custom Classloader CL2:
      directly loads class C
      delegates to custom ClassLoader CL1 for class D
    Thread 1:
      Use CL1 to load class A (locks CL1)
        defineClass A triggers
          loadClass B (try to lock CL2)
    Thread 2:
      Use CL2 to load class C (locks CL2)
        defineClass C triggers
          loadClass D (try to lock CL1)
    Synchronization in the ClassLoader class wa 
jdk7
    Thread 1:
      Use CL1 to load class A (locks CL1+A)
        defineClass A triggers
          loadClass B (locks CL2+B)
    Thread 2:
      Use CL2 to load class C (locks CL2+C)
        defineClass C triggers
          loadClass D (locks CL1+D)


•jvm方面的一些特性增强

适合server端,多处理器下大内存,将heap分成大小相等的多个区域,mark阶段检测每个区域的存活对象,compress阶段将存活对象最小的先做回收,这样会腾出很多空闲区域,这样并发回收其他区域就能减少停止时间,提高吞吐量。

HotSpot性能增强

Tiered Compilation -XX:+UseTieredCompilation 多层编译,对于经常调用的代码会直接编译成本地代码,提高效率

Compressed Oops 压缩对象指针,减少空间使用

Zero-Based Compressed Ordinary Object Pointers (oops) 进一步优化零基压缩对象指针,进一步压缩空间

逃逸分析,对于只是在一个方法使用的一些变量,可以直接将对象分配到栈上,方法执行完自动释放内存,而不用通过栈的对象引用引用堆中的对象,那么对于对象的回收可能不是那么及时。

5、Java编译器API

JSR199是在JDK6中加入的,主要用来提供调用Java编译器的API。除了提供javac的命令行工具,JSR199提供Java编译器到程序交互的能力。Java编译器API要达到三个目标: •对编译器和其它工具的调用

•对结构化的编译信息进行访问

•对文件输入输出定制化处理的能力

6、Java XML处理的API (JAXP)

JSR206即Java API for XML Processing(JAXP),是Java处理XML文档的一个与实现无关,灵活的API。

JAXP1.3的主要特性包括:

•DOM3

•内建通过XML Schema进行文档校验的处理器

•对XML Schema中的数据类型的实现,在javax.xml.datatype包中。

•XSLTC,最快的转换器,也是XSLT处理中的默认引擎。

•提供对XInclude的实现。这将会方便我们使用文本和其它已有的XML来创建新的文档,这样可以对文档片段进行重用。

•JDK7中会包含JAXP1.3,这个是JAXP的最新实现

7、绑定技术(JAXB)

JSR222即Java Architecture for XML Binding(JAXB)。JAXB的目的是便于Java程序进行Java类到XML文档的映射。

JAXB2的主要特性:

•支持全部的W3C XML Schema特性。(JAXB1.0说明了对于W3C XML Schema中某些特性的不支持)

•支持绑定Java到XML文档,通过添加javax.xml.bind.annotation包来控制绑定。

•大量减少了对于schema衍生出来的类。

•通过JAXP1.3的校验API来提供额外的校验能力。

•JDK7中将包括JAXB2.2

8、基于XML的Web服务API(JAX-WS)

JSR224即Java API for XML-based Web Services(JAX-WS),是一个基于Annotation标注的编程模型,主要针对Web Service应用和客户端开发。

JAX-WS2的主要特性包括:

•对JAXB2.1 API的支持(JSR222)

•对Web Services Addressing 1.0的支持

•EndpointReference(EPR)的API:创建(BindingProvider.getEndpointReference(),Endpoint.getEndpointReference(),MessageContext.getEndpointReference())

事务处理(使用JAXB2.1绑定W3C EPR到W3CEndpointReference类,使用JAXB Marshall/Unmarshall W3CendpointReference类)

•提供友好的API来启用和停止某些特性,例如MTOM特性和Addressing特性

•JDK7将包含JAX-WS2.2

9、可插拔的Annotation处理API

JSR269即Pluggable Annotation-Processing API•从JDK5开始,Annotation标注就成了强大的机制用来标注我们的类、属性和方法。通常Annotation标注是在创建阶段或者运行阶段进行处理的,并获取语义结果。JSR269主要用来定义一套API,允许通过可插拔的API来进行标注处理器的创建。

•规范包括一部分的API用来对Java编程语言进行构建,还有就对标注处理器声明和控制运行的部分。

•有了程序中的Annotation标注,就需要有标注处理器框架来反射程序的结构。

•Annotation处理器会指定他们处理的标注并且更多的处理器可以合作运行。

•标注处理器和程序结构的API可以在构建阶段访问。

10、其他 改进

java.util.Objects

提供了一套9个静态方法。其中两个方法用来检测当前对象是null还是非null。两个方法用来提供生成toString()字符串同时支持null对象。两个用来处理hash的方法。两个方法用来处理equals。最后一个compare方法用来进行比较。

Swing JLayer

组件 JXLayer是一个组件装饰器,提供了用来装饰多个组合组件的方式,并且可以捕获所有鼠标、键盘和FocusEvent的事件,并针对所有的XLayer子组件。这个组件只会对public swing的api起作用,对全局设置没有作用,例如对EventQueue或者RepaintManager。(除了这些,Swing还将在JDK7中提供JXDatePicker和CSS方式样式)

并发和集合API JSR166

并发和集合API提供了灵活的异步处理,并发HashMap,传输队列和轻量级的fork/join框架以及本地线程方式的伪随机数生成器。

类加载器体系结构

类加载器已经升级到了可以在无等级类加载器拓扑中避免死锁。JDK7中包含了一个对于多线程自定义类加载器的增强实现,名字为具有并行能力的类加载器。使用平行能力的类加载器加载class,会同步到类加载器和类名。

Locale类

locale改进 Java Locale避免由于小的变化导致数据丢失。除此,Locale应该提供更多的特性,例如IETF BCP 47和UTR 35(CLDR/LDML)。

分离用户Locale和用户接口Locale

JDK7分离了UI语言的locale和格式化locale,这个已经在Vista之后的windows系统中实现了。

严格的类文件检测

通过JavaSE6的规范,version51(SE7)的类文件和之后的版本必须通过类型检测来检验。对于老的推理验证VM不可以宕掉

Elliptic-Curve

Cryptography (ECC)椭圆曲线加密

从JDK7开始,Java提供对标准的ECC算法的灵活实现(基于椭圆曲线的公钥加密算法)

Swing中的Nimbus外观

Nimbus是JDS(Java Desktop System)中的新外观。这个也是Solaris11的GTK主题

Java2D中的XRender Pipeline

JDK7中加入了基于X11 XRender扩展的Java2D图形管道。这将提供更多的对于当前先进的GPUs访问的功能。

TLS1.2

TLS (Transport Layer Security)是一个用在Internet上的数据传输安全协议,用来避免监听、引诱和消息伪造。TLS的主要目的是提供两个应用间通信的隐私和数据完整。TLS是RFC5246标准,在JDK7中提供1.2

JDBC4.0/4.1

JDBC4.1特性只在JDK7或者更高版本中存在。JDBC4.1只是对JDBC4.0进行较小的改动。关于一些JDBC4.0/4.1的特性:•数据源—Derby包括了对于javax.sql.DataSource的新的实现

•JDBC驱动自动加载—应用不必在通过Class.forName()方法来加载数据库驱动了。取而代之的是DriverManager会根据应用请求连接的情况,自动查找到合适的JDBC驱动。

•包装—这是JDBC4.0中的新的概念,主要是通过这种机制可以让应用获取的厂商提供的标准JDBC对象实现,例如Connections,Statements和ResultSets。

•Statement事件—连接池可以监听Statement的关闭和错误时间。addStatementEventListener和removeStatementEventListener被加入到了javax.sql.PooledConnection

•JDK7提供了JDBC4.1全部的支持

//JDBC-ODBC驱动会在jdk8中删除 
    try (Statement stmt = con.createStatement()) { 
      RowSetFactory aFactory = RowSetProvider.newFactory();
      CachedRowSet crs = aFactory.createCachedRowSet();
      RowSetFactory rsf = RowSetProvider.newFactory("com.sun.rowset.RowSetFactoryImpl", null);
      WebRowSet wrs = rsf.createWebRowSet();
      createCachedRowSet 
      createFilteredRowSet 
      createJdbcRowSet 
      createJoinRowSet 
      createWebRowSet 
    }


透明窗体和异形窗体

为了6u10版本的图形处理,JDK提供了透明效果的支持(简单透明和像素透明)并且提供了对于异形窗体的支持(可以将窗体设置成任意形状),轻重混合并且增强了AWT安全警告。透明效果和异形窗体是通过com.sun.awt.AWTUtilities类实现的。

Unicode6.0

Unicode6.0提供了诸如2.088字符集、对已经存在字符集的属性改进、格式化改进以及新的属性和数据文件。

JDK7已经更新到对Unicode6.0的支持。

要来关闭URLClassLoader的方法 对JMX代理和MBeans的改进

通过URLClassLoader,应用可以通过URL搜索路径来加载类和资源。JKD7提供了close()新方法来帮助URLClassLoader清理资源。

这个改进来至于JRockit,可以方便连接平台。MBean服务器可以通过防火墙提供一套MBeans,这些暴露了VM中的一些内部操作的信息

新的垃圾回收器

JDK7提供了新的垃圾回收器,针对目前的CMS垃圾回收器,这将会让垃圾回收器有更少的停顿时间和更高的语言效果。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: