1. 抽象类和接口的区别(简单)
- 单继承多实现。(基础)
- 抽象类中可以有构造方法,接口中不能有构造方法(基础)
- 抽象类中的所有方法并不一定要是抽象的,而接口要求所有的方法都必须是抽象的(基础)
- 抽象类中可以包含静态方法,接口中不可以(基础)
- 抽象类中可以有普通成员变量,接口中不可以(基础)
- 使用动机不同,实现接口是为了使用接口的规范行为,抽象类是为了使用类属性,是继承关系的体现。(高级)
2. JAVA多态的实现原理(一般)
- 面向对象的三大特性:封装、继承、多态(基础)
- 实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。(核心)
- 多态必须要有继承,要有重写,父类引用指向子类对象。(核心&关键)
2.1. 多态的好处(中等)
- 可替换性。多态对已存在代码具有可替换性。(关键)
- 可扩充性。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。(关键)
- 接口性。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。(关键)
- 灵活性。它在应用中体现了灵活多样的操作,提高了使用效率。(一般)
- 简化性。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。(一般)
3. JVM的内存机构模型?哪些是被线程共享的区域(简单)
- 程序计数器、Java虚拟机栈、本地方法栈、java堆、方法区(永久代jdk6-jdk7,jdk8去除永久代改为元数据区)、运行时常量池等。
- 其中堆和方法区是线程共享区域,其他为非线程共享区域。
1.1. 每个区的职责是什么?(困难)
- 程序计数器:这里记录了线程执行的字节码的行号,在分支、循环、跳转、异常、线程恢复等都依赖这个计数器。
- Java虚拟机栈:线程私有,生命周期与线程相同。每个方法执行的时候都会创建一个栈帧(stack frame)用于存放 局部变量表、操作栈、动态链接、方法出口。
- 本地方法栈:与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行Java 方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native 方法服务。
- 方法区:是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
- 运行时常量池:是方法区的一部分。Class 文件中除了有类的版本、字段、方法、接口等描述等信息外,还有一项信息是常量池(Constant PoolTable),用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。
- 字面量:与java语言层面的常量概念接近,包含文本字符串、声明为final的常量值等。
- 符号引用:编译语言层面的概念,包括以下三类:
- 类和接口的全限定名
- 字段的名称和描述符
- 方法的名称和描述符
- java堆:是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存,垃圾回收主要就是作用于这里的。
1.2. 堆与栈分开设计是为什么呢?(一般)
- 栈存储了处理逻辑、堆存储了具体的数据,这样隔离设计更为清晰
- 堆与栈分离,使得堆可以被多个栈共享。
- 栈保存了上下文的信息,因此只能向上增长;而堆是动态分配
1.3. 可能发生OOM的区域,产生OOM的原因分别是什么?(一般)
- 除程序计数器外均可能发生OOM。
- 虚拟机栈:如果虚拟机栈支持动态扩展,当扩展Dao无法申请到内存时抛出;
- 本地方法栈:原因同上
- 堆:队中没有内存完成实例分配并且无法完成扩展时,会抛出OOM异常
- 方法区:同上
1.4. 举一个可以导致栈内存溢出的例子?(一般)
- 递归(栈深度)创建大量线程,导致栈溢出