20.接口组成更新
接口组成更新
接口组成更新概述
接口的组成
-
常量: public static final
-
抽象方法: public abstract
-
默认方法(java8中新增)
-
静态方法(java8中新增)
-
私有方法(java9中新增)
接口的默认方法
定义格式: default void 方法名() {};
MyInterface
package interfaceJava.interfaceUpdate.defaultMethod;
public interface MyInterface {
void show1();
void show2();
// void show3();
/*
public default void show3() {
System.out.println("show3");
}
*/
default void show3() {
System.out.println("show3");
}
}
MyInterfaceImplOne
package interfaceJava.interfaceUpdate.defaultMethod;
public class MyInterfaceImplOne implements MyInterface {
@Override
public void show1() {
System.out.println("One show1");
}
@Override
public void show2() {
System.out.println("One show2");
}
@Override
public void show3() {
System.out.println("One show3");
}
}
MyInterfaceImplTwo
package interfaceJava.interfaceUpdate.defaultMethod;
public class MyInterfaceImplTwo implements MyInterface {
@Override
public void show1() {
System.out.println("Two show1");
}
@Override
public void show2() {
System.out.println("Two show2");
}
}
MyInterfaceDemo
package interfaceJava.interfaceUpdate.defaultMethod;
public class MyInterfaceDemo {
public static void main(String[] args) {
//使用多台方式创建对象并使用
MyInterface my = new MyInterfaceImplOne();
my.show1();
my.show2();
my.show3();
}
}
接口中静态方法
接口中静态方法定义格式
-
格式: public static 返回值类型方法名(参数列表) {};
-
范例: public static void show() {};
Inter
package interfaceJava.interfaceUpdate.staticMethod;
public interface Inter {
void show();
default void method(){
System.out.println("Inter 中默认方法");
}
// public可以省略掉
static void test() {
System.out.println("Inter 中静态方法执行了");
}
}
InterImpl
package interfaceJava.interfaceUpdate.staticMethod;
public class InterImpl implements Inter, Flyable {
@Override
public void show() {
System.out.println("show 方法执行");
}
}
Flyable
package interfaceJava.interfaceUpdate.staticMethod;
public interface Flyable {
public static void test() {
System.out.println("Flyable 静态方法test执行");
}
}
InterDemo
package interfaceJava.interfaceUpdate.staticMethod;
public class InterDemo {
public static void main(String[] args) {
Inter i = new InterImpl();
i.show();
i.method();
// i.test(); // 静态方法只能被接口调用
Inter.test();
// InterImpl.test(); // 实现类也不能
Flyable.test();
// 如果能够通过实现类调用,当实现两个接口中有重复的方法名时, 不知道该调用哪一个, 所以不能用实现类调用
}
}
接口中私有方法
java9中新增了带方法体的私有方法. 当两个默认方法或者静态方法包含一段相同的代码实现时, 程序必然考虑将这段实现代码抽取成一个共性方法, 而这个共性方法是不需要让别人使用的, 因此用私有隐藏起来.
格式一:
- private 返回值类型 方法名(参数列表) {}
- private void show() {}
格式二:
- private static 返回值类型 方法名(参数列表) {}
- private static void method() {}
Inter
package interfaceJava.interfaceUpdate.privateMethod;
public interface Inter {
default void show1() {
System.out.println("show1 开始");
// System.out.println("1");
// System.out.println("2");
// System.out.println("3");
// show();
method();
System.out.println("show1 结束");
}
default void show2() {
System.out.println("show2 开始");
// System.out.println("1");
// System.out.println("2");
// System.out.println("3");
// show();
method();
System.out.println("show2 结束");
}
static void method1(){
System.out.println("method1 开始");
// System.out.println("1");
// System.out.println("2");
// System.out.println("3");
method();
System.out.println("method1 结束");
}
static void method2() {
System.out.println("method2 开始");
// System.out.println("1");
// System.out.println("2");
// System.out.println("3");
method();
System.out.println("method2 结束");
}
private void show() {
System.out.println("1");
System.out.println("2");
System.out.println("3");
}
private static void method() {
System.out.println("1");
System.out.println("2");
System.out.println("3");
}
}
InterImpl
package interfaceJava.interfaceUpdate.privateMethod;
public class InterImpl implements Inter {
}
InterDemo
package interfaceJava.interfaceUpdate.privateMethod;
public class InterDemo {
public static void main(String[] args) {
// 按照多态的方式创建类
Inter i = new InterImpl();
i.show1();
System.out.println("--------");
i.show2();
System.out.println("--------");
Inter.method1();
System.out.println("--------");
Inter.method2();
}
}
注意:
- 默认方法可以调用私有的静态方法和非静态方法
- 静态方法只能调用私有的静态方法
方法引用
如果lambda中指定的操作方案, 已经有地方存在相同方案, 就没有必要重写逻辑, 这就是方法引用, 用来使用已经存在的方案
方法引用符
"::"该符号为引用运算符, 而它所在的表达式被称为方法引用
回顾一下我们在体验方法引用中的代码
- lambda表达式: usePrintable(s -> System.out.println(s));
- 拿到参数s后, 通过lambda表达式, 传递给System.out.println方法
- 方法引用: usePrintable(System.out::println);
推导和省略
-
如果使用lambda, 根据"可推导就是可省略"原则, 无需指定参数类型, 也无需指定重载形式, 他们都将被自动推导
-
如果使用方法引用, 也是同样可以根据上下文进行推导
-
方法引用是lambda的孪生兄弟
Printable
package methodQuote;
public interface Printable {
void printString(String s);
}
PrintableDemo
package methodQuote;
public class PrintableDemo {
public static void main(String[] args) {
// 调用usePrintable
/*
usePrintable((String s) -> {
System.out.println(s);
});
*/
usePrintable(s -> System.out.println(s));
// System.out.println("热爱生活");
// 方法引用符: ::
usePrintable(System.out::println); // 没有参数, 直接引用前面的参数
// 可推导的就可以省略
}
private static void usePrintable(Printable p) {
p.printString("热爱生活");
}
}
lambda表达式支持的方法引用
常见的引用方式
- 引用类方法
- 引用对象的实例方法
- 引用类的实例方法
- 引用构造器
引用类方法
就是引用类的静态方法
- 格式: 类名::静态方法
- 范例: Integer::parseInt
Convert
package methodQuote.staticQuote;
public interface Converter {
int convert(String s);
}
ConverterDemo
package methodQuote.staticQuote;
public class ConverterDemo {
public static void main(String[] args) {
// 调用convert方法
useConverter(s -> Integer.parseInt(s));
// 引用类方法
useConverter(Integer::parseInt);
// 注意: lambda表达式被类方法代替的时候, 它的形式参数全部传递给静态方法做为参数
}
private static void useConverter(Converter c) {
int number = c.convert("666");
System.out.println(number);
}
}
引用对象的实例方法
引用类中的成员方法
-
格式: 对象::成员方法
-
范例: "HelloWrold"::toUpperCase
Printer
package methodQuote.methodQuote;
public interface Printer {
void printUpperCase(String s);
}
PrintString
package methodQuote.methodQuote;
public class PrintString {
public void printUpper(String s) {
String result = s.toUpperCase();
System.out.println(result);
}
}
PrinterDemo
package methodQuote.methodQuote;
public class PrinterDemo {
public static void main(String[] args) {
// 调用usePrinter方法
usePrinter((String s) -> {
System.out.println(s.toUpperCase());
});
// 引用对象的实例方法
PrintString ps = new PrintString();
usePrinter(ps::printUpper);
// lambda表达式被对象的实例方法替代的时候, 它的形式参数全部传递给该方法作为参数
}
private static void usePrinter(Printer p) {
p.printUpperCase("HelloWorld");
}
}
引用类的实例方法
引用类中的成员方法
- 格式: 类名::成员方法
- 范例: String::substring
MyString
package methodQuote.classQuote;
public interface MyString {
String mySubString(String s, int x, int y);
}
MyStringDemo
package methodQuote.classQuote;
public class MyStringDemo {
public static void main(String[] args) {
// 调用useMyString方法
/*
useMyString((String s, int x, int y) -> {
return s.substring(x,y);
});
*/
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);
}
}
引用构造器
引用构造方法
- 格式: 类名::new
- 范例: Student::new
Student
package methodQuote.constructQuote;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
StudentBuilder
package methodQuote.constructQuote;
public interface StudentBuilder {
Student build(String name, int age);
}
StudentDemo
package methodQuote.constructQuote;
public class StudentDemo {
public static void main(String[] args) {
// 调用useStudentBuilder
/*
useStudentBuilder((String name, int age) -> {
return new Student(name, age);
});
*/
useStudentBuilder((name, age) -> new Student(name, age));
// 方法引用
useStudentBuilder(Student::new);
// lambda表达式被构造器替代的时候, 它的形式参数全部传递给构造器作为参数
}
private static void useStudentBuilder(StudentBuilder sb) {
Student s = sb.build("林青霞", 30);
System.out.println(s.getName() + "," + s.getAge());
}
}