interface Test2{}
interface Test3{}
class Main{
public static void main(String[] args) {
Test1Impl test1 = new Test1Impl();
test1.testDef();// 运行结果:被实现类重写的接口默认方法
test1.testDef2();// 运行结果:接口的默认方法,没被实现类重写
test1.testStat();// 运行结果:实现类自定义新方法,和实现接口的静态方法无关系
Test.testStat();// 运行结果:接口静态方法
// 接口使用:多态(向上转型),即接口引用变量可以指向接口实现类对象
Test test = test1;
// 接口使用:多态(强转),即接口实现类对象可以强转为接口类型
Object obj = (Test) test1;
// 接口不能使用:接口不能用于创建实例
// 否则编译报错:‘Test’ is abstract; cannot be instantiated
//Test test2 = new Test();
}
}
思考题
===
0.接口中的成员变量,也叫常量,这里常量是指常量值不会改变吗?
如果接口成员常量的类型是基本数据类型,则对应的常量值不会改变。
如果接口成员常量的类型是引用类型中不可变类类型,则对应的常量值不会改变。
如果接口成员常量的类型是引用类型中可变类类型,则对应的常量值内容是可能改变的。
接口中成员变量默认被public static final修饰,
但是这里的final只是保证 变量名的引用不变,即变量名存储的地址值不变,但是无法变量的引用指向的值不变。
这里的值如果是基本类型数据,则由于基本类型数据本身一旦确定就无法改变。
这里的值如果是引用类型数据,我们需要直到引用类型数据分为两类:不可变类,可变类。
不可变类的概念一旦该类对象被创建,则对象的实例变量值不会再被改变。反之,就可变类概念。
所以不可变类类型的值,一旦确定就无法改变。
1.接口的成员是否都默认被public修饰?
不是。Jdk9之后,接口引入了一个新成员:私有方法。该成员被private修饰。
除了私有方法外,其他成员都都默认被public修饰:
常量: public static final
抽象方法: public abstract
默认方法: public default
静态方法: public static
内部类和枚举类: public static
接口没有构造器和初始化块成员。
2.为什么接口要引入默认方法,静态方法,私有方法?
我们知道在Jdk8之前接口没有默认方法,静态方法成员。
所以如果需求变更,则我们只能在接口中新增抽象方法,而实现接口的实现类必须重写接口定义的全部抽象方法,否则编译报错。
那么接口变更的话,就会造成其实现类的大量修改。这个不符合开发设计的原则。
Jdk8引入了默认方法和静态方法,用于满足拓展接口功能,而不会影响其实现类。因为接口默认方法,其实现类可以选择重写或不重写。而接口静态方法不能被实现类继承和重写,只能通过接口名调用。
那么静态方法的用处是什么呢?
接口静态方法一般用于定义接口级别的工具方法,这类方法用于良好的实现,不希望被重写,防止实现被篡改。
那么如果接口定义了多个默认方法,且多个默认方法中有很多重复代码,或者接口定义了多个静态方法,且多个静态方法中有很多重复代码,那么如何提取这部分重复代码呢?
Jdk9后,java给接口引入了私有方法,用于提取默认方法和静态方法中的重复代码,设计成私有的目的就是为了保证这部分重复代码逻辑只能在接口内调用,不需要也不能被外部调用。体现良好的封装性。
3.由于接口是可以多继承的,那么当多个父接口中定义了重复的抽象方法,默认方法,静态方法,子接口如何处理?
1.由于抽象方法没有具体实现,所以多个父接口中同名的抽象方法,继承给子接口后,子接口只会当成同一个抽象方法,不需要特殊处理。
2.由于默认方法有具体实现,所以子接口从多个父接口继承过来的同名默认方法会发生冲突,子接口必须重写该默认方法。
3.由于接口静态方法不会继承给子接口,而是属于对应父接口。所以无需特殊处理。
package interfaceTest;
public interface Inter extends Inter1,Inter2{
// Inter继承Inter1,Inter2,其中Inter1,Inter2定义了同名的抽象方法,默认方法,静态方法
// 如果不做任何处理,则
// 编译报错:interfaceTest.Inter inherits unrelated defaults for testDef() from types interfaceTest.Inter1 and interfaceTest.Inter2
// 处理编译报错的方式
// 1.无需关注多个父接口的同名抽象方法
// 2.多个父接口存在同名的默认方法,则子接口必须重写该冲突的默认方法,否则编译报错
// 3.无需关注读个父接口的同名静态方法,因为静态方法是属于对应接口的,不会继承给子接口
@Override
default void testDef() {
System.out.println(“重写多个父接口中冲突的同名默认方法”);
}
}
interface Inter1{
void test();
default void testDef(){
System.out.println(“Inter1 的默认方法”);
}
static void testStat(){
System.out.println(“Inter1 的静态方法”);
}
}
interface Inter2{
void test();
default void testDef(){
System.out.println(“Inter2 的默认方法”);
}
static void testStat(){
System.out.println(“Inter2 的静态方法”);
}
}
4.如果子接口和父接口中定义了相同的抽象方法,默认方法,静态方法,子接口是否会编译报错?
不会
1.子接口会将父接口的抽象方法和自己的同名抽象方法当成同一个方法。
2.子接口的默认方法实现会覆盖父接口的默认方法。
3.接口静态方法属于接口,子接口不会继承父接口的静态方法,所以不存在冲突。
另外实现子接口的实现类对象调用接口默认抽象方法时,调用的时子接口的默认方法。
package interfaceTest;
public interface Inter extends Inter1{
void test();
default void testDef(){
System.out.println(“子接口 的默认方法”);
}
static void testStat(){
System.out.println(“子接口 的静态方法”);
}
}
interface Inter1{
void test();
default void testDef(){
System.out.println(“父接口 的默认方法”);
}
static void testStat(){
System.out.println(“父接口 的静态方法”);
}
}
class Main1 implements Inter{
@Override
public void test() {
System.out.println(“实现类重写的接口抽象方法”);
}
public static void main(String[] args) {
Main1 main1 = new Main1();
main1.test();// 实现类重写的接口抽象方法
main1.testDef();// 子接口 的默认方法
Inter.testStat();// 子接口 的静态方法
Inter1.testStat();// 父接口 的静态方法
}
}
5.由于类可以实现多个接口,那么当多个接口存在重复的抽象方法,默认方法,静态方法时,实现类该如何处理?
类实现多个接口,且多个接口存在同名的
1、抽象方法
由于抽象方法没有方法体,所以实现类会将多个接口的同名抽象方法当成一个来处理。
2、默认方法
由于默认方法有方法体,所以实现类从多个接口继承到多个同名不同方法体的方法后,会冲突,编译报错,需要强制实现类重写该默认方法。
3、静态方法
无需考虑,接口静态方法属于接口,和实现类无关。
package interfaceTest;
public interface Inter{
void test();
default void testDef(){
System.out.println(“接口1 的默认方法”);
}
static void testStat(){
System.out.println(“接口1 的静态方法”);
}
}
interface Inter2{
void test();
default void testDef(){
System.out.println(“接口2 的默认方法”);
}
static void testStat(){
System.out.println(“接口2 的静态方法”);
}
}
class Main1 implements Inter,Inter2{
@Override
public void test() {
System.out.println(“实现类重写的接口抽象方法”);
}
// 如果不重写Inter,Inter2中的同名冲突的默认放啊,则编译报错
// interfaceTest.Main1 inherits unrelated defaults for testDef() from types interfaceTest.Inter and interfaceTest.Inter2
@Override
public void testDef() {
System.out.println(“实现类重写的多个接口的同名冲突的默认方法”);
}
public static void main(String[] args) {
Main1 main1 = new Main1();
main1.testDef();
}
}
6.由于类可以同时继承一个父类,和实现多个接口,那么当父类和接口存在重复的抽象方法,默认方法,静态方法时,子类该如何处理?
先给出结论:
父类和父接口的抽象方法定义重复的话,子实现类会将这两个抽象方法当成一个处理,只会重写一次。
父类和父接口的静态方法定义重复的话,子类无需处理,父接口的静态方法属于接口,和实现类无关。父类的静态方法会继承给子类。
父类和父接口的默认方法定义重复的话,子类不会因为冲突而编译报错,但是子类对象调用该默认方法时:父类的方法执行优先级高级父接口的同名默认方法。
具体分析:
首先排除接口静态方法,因为接口静态方法属于接口本身,和实现类无关。所以接口静态方法和实现类的父类的同名静态方法不会冲突。
但是需要注意一点:父类的静态方法会继承给子类类本身。但是子类不能重写父类的静态方法,就算子类中定义一个和父类相同定义的静态方法,也是一个子类本身一个新方法,和父类同名静态方法无关。
package interfaceTest;
public interface Inter{
public static void testStat(){
System.out.println(“父接口 的静态方法”);
}
}
class Father{
public static void testStat(){
System.out.println(“父类 的静态方法(和父接口静态方法同名)”);
}
}
class Main2 extends Father implements Inter{
public static void main(String[] args) {
Main2 main2 = new Main2();
main2.testStat();// 父类 的静态方法(和父接口静态方法同名)
// 父类的静态方法会继承给子类类本身
Main2.testStat();// 父类 的静态方法(和父接口静态方法同名)
Father.testStat();// 父类 的静态方法(和父接口静态方法同名)
}
}
其次默认方法,由于接口的默认方法被实现类继承或重写后就变成普通方法样式,如下
interface Inter{
public default void test(){
System.out.println(“接口的默认方法”);
}
}
class Child implements Inter{
@Override
public void test(){
System.out.println(“实现类重写的默认方法”);
}
}
所以构造冲突场景的话,父类也需要定义一个类似重写接口静态方法后的方法
package interfaceTest;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
![](https://i-blog.csdnimg.cn/blog_migrate/f65a65dd673ec61d24ebe0d0b6684d00.jpeg)
结尾
学习html5、css、javascript这些基础知识,学习的渠道很多,就不多说了,例如,一些其他的优秀博客。但是本人觉得看书也很必要,可以节省很多时间,常见的javascript的书,例如:javascript的高级程序设计,是每位前端工程师必不可少的一本书,边看边用,了解js的一些基本知识,基本上很全面了,如果有时间可以读一些,js性能相关的书籍,以及设计者模式,在实践中都会用的到。
料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
[外链图片转存中…(img-0tzyBJPJ-1712366694425)]
[外链图片转存中…(img-lbUFvOAs-1712366694426)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
[外链图片转存中…(img-jAJknFYU-1712366694426)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
![](https://i-blog.csdnimg.cn/blog_migrate/f65a65dd673ec61d24ebe0d0b6684d00.jpeg)
结尾
学习html5、css、javascript这些基础知识,学习的渠道很多,就不多说了,例如,一些其他的优秀博客。但是本人觉得看书也很必要,可以节省很多时间,常见的javascript的书,例如:javascript的高级程序设计,是每位前端工程师必不可少的一本书,边看边用,了解js的一些基本知识,基本上很全面了,如果有时间可以读一些,js性能相关的书籍,以及设计者模式,在实践中都会用的到。