Java基础面试题
面试题
算数题
1 |
|
结果
1 |
|
- 赋值运算=最后计算
- =右边的从左到右加载值依次压入操作数栈
- 实际先算哪个,看运算符优先级
- 自增,自减操作都是直接修改变量的值,不经过操作数栈
- 最后的赋值结果,临时结果也是存储在操作数栈中
Singleton
Java中指的是单例模式
- 一个类只能有一个实例
- 必须是自行创建实例
- 对外提供获取的方法
饿汉式实现,不存在线程安全问题
- 直接实例化
1
2
3
4
5
6
7
8
9
10
11public class Single1 {
// 自行创建,对外提供实例
public static final single1 INS = new Single1();
// 私有化构造器
private Single1(){}
}
// 获取
Single1 s = Single1.INS;- 使用枚举
1
2
3
4
5
6public enum Single2 {
INS
}
// 获取 枚举重写了toString方法
Single2 s = Single2.INS;- 静态代码块
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public class Single3 {
public static final Single3 INS;
// 使用静态代码块创建
static {
INS = new Single3()
}
// 私有化构造器
private Single3(){}
}
// 获取
Single3 s = Single3.INS;懒汉式实现
- 单线程使用
1
2
3
4
5
6
7
8
9
10
11
12public class Single4 {
private static Single4 ins;
// 私有化构造器
private Single4(){}
public static Single4 getIns(){
if(ins == null){
ins = new Single4();
}
return ins;
}
}- 多线程使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public class Single5 {
private static Single5 ins;
// 私有化构造器
private Single5(){}
public static Single5 getIns(){
if(ins == null){
synchronized(Single5.class){
if(ins == null){
ins = new Single5();
}
}
}
return ins;
}
}- 内部类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public class Single6 {
// 私有化构造器
private Single6(){}
// 在内部类被加载的时候才会去创建对象
// 静态内部类不会自动随着类的加载而初始化,它是单独加载的
// 线程安全
private static class Inner {
private static final Single5 INS = new Single6();
}
public static Single6 getIns(){
return Inner.INS;
}
}
类方法初始化题目
类的初始化过程
main方法所在的类需要先加载和初始化
子类要初始化需要先初始化父类
类的初始化就是执行<clinit>()方法
- clinit方法由静态类变量显示赋值代码和静态代码块组成
- 类变量显示赋值代码和静态代码块代码从上到下顺序执行
- clinit方法只执行一次
实例初始化过程
实例初始化就是执行<init>()方法
- init方法可能重载多个,有几个构造器就重载几个
- init方法由非静态实例变量显示赋值代码和非静态代码块和对应构造器组成
- 非静态实例变量显示赋值代码和非静态代码块从上到下执行,对应的构造器最后执行
- 每次创建实例对象,调用对应构造器,执行对应的init方法
- init方法的首行是**super()获取super(实参列表)**,就是对应父类的init方法
方法的重写
不能被重写的方法
- final方法
- 静态方法
- private等子类不可见的方法
对象的多态
- 子类如果重写了父类的方法,通过子类对象调用的一定是子类重写的方法
- 非静态方法默认的调用对象是this
- this对象在构造器或者init方法中就是正在创建的对象
方法的参数传递
形参是基本数据类型,传递的是值
实参是引用数据类型,传递的是地址值,String和包装类等对象具有不可变性
递归与迭代
递归
- 优点:大问题转换为小问题,可以减少代码量,同时代码精简,可读性好
- 缺点:浪费空间,递归太深容易造成堆栈溢出
迭代
- 优点:代码运行效率好,没有额外的空间开销
- 缺点:代码不如递归简洁,可读性不好
局部变量和成员变量区别
结果
1 |
|
声明的位置
- 局部变量:在方法体{},形参,代码块{}
- 成员变量:类中 方法外
- 类变量:有static修饰
- 实例变量:没有static修饰
修饰符
- 局部变量:final
- 成员变量:public,protected,private,final,static,volatile,transient
值存储位置
- 局部变量存储在栈中
- 实例变量存储在堆中
- 类变量存储在方法区中
作用域
- 局部变量:从声明处开始,到所属的}结束
- 实例变量:在当前类中使用this.,在其他类中使用对象.名访问
- 类变量:在当前类中**类名.,在其他类中类名.或者对象名.**访问
生命周期
- 局部变量:每一个线程,每一次调用执行都是新的生命周期
- 实例变量:随着对象的创建而初始化,随着对象的被回收消亡,每个对象的实例变量都是独立的
- 类变量:随着类的初始化而初始化,随着类的卸载消亡,该类的所有对象的类变量是共享的
BIO,NIO,AIO区别
BIO:Block IO 同步阻塞式IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。
NIO:New IO 同步非阻塞IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。
AIO:Asynchronous IO是NIO的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。