1.接口
接口的由来:当一个抽象类中 所有的函数都是抽象的时候,那么我们就可以将这个抽象类,用另外一种表现形式,即接口。
在JDK7之前 接口中是不可以定义具体函数的
在JDK8以后 接口中是可以定义具体函数的(必须是静态的函数 成员函数还是依旧默认抽象的)
对于接口而言 里面的函数 变量
所有的接口变量:
public static final xxx xxx
所有的函数:
public abstract xxx xxx
2.接口与类之间的关系
一个类可以多现实多个接口=其实就是相当于继承多个抽象类
本质上还是子类与父类的关系 只不过在接口这里 一个类可以有多个接口爸爸
interface interfaceB{
void show();
}
interface interfaceC{
void haha();
}
class Demo1 implements interfaceB,interfaceC{
@Override
public void haha() {
}
@Override
public void show() {
}
}
当一个类想要实现一个接口的时候 有两个选择
1.重写接口中的函数
2.该类定义成抽象即可
1.重写接口中的函数
class Demo1 implements interfaceB,interfaceC{ @Override public void haha() { } @Override public void show() { } }
2.该类定义成抽象即可
abstract class Demo2 implements interfaceB,interfaceC{ public abstract void show(); public abstract void haha(); }
3.接口与接口之间的关系
不可能是实现关系implements;只能是继承关系-多继承
继承到的是属性 抽象函数 但是没有静态函数的继承
Eg: //d4.haha();//这样调用不到接口的静态函数
interfaceA.haha();//只能通过接口调用静态函数
为什么接口与接口之间可以多继承?
接口里面的函数并没有说具体怎样去实现,而具体怎样实现是由子类来决定。
interface interfaceD{
void happyLife(); //你爷爷希望你生活美好
public static void show(){
System.out.println("D show...");
}
}
interface interfaceE{
void happyLife(); //你奶奶希望你生活美好
public static void show(){
System.out.println("F show...");
}
}
//继承到的是属性 抽象函数 但是没有静态函数的继承,所以show()调用不到
interface interfaceF extends interfaceD,interfaceE{
//你爸爸希望你生活美好
public static void show(){ //调用不到
}
}
class Demo3 implements interfaceF{
@Override
public void happyLife() { //具体怎样实现自己来决定
}
}
为什么类与类之间不能多继承?
本质就看 函数是否有函数体!因为类里面有具体的函数体,继承的话就会产生二义性;
class DemoA{
void kill(){
System.out.println("Kill B");
}
}
class DemoB{
void kill(){
System.out.println("Kill A");
}
}
class DemoC extends DemoA,DemoB{
}
DemoC dc=new DemoC();
dc.kill();????? 二义性
4.接口的作用
第一个作用:在后期对类的功能进行扩展,这些功能并不是该类原先所具有的功能!
好处:避免了继承带来的一些弊端 只能单继承。
class Bird{
void fly(){}
}
interface 飞行{
void fly();
}
class Person implements 飞行{
@Override
public void fly() {
System.out.println("人可以飞了....");
}
}
补充:
Java当中最常用的三个接口 内置的接口
- Comparable 比较接口 给我们的类提供比较的功能
int compareTo(T o); 按照自然顺序进行比较
String.compareTo()
- Iterable 可迭代接口 可以将我们该类的对象用于foreach循环
- Serializable 序列化接口 我们可以将该对象的数据写出去
对象的数据在内存中 如何将内存中的数据写出去(硬盘 网络)
想要把内存中的数据提取 就得实现序列化接口
第二个作用:向外提供统一的规范
接口的出现 一定程度上对我们的代码设计进行了解耦;耦合性-两只之间的联系 。
public class InterfaceDemo03 {
public static void main(String[] args) {
Computer computer=new Computer();
Mouse mouse=new Mouse();
KeyBoard keyBoard=new KeyBoard();
MobileHard mobileHard=new MobileHard();
computer.getUSBConnect(mouse);
computer.getUSBConnect(keyBoard);
computer.getUSBConnect(mobileHard);
}
}
class Computer{
public void getUSBConnect(USB device){
device.doSomething();
// device.haha(); 调用不到子类特有的行为
}
}
interface USB{
void doSomething();
}
class Mouse implements USB{
@Override
public void doSomething() {
System.out.println("鼠标:提供坐标的访问和控制。。。。");
}
void haha(){}
}
class KeyBoard implements USB{
@Override
public void doSomething() {
System.out.println("键盘:提供数据的输入。。。。");
}
}
class MobileHard implements USB{
@Override
public void doSomething() {
System.out.println("移动硬盘:提供外部存储。。。。");
}
}
第三个作用:传递代码 和第二个作用很像。
public class InterfaceDemo04 {
public static void main(String[] args) {
Button loginButton=new Button();
Button registButton=new Button();
Button downloadButton=new Button();
//匿名实现子类的匿名对象
//避免了在编译期间所生成的大量备选的类字节码
//在程序运行期间 需要用到了,再去创建实现子类和其对象即可
/*
实现子类的匿名对象 之所以写Mission的原因就在于我们要确定子类是谁的实现子类
new Mission()
匿名实现子类
{
public void doTask() {
System.out.println("登录功能......");
};
}
*/
loginButton.doSometing(new Mission(){
@Override
public void doTask() {
System.out.println("登录功能......");
}
}
);
registButton.doSometing(new Mission(){
public void doTask() {
System.out.println("注册功能......");
};
}
);
downloadButton.doSometing(new Mission(){
public void doTask() {
System.out.println("下载功能......");
};
});
}
}
//按钮---任务 分开看
interface Mission{
//任务的具体内容
public void doTask();
}
class Button{
//当用户点击该按钮的时候 应该触发的一些事情
//每一个按钮对象的任务不同 此处无法决定具体的代码
public void doSometing(Mission mission){
mission.doTask();
}
}