接口组成更新
1.1 接口组成更新概述
接口的组成
常量: public static final 可省略
抽象方法: public abstract 可省略
java8之后 加入了
默认方法:
静态方法:
java9之后 加入了
私有方法:
1.2 接口中的默认方法
接口中默认方法的定义格式
public default 返回值类型 方法名(参数列表){ } public可省略
范例:
default void show3(){ }
接口中默认方法的注意事项:
默认方法不是抽象方法,所以不强制被重写。但是也可以重写 重写时去掉default关键字
public可以省略 default不能省略
1.3 接口中的静态方法
接口中的静态方法的定义格式:
格式: public static 返回值类型 方法名(参数列表){ } public可以省略
范例: static void show() { }
接口中静态方法的注意事项:
静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
public可以省略 static不能省略
1.4 接口中私有方法
java9中新增了带方法体的私有方法,这其实在java8中就埋下了伏笔: java8允许在接口中定义带方法体的
默认方法和静态方法。这样就肯能会引发一个问题: 当两个默认方法或者静态方法中包含同一段相同的代码实现时,
程序必然考虑将这段实现代码抽取成一个共性方法,而这个共性方法是不需要让别人使用的,因此私有给隐藏起来,
这就是java9增加私有方法的必然性
接口中私有方法的定义格式:
格式1: private 返回值类型 方法名(参数列表){ }
范例: private void show() { }
格式2: private static 返回值类型 方法名(参数列表) { }
范例: private static void method() { }
接口中私有方法的注意事项:
默认方法可以调用私有的静态方法和非静态方法
静态方法只能调用私有的静态方法
2 方法引用
2.1 体验方法引用
在使用Lambda表达式的时候,我们实际上传递进去的代码就是一种解决方案: 拿参数做操作
考虑一种情况: 如果我们在Lambda中指定的操作方案,已经有的地方存在相同的方案,还有必要写重复的逻辑吗?
使用已经存在的方案,就是 方法引用
public class PrintableDemo{
public static void main(String[] args){
usePrintable(s -> System.out.println(s));
usePrintable(System.out::println);
}
private static void usePrintable(Printable p){
p.printString("爱生活,爱java");
}
}
2.2 方法引用符
方法引用符: :: 该符号位引用运算符,而它所在的表达式被称为方法引用
回顾在体验方法引用中的代码
Lambda表达式: usePrintable(s -> System.out.println(s));
分析: 拿到参数s之后通过Lambda表达式,传递给System.out.println 方法去处理
方法引用: usePrintable(System.out::println);
分析: 直接使用System.out中的println方法来取代Lambda,代码更加简洁
推导和省略
如果使用Lambda,那么根据 可推导就是可省略 的原则,无需指定参数类型,也无需指定重载形式,他们都将被自动推导
如果使用方法引用,也是同样可以根据上下文进行推导
方法引用是Lambda的孪生兄弟
2.3 Lambda表达式支持的方法引用
常见的引用方式:
引用类方法:
引用对象的实例方法
引用类的实例方法
引用构造器
2.4 引用类方法
引用类方法,其实就是引用类的静态方法
格式: 类名::静态方法
范例: Integer::parseInt
Integer类的方法: public static int parseInt(String s) 将此String转换为int类型数据
练习:
public class ConverterDemo {
public static void main(String[] args) {
//Lambda表达式
useConverter(s -> Integer.parseInt(s));
//引用类方法
useConverter(Integer::parseInt);
//Lambda表达式被类方法替代的时候,它的形式参数全部传递给静态方法作为参数
}
private static void useConverter(Converter c){
int num = c.converter("1998");
System.out.println(num);
}
}
public interface Converter {
int converter(String s);
}
2.5 引用对象的实例方法
引用对象的实例方法,其实就是引用类中的成员方法
格式: 对象::成员方法
范例: "HelloWorld"::toUpperCase
String类中的方法: public String toUpperCase 将此String所有的字符转换成大写
练习:
public class PrinterDemo {
public static void main(String[] args) {
//用Lambda表达式实现
usePrinter(s -> System.out.println(s.toUpperCase()) );
//引用对象的实例方法
PrintString ps = new PrintString();
usePrinter(ps::PrintUpper);
//Lambda表达式 被对象的实例方法替代的时候,它的形式参数全部传递给该方法作为参数
}
private static void usePrinter(Printer p){
p.printUpperCase("HelloWorld");
}
}
public class PrintString {
public void PrintUpper(String s) {
String result = s.toUpperCase();
System.out.println(result);
}
}
public interface Printer {
void printUpperCase(String s);
}
2.6 引用类的实例方法
引用类的实例方法,其实就是引用类的成员方法
格式: 类名::成员方法
范例: String::substring
String类中的方法: public String substring(int begin,int end)
从begin开始到end结束 截取字符串,返回一个字串,字串的长度位end-begin
练习:
public class MyStringDemo {
public static void main(String[] args) {
//Lambda表达式 调用String类中的substring来实现
useMyString((s,x,y) -> s.substring(x,y));
//引用类中的实例方法
useMyString(String::substring);
//Lambda表达式被类的实例方法替代的时候
//第一个参数作为调用者
//后面的参数全部传递给该方法作为参数
}
private static void useMyString(MyString my){
String s = my.mysubString("HelloWorld",2,5);
System.out.println(s);
}
}
public interface MyString {
String mysubString(String s,int x,int y);
}
2.7 引用构造器
引用构造器,其实就是引用构造方法
格式: 类名::new
范例: Student::new
练习:
public class StudentDemo {
public static void main(String[] args) {
//Lambda表达式
useStudentBuilder((name,age) -> new Student(name,age) );
//方法引用 引用构造器
useStudentBuilder(Student::new);
//Lambda表达式被构造器替代的时候,它的形式参数全部传递给构造器作为参数
}
private static void useStudentBuilder(StudentBuilder sb){
Student s = sb.build("fzz", 21);
System.out.println(s.getName()+","+s.getAge());
}
}
省略Student类 一个name,一个age,两个构造(无参、带参),成员各自的get,set
public interface StudentBuilder {
Student build(String name,int age);
}