一、接口
简介:接口可用来实现多重继承,一个接口可以继承多个接口,一个类也可以继承多个接口,但是只能继承一个类。–>接口:多继承;类:单继承
1、接口声明:用 interface 关键字
格式:
[public] interface 接口名 [extends 超接口1,超接口2 ]{ //接口名后缀通常是able
// 1. 常量的定义 //在接口中定义的任何变量都是常量
[public final static] int STATUS = 100; //建议使用枚举类型来定义常量
// 2. 抽象方法的定义
[public abstract] 返回类型 方法名([参数]); //抽象方法只有声明,没有实现
// 3. 静态方法的定义
public static 返回值 静态方法名(){...}
//静态方法不能被继承
//类只能通过 接口名.方法名() 访问接口中的静态方法
// 4. 默认方法的定义: default
public default 返回值 方法名(){...}
}
如果没有public,该接口只能被同一个包中的类使用
2、接口实现:在类声明中用implements 接口,可以实现多个接口
[public] class 类名 implements 接口1,接口2,... {
// 类体定义
//访问抽象方法
注意点:
1、类(不是抽象类)中要实现接口所有的抽象方法,并且全都要用public修饰
2、方法格式要和接口中声明的一致,可在上一行加上@Override 防止方法名写错
//访问静态方法
接口名.静态方法名()
//解决从多个接口继承了相同的默认方法而产生的冲突的问题:
1、在类体中定义一个新的默认方法的实现
public 返回值 默认方法名(){ 自定义内容...}
2、委托其中一个父接口中的默认方法
public 返回值 默认方法名(){
return Identified.super.默认方法名();
}
//如果从父类和接口继承了相同的方法,那么编译器自动遵循“类比接口优先”的原则/
}
二、比较(排序)的两种方法
question:通过什么方法比较用户定义的类的对象的大小?
第一种是自然排序(从小到大):实现java.lang.Comparable 接口,使自定义的类天生具有比较大小的能力。
第二种是比较器排序:实现java.util.Comparator 接口 ,需要自定义比较器类。
自然排序和比较器排序特点比较:
自然排序,实现类继承Comparable接口,并重写compareTo()方法。Arrays.sort()中只需要传递1个比较对象的参数。
比较器排序,是在实现类的外部自定义一个比较器类,比较器类继承Comparator 接口,并重写compare()方法。Arrays.sort()中需传入两个参数:比较对象和比较器对象(new)。
1、Comparable接口
简介:Comparable<T>是泛型接口,泛型类型T会被替换成具体的类型。
可以实现:比较自定义的类中对象的(…)的大小,实现对象的自然排序
方法:定义在类的内部,自定义的类继承Comparable接口 + 实现compareTo()方法(具体比较什么在该方法中定义)
形式:
public class 类 implements Comparable<类型>{
...
public int compareTo(类型 参数){
if(...) //当前对象的...>参数对象,返回1
return 1;
else if(...)
return -1;
else
return 0; //相等返回0
}
public static void main(String[] args){
类型[] 数组名= ... { ... };
Arrays.sort(数组名);
}
}
//eg:
import java.util.Arrays;
public class Circle implements Comparable<Circle>{
//参数声明
//构造方法
...
public double getArea(){
return radius*radius*Math.PI;
}
//下面实现Comparable<T>接口的compareTo()
@Override
public int compareTo(Circle circle){
if(getArea() > circle.getArea()) //当前对象的面积>参数对象,返回1
return 1;
else if(getArea() < circle.getArea())
return -1;
else
return 0; //相等返回0
}
public static void main(String[] args){
Circle[] circles = new Circle[]{
new Circle(2.5),new Circle(2.6),new Circle(2.7),
}; //Circle类型的数组,注意此处用了匿名内部类
circles[0].compareTo(circles[1]); //1、两个对象进行(面积上的)比较大小
Arrays.sort(circles); //2、对数组进行从小到大排序,系统自动调用compareTo()方法
for(Circle c : circles)
System.out.printf("%6.2f%n",c.getArea()); //输出(对面积)排序的结果
}
2、Comparator 接口
基本形式:
import java.util.Comparator;
public class 类1 implements Comparator<类型>{ //先定义比较器类,
@Override
public int compare(类型1 参数1, 类型2 参数2){ //在比较器中定义比较规则
//简单的比较可以直接做减法然后return
}
}
public class 类{
pubic static void main(String[] args){
类型[] 数组名= ... { ... };
...
Arrays.sort(数组名, new 类1() ) //new 类1() 是创建比较器对象
} //也可以通过匿名内部类实现
}
//eg:使用匿名内部类实现比较器
//根据长度对字符串排序
import java.util.Comparator;
public class ComparatorDemo{
pubic static void main(String[] args){
String[] s = {"this","is","a","String"};
Arrays.sort(s,new Comparator<String>(){
@Override
public int compare(String first,String second){
return first.length() - second.length();
}
});
}
}
三、Lambda表达式
简介:Lambda表达式是可以传递给方法的一段代码,它可以是一个语句,也可以是一个代码块。
1、Lambda表达式结构
对象或者类.方法名(...(参数类型 参数1,参数类型 参数2) -> {
//代码
});
//如果参数类型是可以通过 前面的参数或方法固定的参数类型 推导的, 那么可以省略
//如果参数类型可推导,且只有一个参数,那么 参数的()也可以省略 ★
//如果只有一行代码,{} 和 return关键字 可以省略
//eg:用Lambda表达式改写上面 使用匿名内部类实现比较器(根据长度对字符串排序)
Arrays.sort(s,(String first,String second) -> {
return first.length() - second.length();
});
//极简模式:
//由于前面的 参数s 是String类型的数组名,所以可以推导出 first和 second是String类型,所以参数类型可以省略
Arrays.sort(s,(first,second) -> first.length() - second.length());
2、函数式接口
简介:函数式接口指仅包含一个抽象方法的接口
注解: @FunctionalInterface
作用:适用于Lambda使用,为Lambda更简单地实现而定义
函数式接口+Lambda 的基本格式:
函数接口名 <...> 对象名 = 函数接口中方法的参数 -> 方法中的表达式
// <...>中的内容 和 参数的个数 根据具体的函数接口决定
我的理解:函数接口声明会先给出参数类型,这就满足了Lambda的语法:参数可推导即可省略 的条件,所以简化了Lambda表达式
在java.util.function包中定义了大量的函数式接口,它们使编写Lambda表达式变得容易。
(1)Function<T, R>接口定义了apply()方法。其中T:参数类型,R:结果类型
Function <参数类型, 结果类型>,它带一个参数,并返回一个值
BiFunction<参数类型,参数类型,结果类型>,它带两个参数,并返回一个值
import java.util.function.函数式接口名 //注意导入包
//使用匿名内部类实现
Function <Double,Double> fun = new Function <Double,Double>(){
public Double apply(Double c){
return 2*c;
}
}
//使用Lambda表达式实现
Function <Double,Double> fun = c -> 2*c ;
BiFunction <Double,Double,Double> fun2 = (width,length) -> width*length ;
(2)Predicate<参数类型>接口定义了test()方法,它带一个参数T,返回一个布尔值
(3)Supplier<参数类型>接口定义了get()方法,它不带参数,返回一个值。
(4)Consumer<参数类型>接口定义了accept()方法,带一个参数,无返回值
3、方法引用
(1)方法引用
特点:用 :: 进行引用
有点不好解释,先看例子吧:
//不区分大小写进行比较
String[] names = {"One","two","Three"};
Arrays.sort(names,(x,y) -> x.compareToIgnoreCase(y)); //使用Lambda表达式实现比较器对象
//类名::实例方法名
Arrays.sort(names,String::compareToIgnoreCase);
使用方法:
对象::实例方法名 eg:System.out::println
类名::静态方法名 eg:list.removeIf(Objects::isNull);
类名::实例方法名 eg:String::compareToIgnoreCase
(2)构造方法引用
使用方法:
类名::new
数组::new