接口
接口不是类,而是对希望符合这个接口的类的一组需求,也就是说,接口就像一种`规定`。
接口中的所有方法都自动是public方法,因此在接口中申明方法时,可以不用加上public字段。(java9之后可以用private,但没啥用,必须实现,只能用于给接口中的其他实现提供辅助)
但是要注意的是,接口中,千万不能有实例字段
。(java8之后可以实现方法了,但是一直都不能有实列字段)
接口的属性
可以声明接口的变量,但是接口变量的引用必须是实现了这个接口的类对象。
接口可以被拓展,从通用性较高的接口拓展到专用性较高的接口。(就像类的继承层次一样)
接口中的字段总是public static final
的。(符合上面的,接口中不能有实列字段的规定哦)
接口与抽象类
tips:之前被面试题的时候背到过:抽象类更像一种模板,接口像规定。
抽象类表示通用属性存在一个严重的问题:每个类只能扩展一个类。(因为java没有多重继承啦)
但实际上呢,接口可以提供多重继承的大多数好处,同时还能避免多重继承的复杂性和低效性。
默认方法
可以为接口方法提供一个默认实现,必须用default
修饰符标记。
看起来没啥用是吧哈哈,因为对这个接口的具体实现就会把默认方法给覆盖掉。但是本着存在即合理的理念!默认方法还是有一个重要作用的,那就是:接口演化。
比如对于一些已经存在的接口,下面已经有一堆实现类了,这个时候如果为这些接口添加了一些非默认方法,那么下面的实现类都得报错了,但是呢,如果给接口添加的是默认方法呢,就能保证源代码兼容。
解决默认方法冲突
啥叫默认方法冲突呢,通过之前的介绍看得出来,默认方法,和继承一个类得到的方法,没啥区别了都。
那么就有一些情况:
如果在一个接口中定义了一个默认方法,然后又在一个类或者另一个接口中定义了同样的方法,
这样就会出现二义性的问题。
那么解决这个问题,就又一些规则啦:
1、父类优先,总之就是接口没排面,类更牛b
2、接口冲突,如果是两个接口出现了这样的冲突,就必须由程序员自己指定用哪个啦。
由这两条规则就可以解决默认方法冲突啦,所以可以推导出:千万不要让一个默认方法重新定义Object类中的方法,比如toString或equals,默认方法是干不过类方法的啊!!!
对象克隆
老熟人了,之前背各种面试题都有提到:默认的clone是浅拷贝,并没有克隆对象中引用的其他对象。由于通常子对象都是可变的,就必须得重新定义一个clone来建立一个深拷贝,同时克隆所有子对象。
另外,只要用到了clone,这个类都该实现Cloneable
接口,然后重写clone,定义成public,再调用super.clone()
,返回的时候再强转类型(默认是Object的)。Cloneable
是一个标记接口,不包含任何方法,唯一的作用是允许在类型查询中使用instanceof
,如果使用了clone,但是没有实现这个接口的话,就会抛一个检查型异常。
还有就是一定要小心子类克隆! 因为咱重写了clone
方法实现深拷贝,只是保证了当前类的正确拷贝,但是并不能保证子类实现者会去正确修正clone
方法。由此可以看到clone
方法还是相当笨拙的,能不用就不用吧。