Java_接口
类的继承
继承的特点
单继承
class A{}
class B extends A{} 🙆♂️
class C extends A,B{} 🙅♂️
多级继承
-
Java.long.Object
class A{}
class B extends A {} 🙆♂️
class C extends B {} 🙆♂️
多子类
抽象类 (abstract)
-
- 子类就是一个父类,所以是继承关系。
- 子类中共有的方法,但是所有子类都不一样
格式
含有抽象方法的类,必须是抽象类
public abstract class Animal{
//抽象方法定义
public abstract void eat();
//普通方法定义
public void move (){
}
}
- 不能直接使用new关键字
- 必须用子类继承抽象父类
- 子类必须实现父类中所有的抽象方法
- 创建子类对象进行使用
public class Cat extends Animal{
@Override
public void eat(){
sout("猫吃鱼!");
}
}
Cat cat = new Cat;
cat.eat();
注意
- 抽象类不能创建对象
- 抽象类中,可以有构造函数,是供子类创建对象时,初始化父类成员使用的。
- 如果构造函数是抽象的,则子类中用 supper()调用
- 先创建父类
- 后创建子类
- 抽象类不一定有抽象方法,没有抽象方法的抽象类,也不能直接创建对象
- 抽象类的子类,必须实现父类所有的抽象方法,否则依然是一个抽象类
发红包案例
分析
红包分为普通红包和运气红包
- 群主有钱
- 成员收红包,余额增加
- 类: 群主、普通成员、用户类
- 共性:姓名、余额
- 独有:
- 群主: 发红包
- 成员: 收红包
- 发红包
- 返回值类型: ArrayList
- 方法名称: send
- 参数列表:
- 总金额: int totalMoney
- 分数: int count
- 返回值类型: ArrayList
public ArrayList <Integer> send (int totalMoney,int count){
...
}
- 收红包
- 返回值类型:void
- 方法名:receive
- 参数列表:ArrayList
public void receive (ArrayList <Integer> list){
...
}
接口(interface)
接口就是一个 公共的规范接口
符合标准 -> 通用
关键字 interface -> .class 文件
- 包含的内容
- 常量
- 抽象方法
- 默认方法 JDK8
- 静态方法 JDK8
- 私有方法 JDK9
接口是引用类型
public interface 接口名称{
//接口内容
}
- 定义
- 注意:
- 接口不能直接使用,必须使用一个实现类来实现接口
public class 实现类名 implements 接口名称{ } - 实现类必须重写 接口中所有的抽象类
- 创建实现类使用接口
- 如果有抽象方法没有重写,那么该类就是一个抽象类
- 接口不能直接使用,必须使用一个实现类来实现接口
默认方法
-
从JDK8 允许默认方法
-
可以解决接口升级问题
- 如果接口添加抽象方法,就会导致所有子类全部实现
- 使用default 方法,在接口中实现方法体
-
使用
public default 返回值 方法名称(方法参数){
//可以有方法体
//public 可以省略
}
- 默认方法会被实现类所继承
- 也可被实现类重写
静态方法
static :共享方法
public static void test(){
//带有方法体
}
- 接口名称可以直接 . 调用
- 不能通过实现类调用静态方法
- 实现多个接口,静态方法可能发生冲突
- 不需要创建实现类对象
私有方法
一种安全机制
- 普通
- 多个默认方法之间重复代码问题
private void test(){
}
- 静态
- 多个静态方法之间重复代码问题
private static void test(){
}
常量
接口中够可以定义成员"变量" public static final (省略依旧)
不可修改
public static final int x = 1;
共有、接口名称 . 访问
- 常量必须赋值
- 完全大写
- 下划线连接单词
小结
- 在Java 9+ 版本中,接口的内容有:
- 成员变量其实是称量,格式:
- [public] [static] [final] 数据类型 常量名 = 数据值;
- 注意:
- 常量必须进行赋值,且不可改变
- 常量名完全大写,用下划线分割
- 接口中最重要的是抽象方法,格式:
- [public] [abstract] 返回值类型 方法名称 (参数列表);
- 注意:
- 实现类必须实现所有的抽象方法
- 从Java8 开始 ,允许定义默认方法,格式:
- [public] default 返回值类型 方法名称(参数列表)
- 注意:
- 默认方法也可以被覆盖重写
- 从Java8 开始, 允许定义静态方法,格式:
- [public] static 返回值类型 方法名称(参数列表)
- 注意:
- 通过接口名称直接调用,不能通过实现类进行调用
- 从Java9 开始, 允许定义私有方法,格式:
- 普通私有方法:private 返回值类型 方法名称(参数列表)
- 静态私有方法:private static 返回值类型 方法名称(参数列表)
- 注意:
- private 的方法只能在接口内调用,不能被实现类和别人使用。
注意
接口不能有静态代码块和构造方法 抽象类有构造方法
一个类的直接父类只有一个,但是可以实现多个接口
public class MyInterfaceImpl implements MyInterfaceA,MyInterfaceB{}
两个抽象方法重名,只需覆盖重写一次即可
重名的默认方法,实现类一定对重复的覆盖重写
一个类如果直接父类中的方法,和接口中的方法发生冲突,直接使用父类的方法
继承 优先于 接口实现
-
类与类是单继承的
-
类与接口是多实现的
-
接口与接口之间是多继承的
- 多个父接口当中的抽象方法冲突可以
- 多个父接口当中的默认方法冲突,那么子接口必须进行默认方法覆盖,【必须带着 default 关键字】
函数式接口
-
有且只有一个抽象方法的接口,称之为函数式接口
可以包含其他的方法(默认方法、静态方法、私有方法)
函数式编程 Lambda
/**
@FunctionalInterface
可以监测是否是一个函数式接口
*/
@FunctionalInterface
public interface MyFocationInterface{
}
public abstract void method();
使用
一般可以作为参数和返回值来使用
参数
//定义一个方法,参数使用函数式接口
public static void test (MyFunctionInterface myInter){
myInter.method();
}
main(){
//调用 show 方法,参数使用函数式接口的实现类对象
show (new MyFunctionInterfaceImpl());
//调用show方法 ,参数使用 匿名内部类
show(new MyFunctionInterface(){
@Override
public void method(){
sout("使用匿名内部类重写接口中的抽象方法!");
}
});
//调用show方法 ,参数使用 Lambda 表达式
show(()-> sout("Lambda实现接口的抽象方法!"));
}
匿名内部类生成 .class 文件
Lambda表达式不会生成 .class 文件
函数式编程
Lambda 的延迟执行
日志可以快速定位问题
package Demo4.Lambda;
/*
日志案例
性能浪费的问题:
调用 showLog 传递的第二个参数是一个拼接后的字符串
先拼接 后调用方法
showLog 如果等级不是 1 级,不会输出,字符串白 拼接了,浪费
使用Lambda 特性进行 优化
使用前提:必须存在函数式接口
延迟加载
*/
public class Demo01Logger {
//定义一个根据日志等级,显示日志信息
public static void showLog(int level,String message) {
if(level == 1){
System.out.println(message);
}
}
public static void main(String[] args) {
//定义三个日志信息
String msg1 = "Hello";
String msg2 = "World";
String msg3 = "Java";
//调用showLog 方法,传递参数
showLog(1,msg1+msg2+msg3);
//========================
//Lambda 优化
showLog2(1,()->msg1+msg2+msg3);
}
//传递等级 和 接口
public static void showLog2(int level ,MessageBuilder builder){
if(level == 1){
System.out.println(builder.builderMessage());
}
}
}
@FunctionalInterface
public interface MessageBuilder {
public abstract String builderMessage();
}
使用 Lambda 表达式 作为参数传递,仅仅把参数传递到showLog 中
只有满足条件,日志的等级为1
才会调用接口 MessageBuilder 中的方法 BuilderMessage
才会进行字符串的拼接
如果条件不满足 level != 1
MessageBuilder 中的方法不会调用
资源不会浪费
Runable 是一个 函数式接口
public class RunnableLambda {
public static void threadRun (Runnable run){
new Thread(run).start();
}
public static void main(String[] args) {
//匿名内部类
threadRun(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() +"--> 线程启动!");
}
});
//Lambda 表达式
threadRun(()-> System.out.println(Thread.currentThread().getName() +"--> 线程启动!"));
new Thread(()->System.out.println(Thread.currentThread().getName() +"--> 线程启动!")).start();
}
}
返回值
Comparator 也是一个 函数式借口
package Demo4.Lambda;
import java.util.Arrays;
import java.util.Comparator;
public class Demo03Comparator {
public static Comparator<String> getComparator(){
//方法的返回值是一个接口,那么我们可以返回一个匿名内部类
// return new Comparator<String>() {
// @Override
// public int compare(String o1, String o2) {
// return o2.length()-o1.length();
// }
// };
return (o1, o2) -> o2.length()-o1.length();
}
public static void main(String[] args) {
String [] arr = {
"liuxin",
"BBBB",
"ccdsaffda"
};
System.out.println(Arrays.toString(arr));
Arrays.sort(arr,getComparator());
Arrays.sort(arr,getComparator());
System.out.println(Arrays.toString(arr));
}
}
常用函数式接口
- java.util.funtion
Supplier 接口
Supplier
那么接口中的 get 方法 就会生成什么类型的数据
public class DemoSupplier {
public static String getString(Supplier<String> sup){
return sup.get();
}
public static void main(String[] args) {
System.out.println(getString(() -> "test"));
}
}
public static int getMax (Supplier<Integer> max){
return max.get();
}
public static void main(String[] args) {
int []arr = {
1,2,3,4,50,6,7,8,-5,9
};
System.out.println(getMax(()->{
//求数组元素最大值
int max = arr[0];
for (int i : arr) {
if(i > max){
max = i;
}
}
return max;
}));
}
Consumer 接口
是一个消费型接口,accept 消费指定泛型的数据
自定义消费方法,如 输出、计算。
public class DemoConsumer {
public static void print(String name ,Consumer<String > consumer){
consumer.accept(name);
}
public static void main(String[] args) {
print("张三",(o)-> System.out.println(o+",你好!"));
print("张三", new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(new StringBuffer(s).reverse().toString());
}
});
print("李四",(String s) ->{
String x =new StringBuffer(s).reverse().toString();
System.out.println(x);
});
}
}
- 方法 andThen
需要两个 Consumer 接口,可以将两个 Consumer 接口组合到一起进行消费
Consumer<String > con1;
Consumer <String > con2;
String s = "hello";
con1.accept(s);
con2.accept(s);
con1.andThen(con2).accept(s);
package Demo4.Interface;
import java.util.function.Consumer;
public class ConsumerTest1 {
public static void main(String[] args) {
String s = "Hello ";
test(s,(o)-> System.out.println( o.toLowerCase()+"-> 1"),
(o)-> System.out.println(o.toUpperCase()+"-> 2"));
test2(s,(o)-> System.out.println( o.toLowerCase()+"-> 21"),
(o)-> System.out.println(o.toUpperCase()+"-> 22"));
}
public static void test (String s,Consumer<String> con1,Consumer<String > con2){
con1.accept(s);
con2.accept(s);
}
public static void test2 (String s,Consumer<String> con1,Consumer<String > con2){
// con1 在前 先消费
con1.andThen(con2).accept(s);
System.out.println("-----------");
con2.andThen(con1).accept(s);
}
}
Predicate 接口
对某种数据类型进行判断
boolean test(T t)
package Demo4.Interface;
import java.util.function.Predicate;
/*
Predicate 对某种数据类型进行判断
boolean test(T t)
结果:
符合条件返回 true
不符合 返回 false
*/
public class DemoPredicate {
public static void main(String[] args) {
System.out.println(testPredicate("Hello", (o) -> o.equals("Hello")));
}
/**
* 定义一个方法
* 参数传递一个String 类型的字符串
* 传递一个 Predicate 接口,泛型 String
* 使用Predicate 中的test 方法对字符串进行判断,并把返回判断结果返回
* @param s
* @param pre
*/
public static boolean testPredicate(String s,Predicate<String> pre){
return pre.test(s);
}
}
- 方法
- and
- or
- negate
package Demo4.Interface;
import java.util.function.Predicate;
/*
需求:
非(
1. 字符串长度 大于 5
2. 判断字符串是否 含有 i
3. 或者是否以 St 开头 )
Predicate 接口中 有一个 and ,表示并且关系,也可以用于连接两个判断条件
*/
public class PredicateTest {
public static boolean LengthAndIn(String s, Predicate<String> pre1 , Predicate<String > pre2, Predicate<String > pre3){
// return !(pre1.test(s) && pre2.test(s) || pre3.test(s))
return pre1.and(pre2).or(pre3).negate().test(s);
}
public static void main(String[] args) {
System.out.println(LengthAndIn("String",
(o) -> o.length() > 5,
(o) -> o.contains("w"),
(o)->o.startsWith("St")
));
}
}
Function 接口
转换类型接口,根据一个类型数据转换成另一个数据类型
两个泛型参数
- apply 方法
- R apply(T t)
/**
* 字符串转换成 Integer 类型
* Function 接口,<String ,Integer>
*/
public class DemoFunction {
public static void change (String s, Function<String,Integer> fun){
System.out.println(fun.apply(s));
}
public static void main(String[] args) {
change("1",
o-> Integer.parseInt(o));
change("1",Integer::parseInt);
}
}
- andThen 默认方法
- 用来进行组合操作
package Demo4.Interface;
import java.util.function.Function;
/*
String "123" -> 123 -> +10 -> String
fun1.apply("123") +10
fun2.apply(133)
*/
public class andThenFunction {
public static void main(String[] args) {
System.out.println(change("123", o -> Integer.parseInt(o) + 10,
s -> String.valueOf(s)));
System.out.println(change("123", o -> Integer.parseInt(o) + 10,
String::valueOf));
}
public static String change (String s, Function<String ,Integer> fun1, Function<Integer,String> fun2){
//先调用 fun1.apply(String) 后调用 fun2.apply(Integer)
return fun1.andThen(fun2).apply(s);
}
}
综合案例
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
/*
函数模型的拼接
String str= "赵丽颖,20"
截取年龄 String -> Integer -> +100
*/
public class andThenFunctionTest {
public static void main(String[] args) {
String str= "赵丽颖,20";
change(()->str.split(",")[1],
Integer::parseInt,o-> System.out.println(o + 100)
);
}
public static void change (Supplier<String> sup, Function<String,Integer> fun1, Consumer<Integer> con){
con.accept(fun1.apply(sup.get()));
}
}
总结
| 接口名称 | 作用 | 抽象方法 | 实现 |
|---|---|---|---|
| Supplier | 生成型接口 | get | Supplier |
| Consumer | 消费型接口 | accept | Consumer |
| Predicate | 判断型接口 | test | Predicate |
| Function | 转换型接口 | apply | Function<T,Y> |
综合案例
Home + Esc 提示快捷键

浙公网安备 33010602011771号