要想有机会面试,还得先进行笔试,也是考核专业基本功是否扎实。
【考点一】自增运算符
// 例1 从字节码角度分析 a++
public static void main(String[] args){
int a = 1;
// for(int i = 0; i < 10; i++){
for(int i = 0; i < 10; ++i){
a = a++;
}
System.out.println(a); // 1
}
[分析]
iinc
指令是直接在局部变量上进行运算
a++ 与 ++a 的区别是先执行iload
还是先执行iinc
a++
:先执行 iload
++a
:先执行 iinc
首先 a = 1
; 会在局部变量表中存储 a = 1。
其次 a = a++
; a++是先执行 iload
,即先把a的值压入操作数栈,因此此时局部变量表和操作数栈都是1;然后执行 iinc
指令,将局部变量表中的 1 进行 +1;最后,将操作数栈的中值赋给局部变量表中的a,因此将2覆盖为1。
可视化分析过程如下:
// 例2 从字节码角度分析 a++
public static void main(String[] args){
int a = 10;
int b = a++ + ++a + a--;
System.out.println(a); // 11
System.out.println(b); // 34
}
可视化分析过程如下:
// 例3 从字节码角度分析 a++
public static void main(String[] args){
int i = 1;
i = i++;
int j = i++;
int k = i + ++i*i++;
System.out.println(i); // 4
System.out.println(j); // 1
System.out.println(k); // 11
}
分析:
iload
压入操作数栈。
iinc
自增。
istore
将操作数栈中的值赋值给局部变量表的变量。
【考点二】单例模式Singleton
Singleton
:在Java中即指单例设计模式,它是软件开发中最常用的设计模式之一。
单例设计模式,即某个类在整个系统中只能有一个实例对象可被获取和使用的代码模式。
例如:代表JVM运行环境的 Runtime 类
【要点】
一是某个类只能有一个实例;
构造器私有化
二是它必须自行创建这个实例;
含有一个该类的静态变量来保存这个唯一的实例
三是它必须自行向整个系统提供这个实例;
对外提供获取该实例对象的方式:
(1)直接暴露
(2)用静态变量的get方法获取
【几种常见形式】
饿汉式:直接创建对象,不存在线程安全问题子
● 直接实例化饿汉式(简洁直观)
● 枚举式(最简洁)
● 静态代码块饿汉式(适合复杂实例化)
懒汉式:延迟创建对象
● 线程不安全(适用于单线程)
● 线程安全(适用于多线程)
● 静态内部类形式(适用于多线程)
/*
饿汉式:在类初始化的时候,直接创建对象,不管是否需要使用这个对象都会创建
(1)构造器私有化
(2)自行创建,并且用静态变量保存
(3)向外提供这个实例
(4)强调这是一个单利,我们可以使用final修饰
*/
public class Singleton{
public static final Singleton INSTANCE = new Singleton();
// (1)构造器私有化
private Singleton(){
}
// 静态方法不需要依靠实例对象,直接通过类名即可调用
public static void test(){
}
}
/*
枚举式类型:表示该类型的对象是有限的几个,我们可以限定为1个,就成了单例模式。
*/
public enum Singleton{
// 枚举中重写了toString方法
INSTANCE
}
// 测试,
public static void main(String[] args){
Singleton s = Singletion.INSTANCE;
System.out.println(s);
}
/*
静态代码块:
*/
public enum Singleton{
public static final Singleton INSTANCE;
static{
INSTANCE = new Singleton();
}
// (1)构造器私有化
private Singleton(){
}
}
/*
懒汉式:延迟创建这个实例对象 会存在线程安全问题!!!
(1)构造器私有化
(2)自行创建,并且用静态变量保存
(3)提供一个静态方法,获取这个实例对象
*/
public class Singleton{
private static Singleton instance;
// (1)构造器私有化
private Singleton(){
}
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
【考点三】类初始化过程,实例初始化过程,方法的重写
类初始化过程
①一个类要创建实例需要先加载并初始化该类
main方法所在的类需要先加载和初始化
②一个子类要初始化需要先初始化父类
③一个类初始化就是执行<clinit>() 方法
◆ <clinit>() 方法由静态类变量显示赋值代码和静态代码块组成
◆ 类变量显示赋值代码和静态代码块代码从上到下顺序执行
◆ <clinit>() 方法只执行一次
实例初始化过程
①一个类初始化就是执行<init>() 方法
◆ <init>() 方法可能重载有多个,有几个构造器就有几个方法。
◆ <init>() 方法由非静态实例变量显示赋值代码和非静态代码块、对应构造器代码组成。
◆ 非静态实例变量显示赋值代码和非静态代码块代码从上到下顺序执行,而对应构造器的代码最后执行
◆ 每次创建实例对象,调用对应构造器,执行的就是对应的方法
◆ <init>() 方法的首行是super()或super(实参列表),即对应父类的<init>() 方法
方法的重写
①哪些方法不可以被重写
◆ final方法
◆ 静态方法
◆ private等子类中不可见方法
②对象的多态性
◆ 子类如果重写了父类的方法,通过子类对象调用的一定是子类重写过的代码。
◆ 非静态方法默认的调用对象是this 。
◆ this对象在构造器或者说方法中就是正在创建的对象。
进阶要求:
Override 和 Overload 的区别?
Override重写的要求?
◆ 方法名
◆ 形参列表
◆ 返回值类型
◆ 抛出的异常列表
◆ 修饰符
【考点四】方法的参数传递机制:
①形参是基本数据类型
◆ 传递数据值
②实参是引用数据类型
◆ 传递地址值
◆ 特殊的类型:String、包装类等对象不可变性
【考点五】局部变量与成员变量的区别:
①声明的位置
◆ 局部变量:方法体{}中,形参,代码块{}中
◆ 成员变量:类中方法外
类变量:有static修饰
实例变量:没有static修 饰
②修饰符
◆ 局部变量:final
◆ 成员变量:public、protected、private、final、static、volatile、transient
③值存储的位置
◆ 局部变量:栈
◆ 实例变量:唯
◆ 类变量:方法区
堆(Heap),此内存区域的唯–目的就是存放对象实例几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。
通常所说的栈(Stack),是指虚拟机栈。虚拟机栈用于存储局部变量表等。局部变量表存放了编译期可知长度的各种基本数据类型(boolean、byte、char、short、int、float.
long、double)、对象引用(reference 类型,它不等同于对象本身,是对象在堆内存的首地址)。方法执行完,自 动释放。
方法区(Method Area) 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
④作用域
◆ 局部变量:从声明处开始,到所属的 } 结束
◆ 实例变量:在当前类中“this.”(有时this.可以缺省),在其他类中“对象名.”访问
◆ 类变量:在当前类中“类名.”(有时类名.可以省略),在其他类中“类名.”或“对象名.”访问
⑤生命周期
◆ 局部变量:每一个线程,每一次调用执行都是新的生命周期
◆ 实例变量:随着对象的创建而初始化,随着对象的被回收而消亡,每一个对象的实例变量是独立的
◆ 类变量:随着类的初始化而初始化,随着类的卸载而消亡,该类的所有对象的类变量是共享的
当局部变量与xx变量重名时,如何区分:
①局部变量与实例变量重名:在实例变量前面加“this.”
②局部变量与类变量重名:在类变量前面加“类名.”
【考点六】JVM垃圾回收机制
JVM垃圾回收机制,GC发生在JVM哪部分(堆),有几种GC(minor gc / full gc),它们的算法是什么
GC4大算法:
- 引用计数(循环引用问题不能解决)
- 复制算法(年轻代,需要双倍空间,没有内存碎片)
- 标记清除(老年代,先标记幸存者,再清除未标记的,两次扫描,有碎片)
- 标记压缩(老年代,先标记,后压缩,得到连续的内存区域,)
- 标记清除压缩(混合)