Java面试
面向对象
- 什么是面向对象?
- 可根据面向过程进行回答。面向过程更注重事情的每一个步骤及顺序,面对对象更注重事情有哪些参与者(对象)、及各自需要什么。
- 面向过程比较直接高效,而面向对象更易于复用、扩展和维护
- 封装:外部调用午休修改或者关心内部实现
- 继承:继承基类的方法、并作出自己的改变或者扩展
- 多态:基于对象所属类不同,外部对同一个方法的调用,实际执行逻辑不同。
多态的三个特点:继承,方法重写,父类引用指向子类对象
无法调用子类特有的功能
JVM
- JVM从软件层面屏蔽不同操作系统在底层硬件与指令上的区别
-
堆区(heap):
- 堆是用来存放对象的内存空间,堆中不存放基本类型和对象引用,只存放对象本身
- jvm中只有一个堆区,被所有线程所共享
- 在虚拟机启动时创建,垃圾回收的主要场所
- 堆的大小可以是固定的,也可以是扩展的。因此当线程请求分配内存,但堆已满且内存已满无法扩展时,就会抛出OutOfMemoryError
-
栈(线程)(stack):(局部变量表)(操作数栈)(动态链接)(方法出口)
- 基本类型变量去、执行环境上下文,操作指令区
- 每一个线程包含一个stack,随着线程的创建二创建,随着线程消亡而消亡。只保存基本数据类型自定义对象的引用(不是对象)
- 每个stack中的数据都是私有的,其他栈不能使用
- Java虚拟机栈会出现两种异常:StackOverFlowError和OutOfMemoryError
- StackOverFlowError表示当前线程申请栈超过了事先约定好栈的最大深度,且内存空间还有很多
- OutOfMemoryError表示线程申请栈时发现栈已经满了,而且内存也满了
-
方法区(method area):常量+静态变量+类信息
- 方法区中包含的都是程序中唯一的元素,如class,static
- 又叫静态区,被所有线程共享
- 和堆一样,允许固定大小,也允许扩展大小,还允许不是先垃圾回收
-
程序计数器(Program Counter Register):
- 我们都知道JVM是一行一行执行字节码,所以需要计数器来记录当前执行的行号。特点包括以下几个方面:
- 是一块较小的存储空间
- 线程私有的,每个线程都有一个程序计数器
- 生命周期随着线程的创建而创建,随着线程的消亡而消亡
- 是唯一一个不会出现OutOfMemoryError的内存区域
-
本地方法栈(Native method Stack):
- 本地方法栈和JVM虚拟机栈实现的功能类似,只不过本地方法区是本地方法运行的内存模型。本地方法在执行时,会创建一个栈帧来存放方法的各种信息。比如局部变量和返回值。方法执行前就创建栈帧入栈,执行完成后就出栈。
- 总结
-
java虚拟机内存模型中一共有两个栈,分别是java虚拟机栈和本地方法栈。两个栈的功能类似,都是方法运行过程的内存模型,并且两个栈的内部结构相同,都是线程私有的。
-
Java虚拟机的内存模型中一共有两个“堆”,一个是原本的堆,一个是方法区。方法区本质上是属于堆的一个逻辑部分。堆中存放对象,方法区中存放类信息、常量、静态变量、即时编译器编译的代码。
-
堆是Java虚拟机中最大的一块内存区域,也是垃圾收集器主要的工作区域。
-
程序计数器、Java虚拟机栈、本地方法栈是线程私有的,即每个线程都拥有各自的程序计数器、Java虚拟机栈、本地方法区。并且他们的生命周期和所属的线程一样。而堆、方法区是线程共享的,在Java虚拟机中只有一个堆、一个方法栈。并在JVM启动的时候就创建,JVM停止才销毁。
-
操作数栈:在进行加减乘除操作过程中临时存放的内存空间
-
main方法
- main()方法作为程序的入口
- main()方法是一个普通的静态方法
- main()方法可以作为我们与控制台交互的方式。
代码块
-
代码块的作用,用来初始化类、对象
-
代码块如果有修饰的话,只能使用static
-
分类:静态代码块vs非静态代码块
-
静态代码块
内部可以有输出语句
随着对象的创建而执行
每创建一个对象,就执行一次非静态代码块
作用:可以在创建对象时,对对象属性进行初始化
如果一个类中定义了多个静态代码块,则按照声明的先后顺序执行
静态代码块的执行优先于非静态代码块
静态代码块内只能调用静态的属性、静态的方法,不能调用非静态的结构 -
非静态代码块
内部可以有输出语句
随着对象的创建而执行
每创建一个对象,就执行依次非静态代码块
作用:可以在创建对象时,对对象的属性等进行初始化
如果一个类中定义了多个非静态代码块,则按照声明的向后顺序执行
非静态代码块内可以调用静态的属性、静态的方法,或非静态的属性、非静态的方法
- 对属性可以赋值的位置
- 默认初始化
- 显式初始化
- 构造器中初始化
- 有了对象以后,可以通过“对象.属性”或“对象.方法”的方式,进行赋值
- 在代码块中进行赋值