1.接口属性:
-:接口不是类,尽管不能创造接口的实例,但是能声明接口变量
-:接口变量必须引用实现了接口的类对象
-:检查是否实现:if(anobject instanceof Camparable)
-: 接口扩展:接口可扩展接口,接口1 extends 接口2
-:接口中不能包含实例字段,但可以包含常量
-:接口中的方法默认public,字段默认public static final
为什么需要接口:在Java中一个类只能继承一个类,而一个类却可以继承多个接口,这为定义类的行为提供了极大的灵活性!
默认方法:
情景:之前你写了一个程序,有一个接口作为多个类的接口,但是有部分类需要这个接口增加一个方法,接口增加方法后显然另一部分接口没有这个接口的实现,导致报错!
解决方法:使用default方法在接口中提供默认实现,可以满足需要增加方法的一部分类,创建实例后直接调用默认方法名,而不需要的类可不提供具体实现,程序也可以正常运行!
具体代码:
package Interface;
public class DefaultRun
{
public static void main(String[] args)
{
var MyTest=new DefaultTest();
int value=MyTest.cal(4,3);//调用DefaultTest从calculate中拿来的方法
int value1=MyTest.test(2,8);//实例可以调用calculate中的默认方法
System.out.println("value="+value+",value1="+value1);
}
}
package Interface;
public class DefaultTest implements calculate
{
public int cal(int x,int y)
{
int z;
z=x+y;
return z;
}
}
package Interface;
public interface calculate
{
int cal(int x, int y);
default int test(double x, double y)//默认实现,在DefaultTest中可被调用:实例.test(a,b)
{
x=2*y;
return (int) x;
}
}
默认方法冲突原则:
-:超类优先,如果超类提供了一个具体方法,同名而且有相同参数类型的默认方法将会被忽略
-:两个接口的默认方法冲突
package Interface;
public interface InterfaceTest
{
default String getName(){return "I am InterfaceTest!";}
}
interface Named
{
default String getName(){return "I am Named!";}
}
class Student implements InterfaceTest,Named
{
public String getName()
{
return InterfaceTest.super.getName();//接口默认方法冲突,在类中提供冲突的方法,选择两个冲突方法中的一个
}
}
class Run
{
public static void main(String[] args)
{
var MyTest2 = new Student();
String dd=MyTest2.getName();
System.out.println(dd);
}
回调:可以指定某个特定事件发生时应该采取的动作
例子:timer计时每隔1000ms调用接口ActionEvent中的actionPerformed方法
具体实现代码:
package Interface;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Instant;
public class TimerTest
{
public static void main(String[] args)
{
var listener=new TimePrinter();
var timer=new Timer(1000,listener);//构造一个定时器,每隔1000ms通知listener一次
timer.start();
JOptionPane.showMessageDialog(null,"quit program");//第一个参数为null则对话框位于组件中央
System.exit(0);
}
}
class TimePrinter implements ActionListener//ActionListener接口:当达到指定的时间间隔,定时器就调用actionPerformed方法
{
public void actionPerformed(ActionEvent event)
{
System.out.println("At the tone,the time is:"+ Instant.ofEpochMilli(event.getWhen()));//eventwhen()调用会返回这个事件的时间,ofEpochMilli得到更加可读的描述
Toolkit.getDefaultToolkit().beep();//获得默认的工具箱发出一声铃响
}
}
数组顺序排序:用Arrays.sort
package Interface;
import java.util.Arrays;
import java.util.Comparator;
public class StringSort implements Comparator<String>
{
@Override
public int compare(String o1, String o2)//实现接口
{
return o1.length()-o2.length();
}
public static void main(String[] args)
{
String[] friend={"peter","Paul322","Mary"};
Arrays.sort(friend,new StringSort());//数组排序用Arrays.sort比较方便
System.out.println(Arrays.toString(friend));
}
}
"D:\Program Files\bin\java.exe" "-javaagent:D:\IntelliJ IDEA 2020.2.2\lib\idea_rt.jar=50527:D:\IntelliJ IDEA 2020.2.2\bin" -Dfile.encoding=UTF-8 -classpath "D:\Program Files\项目\basic-code\out\production\day01-code" Interface.StringSort
[Mary, peter, Paul322]
Process finished with exit code 0
Comparator接口和数组反序冒泡排序
package Interface;
import javax.print.DocFlavor;
import java.util.Arrays;
import java.util.Comparator;
public class StringCompareTest implements Comparator<String>
{
public static String[]word={"qqq","wq","rrre","ssdaadd","z"};
public static void swap(int a,int b)
{
String t=word[b];
word[b]=word[a];
word[a]=t;
}
@Override
public int compare(String o1, String o2)//实现接口
{
return o1.length()-o2.length();
}
public static void main(String[] args)
{
var com = new StringCompareTest();//compare方法要在比较器对象上调用
for (int i = 0; i < word.length-1; i++)
{
for (int a=i+1;a< word.length;a++)//冒泡排序法,从小到大
{
if (com.compare(word[i], word[a]) > 0)
{
System.out.println("不交换,字符串顺序:"+Arrays.toString(word));
}
else//若word[a]的长度大于word[i]则交换两者位置
{
swap(i, a);
System.out.println("交换后的字符串顺序:"+Arrays.toString(word));
}
}
}
for (String e : word)
System.out.println(e.length());
System.out.println("数组元素个数="+word.length);
}
}
运行结果:
"D:\Program Files\bin\java.exe" "-javaagent:D:\IntelliJ IDEA 2020.2.2\lib\idea_rt.jar=50115:D:\IntelliJ IDEA 2020.2.2\bin" -Dfile.encoding=UTF-8 -classpath "D:\Program Files\项目\basic-code\out\production\day01-code" Interface.StringCompareTest
不交换,字符串顺序:[qqq, wq, rrre, ssdaadd, z]
交换后的字符串顺序:[rrre, wq, qqq, ssdaadd, z]
交换后的字符串顺序:[ssdaadd, wq, qqq, rrre, z]
不交换,字符串顺序:[ssdaadd, wq, qqq, rrre, z]
交换后的字符串顺序:[ssdaadd, qqq, wq, rrre, z]
交换后的字符串顺序:[ssdaadd, rrre, wq, qqq, z]
不交换,字符串顺序:[ssdaadd, rrre, wq, qqq, z]
交换后的字符串顺序:[ssdaadd, rrre, qqq, wq, z]
不交换,字符串顺序:[ssdaadd, rrre, qqq, wq, z]
不交换,字符串顺序:[ssdaadd, rrre, qqq, wq, z]
7
4
3
2
1
数组元素个数=5
Process finished with exit code 0
lambda
***:就是一个代码块,以及必须传入代码的变量规范
注意几点:
-:即使lambda表达式没有参数,依然要提供空括号
-:如果可以推导出一个lambda表达式的参数类型,则可以忽略其类型
-:如果方法只有一个参数,而且这个参数的类型可以推导得出。那么甚至还可以省略小括号
-:无需指定lambda表达式的返回类型
重点:对于只有一个抽象方法的接口,需要这种接口的对象时,就可以提供一个lambda表达式,这种接口称为函数式接口,由于lambda表达式可以转换为接口,使得他很有用。
package Interface;
import javax.swing.*;
import java.util.Arrays;
import java.util.Date;
public class Lambda
{
public static void main(String[] args)
{
var planets=new String[]{"Merury","Venus","Earth","Mars","Jupiter","Saturn","Uranus","Neptune"};
System.out.println(Arrays.toString(planets));
System.out.println("sorted in dictionary order:");
Arrays.sort(planets);
System.out.println(Arrays.toString(planets));//字母顺序排序后输出打印
System.out.println("Sort by length:");
Arrays.sort(planets,(first,second)->first.length()-second.length());//应用Lambda使代码更加整洁
//Lambda表达式可以转换为接口
//简化了代码
// public int compare(String o1, String o2)//实现接口
// {
// return o1.length()-o2.length();
// }
System.out.println(Arrays.toString(planets));//按照长度排序后输出打印
var timer=new Timer(1000, event->
System.out.println("The time is "+new Date()));
timer.start();;
JOptionPane.showMessageDialog(null,"关闭?");
System.exit(0);
}
}
package Interface;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Instant;
public class TimerTest
{
public static void main(String[] args)
{
var timer=new Timer(1000,event->{
System.out.println("At the tone,the time is:"+ Instant.ofEpochMilli(event.getWhen()));
Toolkit.getDefaultToolkit().beep();
});
//var listener=new TimePrinter();
//var timer=new Timer(1000,listener);//构造一个定时器,每隔1000ms通知listener一次
timer.start();
JOptionPane.showMessageDialog(null,"quit program");//第一个参数为null则对话框位于组件中央
System.exit(0);
}
}
/*class TimePrinter implements ActionListener//ActionListener接口:当达到指定的时间间隔,定时器就调用actionPerformed方法
{
public void actionPerformed(ActionEvent event)
{
System.out.println("At the tone,the time is:"+ Instant.ofEpochMilli(event.getWhen()));//eventwhen()调用会返回这个事件的时间,ofEpochMilli得到更加可读的描述
Toolkit.getDefaultToolkit().beep();//获得默认的工具箱发出一声铃响
}
}
*/
可以看出lambda表达式的使用使得代码更加简洁,可读性更好了!