jdk(Java Development Kit)发布及新增特性
Java 1.0
- 1996.01.23
- Sun公司发布了Java的第一个开发工具包
Java 1.1
- 1997.02.19
- JavaOne会议召开,创当时全球同类会议规模之最
Java1.2
- 1998.12.08
- Java拆分成:J2SE(标准版)、J2EE(企业版)、J2ME(微型版)
Java1.3
- 2000.05.08
Java1.4
- 2004.02.06
Java5.0
- 2004.09.30
- 版本号从1.4变为5.0
- 平台更名为JavaSE、JavaEE、JavaME
- 5.0之前需要自定义枚举类型–>5.0之后Java开始支持使用enum关键字来快速定义枚举类型
//java5.0之前
class Season{
private final String seasonName;
private final String seasonDesc;
private Season(String seasonName,String seasonDesc){
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
public static final Season SPRING = new Season("春天","春暖花开");
public static final Season SUMMER = new Season("夏天","夏日炎炎");
public static final Season AUTUMN = new Season("秋天","秋高气爽");
public static final Season WINTER = new Season("冬天","白雪皑皑");
@Override
public String toString() {
return "Season{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
}
enum Season1{
//开头
SPRING("春天","春暖花开"),
SUMMER("夏天","夏日炎炎"),
AUTUMN("秋天","秋高气爽"),
WINTER("冬天","白雪皑皑");
private final String seasonName;
private final String seasonDesc;
private Season1(String seasonName,String seasonDesc){
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}
public String getSeason1Name() {
return seasonName;
}
public String getSeason1Desc() {
return seasonDesc;
}
@Override
public String toString() {
return "Season1{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
}
- 以”@注解名”在代码中添加注解
- 线程状态改变
- 创建线程的新的方法
- 实现Callable接口
- 线程池创建线程
/* * 创建多线程的方式三:实现Callable (jdk5.0新增的) */ //1.创建一个实现Callable的实现类 class NumThread implements Callable { //2.实现call方法,将此线程需要执行的操作声明在call()中 @Override public Object call() throws Exception { int sum = 0; for (int i = 1; i <= 100; i++) { if (i % 2 == 0) { System.out.println(i); sum += i; } Thread.sleep(1000); } return sum; } } public class CallableTest { public static void main(String[] args) { //3.创建Callable接口实现类的对象 NumThread numThread = new NumThread(); //4.将此Callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask的对象 FutureTask futureTask = new FutureTask(numThread); //5.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start() Thread t1 = new Thread(futureTask); t1.start(); System.out.println("main()线程"); try { //6.获取Callable中call方法的返回值 //get()返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值。 Object sum = futureTask.get(); System.out.println("总和为:" + sum); } catch (Exception e) { e.printStackTrace(); } } }
- StringBuilder:可变的字符串;线程不安全,效率高
- foreach循环
Java6.0
- 2006.12.11
- 2009.04.20Oracle宣布收购SUN公司
Java7.0
- 2011.07.02
- 字符串常量池从方法区
- 中存放到堆空间中
- 开始可以在switch中匹配使用
- 泛型类型推断
- 异常处理资源自动关闭
try(资源对象的声明和初始化){
业务逻辑代码,可能会产生异常
}catch(异常类型1 e){
处理异常代码
}catch(异常类型2 e){
处理异常代码
}//举例1 @Test public void test02() { try ( FileWriter fw = new FileWriter("d:/1.txt"); BufferedWriter bw = new BufferedWriter(fw); ) { bw.write("hello"); } catch (IOException e) { e.printStackTrace(); } } //举例2 @Test public void test03() { //从d:/1.txt(utf-8)文件中,读取内容,写到项目根目录下1.txt(gbk)文件中 try ( FileInputStream fis = new FileInputStream("d:/1.txt"); InputStreamReader isr = new InputStreamReader(fis, "utf-8"); BufferedReader br = new BufferedReader(isr); FileOutputStream fos = new FileOutputStream("1.txt"); OutputStreamWriter osw = new OutputStreamWriter(fos, "gbk"); BufferedWriter bw = new BufferedWriter(osw); ) { String str; while ((str = br.readLine()) != null) { bw.write(str); bw.newLine(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
Java8.0(LTS)
-
2014.03.18
-
此版本是继Java5.0以来变化最大的版本。长期支持
-
接口内部结构的说明:
可以声明:
属性:必须使用public static final修饰
方法:jdk8之前:声明抽象方法,修饰为public abstract
jdk8:声明静态方法:只能接口自己调用,实现类不能调用
默认方法:可以被实现类重写
不可以声明:构造器、代码块等- 把方法区改名为元空间
-
日期api的更改
JDK 1.0中包含了一个java.util.Date类,但是它的大多数方法已经在JDK 1.1引入Calendar类之后被弃用了。而Calendar并不比Date好多少。它们面临的问题是:
- 可变性:像日期和时间这样的类应该是不可变的。
- 偏移性:Date中的年份是从1900开始的,而月份都从0开始。
- 格式化:格式化只对Date有用,Calendar则不行。
- 此外,它们也不是线程安全的;不能处理闰秒等。
闰秒,是指为保持协调世界时接近于世界时时刻,由国际计量局统一规定在年底或年中(也可能在季末)对协调世界时增加或减少1秒的调整。由于地球自转的不均匀性和长期变慢性(主要由潮汐摩擦引起的),会使世界时(民用时)和原子时之间相差超过到±0.9秒时,就把协调世界时向前拨1秒(负闰秒,最后一分钟为59秒)或向后拨1秒(正闰秒,最后一分钟为61秒); 闰秒一般加在公历年末或公历六月末。
目前,全球已经进行了27次闰秒,均为正闰秒。
总结:对日期和时间的操作一直是Java程序员最痛苦的地方之一
。
第三次引入的API是成功的,并且Java 8中引入的java.time API 已经纠正了过去的缺陷,将来很长一段时间内它都会为我们服务。
Java 8 以一个新的开始为 Java 创建优秀的 API。新的日期时间API包含:
java.time
– 包含值对象的基础包java.time.chrono
– 提供对不同的日历系统的访问。java.time.format
– 格式化和解析时间和日期java.time.temporal
– 包括底层框架和扩展特性java.time.zone
– 包含时区支持的类
说明:新的 java.time 中包含了所有关于时钟(Clock),本地日期(LocalDate)、本地时间(LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime)和持续时间(Duration)的类。
尽管有68个新的公开类型,但是大多数开发者只会用到基础包和format包,大概占总数的三分之一。
-
Lambda表达式
Lambda 表达式:在Java 8 语言中引入的一种新的语法元素和操作符。这个操作符为 “
->
” , 该操作符被称为Lambda 操作符
或箭头操作符
。它将 Lambda 分为两个部分:
左侧:指定了 Lambda 表达式需要的参数列表
右侧:指定了 Lambda 体,是抽象方法的实现逻辑,也即 Lambda 表达式要执行的功能.语法格式一: 无参,无返回值
@Test public void test1(){ //未使用Lambda表达式 Runnable r1 = new Runnable() { @Override public void run() { System.out.println("我爱北京天安门"); } }; r1.run(); System.out.println("***********************"); //使用Lambda表达式 Runnable r2 = () -> { System.out.println("我爱北京故宫"); }; r2.run(); }
语法格式二: Lambda 需要一个参数,但是没有返回值。
@Test public void test2(){ //未使用Lambda表达式 Consumer<String> con = new Consumer<String>() { @Override public void accept(String s) { System.out.println(s); } }; con.accept("谎言和誓言的区别是什么?"); System.out.println("*******************"); //使用Lambda表达式 Consumer<String> con1 = (String s) -> { System.out.println(s); }; con1.accept("一个是听得人当真了,一个是说的人当真了"); }
语法格式三: 数据类型可以省略,因为可由编译器推断得出,称为“类型推断”
@Test public void test3(){ //语法格式三使用前 Consumer<String> con1 = (String s) -> { System.out.println(s); }; con1.accept("一个是听得人当真了,一个是说的人当真了"); System.out.println("*******************"); //语法格式三使用后 Consumer<String> con2 = (s) -> { System.out.println(s); }; con2.accept("一个是听得人当真了,一个是说的人当真了"); }
语法格式四: Lambda 若只需要一个参数时,参数的小括号可以省略
@Test public void test4(){ //语法格式四使用前 Consumer<String> con1 = (s) -> { System.out.println(s); }; con1.accept("一个是听得人当真了,一个是说的人当真了"); System.out.println("*******************"); //语法格式四使用后 Consumer<String> con2 = s -> { System.out.println(s); }; con2.accept("一个是听得人当真了,一个是说的人当真了"); }
语法格式五: Lambda 需要两个或以上的参数,多条执行语句,并且可以有返回值
@Test public void test5(){ //语法格式五使用前 Comparator<Integer> com1 = new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { System.out.println(o1); System.out.println(o2); return o1.compareTo(o2); } }; System.out.println(com1.compare(12,21)); System.out.println("*****************************"); //语法格式五使用后 Comparator<Integer> com2 = (o1,o2) -> { System.out.println(o1); System.out.println(o2); return o1.compareTo(o2); }; System.out.println(com2.compare(12,6)); }
语法格式六: 当 Lambda 体只有一条语句时,return 与大括号若有,都可以省略
@Test public void test6(){ //语法格式六使用前 Comparator<Integer> com1 = (o1,o2) -> { return o1.compareTo(o2); }; System.out.println(com1.compare(12,6)); System.out.println("*****************************"); //语法格式六使用后 Comparator<Integer> com2 = (o1,o2) -> o1.compareTo(o2); System.out.println(com2.compare(12,21)); } @Test public void test7(){ //语法格式六使用前 Consumer<String> con1 = s -> { System.out.println(s); }; con1.accept("一个是听得人当真了,一个是说的人当真了"); System.out.println("*****************************"); //语法格式六使用后 Consumer<String> con2 = s -> System.out.println(s); con2.accept("一个是听得人当真了,一个是说的人当真了"); }
-
函数式接口
-
方法引用与构造器引用
-
强大的streamAPI
Java9.0
- 2017.09.22
- 此版本开始每半年更新一次
- 不再支持windows 32位系统
接口中可以声明私有方法
提出公共内容以供该接口默认方法调用
- 存储字符串的容器变为byte[];
- jShell
- try的前面可以定义流对象,try后面的()中可以直接引用流对象的名称。在try代码执行完毕后,流对象也可以释放掉,也不用写finally了。
A a = new A();
B b = new B();
try(a;b){
可能产生的异常代码
}catch(异常类名 变量名){
异常处理的逻辑
}@Test public void test04() { InputStreamReader reader = new InputStreamReader(System.in); OutputStreamWriter writer = new OutputStreamWriter(System.out); try (reader; writer) { //reader是final的,不可再被赋值 // reader = null; } catch (IOException e) { e.printStackTrace(); } }
Java10.0
- 2018.03.21
- 局部类型推断
Java11.0(LTS)
- 2018.09.25
- JDK安装包取消独立JRE安装包
Java12.0
- 2019.03.19
Java13.0
-
文本块
使用"""作为文本块的开始符和结束符,在其中就可以放置多行的字符串,不需要进行任何转义。因此,文本块将提高Java程序的可读性和可写性。
原有写法:
String text1 = "The Sound of silence\n" + "Hello darkness, my old friend\n" + "I've come to talk with you again\n" + "Because a vision softly creeping\n" + "Left its seeds while I was sleeping\n" + "And the vision that was planted in my brain\n" + "Still remains\n" + "Within the sound of silence"; System.out.println(text1);
现在写法:
String text2 = """ The Sound of silence Hello darkness, my old friend I've come to talk with you again Because a vision softly creeping Left its seeds while I was sleeping And the vision that was planted in my brain Still remains Within the sound of silence """; System.out.println(text2);
Java14.0
- instanceof的模式匹配
14以前:
if(obj instanceof String){ String str = (String)obj; //需要强转 .. str.contains(..).. }else{ ... }
14以后
if(obj instanceof String str){ .. str.contains(..).. }else{ ... }
- Record
//旧写法 class Point { private final int x; private final int y; Point(int x, int y) { this.x = x; this.y = y; } int x() { return x; } int y() { return y; } public boolean equals(Object o) { if (!(o instanceof Point)) return false; Point other = (Point) o; return other.x == x && other.y == y; } public int hashCode() { return Objects.hash(x, y); } @Override public String toString() { return "Point{" + "x=" + x + ", y=" + y + '}'; } } //新写法 record Point(int x, int y) { }
Java15.0
- 密封类
在 Java 中如果想让一个类不能被继承和修改,这时我们应该使用
final
关键字对类进行修饰。不过这种要么可以继承,要么不能继承的机制不够灵活,有些时候我们可能想让某个类可以被某些类型继承,但是又不能随意继承,是做不到的。Java 15 尝试解决这个问题,引入了sealed
类,被sealed
修饰的类可以指定子类。这样这个类就只能被指定的类继承。
通过密封的类和接口来限制超类的使用,密封的类和接口限制其它可能继承或实现它们的其它类或接口。
具体使用:
使用修饰符sealed
,可以将一个类声明为密封类。密封的类使用保留关键字permits
列出可以直接扩展(即extends)它的类。
sealed
修饰的类的机制具有传递性,它的子类必须使用指定的关键字进行修饰,且只能是final
、sealed
、non-sealed
三者之一。public abstract sealed class Shape permits Circle, Rectangle, Square {...} public final class Circle extends Shape {...} //final表示Circle不能再被继承了 public sealed class Rectangle extends Shape permits TransparentRectangle, FilledRectangle {...} public final class TransparentRectangle extends Rectangle {...} public final class FilledRectangle extends Rectangle {...} public non-sealed class Square extends Shape {...} //non-sealed表示可以允许任何类继承
Java16.0
Java17.0(LTS)
- 2021.09
- 版本号也称21.9
- switch模式匹配
- Java 12将会对switch声明语句进行扩展,使用
case L ->
来替代以前的break;
,省去了 break 语句,避免了因少写 break 而出错。- 同时将多个 case 合并到一行,显得简洁、清晰,也更加优雅的表达逻辑分支。
- 为了保持兼容性,case 条件语句中依然可以使用字符
:
,但是同一个 switch 结构里不能混用->
和:
,否则编译错误。