JDK8新特性介绍
Oracle甲骨文公司终于在2014年3月发布了Java 8正式版,它是 java的一个里程牌版本,带来了诸多新特性。官网介绍: http://www.oracle.com/technetwork/java/javase/8-whats-new-2157071.html
- 一、针对java编程语言(Java Programming Language)
- 二、针对集合(Collections)
- 三、Compact Profiles
- 四、安全性
- 五、JavaFX
- 六 工具(tools)
- 七、国际化
- 八、部署
- 九、Date-Time Package
- 十、Scripting
一:java编程语言
- 函数式接口
- lambda表达式:
- 方法引用
- 默认方法:
- 重复注解:
- 改善了类型推断
- 方法参数反射
1.1 函数式接口
Java 8 引入的一个核心概念是函数式接口(Functional Interfaces)。 接口定义个唯一一个抽象方法, 那么这个接口就成为函数式接口 同时,引入了一个新的注解:@FunctionalInterface。可以把他它放 在一个接口前,表示这个接口是一个函数式接口。这个注解是非 必须的,只要接 口只包含一个方法的接口,虚拟机会自动判断, 不过最好在接口上使用注解 @FunctionalInterface进行声明。
@FunctionalInterface
public interface Runnable { public abstract void run();
}
1.2 Lambda表达式
一种新的语言特性,能够把函数作为方法的参数或将代码 作为数据。lambda表达式使你在表示函数接口(具有单个方法的接口)的实 例更加紧凑。
- 函数式接口的重要属性是:我们能够使用 Lambda实例化它们, Lambda 表达式实例化函数接口作为方法参数,或者将代码作为数据对待。
- 在 Java 8 之前:匿名内部类,监听器和事件处理器的使用都显得很冗长,代码可读 性很差。
- 在 Java 8:Lambda 表达式的应用则使代码变得更加紧凑,可读性增强; Lambda 表达式使并行 操作大集合变得很方便,可以充分发挥多 核 CPU的优势,更易于为多核处理器编写代码;
- Lambda 表达式由三个部分组成:
- 第一部分为一个括号内用逗号分隔 的形式参数,参数是函数式接口里面方法的参数;
- 第二部分为一个箭 头符号: ->
- 第三部分为方法体,可以是表达式和代码块。
- 语法如下:
- 1.方法体为表达式,该表达式的值作为返回值返回。 (parameters) -> expression
- 2.方法体为代码块,必须用 {}来包裹起来,且需要一个 return返回 值,但若函数式接 口里面方法返回值是 void,则无需返回值。
import java.awt.Button;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class DemoTest {
public static void main(String[] args) {
/**
* Lambda和匿名内部类表示法
*/
Button button = new Button("测试");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.print("这是内部类的表示法!");
}
});
button.addActionListener((ActionEvent e) -> System.out.print("Helllo Lambda in actionPerformed"));
/**
* Lambada扩展
*/
// 类型声明
MathOperation<Integer, Integer> addition = (Integer a, Integer b) -> a + b;
// 不用类型声明
MathOperation<Integer, Integer> subtraction = (a, b) -> a - b;
// 大括号中的返回语句
MathOperation<Long, Long> multiplication = (a, b) -> {
return a * b;
};
// 没有大括号及返回语句
MathOperation<Float, Float> division = (Float a, Float b) -> a / b;
/**
* 测试
*/
DemoTest test = new DemoTest();
System.out.println("10 + 5 = " + test.operate(10, 5, addition));
System.out.println("10 - 5 = " + test.operate(10, 5, subtraction));
System.out.println("10 * 5 = " + test.operate(10l, 5l, multiplication)); //注意类型,下同
System.out.println("10 / 5 = " + test.operate(10f, 5f, division));
}
/**
* 自定义函数。只有一个方法,可使用FunctionalInterface注解,不是必须的
* 注:和jdk8提供 Function接口的区别,是有两个参数。用于测试
* @author:whh
* @date:2018年1月13日下午12:50:14
* @param <T> 参数类型
* @param <R> 返回类型
*/
@FunctionalInterface
interface MathOperation<T, R> {
R operation(T a, T b);
}
private <T, R> R operate(T a, T b, MathOperation<T, R> mathOperation) {
return mathOperation.operation(a, b);
}
}
1.3 方法引用
是lambda表达式的一个简化写法,所引用的方法其实是lambda表 达式的方法体实现,这样使代码更容易阅读
List<String> names = Arrays.asList("zhangsan", "lisi", "wangwu", "zhaoliu");
Collections.sort(names, String::compareTo); Function<Integer, String> f1 = String::valueOf;
Function<String,String> function = String::new; Supplier<String> supplier = String::new;
1.4 默认方法
Java 8引入default method,或者叫virtual extension method, 目的是为了让接口可以事后添加新方法而无需强迫所有实现该接口的类都提 供新方法的实现。
比中:
public interface MyInterface {
//注意:default修饰,使接口可以有具体的实现方法
default void myMethod() {
System.out.println("MyInterface");
}
}
1.5 重复注解
重复注解:允许在同一声明或类型(类,属性,或方法)的 使用中多次使用同一个注解
JDK8的写法:
/**
* jdk8的重复注解
* @author:spinach
* @date:2018年1月13日下午1:00:23
*/
@Repeatable(Authorities.class)
public @interface Authority {
String role();
}
public @interface Authorities {
Authority[] value();
}
public class RepeatAnnotationUseNewVersion {
@Authority(role = "Admin")
@Authority(role = "Manager")
public void doSomeThing() {}
}
JDK7的写法 :
/**
* jdk7的重复注解写法
* @author:spinach
* @date:2018年1月13日下午1:00:23
*/
public class RepeatAnnotationUseNewVersion {
@Authorities{@Authority(role = "Admin"),@Authority(role = "Manager")}
public void doSomeThing() {}
}
public @interface Authority {
String role();
}
public @interface Authorities {
Authority[] value();
}
1.6 泛型的推断改进
/**
* jdk8的类型推断的改进。
* @author:spinach
* @date:2018年1月13日下午1:00:23
*/
public class DemoTest {
public static void main(String[] args) {
// jdk1.5:
List<String> strList = new ArrayList<String>();
// Jdk1.7:
List<String> strList2 = new ArrayList<>();
// Jdk1.8:
List<String> strList3 = new ArrayList<>();
strList.addAll(new ArrayList<>()); // 由于addAll期望获得Collection<? extends String>类型的参数,JDK8可以根据声明的类型自动判断。
// lambda表达式的推断
Function<Integer, Integer> odd = a -> a + 2;
}
}
1.7 方法参数反射
//直接通过method就能拿到所有的参数
Parameter[] params = method.getParameters();
二:针对集合Stream介绍
官网介绍:Classes in the new java.util.stream package provide a Stream API to support functional-style operations on streams of elements. The Stream API is integrated into the Collections API, which enables bulk operations on collections, such as sequential or parallel map-reduce transformations.
翻译:提供了新包java.util.stream,这个包提供了Stream API功能, 支持以函数风格(functional-style)去处理流中的元素。在 Collections API中已经整合了Stream API,可以在集合上进行 批量操作(bulk operations),如顺序或并行的map-reduce转换。
Stream API提供了一种操作大数据的接口,让数据操作更容 易和更快。它具有过滤、映射以及减少遍历数等方法,这些 方法分两种:中间方法和终端方法,“流”抽象天生就该是 持续的,中间方法永远返回的是Stream,因此如果我们要获 取最终结果的话,必须使用终点操作才能收集流产生的最终结果
2.1 Sream概念
Stream不是集合元素,也不是数据结构,它相当于一个高 级版本的 Iterator,不可以重复遍历里面的数据,像水一样, 流过了就一去不复返。它和普通的 Iterator不同的是,它可 以并行遍历,普通的 Iterator只能是串行,在一个线程中执 行。
- 操作包括:中间操作 和 最终操作(只能操作一遍)
- 串行流操作在一个线程中依次完成。
- 并行流在多个线程中完成,主要利用了 JDK7 的 Fork/Join 框 架来拆分任务和加速处理。相比串行流,并行流可以很大程 度提高程序的效率
2.2 流的类型分类
- 串行流:串行流上的操作是在一个线程中依次 完成。
- 并行流则是在多个线程上同时执行。相比较串行的流,并行的流可以很大程度上提高 程序的执行效率。
- 并行与串行的流可以相互切换:通过 stream.sequential()返回串行的流, 通过 stream.parallel()返回并行的流。比如:串行的方式对集合进行排序。list.stream().sequential()).sorted().count();
2.3 流的操作分类
- 中间操作:Intermediate
- 短路操作(Short-circuiting)
- 最终操作
2.3.1 中间操作:
中间操作(Intermediate)主要是用来对Stream做出相应转换及限制流,实际上是将源Stream转换为一个新的Stream,以达到需求效果。
常用API
- filter(): 元素过滤:Stream.of(1, 2, 3, 4, 5).filter(item -> item > 3);
- sorted():元素排序:Stream.of(1,5,3,2,9,3).sort();
- map(): 元素映射:Stream.of(“a”, “b”, “hello”).map(item-> item.toUpperCase());
- flatMap: 元素映射:Stream.of(1, 2, 3).flatMap(integer -> Stream.of(integer * 10))
- distinct():去重操作:Stream.of(1,2,3,1,2,3).distinct()
- concat(): 拼接:Stream.concat(Stream.of(1, 2, 3), Stream.of(4, 5));
- Peek:peek方法生成一个包含原Stream的所有元素的新Stream,同时会提供一个消费函数(Consumer实例),新Stream每个元素被消费的时候都会执行给定的消费函数,并且消费函数优先执行
- skip:跳过。skip方法将过滤掉原Stream中的前N个元素,返回剩下的元素所组成的新Stream
- Iterate: 其返回的也是一个无限长度的Stream,通过函数f迭代对给指定的元素种子而产生无限连续有序Stream,其 中包含的元素可以认为是:seed,f(seed),f(f(seed))无限循环
- generator方法,返回一个无限长度的Stream,其元素由Supplier接口的提供。
常用API例子
import java.util.stream.Stream;
/**
* jdk8 流的中间操作例子。
* @author:spinach
* @date:2018年1月13日下午1:00:23
*/
public class DemoTest {
public static void main(String[] args) {
String[] strings = {"helo","world","hi","sprin"};
String[] strings2 = {"HELLO","World","world","WorLd","World","heLLo"};
/**
* Filter:过滤,侧重于过滤。forEach:循环
*/
Stream.of(strings).filter((a)->a.startsWith("h")).forEach(System.out::print);
/**
* Sorted:排序:默认按字符排序,也可以自定义排序。
* 如果数字类型:默认按从小到大的顺序。
*/
Stream.of(strings).sorted().forEach(System.out::println);
/**
* 中间操作:去重 distinct:过滤,Stream中包含的元素进行去重操作
*/
Stream.of(strings2).distinct().forEach(System.out::println); //注:区分大小写
/**
* 中间操作:映射 Map映射:侧重于对元素的转换和操作。
* JDK8提供三种变形:mapToDouble,mapToInt,mapToLong
*/
Stream.of(strings2).map(String::toLowerCase).forEach(System.out::println);
Stream.of(strings2).map(a->a.concat("_aa")).forEach(System.out::println);
/**
* flatMap映射:该换转函数的对象是一个Stream,也不会再创建一个新 的Stream,而是将原Stream的元素取代为转换的Stream。
* JDK8提供三种变形:flatMapToInt,flatMapToLong和flatMapToDouble。
*/
Stream.of(strings,strings2).flatMap(theList -> Stream.of(theList))
.map(String::toLowerCase).distinct()
.forEach(System.out::println);
}
}
2.3.2 短路操作
短路操作(Short-circuiting):对流中的元素进行判断、取值等操作。常用的API方法:
常用API
- allMatch:判断Stream中的元素是否全部满足指定条件。如果全部满足条件 返回true,否则返回false。
- anyMatch:判断Stream中的是否有满足指定条件的元素。如果最少有一个满 足条件返回true,否则返回false。
- findAny:操作用于获取含有Stream中的某个元素的Optional,如果Stream为 空,则返回一个空的Optional。由于此操作的行动是不确定的,其会自由的 选择Stream中的任何元素
- findFirst:findFirst操作用于获取含有Stream中的第一个元素的Optional,如 果Stream为空,则返回一个空的Optional。
- limit:截取原Stream前指定值N个元素
- noneMatch:noneMatch方法将判断Stream中的所有元素是否满足指定的条 件,如果所有元素都不满足条件,返回true;否则,返回false.
常用API例子
import java.util.Optional;
import java.util.stream.Stream;
/**
* jdk8: 短路操作
* @author:spinach
* @date:2018年1月13日下午1:00:23
*/
public class DemoTest {
public static void main(String[] args) {
//allMatch:
boolean result1 = Stream.of(1, 2, 3, 4) .allMatch(integer -> integer > 0);
//findAny
Optional<Integer> result2 = Stream.of(1, 2, 3, 4).findAny();
Optional<Integer> result22 = Stream.of(1, 2, 3, 4).parallel().findAny();
//findFirst:
Optional<Integer> result3 = Stream.of(1, 2, 3, 4).findFirst();
//Limit:
Stream<Integer> result4 = Stream.of(1, 2, 3,4,5).limit(2);
//noneMatch:
boolean result5 = Stream.of(1, 2, 3, 4, 5).noneMatch(integer -> integer > 10);
/**
* 经过测试:Stream.of()默认是串行流,
* 串行流执行findAny:结果都是第一个
* Stream.of().parallel()并行流执行findAny:结果是随机的
*/
for(int i=0;i<10;i++){
Optional<Integer> resul = Stream.of(1, 2, 3, 4).findAny();
Optional<Integer> resul2 = Stream.of(1, 2, 3, 4).parallel().findAny();
System.out.println(resul.get() + " " +resul2.get());
}
}
}
2.3.3 最终操作
最终操作只能操作一遍,操作完成后,该流就会关闭。如再进行操作,便会报错(stream has already been operated upon or closed)。
常用API
- forEach():遍历每个元素。避免了使用for循环,让代码更简洁,逻辑更清晰。
- reduce():把Stream元素组合起来。例如,字符串拼接,数值的 sum,min,max,average都是特殊的 reduce。
- collect():返回一个新的集合。
- min():找到最小值。
- max():找到最大值。max方法根据指定的Comparator,返回一个Optional,该 Optional中的value值就是Stream中最大的元素。原Stream根据比较器Comparator,进行排序(升序或者是降序), 所谓的最大值就是从新进行排序的. eg: Stream.of(1, 2, 3, 4, 5).max(); 默认最大值
- Stream.of(1, 2, 3, 4, 5).max((o1, o2) -> o2 - o1);:改变了对比器,此时取的是最小值。
- count方法将返回Stream中元素的个数。
常用API例子
import java.util.OptionalInt;
import java.util.stream.IntStream;
/**
* 最终操作的举例
* @author:spinach
* @date:2018年1月13日下午3:03:12
*/
public class Stream02_IntStream {
public static void main(String[] args) {
int[] ints = new int[]{6, 5, 7,9};
IntStream.of(ints).forEach(System.out::println);
System.out.println("-----");
IntStream.range(3, 8).forEach(System.out::println);
System.out.println("-----");
IntStream.rangeClosed(3, 8).forEach(System.out::println);
System.out.println(IntStream.of(ints).count());
System.out.println(IntStream.of(ints).toString());
System.out.println(IntStream.of(ints).equals(new int[]{6, 5, 7,9}));
int sum = IntStream.of(ints).sum();
int [] ints2 = IntStream.of(ints).toArray();
for(int i=0;i<10;i++){
OptionalInt any = IntStream.of(ints).findAny();
System.out.println(any.getAsInt());
}
IntStream.of(ints).sorted().forEach(System.out::print);
OptionalInt max = IntStream.of(ints).max(); //最大
OptionalInt min = IntStream.of(ints).min(); //最小
OptionalInt findFirst = IntStream.of(ints).findFirst(); //第一个元素
System.out.println("-----------");
IntStream skip = IntStream.of(ints).skip(2); //跳过前两个之后的流
skip.forEach(System.out::print);
}
}
collect()和Collectors使用
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.spinach.jdk8.entity.Student;
public class Stream13_Collectors {
public static void main(String[] args) {
Student student1 = new Student("zhangsan", 100, 20);
Student student2 = new Student("lisi", 90, 20);
Student student3 = new Student("wangwu", 90, 30);
Student student4 = new Student("zhangsan", 80, 50);
List<Student> students = Arrays.asList(student1, student2, student3, student4);
/**
* KEY:以名称分组,VALUE:对应的LIST<T>集合
*/
Map<String, List<Student>> map = students.stream().collect(Collectors.groupingBy(Student::getName));
List<Student> result1 = map.get("zhangsan");
Map<Integer, List<Student>> map2 = students.stream().collect(Collectors.groupingBy(Student::getScore));
List<Student> result2 = map2.get(90); // get("90")取不到数据,因为不是字符串
/**
* KEY:以名称分组,VALUE:对应的数量
*/
Map<String, Long> map3 = students.stream().collect(Collectors.groupingBy(Student::getName, Collectors
.counting()));
/**
* KEY:以名称分组,VALUE:对应 分数平均值
*/
Map<String, Double> map4 = Arrays.asList(student1, student2, student3, student4).stream().collect(Collectors
.groupingBy(Student::getName, Collectors.averagingDouble(Student::getScore)));
/**
* 获得以分数大于等于90 的集合。
*/
Map<Boolean, List<Student>> map5 = Arrays.asList(student1, student2, student3, student4).stream().collect(
Collectors.partitioningBy(student -> student.getScore() >= 90));
List<Student> result51 = map5.get(true); // get(true):满足条件
List<Student> result52 = map5.get(false); // get("90"):不满足条件
System.out.println(map5);
}
}
2.4 流的压力测试
由于流可以并行操作,充分使用计算机的多线程操作,所以写了一个压力测试。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 压力测试
* @author:whh
* @date:2018年1月10日下午2:31:14
*/
public class Stream09_pressure {
public static void main(String[] args) {
Stream.iterate(100, item -> item * 10).limit(10).forEach(item -> {
testSort(item);
});
System.out.println("压力测试完成!");
}
/**
* 压力测试结果(合并):
* 100 18 2
* 1000 11 56
* 10000 31 46
* 100000 94 165143 十万级 数据可以处理。
* 1000000 550 失败
* 流方式单独测试:
* 流的方式:数量:100 排序耗时13
流的方式:数量:1000 排序耗时7
流的方式:数量:10000 排序耗时32
流的方式:数量:100000 排序耗时109
流的方式:数量:1000000 排序耗时533
流的方式:数量:10000000 排序耗时6261,千万级数据可能成功排序。
流的方式:数量:100000000 加内存大小,报错:java.lang.OutOfMemoryError: GC overhead limit exceeded
* @author:whh
* @date:2018年1月10日下午2:55:47
* @param i
*/
private static void testSort(int length) {
List<String> list = new ArrayList<>(length);
List<String> list2 = new ArrayList<>(Arrays.asList(new String[length]));
for (int i = 0; i < length; ++i) {
list.add(UUID.randomUUID().toString());
}
Collections.copy(list2, list);
sortStream(list, length);
//sortOrinal(list2,length);
}
private static void sortStream(List<String> list, int length) {
long startTime = System.nanoTime();
//list.parallelStream().sorted().count();
List<String> list_new = list.parallelStream().sorted().collect(Collectors.toList());//.forEach(System.out::println);
long endTime = System.nanoTime();
long millis = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);
System.out.println("流的方式:数量:" + length + " 排序耗时" + millis);
/**
System.out.println("-----------------------------------------------------------------");
System.out.println("----------------------Stream:方式打印前5个,排序耗时: "+millis+" ------------");
System.out.println("-----------------------------------------------------------------");
for(int i=0;i<5;i++){
System.out.println(list_new.get(i));
}
*/
}
/**
* 原始方式排序
* @author:whh
* @param list
* @date:2018年1月10日下午3:26:53
* @param length
*/
private static void sortOrinal(List<String> list, int length) {
/**
* 经过本人压力测试,
* 100000:排序耗时:165143
* 1000000: 报错
* #报错信息
# A fatal error has been detected by the Java Runtime Environment:
#
# Internal Error (safepoint.cpp:310), pid=11499, tid=11523
# guarantee(PageArmed == 0) failed: invariant
#
# JRE version: Java(TM) SE Runtime Environment (8.0_40-b27) (build 1.8.0_40-b27)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.40-b25 mixed mode bsd-amd64 compressed oops)
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /users/apple/workspace_my_project/study_jdk8/hs_err_pid11499.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
*/
if (length > 100000) {
return;
}
int size = list.size();
String temp = "";
long startTime1 = System.nanoTime();
for (int i = 0; i < size - 1; i++) {
for (int j = i + 1; j < size; j++) {
if (list.get(i).compareTo(list.get(j)) > 0) {
temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
}
}
long endTime1 = System.nanoTime();
long millis1 = TimeUnit.NANOSECONDS.toMillis(endTime1 - startTime1);
System.out.println("流的方式:数量:" + length + " 排序耗时" + millis1);
/**
System.out.println("-----------------------------------------------------------------");
System.out.println("------------------------原始:方式打印前5个,排序耗时: "+millis1+" -----------");
System.out.println("-----------------------------------------------------------------");
for(int i=0;i<5;i++){
System.out.println(list.get(i));
}
*/
}
}
三:安全性
Java一直缺少BASE64编码 API,以至于通常在项目开发中会选用第三 方的API实现(commons-codec或sun.misc.BASE64Decoder)。Java 8实现了BASE64编解码API,它包含到java.util中。
// 编码
String asB64 = Base64.getEncoder().encodeToString("Hello JDK8".getBytes("utf-8"));
System.out.println(asB64); // 输出为: SGVsbG8gSkRLOA==
// 解码
byte[] asBytes = Base64.getDecoder().decode("SGVsbG8gSkRLOA==");
System.out.println(new String(asBytes, "utf-8")); // 输出为: Hello JDK8
四:IO/NIO的改进
主要包括:改进了 java.nio.charset.Charset 的实 现,使编码和解码 的效率得以提升,也精简了 jre/lib/charsets.jar包;优化了 String(byte[],*)构造方法和 String.getBytes()方法的性能;还增加 了一些新的 IO/NIO方法,使用这些方法可以从文件或者输入流中 获取流(java.util.stream.Stream), 通过对流的操作,可以简化文 本行处理、目录遍历和文件查找。
新增的API如下:
- BufferedReader.line():返回文本行的流
- Stream File.lines(Path, Charset):返回文本行的流
- Stream File.list(Path): 遍历当前目录下的文件和目录
- File.walk(Path, int, FileVisitOption): 遍历某一个目录下的所有文件 和指定深度的子目录
- File.find(Path, int, BiPredicate, FileVisitOption… ): 查找相应的文件
- Files.list(new File(“.”).toPath()).forEach(System.out::println);操作列出当前目录下的所有文件和目录
五:国际化功能
支持新的 Unicode 6.2.0 标准,新增了日历和本地化的 API, 改进了日期时间的管理等。
Java 8 吸收了 Joda-Time 的精华,以一个新的开始为 Java 创 建优秀的 API。新的 java.time 中包含了 所有关于时钟 (Clock),本地日期(LocalDate)、本地时间(LocalTime)、本地 日期时间 (LocalDateTime)、时区(ZonedDateTime)和持续时 间(Duration)的类。历史悠久的 Date类新增了 toInstant()方 法,用于把 Date转换成新的表示形式。这些新增的本地化时 间 日期 API 大大简化了了日期时间和本地化的管理。
5.1 时间操作举例
例如,下面是对 LocalDate,LocalTime的简单应用:
//LocalDate
LocalDate localDate = LocalDate.now(); //获取本地日期
localDate = LocalDate.ofYearDay(2014, 200); // 获得 2014 年的第 200天 System.out.println(localDate.toString());//输出:2014-07-19
localDate = LocalDate.of(2014, Month.SEPTEMBER, 10); //2014 年 9 月 10日 System.out.println(localDate.toString());//输出:2014-09-10 //LocalTime
LocalTime localTime = LocalTime.now(); //获取当前时间
System.out.println(localTime.toString());//输出当前时间
localTime = LocalTime.of(10, 20, 50);//获得 10:20:50 的时间点 System.out.println(localTime.toString());//输出: 10:20:50
//Clock 时钟
Clock clock = Clock.systemDefaultZone();//获取系统默认时区 (当前 瞬时时间 )
long millis = clock.millis(); //获得毫秒数
六:js引擎Nashorn
高性能的轻型JavaSript引擎:集成到JRE使用现有的:javax.script api 符合ECMAScript-262 5.1版本规范。 新命令行工具JJS可支持Javascript
注:Nashorn不支持浏览器DOM的对象
Nashorn举例
javascript运行在jvm已经不是新鲜事了,Rhino早在jdk6的时候已 经存在,但现在为何要替代Rhino,官方的解释是Rhino相比其他 javascript引擎(比如google的V8)实在太慢了,要改造Rhino还 不如重写。
Nashorn比Rhino速度快了许多,作为高性能的javascript运行环 境,Nashorn有很多可能。
//声明
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
//引用JS文件
engine.eval(new FileReader("script.js"));
//使用script语句
engine.eval(“print(‘Hello World!’);”);
七:JVM内存
去除了永久代(PermGen) 被元空间(Metaspace)代替
配置:-XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=80m 代替 -XX:PermSize=10m -XX:MaxPermSize=10m
原因:移除永久代是为融合HotSpot JVM与 JRockit VM而做 出的努力,因为JRockit没有永久代,不需要配置永久代。
谢谢大家