java基础面试题

java后端面试题大全

  • 1.java基础
    • 1.1 java中==和equals的区别
    • 1.2 String、StringBuffer、StringBuilder的区别
    • 1.3 intern方法的作用及原理
    • 1.4 String不可变的含义
    • 1.5 static用法、使用位置、实例
    • 1.6 为什么静态方法不能调用非静态方法和变量
    • 1.7 异常/Exception
    • 1.7 try/catch/finally的return顺序
    • 1.8 字符流和字节流

1.java基础

1.1 java中==和equals的区别

  • 等等于(==)是运算符, 如果是基本数据类型, 则比较存储的值; 如果是引用数据类型, 则比较所指向对象的地址值 (是否同一个对象)
  • equals是Object的方法, 如果类未重写equals方法, 则相当于==, 一般情况下, 类会重写equals方法来比较两个对象的内容是否相等
public boolean equals(Object obj) {
    return (this == obj);
}

面试题:

一、下面的代码将创建几个字符串对象
String s1 = new String(“Hello”);
String s2 = new String(“Hello”);

答案: 3个

new这个关键词, 毫无以为会在堆中分配内存, 创建一个String类对象, 因此s1在栈中的引用指向堆中的这个String对象, 因为"Hello"是一个常量, 所以会去常量池中找有没有这个常量存在, 没有的话会在常量池中分配一个空间, 存储这个常量, 并将这个常量对象的空间地址给到堆中的String对象; 如果常量池中已经有了这个常量,就直接用那个常量池中的常量对象的引用呗,就只需要创建一个堆中的String对象。
java基础面试题_第1张图片
注意: JDK1.7之后, 方法区的常量池被移动到堆中

二、字面量+字面量
创建了一个对象

String s = "abc" + "def"

当+号两端都是编译期确定的字符串常量时, 编译器会进行相应的优化, 直接将两个字符串常量拼接好, 放到常量池中, 所以只会创建一个"abcdef"对象

二、字面量+对象
创建了三个对象

String s1="abc";
String s2 ="abc"+s1+"def";

s1="abc"一个
s2中:"abc"已经存在,不再创建,"def"一个,"abcdef"一个

三、new String(“xx”) + new String(“xx”)
创建4个String对象

String s = new String("abc") + new String("abc");

第一个new String(“abc”)创建了两个
第二个new String(“abc”)创建了一个(常量池中有"abc"不再创建)
new String(“abc”) + new String(“abc”)一个

ps: 两个字符串相加会在堆上创建1个String对象”abcabc”(因为没有显式使用双引号指定,也没有调用intern,所以常量池里边目前没有“abcabc”对象)

String s = new String("abc") + new String("def");

这种情况下, 则会创建5个对象

1.2 String、StringBuffer、StringBuilder的区别

String StringBuffer StringBuilder
可变性 不可变 可变 可变
线程安全性 线程安全 线程安全 线程不安全

一、可变性
String是不可变的对象(final修饰), 所以每次修改String类型变量, 实质上都等同于生成一个新的String对象, 然后将指针指向新的String对象

String对象的字符内容是存储在一个字符数组value[]中, 而这个value[]是被final修饰
java基础面试题_第2张图片
这样不仅效率低下, 而且大量浪费有限的内存空间,所以经常改变内容的字符串最好不要用 String. 因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢

StringBuffer、StringBuilder的父类AbstractStringBuilder的value数组不是final类型
java基础面试题_第3张图片

二、线程安全性

String的线程是安全的, 因为value数组是final
StringBuffer是线程安全的, 因为他的方法使用了synchronized(单线程时没必要使用, 因为加锁了, 速度慢)
java基础面试题_第4张图片
StringBuilder是线程不安全的(单线程时建议使用,因为没加锁,速度快)
java基础面试题_第5张图片

1.3 intern方法的作用及原理

在java中存在8种基本类型以及一种特殊的类型String, 这些类型为了使它们在运行过程中速度更快, 更节省内存, 都提供了一种常量池的概念(在方法区), 常量池相当于java系统提供的缓存

String类型的常量池比较特殊, 主要使用方式有两种

  1. 直接使用双引号声明出来的String对象会直接存储在常量池中
  2. 如果不是用双引号声明的String对象, 可以使用intern方法将其缓存到常量池

1.4 String不可变的含义

String不可变的含义: 将一个已有字符串"123"重新赋值为"456", 不是在原内存地址上修改数据, 而是重新指向一个新对象、新地址

也就是说, 不可变的含义是内部数据不可变, 而非引用不可变

String str= "123";
str = "456";
System.out.println(str);

java基础面试题_第6张图片

1.5 static用法、使用位置、实例

  1. 修饰成员属性(静态变量)
  2. 修饰成员方法(静态方法)
  3. 修饰代码块(静态代码块)
  4. 修饰内部类(静态内部类)
  5. 静态导包

1.6 为什么静态方法不能调用非静态方法和变量

与类的加载顺序有关, 加载静态方法时, 非静态的还未初始化

1.7 异常/Exception

java基础面试题_第7张图片
Throwable有两个直接子类

  • Error
    • JVM内部的严重问题, 比如资源不足等, 无法恢复
    • 处理方式: 程序员不用处理
  • Exception
    • JVM通过处理还可回到正常执行流程, 即可恢复
    • 分RuntimeException和其他Exception
      • RuntimeException(unchecked exception)
        处理或者不处理都可以(不需try…catch或在方法声明时throws)
      • 其他Exception(checked exception)
        java编译器要求程序必须捕获(try…catch) 或者声明抛出(throws)这种异常

为什么要对unchecked异常和checked异常进行区分?
编译器将检查你是否为所有的checked异常提供了异常处理机制, 比如使用Class.forName()来查找给定的字符串的class对象的时候, 如果没有为这个方法提供异常处理, 编译将无法通过
java基础面试题_第8张图片

1.7 try/catch/finally的return顺序

finally语句与return语句详解

1.8 字符流和字节流

字节流、字符流、缓冲流
字节流和字符流的使用非常相似

java基础面试题_第9张图片

你可能感兴趣的:(spring,java,后端)