Java基础面试题

面试题

算数题

1
2
3
4
5
6
int i = 1;
i = i++;
int j = i++;
int k = i + ++i * i++;

i, j, k ?
结果
1
2
3
i = 4
j = 1
k = 11
  • 赋值运算=最后计算
  • =右边的从左到右加载值依次压入操作数栈
  • 实际先算哪个,看运算符优先级
  • 自增,自减操作都是直接修改变量的值,不经过操作数栈
  • 最后的赋值结果,临时结果也是存储在操作数栈中

Singleton

  • Java中指的是单例模式

    • 一个类只能有一个实例
    • 必须是自行创建实例
    • 对外提供获取的方法
  • 饿汉式实现,不存在线程安全问题

    • 直接实例化
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class Single1 {

    // 自行创建,对外提供实例
    public static final single1 INS = new Single1();

    // 私有化构造器
    private Single1(){}
    }

    // 获取
    Single1 s = Single1.INS;
    • 使用枚举
    1
    2
    3
    4
    5
    6
    public enum Single2 {
    INS
    }

    // 获取 枚举重写了toString方法
    Single2 s = Single2.INS;
    • 静态代码块
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public 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
    12
    public 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
    16
    public 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
    15
    public 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
2
2,1,5
1,1,5

声明的位置

  • 局部变量:在方法体{},形参,代码块{}
  • 成员变量:类中 方法外
    • 类变量: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 的操作基于事件和回调机制。

相关文章

Java框架面试题

JVM-虚拟机栈面试题

JUC-JVM面试题