JAVA面试100道必考题

本文详细解析了Java面试中常见的100道题目,涵盖了Java语法、面向对象、JVM优化、集合框架、多线程、异常处理、类加载器、分布式、并发工具、数据库以及网络协议等多个方面,深入探讨了Java核心技术及其在实际开发中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.如下代码的执行结果: 4,1,11

 @Test
    void demo01(){
   
        int i=1;
        i=i++;
        int j=i++;// i=2  j=1
        int k=i+ ++i * i++;//2+3*3=11
        System.out.println("i="+i);//4
        System.out.println("j="+j);//1
        System.out.println("k="+k);//k=2+3*3=11
    }

=号右边为操作数栈,=号左边变量为局部变量表,
=号右边的从左到右加载值依次压入操作数栈中,实际运算哪个看运算符优先级
自增,自减操作都是直接修改变量的值,不经过操作数栈
最后的赋值之前,临时结果也是存储在操作数栈中.

2.什么是Singleton?
单例设计模式: 即某个类在整个系统中只能有一个实例对象,可被获取和使用的设计模式.

3.面向过程和面向对象的区别?什么是面向对象?
面向过程:是分析解决问题的步骤,然后用函数把这些步骤一一的实现,然后再使用的时候一一调用.
面向过程,更加注重事情的每一个步骤和顺序

面向对象:是把构成问题的事物分解成若干个对象,而建立对象的目的是为了描述整个事物在解决整个问题中所发生的行为,
面向对象更注重事情有哪些参与者(对象),及各自都需要作什么

可以看出: 面向过程直接高效, 而面向对象更易于扩展和维护.

面向对象: 封装,继承.,多态
封装: 封装对象的属性和细节,并对外提供统一的访问方式
在这里插入图片描述
继承: 继承基类的方法,并做出自己的改变或扩展

ORM 对象关系映射.实现数据模型与数据库的解耦;

子类共性的方法或者属性直接使用父类的,而不需要自己再定义,只需要自己扩展自己个性的

多态:方法重写,父类引用指向子类对象,无法调用子类特有的功能,调用的是父类的方法
如果调用子类方法,.那么调用的方法必须是子类重写的方法—看引用的类型
在这里插入图片描述

4.HashCode的作用?
作用为:获取哈希码,也叫散列码,实际上返回的是一个int整数,
这个哈希码的作用: 确定该对象在哈希表中的索引位置.

再向集合中添加元素时,先计算该元素的hashCode的值.就可以定位到该元素所在的物理位置. 如果这个位置上没有元素,则直接存储,如果该位置已经存放了元素,就调用它的equals()方法和新元素进行比较,相同的话就不存储,不相同的话,就散列到其他位置.
这样一来,实际调用equals()方法的次数就大大降低,

hashCode() 定义在JDK.Object.java中, java中的任何类都包含有hashCode()函数. 散列表存储的是键值对key-value,
特点是: 能够根据键快速的检索出对应的值.-----这其中就利用到了散列码----可以快速的找到所需要的对象

hashCode和equals的区别?
在这里插入图片描述
为什么要有hashCode?

hashCode的默认行为是堆上的对象产生的独特值,如果没有重写hashCode()方法,则该Class的两个对象一定不相同.即使两个对象有相同数据
在这里插入图片描述

5.JVM性能调优?
JVM调优目标:使用较小的内存占用来获得较高的吞吐量或者较低的延迟。
在这里插入图片描述
JVM虚拟机底层:
在这里插入图片描述
在target -classes 文件夹中,找到编译后的文件 ,右键 open in Terminal 打开终端
然后javap 命令,可以查看方法参数 -c 为 JVM的反汇编
javap -c Math.class >Math.txt 将Math.txt文件打到记事本文件下

FILO 栈 先进后出 ,方法嵌套调用,用完就销毁了,
程序计数器: 线程切换, 比如线程被抢占CPU时间片 ,线程被挂起,记录线程被挂起的位置

线程栈:compute()方法栈帧
局部变量表: 给局部变量分配内存空间.把数据放进去
操作数栈: 操作数在程序运行过程中,做操作的临时中转的运行空间
动态链接
方法出口: 传给main方法

栈里面有很多变量,其中一部分变量指向堆,指向对象在内存中的内存地址

方法区(元空间): 存放 常量+静态变量+类信息
方法区:在JDK1.8之前叫永久态,持久态, 在JDK1.8后叫元空间.使用的是操作系统的物理地址

本地方法栈 new Thread().start();
private native void start0();

注意: 线程栈,本地方法栈,程序计时器是线程私有的. 堆和方法区是所有线程共有的

如何判断对象是否可以被回收呢?
GC Roots的根结点; 线程栈的本地变量.静态变量,本地方法栈的变量等
在这里插入图片描述
若分代第15次还存活,则会分到老年代里面

年轻代满了.就会触发Minor GC(新生代GC),可能有1%少数进入Survivor幸存区,
默认的设置下,当对象的年龄达到15岁时,也就是躲过15次GC的时候,他就会转移到老年代里去
在这里插入图片描述
JVM调试工具
第一种: cmd---->jvisualvm
在这里插入图片描述
第二种: Arthas 阿里巴巴
网址: https://arthas.aliyun.com/doc/en/quick-start.html
java -jar arthas-boot.jar 输入数字 dashboard仪表盘

  1. JDK,JRE,JVM的区别?
    在这里插入图片描述
    JVM分代年龄里面为什么是15次进入老年代?
    JAVA对象存储在堆内存, MarkWord为对象头
    在这里插入图片描述
    其中对象的分代年龄占4位,也就是0000,最大值为1111也就是最大为15.而不可能为16或者17之类的。

  2. ==和equals比较?
    ==对比的是栈中的值,基本数据类型是变量值,引用类型是堆中内存对象的地址

equals; Object中默认也是采用==比较, String类中被重写了equals()方法,其实是比较两个字符串的内容

 /**
     * ==对于基本类型,
     */
    @Test
    public void test06(){
   
        Integer i6=128;
        Integer i7=128;
        int i8=128;
        System.out.println(i6==i7);//false
        System.out.println(i6==i8);//true 自动拆箱,数值
    }

String类重写了equals()方法.String类new的话,是在堆中new创建了一块内存区域,
String str1=“abc”;是在常量池中的一块区域.
字符串是不可变的对象,在字符串拼接时会新创建一块对象.

8.简述final的作用? 为什么局部内部类和匿名内部类只能访问局部final变量?
局部内部类和匿名内部类只能访问局部final变量

注意:
final修饰的是基本数据类型,这个值本身不能被修改.
修饰的是引用数据类型.引用的指向不能被修改.
在这里插入图片描述

  /***
     * final 修饰的是引用类型,引用的指向不能被改变
     */
    @Test
    public void test04(){
   
        final Person p1 = new Person("abc", 12);
        p1.setAge(15);
        System.out.println(p1);//Person{name='java', age=15, height=null}
        System.out.println(p1.getAge());//15
    }

因为匿名内部类线程可能还没有跑完.,当外部类结束后,内部类对象仍然有引用指向它,内部类访问一个不存在的变量.
就将局部变量复制了一份,作为内部类的成员变量,copy了一份,延长了局部变量的生命周期,
使用final修饰,保证了内部类的局部变量和外部类的成员变量一致性

!!!
内部类和外部类是同一级别的,内部类不会随着因为定义在方法中就会随着方法的执行完毕就被销毁
如果内部类修改成员变量,方法中的局部变量也会跟着改变,这实际上也是一种妥协
在这里插入图片描述

package test;

/**
 * @author guoxin
 * @date 2021/10/13
 */
public class Final {
   
  public static void main(String[] args) {
   
      new OutClass().outPrint(15);
  }

  public static void test(final int b) {
   
    // 局部final变量a和b
    final int a = 10;
    // 匿名内部类
    new Thread() {
   
      @Override
      public void run() {
   
        System.out.println(a);
        System.out.println(b);
      }
    }.start();
  }
}

/**
 * 内部类和外部类是同一级别,
 */
class OutClass {
   
  private int age = 12;

  public void outPrint(final int x) {
   
    class InClass {
   
      public void InPrint() {
   
        System.out.println(x);
        System.out.println(age);
      }
    }
    new InClass().InPrint();
  }
}

9.String,StringBuilder,StringBuffer的区别以及使用场景?
StringBuilder, StringBuffer继承了AbstractStringBuilder, 里面是一个可变的char类型的字符数组
String private final char value[]; 不可变对象
在这里插入图片描述
优先使用StringBuilder,单线程安全.

开发中你用StringBuilder解决什么问题?
多线程情况下,访问同一个资源的时候,

一个对象是线程安全的 ?
多线程环境下.对这个对象的访问,不需要额外的同步控制,操作的数据结果仍然正确 ///多线程使用共享变量StringBuffer

10.重载和重写的区别?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值