JDK各版本新特性总结
JDK1.4
NIO
JDK 1.5
静态导入
- 被导入方法必须是静态的
- 如果有多个同名的静态方法,容易不知道使用谁?这个时候要使用,必须加前缀。由此可见,意义不大,所以一般不用,但是要能看懂。
import static java.lang.Math.abs;
import static java.lang.Math.pow;
import static java.lang.Math.max;
//错误
//import static java.util.ArrayList.add;
public class test {
public static void main(String[] args) {
// System.out.println(java.lang.Math.abs(-100));
// System.out.println(java.lang.Math.pow(2, 3));
// System.out.println(java.lang.Math.max(20, 30));
// 太复杂,我们就引入到import
// System.out.println(Math.abs(-100));
// System.out.println(Math.pow(2, 3));
// System.out.println(Math.max(20, 30));
// 太复杂,有更简单
// System.out.println(abs(-100));
System.out.println(java.lang.Math.abs(-100));
System.out.println(pow(2, 3));
System.out.println(max(20, 30));
}
public static void abs(String s){
System.out.println(s);
}
}
自动装箱、拆箱
Integer i = 1;//装箱
int j = i;//拆箱
// ==比较时候也会自动拆箱
Integer localInteger = Integer.valueOf(1);
if (localInteger.intValue() == 1) {
}
switch可以使用枚举值
增强for循环
public static int add(int x,int ...args) {
int sum = x;
for(int arg:args) {
sum += arg;
}
return sum;
}
注意
- 集合变量可以是数组或实现了Iterable接口的集合类
可变参数
public void game(int a,String ...args){
}
- 只能出现在参数列表的最后
- …位于变量类型和变量名之间,前后有无空格都可以
String...args
String ...args
String... args
String ... args
- 这里的变量其实是一个数组,调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。
- 如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个
- Arrays.asList()虽然可以把数组转成集合,但是集合的长度不能改变。
List<String> list = Arrays.asList("hello", "world", "java");
// UnsupportedOperationException
// list.add("javaee");
// UnsupportedOperationException
// list.remove(1);
枚举
枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就会报错。枚举可以让编译器在编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段无法实现这一目标。
注意
- 所有枚举类都是Enum的子类
- 枚举类的第一行上必须是枚举项,最后一个枚举项后的分号是可以省略的,但是如果枚举类有其他的东西,这个分号就不能省略。建议不要省略
- 枚举类可以有构造器,但必须是private的,它默认的也是private的
- 枚举类也可以有抽象方法,但是枚举项必须重写该方法
- 枚举可以在switch语句中使用
public enum Direction3 {
FRONT("前") {
@Override
public void show() {
System.out.println("前");
}
},
BEHIND("后") {
@Override
public void show() {
System.out.println("后");
}
},
LEFT("左") {
@Override
public void show() {
System.out.println("左");
}
},
RIGHT("右") {
@Override
public void show() {
System.out.println("右");
}
};
private String name;
private Direction3(String name) {
this.name = name;
}
public String getName() {
return name;
}
public abstract void show();
}
Direction3.RIGHT.getClass().getName();// Direction3
枚举的常用方法
Direction d1 = Direction.FRONT;
Direction d2 = Direction.BEHIND;
Direction d3 = Direction.LEFT;
Direction d4 = Direction.RIGHT;
// int compareTo() 比较 根据编号 self.ordinal - other.ordinal
System.out.println(d1.compareTo(d1));
// String name() //获取枚举名称
System.out.println(d1.name());
// int ordinal() //获取编号
System.out.println(d1.ordinal());
// String toString() 默认返回枚举名称
System.out.println(d1.toString());
// <T> T valueOf(Class<T> type,String name) 通过name获取枚举对象
Direction d = Enum.valueOf(Direction.class, "FRONT");
System.out.println(d.getName());
// values() 遍历枚举对象
// 此方法虽然在JDK文档中查找不到,但每个枚举类都具有该方法,它遍历枚举类的所有枚举值非常方便
Direction[] dirs = Direction.values();
for (Direction d : dirs) {
System.out.println(d);
System.out.println(d.getName());
}
泛型
元数据
Scanner类处理用户录入
Lock
// 定义票
private int tickets = 100;
// 定义锁对象
private Lock lock = new ReentrantLock();// ReentrantLock是Lock的实现类
@Override
public void run() {
while (true) {
try {
// 加锁
lock.lock();
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "正在出售第" + (tickets--) + "张票");
}
} finally {
// 释放锁
lock.unlock();
}
}
}
线程并发库
线程并发库是Java1.5提出的关于多线程处理的高级功能,所在包:java.util.concurrent
- public static ExecutorService newCachedThreadPool() 创建一个具有缓存功能的线程池
- public static ExecutorService newFixedThreadPool(int nThreads) 创建一个可重用的,具有固定线程数的线程池
- public static ExecutorService newSingleThreadExecutor() 创建一个只有单线程的线程池,相当于上个方法的参数是1
1.线程互斥 工具类描述:Lock,RedWriteLock 2.线程通信 描述:Condition 3.线程池 ExecutorService 3.同步队列 ArrayBlockingQueue 4.同步集合 ConcurrentHashMap,CopyOnWriteArrayList 5.线程同步工具 Semaphore
注解
JDK默认提供的注解:
- Deprecated
- Override
- SuppressWarnings
元注解(注解的注解)
- @Retention 保留
- RetetionPolicy.SOURCE java源文件
- RetetionPolicy.CLASS class文件 (默认)
- RetetionPolicy.RUNTIME 内存中的字节码
- @Target
- ElementType.TYPE 类型 包括Class、Interface、Enum等的父,对类、接口和枚举等对象生效
- ElementType.FIELD 成员变量
- ElementType.METHOD 方法
- ElementType.PARAMETER 参数
- ElementType.CONSTRUCTOR 构造方法
- ElementType.LOCAL_VARIABLE 局部变量
- ElementType.ANNOTATION_TYPE 注解
- ElementType.PACKAGE 包
注解属性
枚举的属性类型包括:基本数据类型,String,Class,枚举,其他注解,以及这些类型的数组。
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface MyAnnotation {
// 注解属性
String color() default "blue"; //String类型并指定默认值
String value();//特殊字段value
int[] arrayAttr() default {3,4,4};//数组类型字段
TrafficLamp lamp() default TrafficLamp.RED;//枚举类型
MetaAnnotation annotationAttr() default @MetaAnnotation("test");//注解类型
Class classValue() default String.class;//class类型
}
public @interface MetaAnnotation {
String value();
}
public enum TrafficLamp{
RED(30){
public TrafficLamp nextLamp(){
return GREEN;
}
},
GREEN(45){
public TrafficLamp nextLamp(){
return YELLOW;
}
},
YELLOW(5){
public TrafficLamp nextLamp(){
return RED;
}
};
public abstract TrafficLamp nextLamp();
private int time;
private TrafficLamp(int time){this.time = time;}
}
@MyAnnotation(annotationAttr=@MetaAnnotation("test"),color="red",value="abc",arrayAttr=1)//数组类型只有一个值可以省略花括号
public class AnnotationTest {
@MyAnnotation("xyz")//只有value字段可以省略字段名和等号
public static void main(String[] args) throws Exception{
if(AnnotationTest.class.isAnnotationPresent(MyAnnotation.class)){
MyAnnotation annotation = (MyAnnotation)AnnotationTest.class.getAnnotation(MyAnnotation.class);
System.out.println(annotation.color());// red
System.out.println(annotation.value());// abc
System.out.println(annotation.arrayAttr()[0]);// 1
System.out.println(annotation.lamp().nextLamp().name());// GREEN
System.out.println(annotation.annotationAttr().value());// test
System.out.println(annotation.classValue().getName());// java.lang.String
}
}
}
@Override、@SuppressWarnings和@Deprecated这三个注解的属性值分别是什么?
@Override、@SuppressWarnings是SOURCE
@Deprecated是RUNTIME,因为编译器拿到class文件加载到内存后才能检查是否已经过时,所以是RUNTIME
JDK 1.6
https://www.ibm.com/developerworks/cn/java/j-lo-jse61/index.html
Instrumentation新功能(Java Agent)
instrumentation包被赋予了更强大的功能:
- 启动后的instrument
- 本地代码(native code)instrument
- 以及动态改变classpath 等等
HTTP增强
- NTLM 认证提供了一种 Window 平台下较为安全的认证机制;
- JDK 当中提供了一个轻量级的 HTTP 服务器;
- 提供了较为完善的 HTTP Cookie 管理功能;
- 更为实用的 NetworkInterface;DNS 域名的国际化支持等等。
JMX增强
https://www.ibm.com/developerworks/cn/java/j-lo-jse63/index.html
编译器API
- 老版本的编程接口并不是标准 API 的一部分,而是作为 Sun 的专有实现提供的,而新版则带来了标准化的优点
- 可以编译抽象文件,理论上是任何形式的对象 —— 只要该对象实现了特定的接口。
- 第三个新特性是可以收集编译时的诊断信息
import java.util.Date;
public class Target {
public void doSomething(){
Date date = new Date(10, 3, 3);
// 这个构造函数被标记为deprecated, 编译时会
// 向错误输出输出信息。
System.out.println("Doing...");
}
}
import javax.tools.*;
import java.io.FileOutputStream;
public class Compiler {
public static void main(String[] args) throws Exception{
String fullQuanlifiedFileName = "compile" + java.io.File.separator +
"Target.java";
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
FileOutputStream err = new FileOutputStream("err.txt");
int compilationResult = compiler.run(null, null, err, fullQuanlifiedFileName);
if(compilationResult == 0){
System.out.println("Done");
} else {
System.out.println("Fail");
}
}
}
package math;
import javax.tools.*;
import java.io.FileOutputStream;
import java.util.Arrays;
public class AdvancedCompiler {
public static void main(String[] args) throws Exception{
// Steps used to compile Calculator
// Steps used to compile StringObject
// construct CalculatorTest in memory
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager =
compiler.getStandardFileManager(null, null, null);
JavaFileObject file = constructTestor();
Iterable<? extends JavaFileObject> files = Arrays.asList(file);
DiagnosticCollector<JavaFileObject> collector = new DiagnosticCollector<JavaFileObject>();
JavaCompiler.CompilationTask task = compiler.getTask (
null, fileManager, collector, null, null, files);
Boolean result = task.call();
if( result == true ) {
System.out.println("Succeeded");
}
}
private static SimpleJavaFileObject constructTestor() {
StringBuilder contents = new StringBuilder(
"package math;" +
"class CalculatorTest {\n" +
" public void testMultiply() {\n" +
" Calculator c = new Calculator();\n" +
" System.out.println(c.multiply(2, 4));\n" +
" }\n" +
" public static void main(String[] args) {\n" +
" CalculatorTest ct = new CalculatorTest();\n" +
" ct.testMultiply();\n" +
" }\n" +
"}\n");
StringObject so = null;
try {
so = new StringObject("math.CalculatorTest", contents.toString());
} catch(Exception exception) {
exception.printStackTrace();
}
return so;
}
}
Derby和JDBC 4.0
JDBC 4.0
- 自动加载驱动
- 所有 JDBC 4.0 的驱动 jar 文件必须包含一个 java.sql.Driver,它位于 jar 文件的 META-INF/services 目录下
- RowId类型
- SQLXML
- SQLExcpetion 的增强
Derby
try { // load the driver
Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
System.out.println("Load the embedded driver");
Connection conn = null;
Properties props = new Properties();
props.put("user", "user1");
props.put("password", "user1");
//create and connect the database named helloDB
conn = DriverManager.getConnection("jdbc:derby:helloDB;create=true", props);
System.out.println("create and connect to helloDB");
conn.setAutoCommit(false);
// create a table and insert two records
Statement s = conn.createStatement();
s.execute("CREATE TABLE hellotable(name VARCHAR(40), score INT)");
System.out.println("Created table hellotable");
s.execute("INSERT INTO hellotable VALUES('Ruth Cao', 86)");
s.execute("INSERT INTO hellotable VALUES ('Flora Shi', 92)");
// list the two records
ResultSet rs = s.executeQuery(
"SELECT name, score FROM hellotable ORDER BY score");
System.out.println("name\t\tscore");
while (rs.next()) {
StringBuilder builder = new StringBuilder(rs.getString(1));
builder.append("\t");
builder.append(rs.getInt(2));
System.out.println(builder.toString());
}
// delete the table
s.execute("DROP TABLE hellotable");
System.out.println("Dropped table hellotable");
rs.close();
s.close();
System.out.println("Closed result set and statement");
conn.commit();
conn.close();
System.out.println("Committed transaction and closed connection");
try { // perform a clean shutdown all
DriverManager.getConnection("jdbc:derby:;shutdown=true");
// shutdown current connection
//DriverManager.getConnection("jdbc:derby:helloDB;shutdown=true ");
} catch (SQLException se) {
System.out.println("Database shut down normally");
}
} catch (Throwable e) {
// handle the exception
e.printStackTrace();
}
System.out.println("SimpleApp finished");
对脚本语言的支持
- 获取脚本程序输入,通过脚本引擎运行脚本并返回运行结果,这是最核心的接口。
- 发现脚本引擎,查询脚本引擎信息。
- 通过脚本引擎的运行上下文在脚本和 Java 平台间交换数据。
- 通过 Java 应用程序调用脚本函数。
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
ScriptObjectMirror eval = (ScriptObjectMirror) engine.eval(" 'Hello World'.split(' ')");
Set<Map.Entry<String, Object>> entries = eval.entrySet();
for (Map.Entry<String, Object> entry : entries) {
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
XML API 与 Web 服务
- 对 XML 处理技术进行了扩展。包括新加入的 StAX 和 JAXB。
- 和较早的 JDK 5 相比,新版本的 JDK Web 服务功能更改了名称 —— 从 JAX-RPC 变成 JAX-WS。JDK 5 只支持基于 remote-procedure-call 的 Web 服务,JDK 6 在此基础上,还支持基于 SOAP message 的 Web 服务实现
JDK 1.7
https://www.ibm.com/developerworks/cn/java/j-lo-jdk7-1/index.html
switch可以使用String
switch语句的表达式可以是byte吗?可以是long吗?可以是String吗
可以,不可以,JDK7以后可以
异常的多个catch合并
- 处理方式是一致的。(实际开发中,好多时候可能就是针对同类型的问题,给出同一个处理)
- 多个异常间必须是平级关系。
// JDK7的处理方案
try {
System.out.println(a / b);
System.out.println(arr[3]);
} catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
System.out.println("出问题了");
}
try-with-resources 语句
好处
- 资源自动释放,不需要close()了
- 把需要关闭资源的部分都定义在这里就ok了
- 主要是流体系的对象是这个接口的子类(看JDK7的API)
// try-with-resources 语句
// try(必须是java.lang.AutoCloseable的子类对象){…}
try {
FileReader fr = new FileReader("a.txt");
FileWriter fw = new FileWriter("b.txt");
int ch = 0;
while ((ch = fr.read()) != -1) {
fw.write(ch);
}
fw.close();
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
// 改进版的代码
try (FileReader fr = new FileReader("a.txt");
FileWriter fw = new FileWriter("b.txt");) {
int ch = 0;
while ((ch = fr.read()) != -1) {
fw.write(ch);
}
} catch (IOException e) {
e.printStackTrace();
}//自动释放资源 不用手动关闭
NIO改进
NIO2 主要包括了 3 个方面的改进:
- 新的文件系统 API 支持大量文件属性的访问、文件系统监控服务、平台相关的 API,如 DosFileAttributes 和 PosixFileAttributes 等,以及一个可插拔文件系统的 SPI。
- Socket 和文件的异步 IO。
-
Socket channel 的功能完善,支持 binding、多播等。
- Path:与平台无关的路径。
- Paths:包含了返回Path的静态方法。
- Files:操作文件的工具类。提供了大量的方法
二进制的表现形式(二进制字面量)
JDK7开始,终于可以用二进制来表示整数(byte,short,int和long)。使用二进制字面量的好处是,可以使代码更容易被理解。语法非常简单,只要在二进制数值前面加 0b或者0B
// 二进制字面量
int x = 0b100101;
用_分隔数据
为了增强对数值的阅读性,如我们经常把数据用逗号分隔一样。JDK7提供了_对数据分隔。
注意
- 不能出现在进制标识和数值之间
- 不能出现在数值开头和结尾
- 不能出现在小数点旁边
// 数字字面量可以出现下划线
int y = 1_1123_1000;
// 不能出现在进制标识和数值之间
int z = 0x111_222;
// 不能出现在数值开头和结尾
int a = 0x11_22;
// 不能出现在小数点旁边
double d = 12.3_4;
泛型推断(菱形泛型)
泛型简化
ArrayList<String> array = new ArrayList<>();
JSR292:支持动态类型语言(InvokeDynamic)
动态类型语言在 JVM 上的执行速度得到了大大提升
G1 垃圾回收器
G1 在堆上分配一系列相同大小的连续区域,然后在回收时先扫描所有的区域,按照每块区域内存活对象的大小进行排序,优先处理存活对象小的区域,即垃圾对象最多的区域,这也是 Garbage First 这个名称的由来。G1 把要收集的区域内的存活对象合并并且复制到其他区域,从而避免了 CMS 遇到的内存碎片问题。此外,G1 采用了一个可预测暂停时间模型来达到软实时的要求。
JDK 1.8
https://www.ibm.com/developerworks/cn/java/j-lo-jdk8newfeature/index.html
函数式接口(Functional Interfaces)
Functional Interface(函数式接口,以下简称FI)FI的定义:任何接口,如果只包含 唯一一个抽象方法,那么它就是一个FI。为了让编译器帮助我们确保一个接口满足FI的要求(也就是说有且仅有一个抽象方法),Java8提供了@FunctionalInterface注解。
函数式接口的重要属性是:我们能够使用 Lambda 实例化它们,Lambda 表达式让你能够将函数作为方法参数,或者将代码作为数据对待。
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
Lamba
好处
- 在 Java 8 之前,匿名内部类,监听器和事件处理器的使用都显得很冗长,代码可读性很差,Lambda 表达式的应用则使代码变得更加紧凑,可读性增强;
- Lambda 表达式使并行操作大集合变得很方便,可以充分发挥多核 CPU 的优势,更易于为多核处理器编写代码;
组成
- 第一部分为一个括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数
- 第二部分为一个箭头符号:->
- 第三部分为方法体,可以是表达式和代码块
// 方法体为表达式,该表达式的值作为返回值返回。
(parameters) -> expression
// 方法体为代码块,必须用 {} 来包裹起来,且需要一个 return 返回值
// 但若函数式接口里面方法返回值是 void,则无需返回值。
(parameters) -> { statements; }
为了减少过量的函数式接口,Java 8 在 java.util.function 中增加了不少新的函数式通用接口
Function<T, R>
:将 T 作为输入,返回 R 作为输出,他还包含了和其他函数组合的默认方法。Predicate<T>
:将 T 作为输入,返回一个布尔值作为输出,该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(与、或、非)。Consumer<T>
:将 T 作为输入,不返回任何内容,表示在单个参数上的操作。
//run 没有参数传入,所以用 (), 后面用 {} 包起方法体
Thread thread = new Thread(
() -> {
System.out.println("Hello from a thread in run");
}
);
// 使用内部类
Function<Integer, String> f = new Function<Integer, String>() {
@Override
public String apply(Integer integer) {
return String.valueOf(integer);
}
};
// 使用 Lambda 表达式
Function<Integer, String> f3 = (integer) -> String.valueOf(integer);
// 省去括号
Function<Integer, String> f2 = integer -> String.valueOf(integer);
// 使用方法引用的方式
Function<Integer, String> f1 = String::valueOf;
// lambda排序
list.sort((String o, String o1) -> {
return Double.valueOf(o).compareTo(Double.valueOf(o1));
});
// 简化
list.sort(Comparator.comparing(Double::valueOf));
class People {
private List<Person> persons = new ArrayList<>();
public List<Person> getMaleList(Predicate<Person> predicate) {
List<Person> res = new ArrayList<>();
persons.forEach(// Iterable新增默认方法,接收一个Consumer对象
person -> {
if (predicate.test(person)) {//调用 Predicate 的抽象方法 test
res.add(person);
}
});
return res;
}
}
接口的增强
Java 8 对接口做了进一步的增强。在接口中可以添加使用 default 关键字修饰的非抽象方法(扩展方法)。还可以在接口中定义静态方法。
interface Inter {
//抽象方法
public abstract void show();
//default方法
public default void defaultPrint() {
System.out.println("defaultPrint 我爱林青霞");
}
//static方法
public static void staticPrint() {
System.out.println("staticPrint 我爱林青霞");
}
}
//实现类
class InterImpl implements Inter{
public void show() {
System.out.println("重写接口中的方法");
}
}
//测试类
public class Demo01 {
public static void main(String[] args) {
//Inter.defaultPrint(); //非静态方法不能直接使用
Inter.staticPrint();
Inter i = new InterImpl();
i.defaultPrint();
i.show();
}
}
集合之流式操作
Java 8 引入了流式操作(Stream),可以实现对集合(Collection)的并行处理和函数式操作
根据操作返回的结果不同,流式操作分为
中间操作
和最终操作
最终操作返回一特定类型的结果,而中间操作返回流本身,这样就可以将多个操作依次串联起来。
根据流的并发性,流又可以分为串行
和并行
两种。
流式操作实现了集合的过滤、排序、映射等功能。
List<String> list = new ArrayList<String>();
for (int i = 0; i < 1000000; i++) {
double d = Math.random() * 1000;
list.add(d + "");
}
// array结果为排序后的结果,原list不变
list = list.stream().sequential().sorted().collect(Collectors.toList());
list = list.stream().parallel().sorted().collect(Collectors.toList());
// 串行输出为 1200ms,并行输出为 800ms
// 而传统排序要10S左右
中间操作
该操作会保持 stream 处于中间状态,允许做进一步的操作。它返回的还是的 Stream,允许更多的链式操作。常见的中间操作有:
- filter():对元素进行过滤
- sorted():对元素排序
- map():元素的映射
- distinct():去除重复元素
- subStream():获取子 Stream 等
终止操作
该操作必须是流的最后一个操作,一旦被调用,Stream 就到了一个终止状态,而且不能再使用了。常见的终止操作有:
- forEach():对每个元素做处理
- toArray():把元素导出到数组
- findFirst():返回第一个匹配的元素
- anyMatch():是否有匹配的元素等
list.stream()
.filter((s) -> s.startsWith("s"))
.forEach(System.out::println);
注解的更新
主要有两点改进:类型注解
和重复注解
- 现在几乎可以为任何东西添加注解:局部变量、类与接口,就连方法的异常也能添加注解
- Java 8 引入了重复注解机制,这样相同的注解可以在同一地方声明多次。重复注解机制本身必须用 @Repeatable 注解
日期和时间
Java 8 吸收了 Joda-Time 的精华,以一个新的开始为 Java 创建优秀的 API
新的 java.time 中包含:
- 时钟(Clock)
- 本地日期(LocalDate)
- 本地时间(LocalTime)
- 本地日期时间(LocalDateTime)
- 时区(ZonedDateTime)
- 持续时间(Duration)
- 历史悠久的 Date 类新增了 toInstant() 方法,用于把 Date 转换成新的表示形式。
//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();//获取毫秒数
System.out.println(millis);
ZonedDateTime zonedDateTime = Instant.ofEpochMilli(millis).atZone(ZoneId.systemDefault());
System.out.println(zonedDateTime.toLocalDate());
System.out.println(zonedDateTime.toLocalTime());
System.out.println(Arrays.toString(TimeZone.getAvailableIDs()));
// 2014-07-19
// 2014-09-10
// 17:50:49.322
// 10:20:50
// 1502963449323
// 2017-08-17
// 17:50:49.323
// [Africa/Abidjan, Africa/Accra, ....