深圳店小秘Java后端面试

本文详述了一次深圳店小秘Java后端面试的笔试环节,涵盖JVM、异常处理、线程、字符串、数据库事务、Linux命令等多个核心知识点。面试者分享了Java中JDK、JVM、JRE、JIT的区别,session与cookie的联系,Error与Exception的差异,以及垃圾回收机制等,并解析了代码示例,如String与StringBuffer的区别,数据库查询,线程实现方式等。

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

深圳店小秘Java后端面试

1.笔试

1.JDKJVMJREJIT是什么?
  • JDKJava Development Kit。是Java开发工具包,提供Java编程语言内库。
  • JVMJava Virtual Machine。是Java虚拟机,将.java文件加载为.class文件,并使Java程序运行。
  • JREJava Runtime Environment。是Java运行时环境。
  • JITJust In Time CompliactionJava即时编译器,将Java对应的字节码文件转换为机器码文件。
2.session是什么,sessioncookie的关联是什么?
  • cookie可以存储在本地或者浏览器,session只能存储在服务端。
  • cookie只能存储String字符串,session可以存储任意Java对象。
  • cookie没有session安全,因为前者在客户端,后者在服务端。
  • cookie存在于客户端,不会占用服务器性能,session存在于服务端,session过多会给服务器造成压力。
  • cookie最大不能超过4k,浏览器会限制一个网站的cookie存储数量,一般为20个。session没有大小限制只与服务器内存相关。
3.ErroException的区别是什么?

ErrorException都是Throwable的子类, 在Java中只有Throwable类型的实例才可以被抛出或者捕获,它是异常处理机制的基本类型。

ErroeException体现了Java平台设计者针对不同异常情况的分类,Exception是程序正常运行中,可以预料到的意外情况,可以被捕获并进行相应的处理。

Error是指正常情况下,不大可能出现的情况,绝大部分的Error会导致程序处于非正常的,不可恢复的状态,不需要捕获,因为就算你捕获到了也没任何意义。常见的OutOfMemoryErrorError的子类.

Exception分为可检查异常checked和不可检查异常unchecked。可检查异常在源代码里必须显式的进行捕获处理,这是编译期检查的一部分,不可检查异常是指运行时异常,比如NullPointerExceptionArrayIndexOutOfBoundsException之类,通常是可以编码避免的逻辑错误,具体根据需要来判断是否需要捕获,并不会在编译期强制要求。

其实不需要回答这么多。我的回答就是:Error会导致程序处于非正常,不可恢复的状态。

4.什么是GC?为什么有GC?调用GC的方法有哪几种?

GCGarbage Collection,字面意思是垃圾回收。

Java中每创建一个对象就会在JVM中的堆内存中为对象开辟一段内存空间用于存储该对象。由于Java中大多对象的存活期都很短,而JVM的堆内存并不是无限大的,堆内存的大小是有限的。所以当堆内存被使用完时,而又有创建新生对象的需求,此时堆内存中可用空间不足以为新生对象分配内存,此时就需要对堆内存进行垃圾回收也就是GC,将系统中不再使用的Java对象当作垃圾回收掉,释放占用的堆内存空间为后续新生对象使用。JVM采用分代收集策略进行垃圾回收,对于新生代有MinorGC,对于老年代有Major GC,对于整堆有Full GC

System.gc();

Runtime.getRuntime.gc();

java.lang.management.MemeoryMXBean.gc();

熟悉JVM堆相关的,这一块基本没难度,用自己的话概括一下就行,面试官也不会仔细看,因为看还不如直接问你问题来的直接。

5.StringStringBuffer的区别是什么?
  • String:被final修饰,不可变字符串。
  • StringBuffer:可变字符串,线程安全,效率低于StringBuilder
6.String s = new String("xyz")创建了几个String Object
  • 当在JVM堆中的字符串常量池中存在xyz时,只会在对上创建一个s字符串对象。此时创建一个String Object
  • 当在JVM堆中的字符串常量池中不存在xyz时,会在堆上的字符串常量池中创建一个xyz字符串对象,然后在堆中创建一个s字符串对象,并将s字符串对象中的值引用指向字符串常量池中的zyx字符串对象。此时创建两个String Object
7.Math.round(11.5)Math.round(-11.5)的结果
// 坐标轴向下取整
Math.round(11.5) = 12;
Math.round(-11.5) = -11;
8.finalfinallyfinalize分别有什么意义?

final:可修饰字段、方法、类。修饰字段表示该字段不可变,修饰方法表示该方法不能被重写覆盖,修饰类表示该类不可继承。

finally:配置try...catch...finally使用的代码块。

finalize:在对象被回收之前,显式调用用于释放一些资源。对于每个即将回收的对象,JVM都会调用一次finalize方法。

9.Abstract Classinterface的区别
  • 抽象类可以提供成员方法的具体实现,而接口中只能定义方法签名不能定义方法体。
  • 抽象类中的成员变量可以为任意类型的变量,而接口中的变量只能为public static final常量。
  • 抽象类中可以存在静态代码块和静态方法,而接口中不能。
  • 一个类只能继承一个抽象类,但是却可以实现多个接口。
10.Java实现线程的方式有哪几种?
  • 继承Thread类,重写run()方法。
  • 实现Runnable接口,重写run()方法。
  • 实现Callable接口,重写call()方法。
  • 使用Executors类提供的静态方法。
11.以下代码输出结果是什么?
public class A {

    static {
        System.out.println("Hello Word!");
    }

    public static void main(String[] args) {
        A a = new A();
        a = new A();
    }
    
}

输出Hello Word!

非常简单,因为一个类的静态代码块只会在类加载时器的Linking链接中的parpare准备阶段中执行一次,可以理解为静态先行。

12.以下代码输出结果是什么?
public class IntegerTest {

    public static void main(String[] args) {
        Integer a = new Integer(155);
        Integer b = new Integer(155);
        if (a == b) {
            System.out.println(true);
            System.out.println(true);
        }
    }

}

无任何输出。

这个原因其实也很简单,因为Java中大多数的基本数据类型都开启了享元模式,Integer类中有一个IntegerCache静态内部类,IntegerCache类会在类中维护一个cache数组,用于存Java默认创建的-128 ~ 127对象。在[-128, 127]范围内的整型变量,Integer类会默认从IntegerCache.cache[]中根据数组下标获取,而不会去堆中创建一个新的Integer对象。当超出[-128, 127]这个范围的整型,Integer才会在堆中new一个对象。

Java8种基本数据类型的包装类除了FloatDouble没有实现常量池,其余的类型都实现了。

13.什么是数据库事务?

​ 事务是数据库中最小的执行单元。作为单个逻辑单元执行的一系列操作的集合,它不可分隔,这些操作会一起像数据库操作系统提交,要么都执行,要么都不执行。

14.什么是索引?索引的缺点是什么?有哪些索引?你用过哪些索引?

索引是一种特殊的数据存储结构,能够加快数据检索的速度。

缺点是索引需要维护,维护索引需要额外的时间与性能开销。同时也会占用物理内存。

主键索引、辅助索引、唯一索引、覆盖索引。

使用过主键索引、联合索引、唯一索引(不推荐使用,在写数据时不能使用change buffer)、覆盖索引、索引下推。

15.现在有一个表A(name, email),查询出表A中的name以及name重复的次数,按照重复次数从大到小取前10条
SELECT
    a.name,
    COUNT(a.name) num
FROM
    a a
GROUP BY
    a.name
ORDER BY
    COUNT(a.name) DESC
LIMIT 10;


--
SELECT
    t.name,
    t.num
FROM
    (SELECT
         a.name,
         COUNT(a.name) num
     FROM
         a a
     GROUP BY
         a.name) t
ORDER BY
    t.num DESC
LIMIT 10;
16.写出你熟悉的key/value数据库

redis

实话实说,我就只用过rediskey/value数据库。不要给自己挖坑,会什么写什么。

17.常用Linux命令
rm -rf  删除
touch ${filename}  创建文件

vim ${filename}  查看文件
i  进入插入模式
ESC  退出
:wq  保存退出
:q!  不保存退出
:q   不保存退出

cat ${filename}  查看文件的最后一页
more ${filename}  从第一页开始查看文件内容, 按回车键一行一行进行查看, 按空格键一页一页进行查看, q退出
less ${filename}  从第一页开始查看文件内容, 按回车键一行一行的看, 按空格键一页一页的看, 支持使用PageDown和PageUp翻页, q退出

tail -f ${filename}  查看文件的后10行
head -f ${filename}  查看文件的前10行

tail -n 7 ${filename}  查看文件的后7行
head -n 7 ${filename}  查看文件的前7行

sed -i '1d' ${filename}  删除文件第一行
sed -i '2d' ${filename}  删除文件第二行

grep ${keyword} ${filename}  在文件中搜索keyword字符串,大小写敏感,显示行
grep -n ${keyword} ${filename} 		在文件中搜索keyword字符串,大小写敏感,显示行及行号
grep -v ${keyword} ${filename} 		在文件中搜索keyword字符串,大小写敏感,显示没搜索到的行
grep -i ${keyword} ${filename} 		在文件中搜索keyword字符串,大小写敏感,显示行
grep -ni ${keyword} ${filename} 		在文件中搜索keyword字符串,大小写敏感,显示行及行号

head -n 10000 ${filename} > ${filename1}  复制filename文件的前10000行到filename2
18.如何在vi中删除某一行
dd   删除当前行
ndd  删除n行数据
dG   删除当前行之后的全部行
19.编写一个冒泡排序或者二分排序
    public static int[] doBubbleSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return arr;
        }

        int n = arr.length;
        for (int i = 0; i < n - 1; i++) {
            for (int j = 0; j < n - i - 1; j++) {
                if (arr[j] > arr[j + 1]) {
                    swap(arr, j, j + 1);
                }
            }
        }
        return arr;
    }

    private static void swap(int[] arr, int i, int j) {
        arr[i] = arr[i] ^ arr[j];
        arr[j] = arr[i] ^ arr[j];
        arr[i] = arr[i] ^ arr[j];
    }

这里可以使用无进制位相加骚一下。但是使用异或的前提是需要保证两个变量在堆内存中的地址不能为同一个,使用是有前提的,不要骚过头了!!!

20.写出一个单例
public class DCLSingleton {
    
    private DCLSingleton() {}
    
    private static volatile DCLSingleton instance = null;
    
    public static DCLSingleton getInstance() {
        if(instance == null) {
            synchronized (DCLSingleton.class){
                if(instance == null) {
                    instance = new DCLSingleton();
                }
            }
        }
        return instance;
    }
    
}

还可以用静态内部类。记得私有化构造器,细节。

21.写出最有效率遍历Map集合的方法
        Map<String, Object> map = new HashMap<>(1 << 4);

        map.forEach((key, value) -> {
            System.out.println("key is : " + key + " value is : " + value)
        });

forEach()底层使用的是entrySet进行遍历,所以这就是最有效率最优雅的遍历方式。ps个人认为。

​ 笔试没难度,就是要花时间写。用电脑用久了,突然一下需要写这么多还是有点不习惯,特别是有些字还忘记了怎么写!!!

​ 笔者笔试后就是HR面,然后就是部门组长技术面,技术负责人技术面,HR面。下午两点去的,最后弄完都快六点,说了一下午都没给杯水喝,喉咙都快说破了。面试之前记得自己买瓶水!!!

鉴于本人技术有限,文中难免出现一些错误,感谢大家批评指正。

作为一个三年的Java后端开发工程师,准备面试时可以从以下几个方面进行准备: 1. 复习基础知识:回顾Java核心概念、语法和常用的类库,例如集合框架、IO操作等。确保你对面试常见的Java问题有清晰的理解。 2. 数据结构和算法:熟悉常见的数据结构和算法,并能够解决一些常见的算法问题。例如,链表、树、排序算法等。 3. 多线程和并发:掌握Java多线程编程的基本概念和常用的并发工具,如synchronized关键字、Lock、线程池等。了解并发编程的常见问题和解决方案。 4. 数据库和SQL:熟悉数据库基本操作和SQL语句的编写。回顾数据库的基本原理、事务和索引等概念。 5. Web开发:了解常用的Web开发框架,如Spring、SpringMVC和MyBatis。熟悉HTTP协议和RESTful风格的接口设计。 6. 设计模式:了解常见的设计模式,并能够将其应用于实际开发中。例如单例模式、工厂模式、代理模式等。 7. 项目经验准备:准备一些自己在项目中遇到的难点和解决方案,以及在项目中承担的核心角色和贡献。 8. 面试准备:预先查找一些面试常见的问题,并准备好自己的回答。可以通过搜索相关的面试指南和面试题库来进行准备。 此外,还需要注意以下几点: - 注意简历和个人介绍的准备,突出自己的项目经验和技术能力。 - 针对深圳地区的特点,了解当地的一些互联网公司和行业趋势。 - 提前了解面试流程和要求,准备好可能需要的材料,如证件复印件、项目展示等。 最重要的是保持自信和积极的态度,在面试中展示出你的技术能力和解决问题的能力。祝你面试顺利!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值