Java岗笔试示例题
Java核心与并发编程选择题
关于 Java 中的 String 类,以下说法正确的是?
- A. String 是可变对象,修改字符串内容不会创建新对象
- B. String s = “abc” 和 String s = new String(“abc”) 在内存中创建的对象数量相同
- C. String 类被 final 修饰,不能被继承
- D. 推荐使用 String 拼接大量字符串,性能最好
答案:C
解析:
String 是不可变对象(A错);“abc” 会先在字符串常量池创建对象,而 new String(“abc”) 会在堆和常量池各创建一个(或复用常量池),对象数量不同(B错);拼接大量字符串应使用 StringBuilder 或 StringBuffer(D错)。
要掌握字符串的内存分配:主要涉及两个区域:字符串常量池和Java堆内存。使用new关键字JVM会强制在普通内存中创建一个新的String对象,所以new String(“abc”)是创建了两个对象
在多线程环境下,以下哪个关键字可以保证变量的可见性和禁止指令重排序?
- A static
- B volatile
- C transient
- D synchronized
答案:B
解析:volatile 关键字的核心作用是保证共享变量的可见性,并禁止 JVM 进行指令重排序,但不保证原子性。synchronized 虽然也能保证可见性,但它是通过锁机制实现的,而 volatile 是轻量级的。
使用synchronized保证线程同步
关于 HashMap 的底层数据结构,以下描述错误的是?
- A. JDK 1.7 中底层是数组 + 链表
- B. JDK 1.8 中底层是数组 + 链表 + 红黑树
- C. 当链表长度超过 8 时,链表一定会立即转换为红黑树
- D. HashMap 是非线程安全的
答案:C
解析:在 JDK 1.8 中,链表转红黑树需要同时满足两个条件:**链表长度大于等于 8 且 数组长度大于等于 64。**如果数组长度不足 64,会优先进行数组扩容,而不是转红黑树。
Spring框架与JVM选择题
在 Spring 框架中,@Transactional 注解默认的事务传播行为是?
- A. REQUIRED
- B. REQUIRES_NEW
- C. NESTED
- D. SUPPORTS
答案:A
解析:Spring 事务默认传播行为是 REQUIRED,即如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新事务。这是最常用也最符合大多数业务场景的传播机制。
了解Spring 事务,深入理解Spring事务,
了解数据库中事务,是数据库操作的基本单元,其四个特性ACID特性。
Spring 事务的核心是声明式事务管理,它通过 AOP(面向切面编程)实现,开发者无需手动编写事务控制代码(如begin、commit、rollback),只需通过注解或 XML 配置即可完成事务管理。
事务管理的两种方式:
- 编程式事务
- 声明式事务:通过@Transactional注解或 XML 配置声明事务规则,由 Spring 自动管理事务,代码简洁,是日常开发的首选方式。
spring事务的核心属性:
- 传播行为,默认为REQUIRED
- 隔离级别,基于数据库的隔离级别实现,默认为DEFAULT
以下哪种 GC 算法主要解决内存碎片问题?
- A. 复制算法
- B. 标记 - 清除算法
- C. 标记 - 整理算法
- D. 分代收集算法
答案:C
解析:标记 - 清除算法会产生大量不连续的内存碎片;复制算法主要用于新生代;而标记 - 整理算法在标记并清除死亡对象后,会将存活对象向一端移动,从而解决内存碎片问题,常用于老年代。
数据库与SQL专项题
在 SQL 中,若要查询某表中某列值为 NULL 的记录,以下写法正确的是?
- A. WHERE col = NULL
- B. WHERE col IS NULL
- C. WHERE col != NULL
- D. WHERE col NOT NULL
答案:B
解析:在 SQL 标准中,NULL 代表未知,不能使用等号(=)进行比较,必须使用 IS NULL 或 IS NOT NULL 来判断。
关于数据库事务的隔离级别,以下哪个级别可以解决“不可重复读”问题?
- A. Read Uncommitted(读未提交)
- B. Read Committed(读已提交)
- C. Repeatable Read(可重复读)
- D. Serializable(串行化)
答案:C
解析:Read Committed 解决了脏读但存在不可重复读;Repeatable Read 通过锁定读取的行或 MVCC 机制,保证了在同一事务中多次读取同一数据结果一致,解决了不可重复读问题(MySQL 默认隔离级别)。
以下 SQL 语句的执行结果是?
SELECT COUNT(*) FROM employees WHERE salary > 5000;
- A. 查询 salary 大于 5000 的记录数,包含 salary 为 NULL 的记录
- B. 查询 salary 大于 5000 的记录数,不包含 salary 为 NULL 的记录
- C. 查询所有记录数
- D. 语法错误
答案:B
解析:WHERE 条件 salary > 5000 会过滤掉不满足条件的行,而 NULL 值与任何数值比较(包括大于)结果都为 UNKNOWN(即 false),因此 NULL 值会被排除在结果集之外。
在 SQL 中,LEFT JOIN 和 RIGHT JOIN 的主要区别是?
- A. LEFT JOIN 返回左表所有记录,RIGHT JOIN 返回右表所有记录
- B. LEFT JOIN 返回右表所有记录,RIGHT JOIN 返回左表所有记录
- C. 两者返回的结果集总是相同的
- D. LEFT JOIN 只能用于内连接
答案:A
解析:LEFT JOIN(左连接)会返回左表的所有记录,即使右表中没有匹配的记录(右表对应字段为 NULL);RIGHT JOIN(右连接)则相反,返回右表的所有记录。
若要查询每个部门中薪资最高的员工信息,以下哪种 SQL 思路最合适?
A. 使用简单的 GROUP BY 部门分组
B. 使用子查询或窗口函数(如 ROW_NUMBER())
C. 使用 LEFT JOIN 连接两次员工表
D. 使用 UNION 合并所有员工记录
答案:B
解析:简单的 GROUP BY 只能对分组列或聚合函数(如 MAX(salary))进行查询,无法直接获取该员工的其他详细信息(如姓名)。通常需要使用子查询先找出各部门最高薪资,再关联员工表;或者使用窗口函数 ROW_NUMBER() PARTITION BY 部门 ORDER BY 薪资 DESC 来取排名第一的记录。
sql示例:假设一张员工表employees,查询示例
SELECTdepartment_id,employee_name,salaryFROM(SELECTdepartment_id,employee_name,salary,-- 按部门分组,并按薪资降序进行排名ROW_NUMBER()OVER(PARTITIONBYdepartment_idORDERBYsalaryDESC)ASrnFROMemployees)ASranked_employeesWHERErn=1;SQL题考察
考察基础查询、多表关联、分组聚合以及窗口函数等核心能力
基础查询与条件筛选
题目 1:有一张员工表 employees(字段:id, name, salary, dept_id, hire_date)。请查询薪资大于 8000 且入职时间在 2023 年之后的员工姓名和薪资,按薪资从高到低排序。
SELECTname,salaryFROMemployeesWHEREsalary>8000ANDhire_date>'2023-12-31'ORDERBYsalaryDESC;考查 WHERE 多条件筛选(AND)、日期比较以及 ORDER BY 降序排列。
题目2:查询员工表中名字以“张”开头,且薪资在5000到10000之间的员工信息。
SELECT*FROMemployeesWHEREnameLIKE'张%'ANDsalaryBETWEEN5000AND10000;考点解析:考查模糊查询 LIKE 的通配符用法,以及 BETWEEN…AND 的范围筛选。
多表关联查询
题目 3:有一张部门表 departments(字段:dept_id, dept_name)。请查询所有员工的姓名、所属部门名称,包含那些暂时没有分配部门的员工(部门名称显示为 NULL)。
SELECTe.name,d.dept_nameFROMemployees eLEFTJOINdepartments dONe.dept_id=d.dept_id;考点解析:考查 LEFT JOIN 的使用场景,即保留左表(员工表)所有记录,右表无匹配时显示 NULL。
题目 4:查询“技术部”所有员工的姓名和薪资
SELECTe.name,e.salaryFROMemployees eINNERJOINdepartments dONe.dept_id=d.dept_idWHEREd.dept_id='技术部';考点解析:考查 INNER JOIN 内连接,只返回两表中关联字段匹配成功的记录。
分组与聚合统计
题目 5:查询每个部门的平均薪资,并筛选出平均薪资大于 7000 的部门。
直接使用聚合函数求平均,按照GROUP BY分组,并使用HAVING子句对聚合结果筛选
SELECTdept_id,AGV(salary)ASavg_salaryFROMemployeesGROUPBYdept_idHAVINGAVG(salary)>7000;考点解析:考查 GROUP BY 分组以及 HAVING 子句对聚合结果进行筛选(注意:不能用 WHERE 筛选聚合函数结果)。
题目 6:统计每个部门的人数,并按人数从多到少排序。
SELECTdept_id,COUNT(*)ASemp_countFROMemployeesGROUPBYdept_idORDERBYemp_countDESC;考点解析:考查聚合函数 COUNT(*) 的使用以及分组后的排序。
进阶窗口函数与子查询
题目 7:查询每个部门薪资排名前三的员工姓名、部门ID和薪资。(假设薪资不重复,若重复可考虑使用 DENSE_RANK())
显然需要使用子查询,然后获取前三排名
SELECTname,dept_id,salaryFROM(SELECTname,dept_id,salary,ROW_NUMBER()OVER(PARTITIONBYdept_idORDERBYsalaryDESC)ASrankFROMemployees)tWHEREt.rank<=3;考点解析:考查窗口函数 ROW_NUMBER() 或 RANK(),配合 PARTITION BY 进行分组排名,这是银行科技岗笔试中区分度较高的考点。
题目 8:查询薪资高于公司所有员工平均薪资的员工姓名和薪资。
参考 SQL:
SELECTname,salaryFROMemployeesWHEREsalary>(SELECTAVG(salary)FROMemployees);考点解析:考查子查询的使用,先通过子查询计算出全局平均值,再在外层进行筛选。