【第二章:Java核心技术解析】第4节:Java基础 - 必知必会(中)
大家好,很高兴我们可以继续学习交流Java高频面试题。本小节是Java基础篇章的第二小节,主要讲述抽象类与接口的区别,注解以及反射等知识点。熟练掌握本小节的知识点,可以帮助大家更好的复习与掌握Java面试中的基础类题目,并且在与面试官的热身题目中占据先机,留下好印象。
(1)抽象类和接口有什么区别?
答:抽象类和接口的主要区别可以总结如下。
- 抽象类中可以没有抽象方法,也可以抽象方法和非抽象方法共存
- 接口中的方法在JDK8之前只能是抽象的,JDK8版本开始提供了接口中方法的default实现
- 抽象类和类一样是单继承的;接口可以实现多个父接口
- 抽象类中可以存在普通的成员变量;接口中的变量必须是static final类型的,必须被初始化,接口中只有常量,没有变量
解析:
基础题目,绝对的基础并且高频的面试考察点。在Java中,我们通过abstract来定义抽象类,通过interface关键字来定义接口。如下所示:
// 这是一个抽象类 abstract class Animal{ } // 这是一个接口 interface Bird{ }
我们知道接口和抽象类中都可以定义抽象方法,然后交由其实现类来实现该抽象方法。来看如下的面试官追问。
面试官追问:抽象类和接口应该如何选择?分别在什么情况下使用呢?
答:根据抽象类和接口的不同之处,当我们仅仅需要定义一些抽象方法而不需要其余额外的具体方法或者变量的时候,我们可以使用接口。反之,则需要使用抽象类,因为抽象类中可以有非抽象方法和变量。
默认方法:
既然说到了JDK8接口中的方法可以实现,那么我们来看下default方法的具体实现。我们先给出一个接口中的default方法Demo,如下所示:
public interface MyInterface { // 定义一个已经实现的方法,使用default表明 default void say(String message){ System.out.println("Hello "+message); } // 普通的抽象方法 void test(); }
当一个类实现该接口时,可以继承到该接口中的默认方法,如下所示:
public interface MyInterface { // 定义一个已经实现的方法,使用default表明 default void say(String message){ System.out.println("Hello "+message); } // 普通的抽象方法 void test(); } class MyClass implements MyInterface{ @Override public void test() { System.out.println("test..."); } } class Main{ public static void main(String[] args) { MyClass client = new MyClass(); client.test(); client.say("World..."); } }
这样的话,大家就会有疑问,如果两个接口中存在同样的默认方法,实现类继承的是哪一个呢?Demo如下:
public interface MyInterface { // 定义一个已经实现的方法,使用default表明 default void say(String message){ System.out.println("Hello "+message); } // 普通的抽象方法 void test(); } interface MyInterface2{ // 定义一个已经实现的方法,使用default表明 default void say(String message){ System.out.println("[2]-Hello "+message); } } // 此处会编译错误 class MyClass implements MyInterface, MyInterface2{ @Override public void test() { System.out.println("test..."); } }
这个时候,实现类那里会编译错误,错误如下:
这个编译错误的大概意思就是说:有两个相同的方法,编译器不知道该如何选择了。我们有两种处理方式,如下所示:
- 重写多个接口中的相同的默认方法
- 在实现类中指定要使用哪个接口中的默认方法
重写多个接口中的相同的默认方法:
class MyClass implements MyInterface, MyInterface2{ @Override public void say(String message) { System.out.println("[Client]-Hello "+message); } @Override public void test() { System.out.println("test..."); } }
在实现类中指定要使用哪个接口中的默认方法:
class MyClass implements MyInterface, MyInterface2{ // 手动指定哪个默认方法生效 public void say(String message) { MyInterface.super.say(message); } @Override public void test() { System.out.println("test..."); } }
那么JDK8中为什么会出现默认方法呢?
答:使用接口,使得我们可以面向抽象编程,但是其有一个缺点就是当接口中有改动的时候,需要修改所有的实现类。在JDK8中,为了给已经存在的接口增加新的方法并且不影响已有的实现,所以引入了接口中的默认方法实现。
默认方法允许在不打破现有继承体系的基础上改进接口,解决了接口的修改与现有的实现不兼容的问题。:给java.util.Collection接口添加新方法,如stream()、parallelStream()、forEach()和removeIf()等等。在我们实际开发中,接口的默认
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
<p> Java开发岗高频面试题全解析,专刊正文共计31节,已经全部更新完毕。专刊分9个模块来对Java岗位面试中的知识点进行解析,包括通用面试技能,Java基础,Java进阶,网络协议,常见框架以及算法,设计模式等。专刊串点成面的解析每个面试题背后的技术原理,由浅入深,循序渐进,力争让大家掌握面试题目的背后的技术原理,摒弃背题模式的陋习。 专刊详细信息,请查阅专刊大纲和开篇词的介绍。 本专刊购买后即可解锁所有章节,故不可以退换哦~ </p> <p> <br /> </p>