别怕失败,大不了重头再来
—— 24.6.20
一、接口的私有方法
Java8版本接口增加了两类成员:
公共的默认方法
公共的静态方法
Java9版本接口又新增了一类成员:
私有的方法
为什么IDK1.9要允许接口定义私有方法呢?
因为我们说接口是规范,规范是需要公开让大家遵守的
私有方法::因为有了默认方法和静态方法这样具有具体实现的方法,那么就可能出现多个方法由共同的代码可以抽取,而这些共同的代码抽取出来的方法又只希望在接口内部使用,所以就增加了私有方法。
接口
public interface USB {
private void open(){
System.out.println("私有非静态方法");
}
private static void close(){
System.out.println("私有静态方法");
}
// 定义一个默认方法,去调用私有方法
public default void methodDef(){
open();
close();
}
}
实现类
public class UsbImpl implements USB{
public static void main(String[] args) {
new UsbImpl().methodDef();
}
}
测试方法
public class Demo329UsbImple {
public static void main(String[] args) {
new UsbImpl().methodDef();
}
}
二、钻石操作符与匿名内部类结合
自Java 9之后我们将能够与匿名实现类共同使用钻石操作符(泛型),即匿名实现类也支持类型自动推断
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Demo330Combine {
public static void main(String[] args) {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("张三",10));
list.add(new Person("李四",8));
list.add(new Person("王五",20));
Collections.sort(list,new Comparator<>() {
// 从jdk9开始可以省略参数中的泛型
@Override
public int compare(Person o1, Person o2) {
return o1.getAge()-o2.getAge();
}
});
System.out.println(list);
}
}
Javà 8的语言等级编译会报错:"'<>' cannot be used with anonymous classes。”java 9及以上版本才能编译和运行正常。
三、try...catch的升级
之前我们讲过JDK 1.7引入了trywith-resources的新特性,可以实现资源的自动关闭,此时要求:
该资源必须实现java.io.Closeable接口
在try子句中声明并初始化资源对象
该资源对象必须是final的
try(IO流对象1声明和初始化;IO流对象2声明和初始化){
可能出现异常的代码
}catch(异常类型 对象名){
异常处理方案
}
jdk1.9后,对trywith- resources的语法进行升级
该资源必须实现java.io.Closeable接口
在try子句中声明并初始化资源对象,也可以直接使用已初始化的资源对象
该资源对象必须是final的
语法
IO流对象1声明和初始化;
IO流对象2声明和初始化;
try(IO流对象1;IO流对象2){
可能出现异常的代码
}catch(异常类型 对象名){
异常处理方案
}
import java.io.File;
import java.io.FileWriter;
import java.io.FilterWriter;
public class Demo331TryCatchUp {
public static void main(String[] args) throws Exception {
//method01();
method02();
}
/**
* jdk8之前
*/
private static void method01() {
try(FileWriter fw = new FileWriter("AllWillBest_Java\\io.txt")){
fw.write("一切都会好的");
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* JDk9开始,为了减轻try的压力,可以将对象放到外面去new,然后将对象名放在try中
* 而且依然能够自动刷新和关流
*/
private static void method02() throws Exception {
FileWriter fw = new FileWriter("AllWillBest_Java/io.txt");
try(fw){
fw.write("你好");
}catch (Exception ex) {
ex.printStackTrace();
}
}
}
四、局部变量的类型自动推断
jdk10之前,我们定义局部变量都必须要明确教据的数据类型,但是到了!DK10,出现了一个最为重要的特性,就是局部变量类型推断,顾名思义,就是定义局部变量时,不用先确定具体的数据类型了,可以直接根据具体数据推断出所属的数据类型。
var 变量名 = 值;
public class Demo332Var {
public static void main(String[] args) {
var i = 10;
System.out.println(i);
var j = "一切都会好的";
System.out.println(j);
var arr = new int[]{1, 2, 3, 4, 5};
for (int i1 : arr) {
System.out.print(i1+" ");
}
}
}
五、switch表达式
1.Java12的switch表达式
Java 12对switch语句进行了扩展,将其作为增强版的switch语句或称为switch表达式,可以写出更加简化的代码。
允许将多个case语句合并到一行,可以简洁、清晰也更加优雅地表达逻辑分支。
可以使用->代替:
写法默认省略break语句,避免了因少写break语句而出错的问题。
写法在标签右侧的代码段可以是表达式、代码块或 throw语句。
写法在标签右侧的代码块中定义的局部变量,其作用域就限制在代码块中,而不是延到整个switch结构。
同一个switch结构中不能混用“一>"和”:",否则会有编译错误。使用字符":",这时fall-through规则依然有效,即不能省略原有的break语句。":"的写法表示继续使用传统switch语法。
案例需求:判断季节
请使用switch-case结构实现根据月份输出对应季节名称。例如,3~5月是春季,6~8月是夏季,9~11月是秋季,12~2月是冬季。
public class Demo333Switch {
public static void main(String[] args) {
method01();
method02();
}
private static void method02(){
int month = 9;
switch (month) {
case 12,1,2 ->
System.out.println("冬季");
case 3,4,5 ->
System.out.println("春季");
case 6,7,8 ->
System.out.println("夏季");
case 9,10,11 ->
System.out.println("秋季");
}
}
private static void method01() {
int month = 5;
/**
* 用: 方式,改正后不写break依然会case穿透,如果想不加break也不穿透,将case后的:改为->
*/
switch (month) {
case 12,1,2:
System.out.println("冬季");
break;
case 3,4,5:
System.out.println("春季");
break;
case 6,7,8:
System.out.println("秋季");
break;
case 9,10,11:
System.out.println("冬季");
break;
default:
System.out.println("没有这个季节,您输入错误");
}
}
}
2.Java13的switch表达式
Java 13提出了第二个switch表达式预览,引入了yield语句,用于返回值。这意味着,switch表达式(返回值)应该使用yield语句,switch语句(不返回值)应该使用break语句。
案例需求:判断季节
public class Demo333Switch {
public static void main(String[] args) {
method01();
method02();
method03();
method04();
}
/**
* jdk13之后,
*/
private static void method04() {
int month = 7;
var season = switch (month) {
case 12,1,2 -> {
yield "冬季";
}
case 3,4,5 -> {
yield "春季";
}
case 6,7,8 -> {
yield "夏季";
}
case 9,10,11 -> {
yield "秋季";
}
default -> {
yield "错误输入";
}
};
System.out.println("season = " + season);
}
/**
* jdk13之前想要拿到switch结果,需要定义一个变量,然后为其赋值
*/
private static void method03() {
int month = 11;
String season = "";
switch (month) {
case 12,1,2:
season = "冬季";
break;
case 3,4,5:
season = "春季";
break;
case 6,7,8:
season = "夏季";
break;
case 9,10,11:
season = "秋季";
break;
default:
season="错误输入";
break;
}
System.out.println(season);
}
private static void method02(){
int month = 9;
switch (month) {
case 12,1,2 ->
System.out.println("冬季");
case 3,4,5 ->
System.out.println("春季");
case 6,7,8 ->
System.out.println("夏季");
case 9,10,11 ->
System.out.println("秋季");
}
}
private static void method01() {
int month = 5;
/**
* 用: 方式,改正后不写break依然会case穿透,如果想不加break也不穿透,将case后的:改为->
*/
switch (month) {
case 12,1,2:
System.out.println("冬季");
break;
case 3,4,5:
System.out.println("春季");
break;
case 6,7,8:
System.out.println("夏季");
break;
case 9,10,11:
System.out.println("秋季");
break;
default:
System.out.println("没有这个季节,您输入错误");
break;
}
}
}
六、文本块
预览的新特性文本块在Java 15中被最终确定下来,Java 15之后我们就可以放心使用该文本块了。
JDK 12引入了Raw String Literals特性,但在其发布之前就放弃了这个特性。这个JEP与引入多行字符串文字(文本块)在意义上是类似的。Java13中引入了文本块(预览特性),这个新特性跟Kotlin中的文本块是类似的。
现实问题
在java中,通常需要使用String类型表达HTML,XML,SQL或ISON等格式的字符串,在进行字符串赋值时需要进行转义和连接操作,然后才能编译该代码,这种表达方式难以阅读并且难以维护。
文本块就是指多行字符串,例如一段格式化后的XML、JSON等。而有了文本块以后,用户不需要转义,java能自动搞定。因此,文本块将提高Java程序的可读性和可写性。
目标
简化跨越多行的字符串,避免对换行等特殊字符进行转义,简化编写Java程序。.
增强Java程序中字符串的可读性。
举例
package S111NewJdk;
public class Demo334TextPiece {
public static void main(String[] args) {
String s = "<html>\n" +
" <body>\n" +
" <p>一切都会好的,我一直相信</p>\n" +
" </body>\n" +
"</html>";
System.out.println(s);
System.out.println("——————————————————————————————————————");
String s1 = """
<html>
<body>
<p>一切都会好的,我一直相信</p>
</body>
</html>
""";
System.out.println(s1);
}
}
七、instanceof模式匹配
instanceof的模式匹配在JDK14、15中预览,在JDK16中转正。有了它就不需要编写先通过instanceof判断再强制转换的代码。
多态重写进行判断
public class Demo335Instanceof {
public static void main(String[] args) {
Dog dog = new Dog();
method(dog);
Cat cat = new Cat();
method(cat);
}
public static void method(Animal animal){
if(animal instanceof Dog){
Dog dog = (Dog)animal;
dog.eat();
dog.lookDoor();
} else if (animal instanceof Cat) {
Cat cat = (Cat)animal;
cat.eat();
cat.catchMouse();
}
}
}
instanceof
public class Demo335Instanceof {
public static void main(String[] args) {
Dog dog = new Dog();
method(dog);
Cat cat = new Cat();
method(cat);
method01(dog);
method01(cat);
}
public static void method01(Animal animal) {
if (animal instanceof Dog dog) {
dog.eat();
dog.lookDoor();
}else if (animal instanceof Cat cat) {
cat.eat();
cat.catchMouse();
}
}
public static void method(Animal animal){
if(animal instanceof Dog){
Dog dog = (Dog)animal;
dog.eat();
dog.lookDoor();
} else if (animal instanceof Cat) {
Cat cat = (Cat)animal;
cat.eat();
cat.catchMouse();
}
}
}
八、Record类
Record类在JDK14、15预览特性,在JDK16中转正。
record是一种全新的类型,它本质上是一个 final类,同时所有的属性都是 final修饰,它会自动编译出get、hashCode 、比较所有属性值的equals、tostring,等方法,减少了代码编写量。使用 Record 可以更方便的创建一个常量类。
注意:
Record只会有一个全参构造
重写的equals方法比较所有属性值
可以在Record声明的类中定义静态字段、静态方法或实例方法(非静态成员方法),。不能
Record声明的类中定义实例字段(非静态成员变量);
类不能声明为abstract;
不能显式的声明父类,默认父类是java.lang.Record类
因为Record类是一个 final类,所以也没有子类等
示例
import S106Lombok.Person;
import org.w3c.dom.ls.LSOutput;
public class Demo336Record {
public static void main(String[] args) {
PersonR personR = new PersonR("张三");
PersonR personR1 = new PersonR("张三");
System.out.println(personR.equals(personR1));
// 提供了比较对象的equals方法
}
}
九、密封类
其实很多语言中都有密封类的概念,在]ava语言中,也早就有密封类的思想,就是final修饰的类,该类不允许被继承。而从IDK15开始,针对 密封类进行了升级。
java 15通过密封的类和接口来增强|ava编程语言,这是新引入的预览功能并在|ava16中进行了二次预览,并在ava17最终确定下来。这个预览功能用于限制超类的使用,密封的类和接口限制其他可能继承或实现它们的其他类或接口。
【修饰符】sealed class 密封类【extends 父类】【implements 父接口】permits 子类{
}
【修饰符】 sealed interface 接口【extends 父接口们】permits 实现类{
}
密封类用 sealed 修饰符来描述,
使用 permits 关键字来指定可以继承或实现该类的类型有哪些
一个类继承密封类或实现率封接口,该类必须是sealed、non-sealed、final修饰的
sealed修饰的类或接口必须有了类或实现类
public sealed class AnimalS permits DogS,CatS {
}
public non-sealed class DogS extends AnimalS{
}
public non-sealed class CatS extends AnimalS{
}