「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战」
1.JDK
jdk的发布周期
OpenJDK和OracleJDK
区别如下:
- OracleJDK每3年发布一次稳定版本,OpenJDK每3个月发布一次
- OracleJDK支持LTS(Long-Trem-Support),OpenJDK只支持档期版本至下一个版本发布
- OracleJDK采用Oracle Binary Code License协议,OpenJDK采用GPL v2协议
- OracleJDK基于OpenJDK构建
Android和JDK
Android最开始使用Java版本基于Apache协议发布的Harmony,从Android N开始使用OpenJDK
JAVA8
1.Lambda和函数式接口
函数式接口就是有且仅有一个抽象方法,但是可以有多个非抽象方法的接口,可以隐式转换为Lambda表达式
定义一个函数式接口
@FunctionalInterface
public interface IOperation {
int operation(int a, int b);
}
定义操作类
public class OperationImpl {
public int operation(int a, int b, IOperation operation) {
return operation.operation(a, b);
}
}
OperationImpl oImpl = new OperationImpl();
在java8之前操作需要定义匿名实现,
oImpl.operation(1, 2, new IOperation(){
public int operation(int a, int b) {
return a + b;
};
});
使用Lambda表达式之后
oImpl.operation(2, 3, (a, b) -> a + b);
2.方法引用
通过方法应用可以使用方法的名字来指向一个方法,使用一对冒号来应用方法"::"
@FunctionalInterface
public interface IOperation {
int operation(int a, int b);
}
interface Creator<T> {
T get();
}
interface TestInt {
int cp(Test test, Test test2);
}
public class Test {
public static Test create(Creator<Test> creator) {
return creator.get();
}
public int operation(int a, int b, IOperation operation) {
return operation.operation(a, b);
}
private static int add(int a, int b) {
return a + b;
}
private int sub(int a, int b) {
return a - b;
}
public int testM(Test test) {
return 0;
}
public void test(TestInt testInt) {
Test t1 = Test.create(Test::new);
Test t2 = Test.create(Test::new);
testInt.cp(t1, t2);
}
}
对应的引用方法
构造方法引用,Class::new
Test test = Test.Create(Test::new);
静态方法引用,Class::staticMethod
test.operation(1, 2, Test::add);
对象的实例引用,instance::method
test.operation(1, 2, test::sub);
类的实例引用,Class::method
test.test(Test::testM);
3.接口默认方法和静态方法
接口通过使用default方法,提供默认方法
public interface KingListener {
void getName();
//默认方法
default void getAge() {
System.out.println("Age is 1024.");
}
}
4.重复注解
Java8之前重复注解需要如下:
@interface Author {
String name();
}
@interface Authors {
Author[] value();
}
@Authors({@Author(name="a"), @Author(name = "b")})
class Article {
}
Java8之后可采取如下:
@Repeatable(Authors.class)
@interface Author {
String name();
}
@interface Authors {
Author[] value();
}
@Author(name = "a")
@Author(name = "b")
class Article {
}
解析注解时,Java8提供新的Api
AnnotatedElement.getAnnotationsByType(Class<T>)
5.类型注解
Java8之前注解智能在声明中,Java8之后可以在任何地方
@Author(name = "a")
private Object name = "";
private String author = (@Author(name="a")String) name;
6.更好的类型推断
Java8更新了类型推断
java7写法如下
List<String> stringList = new ArrayList<>();
stringList.add("A");
stringList.addAll(Arrays.<String>asList());
java8后
List<String> stringList = new ArrayList<>();
stringList.add("A");
stringList.addAll(Arrays.asList());
7.Optional
Java8中新增了Optional类来解决空指针异常,Optional是一个可以保持null的容器对象。通过isPresent()方法检测值是否存在,通过get()方法获取返回对象
// 创建一个 String 类型的容器
Optional<String> str = Optional.of("str");
// 值是否存在
boolean pre = str.isPresent();
// 值如果存在就调用 println 方法,这里传入的是 println 的方法引用
str.ifPresent(System.out::println);
// 获取值
String res = str.get();
// 传入空值
str = Optional.ofNullable(null);
// 如果值存在,返回值,否则返回传入的参数
res = str.orElse("aa");
str = Optional.of("str");
// 如果有值,对其调用映射函数得到返回值,对返回值进行 Optional 包装并返回
res = str.map(s -> "aa" + s).get();
// 返回一个带有映射函数的 Optional 对象
res = str.flatMap(s -> Optional.of(s + "bb")).flatMap(s -> Optional.of(s + "cc")).get();
8.Stream
Java8中增加了Stream类,提供了新的数据处理方式,可以将元素集合看成一种流,在管道中传输,经过一系列处理节点,最终输出结果
List<String> list = Arrays.asList("maa", "a", "abbb", "cccc");
list.stream().filter(s -> s.contains("a"))
.map(s -> s + "sb")
.sorted()
.forEach(System.out::println);
System.out.println("#####");
list.parallelStream().forEach(System.out::println);
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
int aaaaaa = numbers.stream().map(i -> i + 1).mapToInt(i -> i).summaryStatistics().getMax();
System.out.println(aaaaaa);
9.日期时间Api
LocalDate now = LocalDate.now();
System.out.println(now);
System.out.println(now.getYear());
System.out.println(now.getMonth());
System.out.println(now.getDayOfMonth());
LocalTime localTime = LocalTime.now();
System.out.println(localTime);
LocalDateTime localDateTime = now.atTime(localTime);
System.out.println(localDateTime);
10.Base64支持
Java8提供了对Base64编码的支持
byte[] base64 = Base64.decode(content, Base64.NO_WRAP);
Base64.encodeToString(data, Base64.NO_WRAP);
11.并行数组ParallelSort
Arrays.parallelSort(new int[] {1, 2, 3, 4, 5});
12.其他新特性
- 对并发的增强
- java.util.concurrent.atomic包中增加了
DoubleAccumulator
DoubleAdder
LongAccumulator
LongAdder
- 提供了新的Nashorn javascript引擎
- 提供了jjs,是一个给予Nashorn的命令行工具,可以用来执行JavaScript源码
- 提供了新的类依赖分析工具jdeps
- JVM新特性,内存永久区被metaspace替换(JEP 122)
\
Java9
1.Jigsaw模块系统
在 Java 9 以前,打包和依赖都是基于 JAR 包进行的。JRE 中包含了 rt.jar,将近 63M,也就是说要运行一个简单的 Hello World,也需要依赖这么大的 jar 包。在 Java 9 中提出的模块化系统,对这点进行了改善。
2.JShell REPL
Java 9 提供了交互式解释器。有了 JShell 以后,Java 终于可以像 Python,Node.js 一样在 Shell 中运行一些代码并直接得出结果了。
3. 私有接口方法,接口中使用私有方法
public interface TestInterface {
String test();
// 接口默认方法
default String defaultTest() {
pmethod();
return "default";
}
private String pmethod() {
System.out.println("private method in interface");
return "private";
}
}
4. 集合不可变实例工厂方法
在以前,我们想要创建一个不可变的集合,需要先创建一个可变集合,然后使用 unmodifiableSet 创建不可变集合。代码如下:
Set<String> set = new HashSet<>();
set.add("A");
set.add("B");
set.add("C");
set = Collections.unmodifiableSet(set);
System.out.println(set);
Java 9 中提供了新的 API 用来创建不可变集合。
List<String> list = List.of("A", "B", "C");
Set<String> set = Set.of("A", "B", "C");
Map<String, String> map = Map.of("KA", "VA", "KB", "VB");
5. 改进 try-with-resources
Java 9 中不需要在 try 中额外定义一个变量。Java 9 之前需要这样使用 try-with-resources:
InputStream inputStream = new StringBufferInputStream("a");
try (InputStream in = inputStream) {
in.read();
} catch (IOException e) {
e.printStackTrace();
}
在 Java 9 中可以直接使用 inputStream 变量,不需要再额外定义新的变量了。
InputStream inputStream = new StringBufferInputStream("a");
try (inputStream) {
inputStream.read();
} catch (IOException e) {
e.printStackTrace();
}
6. 多版本兼容 jar 包
Java 9 中支持在同一个 JAR 中维护不同版本的 Java 类和资源。
7. 增强了 Stream,Optional,Process API
8. 新增 HTTP2 Client
9. 增强 Javadoc,增加了 HTML 5 文档的输出,并且增加了搜索功能
10. 增强 @Deprecated
对 Deprecated 新增了 since 和 forRemoval 属性
11. 增强了钻石操作符 "<>",可以在 匿名内部类中使用了。
在 Java 9 之前,内部匿名类需要指定泛型类型,如下:
Handler<? extends Number> intHandler1 = new Handler<Number>(2) {
}
而在 Java 9 中,可以自动做类型推导,如下:
Handler<? extends Number> intHandler1 = new Handler<>(2) {
}
12. 多分辨率图像 API:定义多分辨率图像API,开发者可以很容易的操作和展示不同分辨率的图像了。
13. 改进的 CompletableFuture API
CompletableFuture 类的异步机制可以在 ProcessHandle.onExit 方法退出时执行操作。
Java 10
1. 新增局部类型推断 var
var a = "aa";
System.out.println(a);
注:var 关键字目前只能用于局部变量以及 for 循环变量声明中。
2. 删除工具 javah
从JDK中移除了 javah 工具,使用 javac -h 代替。
3. 统一的垃圾回收接口,改进了 GC 和其他内务管理
其他特性
ThreadLocal 握手交互
JDK 10 引入一种在线程上执行回调的新方法,很方便的停止单个线程而不是停止全部线程或者一个都不停。
基于Java的实验性JIT编译器
Java 10 开启了 Java JIT编译器 Graal,用作Linux / x64平台上的实验性JIT编译器。
提供默认的 CA 根证书
将 JDK 生态整合到单个仓库
此JEP的主要目标是执行一些内存管理,并将JDK生态的众多存储库组合到一个存储库中。
ava 11
1. Lambda 中使用 var
(var x, var y) -> x.process(y)
2. 字符串 API 增强
Java 11 新增了 一系列字符串处理方法,例如:
// 判断字符串是否为空白
" ".isBlank();
" Javastack ".stripTrailing(); // " Javastack"
" Javastack ".stripLeading(); // "Javastack "
3. 标准化 HttpClient API
3. java 直接编译并运行,省去先 javac 编译生成 class 再运行的步骤
3. 增加对 TLS 1.3 的支持
Java12
switch表达式
Java 12 以后,switch 不仅可以作为语句,也可以作为表达式。
private String switchTest(int i) {
return switch (i) {
case 1 -> "1";
default -> "0";
};
}