1.性能提升
每次JDK版本升级JVM速度都会有一定的提升,jdk9-11 JVM的性能提升主要体现在垃圾回收;
垃圾收集器:
- java8默认的配置为UseParallelGC。虚拟机运行在Server模式下的默认值。使用Parallel Scavenge + Serial Old的收集器组合进行内存回收。有很多项目会使用UseConeMarkSweepGC。使用ParNew + CMS + Serial Old的收集器组合进行内存回收。Serial Old收集器将作为CMS收集器出现Concurrent Mode Failure失败后的后备收集器使用。java14中移除了CMS;
//**查看GC配置 java -XX:+PrintCommandLineFlags -version
- java9默认的配置为UseG1GC。使用G1收集器进行内存回收;
- java10改进G1收集器,允许并行Full GC,改善G1的延迟。G1会尽量避免Full GC,但是仍然会出现Full GC。java10使用并行的标记-清除-压缩算法,可用-XX:ParallelGCThreads配置线程数。
- java11引进了配置UseEpsilonGC。使用Epsilon垃圾收集器进行内存回收。它是一个无操作的垃圾收集器,处理内存分配但不实现任何实际内存回收机制,一旦可用堆内存用完,JVM就会退出;
- java11引进了配置UseZGC。使用ZGC垃圾收集器进行内存回收。它是一个可伸缩低延迟垃圾收集器,但还是实验性的,不建议用到生产环境;
2.语法特性
java9
集合工厂方法
集合工厂方法(创建不可变的集合),简化创建集合的代码,特别是Map;
public class MyCollections {
//**集合工厂方法,简化创建集合的代码
public static void test() {
List list = List.of(1, 2, 3);
System.out.println(list);
Set set = Set.of(1, 2, 3);
System.out.println(set);
Map map = Map.of("key1", "value1", "key2", "value2");
System.out.println(map);
}
}
CompletableFuture新增方法
public class MyCompletableFuture {
public static void main(String[] args) throws Exception {
//**工厂方法,返回异常完成的CompletableFuture
CompletableFuture<String> future1 = CompletableFuture.failedFuture(new RuntimeException("错误"));
//future1.get();
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(5);
} catch (Exception ignored) {}
return "pings1";
});
//**在给定的时间内,如果future2能完成就返回future2的返回值,否则返回默认值
//CompletableFuture<String> future3 = future2.completeOnTimeout("pings2", 4, TimeUnit.SECONDS);
//System.out.println(future3.get());
//**在给定的时间内,如果future2能完成就返回future2的返回值,否则以TimeoutException完成
CompletableFuture<String> future4 = future2.orTimeout(4, TimeUnit.SECONDS);
System.out.println(future4.get());
}
}
泛型改进
public class MyGenerics {
interface MyClass<T> {
T get();
T get1();
}
public static void main(String[] args) {
//**匿名类泛型推断
MyClass<String> myClass = new MyClass<>() {
@Override
public String get() {
return "pings";
}
@Override
public String get1() {
return "pings1";
}
};
System.out.println(myClass.get());
}
}
接口私有方法
现在接口和抽象方法的区别:
- 抽象方法可以定义各种作用域的属性,接口只能定义公有的静态属性
- 抽象方法可以定义各种作用域的方法,接口只能定义私有方法和公用方法的默认实现
public interface MyInterface {
private void b() {
//**可使用this关键字
System.out.println("b: " + this.getClass().getSimpleName());
}
class MyInterfaceImpl implements MyInterface { }
static void main(String[] args) {
MyInterface myInterface = new MyInterfaceImpl();
myInterface.b();
}
}
Optional新增方法
public class MyOptional {
public static void main(String[] args) {
//**Optional.stream
List<Optional<String>> list = List.of(Optional.of("A"), Optional.empty(), Optional.of("B"));
list.stream().flatMap(Optional::stream).forEach(System.out::println);
//**Optional.ifPresentOrElse
List<Integer> list1 = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Optional<Integer> optional = list1.stream().filter(i -> i > 5).findAny();
optional.ifPresentOrElse(System.out::println, () -> { throw new IllegalArgumentException(); });
//**Optional.or,与orElseGet区别:orElseGet参数返回Optional包装的类型,or仍然返回Optional
optional = list1.stream().filter(i -> i > 10).findAny();
Optional optional1 = optional.or(() -> Optional.of(100));
int rst = optional.orElseGet(() -> 100);
System.out.println(optional1.get());
System.out.println(rst);
}
}
stream新增方法
public class MyStream {
public static void main(String[] args) {
List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
//**takeWhile,返回符合表达式的元素,直到第一次不满足表达式
List<Integer> list1 = list.stream().takeWhile(i -> i < 5).collect(toList());
System.out.println(list1);
//**dropWhile,删除表达式的元素,直到第一次不满足表达式
List<Integer> list2 = list.stream().dropWhile(i -> i < 5 || i > 9).collect(toList());
System.out.println(list2);
//**for(int i = 1; i < 10; i +=2)
IntStream.iterate(1, x -> x < 10, x -> x + 2).forEach(System.out::println);
Stream.iterate("ping", s -> s.length() < 10, s -> s = s + "1").forEach(System.out::println);
//**元素不支持是list,不知道实际有什么用
Stream.ofNullable(null).forEach(System.out::println);
//**通过这种方法可以避免list3为空时出现空指针,还是感觉没啥用
List list3 = null;
List<Integer> list4 = List.of(1, 2);
Stream.ofNullable(list3).flatMap(List::stream).forEach(System.out::println);
Stream.ofNullable(list4).flatMap(List::stream).forEach(System.out::println);
}
}
try-with-resources改进
public class MyTryWithResources {
public static void main(String[] args) throws IOException {
Reader reader = new StringReader("pings");
BufferedReader br = new BufferedReader(reader);
//**相对于jdk7的改进,可引用外部变量br,br必须是final
try (reader; br) {
System.out.println(br.readLine());
}
}
}
java10
集合copyOf静态方法
public class MyCollections {
//**集合工厂方法,简化创建集合的代码
public static void test() {
var list = List.of(1, 2, 3);
var newList = List.copyOf(list);
System.out.println(newList);
var map = Map.of("key1", "value1", "key2", "value2");
System.out.println(Map.copyOf(map));
}
public static void main(String[] args) {
test();
}
}
局部变量类型推断
引入var作为局部变量类型推断标识符,仅适用于局部变量,不能使用于方法形式参数,构造函数形式参数,方法返回类型,catch形式参数或任何其他类型的变量声明;
public class MyVar {
public static void main(String[] args) {
var ss = 123;
//**可以推断出泛型的类型
var list = List.of(1, 2, 3, 4);
var newList = list.stream().map(Integer::getClass).collect(toList());
System.out.println(newList);
}
}
java11
字符串新增方法
public class MyString {
public static void main(String[] args) {
String str = "pings";
boolean isBlank = str.isBlank(); //**判断字符串是空白
System.out.println(isBlank);
//str = null;
//System.out.println(str.isBlank()); //**不能判断非null,我还以为可以替换StringUtils.isBlank()方法了
boolean isEmpty = str.isEmpty(); //判断字符串是否为空
System.out.println(isEmpty);
String result1 = str.strip(); //**首位空白
String result2 = str.stripTrailing(); //**去除尾部空白
String result3 = str.stripLeading(); //**去除首部空白
System.out.println("12".repeat(5)); //**复制几遍字符串
str.lines().forEach(System.out::println); //**按行读取
}
}
局部变量类型推断增强
var可引用到lambda表达式的参数上;
public class MyVar {
public static void main(String[] args) {
//**var可引用到lambda表达式的参数上,本来lambda表达式的参数不用写类型也可以,那这样写有什么作用了
Consumer<String> consumer1 = (var t) -> System.out.println(t.toUpperCase());
consumer1.accept("pings");
//**lambda表达式的参数如果要加注解,就必须有类型
//**作用就是要在lambda表达式的参数加注解时定义参数类型
Consumer<String> consumer2 = (@Deprecated var t) -> System.out.println(t.toUpperCase());
consumer2.accept("pings");
}
}
HttpClient
public class MyHttpClient {
public static void test() throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(URI.create("http://www.baidu.com")).build();
HttpResponse.BodyHandler<String> handler = HttpResponse.BodyHandlers.ofString();
//**同步调用
//HttpResponse<String> response = client.send(request, handler);
//String body = response.body();
//**异步调用
CompletableFuture<HttpResponse<String>> response = client.sendAsync(request, handler);
HttpResponse<String> result = response.get();
String body = result.body();
System.out.println(body);
}
}