Java8新特性及使用(二)


扩展注解的支持

Java 8扩展了注解的上下文。现在几乎可以为任何东西添加注解:局部变量、泛型类、父类与接口的实现,就连方法的异常也能添加注解。下面演示几个例子:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Collection;

public class Annotations {

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ ElementType.TYPE_USE, ElementType.TYPE_PARAMETER })
    public @interface NonEmpty {
    }

    public static class Holder<@NonEmpty T> extends @NonEmpty Object {
        public void method() throws @NonEmpty Exception {
        }
    }

    @SuppressWarnings("unused")
    public static void main(String[] args) {
        final Holder<String> holder = new @NonEmpty Holder<String>();
        @NonEmpty Collection<@NonEmpty String> strings = new ArrayList<>();
    }

}

Base64

在Java 8中,Base64编码已经成为Java类库的标准。它的使用十分简单,下面让我们看一个例子:

import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class Base64s {

    public static void main(String[] args) {
        final String text = "Base64 finally in Java 8!";

        final String encoded = Base64.getEncoder().encodeToString(text.getBytes(StandardCharsets.UTF_8));
        System.out.println(encoded);

        final String decoded = new String(Base64.getDecoder().decode(encoded), StandardCharsets.UTF_8);
        System.out.println(decoded);
    }

}

程序在控制台上输出了编码后的字符与解码后的字符:

QmFzZTY0IGZpbmFsbHkgaW4gSmF2YSA4IQ==
Base64 finally in Java 8!

Base64类同时还提供了对URL、MIME友好的编码器与解码器(Base64.getUrlEncoder() / Base64.getUrlDecoder(), Base64.getMimeEncoder() / Base64.getMimeDecoder())。

JavaFX

JavaFX是一个强大的图形和多媒体处理工具包集合,它允许开发者来设计、创建、测试、调试和部署富客户端程序,并且和Java一样跨平台。从Java8开始,JavaFx已经内置到了JDK中。关于JavaFx更详细的文档可参考JavaFX中文文档

其它

1. JDBC4.2规范

JDBC4.2主要有以下几点改动:

  • 增加了对REF Cursor的支持
  • 修改返回值大小范围(update count)
  • 增加了java.sql.DriverAction接口
  • 增加了java.sql.SQLType接口
  • 增加了java.sql.JDBCtype枚举
  • java.time包时间类型的支持

2. 更好的类型推测机制

Java 8在类型推测方面有了很大的提高。在很多情况下,编译器可以推测出确定的参数类型,这样就能使代码更整洁。让我们看一个例子:

public class Value<T> {

    public static<T> T defaultValue() {
        return null;
    }

    public T getOrDefault(T value, T defaultValue) {
        return (value != null) ? value : defaultValue;
    }

}

这里是Value<String>类型的用法。

public class TypeInference {

    public static void main(String[] args) {
        final Value<String> value = new Value<>();
        value.getOrDefault("22", Value.defaultValue());
    }

}

Value.defaultValue()的参数类型可以被推测出,所以就不必明确给出。在Java 7中,相同的例子将不会通过编译,正确的书写方式是Value.<String>defaultValue()

3. HashMap性能提升

Java8中,HashMap内部实现又引入了红黑树,使得HashMap的总体性能相较于Java7有比较明显的提升。以下是对Hash均匀和不均匀的情况下的性能对比

(1). Hash较均匀的情况

Hash较均匀时的性能对比

(2). Hash极不均匀的情况

Hash极不均匀时的性能对比

4. IO/NIO 的改进

Java8 对IO/NIO也做了一些改进。主要包括:改进了java.nio.charset.Charset的实现,使编码和解码的效率得以提升,也精简了jre/lib/charsets.jar包;优化了String(byte[], *)构造方法和String.getBytes()方法的性能;还增加了一些新的IO/NIO方法,使用这些方法可以从文件或者输入流中获取流(java.util.stream.Stream),通过对流的操作,可以简化文本行处理、目录遍历和文件查找。

新增的 API 如下:

  • BufferedReader.line(): 返回文本行的流Stream<String>
  • File.lines(Path, Charset): 返回文本行的流Stream<String>
  • File.list(Path): 遍历当前目录下的文件和目录
  • File.walk(Path, int, FileVisitOption): 遍历某一个目录下的所有文件和指定深度的子目录
  • File.find(Path, int, BiPredicate, FileVisitOption...): 查找相应的文件

下面就是用流式操作列出当前目录下的所有文件和目录:

Files.list(new File(".").toPath()).forEach(System.out::println);

5. JavaScript引擎Nashorn

Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。Nashorn javascript引擎只是javax.script.ScriptEngine另一个实现,而且规则也一样,允许Java和JavaScript互相操作。这里有个小例子:

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");

System.out.println(engine.getClass().getName());
System.out.println("Result:" + engine.eval("function f(){return 1;}; f() + 1;"));

输出如下:

jdk.nashorn.api.scripting.NashornScriptEngine
Result: 2

6. 并发(Concurrency)

在新增Stream机制与Lambda的基础之上,在java.util.concurrent.ConcurrentHashMap中加入了一些新方法来支持聚集操作。同时也在java.util.concurrent.ForkJoinPool类中加入了一些新方法来支持共有资源池(common pool)(请查看我们关于Java 并发的免费课程)。

新增的java.util.concurrent.locks.StampedLock类提供一直基于容量的锁,这种锁有三个模型来控制读写操作(它被认为是不太有名的java.util.concurrent.locks.ReadWriteLock类的替代者)。

java.util.concurrent.atomic包中还增加了下面这些类:

  • DoubleAccumulator
  • DoubleAdder
  • LongAccumulator
  • LongAdder

7. 类依赖分析器jdeps

Jdeps是一个功能强大的命令行工具,它可以帮我们显示出包层级或者类层级java类文件的依赖关系。它接受class文件、目录、jar文件作为输入,默认情况下,jdeps会输出到控制台。

作为例子,让我们看看现在很流行的Spring框架的库的依赖关系报告。为了让报告短一些,我们只分析一个jar: org.springframework.core-3.0.5.RELEASE.jar.

jdeps org.springframework.core-3.0.5.RELEASE.jar这个命令输出内容很多,我们只看其中的一部分,这些依赖关系根绝包来分组,如果依赖关系在classpath里找不到,就会显示not found.

C:\Program Files\Java\jdk1.8.0\jre\lib\rt.jar
   org.springframework.core (org.springframework.core-3.0.5.RELEASE.jar)
      -> java.io
      -> java.lang
      -> java.lang.annotation
      -> java.lang.ref
      -> java.lang.reflect
      -> java.util
      -> java.util.concurrent
      -> org.apache.commons.logging                         not found
      -> org.springframework.asm                            not found
      -> org.springframework.asm.commons                    not found
   org.springframework.core.annotation (org.springframework.core-3.0.5.RELEASE.jar)
      -> java.lang
      -> java.lang.annotation
      -> java.lang.reflect
      -> java.util

8. JVM的PermGen空间被移除

PermGen空间被移除了,取而代之的是Metaspace(JEP 122)。JVM选项-XX:PermSize-XX:MaxPermSize分别被-XX:MetaSpaceSize-XX:MaxMetaspaceSize所代替。


参考文档:


文章作者: blinkfox
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 blinkfox !
 上一篇
单元测试指南 单元测试指南
一、必要性在我们公司中要做单元测试,确实比较难,因为公司缺少这种氛围,有也只是局部的,大多数工程师没有这方面的习惯和素养,很多人都是有一定的抵触的心理,经过我私下的了解大概有以下几种原因吧。 写单元测试太耗费时间了,项目要赶进度,编写单元
2018-11-15
下一篇 
Java8新特性及使用(一) Java8新特性及使用(一)
新特性列表以下是Java8中的引入的部分新特性。关于Java8新特性更详细的介绍可参考这里。 接口默认方法和静态方法 Lambda 表达式 函数式接口 方法引用 Stream Optional Date/Time API 重复注解 扩展注
2018-11-13
  目录