Java核心知识点解析与常见问题总结
1. 局部变量必须显式初始化
在Java中,局部变量在参与运算前必须被赋值,否则编译器会报错。例如以下代码无法通过编译:
public static void main(String[] args) {
int x = 1;
int y; // 未初始化
int z = x + y; // 编译错误:可能尚未初始化变量 y
}
这是因为局部变量不会自动赋予默认值,开发者需手动初始化。
2. ArrayList 与 Vector 的主要区别
两者均基于动态数组实现,但关键差异在于线程安全性:
- Vector 是线程安全的,其方法内部使用 synchronized 关键字同步,适合多线程环境,但性能较低。
- ArrayList 非线程安全,操作更高效,在单线程场景下推荐使用。
因此正确选项是:A — Vector 支持线程同步。
3. 类初始化顺序分析
执行如下继承结构的类时:
class A {
static { System.out.println("class A static"); }
{ System.out.println("I'm A class"); }
public A() { System.out.println("class A"); }
}
public class B extends A {
static { System.out.println("class B static"); }
{ System.out.println("I'm B class"); }
public B() { System.out.println("class B"); }
public static void main(String[] args) {
new B();
}
}
输出结果为:
class A static class B static I'm A class class A I'm B class class B
初始化顺序规则如下:
- 父类静态代码块
- 子类静态代码块
- 父类实例代码块
- 父类构造函数
- 子类实例代码块
- 子类构造函数
4. 加载 JDBC 驱动的正确方式
JDBC驱动可通过以下方式加载:
Class.forName("driver.class.name"):触发驱动类加载并注册到 DriverManagerDriverManager.registerDriver():直接注册驱动实例- 设置系统属性
jdbc.drivers
而 DriverManager.getConnection() 是在驱动已加载后用于建立连接的方法,并不负责加载驱动本身。故不是驱动加载方式的是:A。
5. Servlet 与 CGI 的对比
- Servlet 运行于服务器进程内,采用多线程处理请求,每个请求由独立线程执行 service 方法,资源利用率高。
- CGI 每次请求都会创建新进程,处理完即销毁,开销大、效率低。
虽然 CGI 具有较好的跨平台性,但由于现代 Web 容器普遍支持 Servlet,且其性能和功能优势明显,因此说"CGI 移植性高于 Servlet"并不准确。错误说法为:D。
6. 实现 Collection 接口的类
Collection 接口的主要子接口包括 List 和 Set,常见实现类有:
- ArrayList:实现了 List 接口,属于 Collection 体系
- Vector:同样是 List 的实现类
而 HashMap 实现的是 Map 接口,与 Collection 无直接继承关系;Iterator 是迭代器接口,不属于集合类。正确答案为:B、C。
7. 接口与抽象类特性(JDK 8 前)
- 接口没有构造方法(不能实例化),B 正确
- 抽象类可以有构造函数,用于子类调用,A 错误
- Java 不支持多继承,抽象类也不能多重继承,C 正确
- JDK 8 前接口中的方法均为抽象,不能有方法体,D 错误
正确选项为:B、C。
8. Object 类中不存在的方法
Object 类定义了所有对象共有的基本方法,如:
clone():复制对象finalize():垃圾回收前调用(已废弃)toString():返回字符串表示
而 hasNext() 是 Iterator 接口的方法,用于判断是否还有下一个元素,不属于 Object 类。正确答案:D。
9. 包访问权限控制
若要使一个类仅能被同一包内的其他类访问,应使用默认(包级)访问修饰符,即不加任何关键字:
- 无修饰符:包内可见
private:仅本类可见protected:包内 + 子类可见void:非法修饰符(是返回类型)
正确做法是:A — 不使用任何关键字。
10. Java 线程锁定机制
- Java 中每个对象都有一把内置锁(monitor lock)
synchronized可用来获取对象的互斥锁,保证线程安全- 线程调度策略依赖 JVM 和操作系统,不同平台行为可能不同,故具有平台相关性
正确选项为:C、D。
11. 自增自减运算符的计算
分析如下代码:
int a = 10;
System.out.println(a++ + a--);
运算过程分解:
- 先计算
a++:表达式取当前值 10,之后 a 变为 11 - 再计算
a--:此时 a 为 11,表达式取值 11,之后 a 减为 10 - 总和为 10 + 11 = 21
最终输出:21,正确答案为 C。
12. HttpServletResponse 不具备的功能
HttpServletResponse 主要职责包括:
- 设置响应头(setHeader)
- 添加 Cookie
- 获取输出流(getOutputStream / getWriter)发送数据
而路径信息(如请求 URI、上下文路径等)来源于客户端请求,应由 HttpServletRequest 获取。读取路径信息不属于 HttpServletResponse 功能。正确答案:C。
13. 多线程实现方式
Java 中创建线程的两种标准方式:
- 继承
Thread类,重写 run() 方法 - 实现
Runnable接口,将其实例传入 Thread 构造函数
不存在"实现 Thread 接口"的说法(Thread 是类)。正确答案:A、B。
14. String 引用与不可变性
看下面代码:
String lx = "LeXin";
String nb = lx;
lx = "Fenqile";
System.out.println(nb);
尽管 lx 被重新赋值为 "Fenqile",但 nb 仍指向原字符串 "LeXin"。因为 String 是不可变对象,变量只是引用。修改引用不影响其他指向同一对象的变量。
程序正常运行,输出为 "LeXin"。正确选项:B、C。
15. CMS 垃圾收集器的暂停阶段
CMS(Concurrent Mark-Sweep)以最小停顿时间为目标,分为四阶段:
- 初始标记:短暂暂停,标记 GC Roots 直接可达对象
- 并发标记:与用户线程并发运行
- 重新标记:再次暂停,修正并发期间的变化
- 并发清理:与用户线程并发进行
其中只有初始标记和重新标记需要暂停用户线程。答案为:A、C。
16. 接口中方法的实现要求
接口中方法默认为 public abstract,实现类重写时访问级别不能低于原方法。因此:
void drink()或protected drink()访问级别低于 public,非法- 必须使用
public void drink()
正确选项:C。
17. request 参数编码来源
getParameter() 获取的参数编码受多种因素影响:
- HTML 页面中指定的字符集(如 meta 标签)
- 浏览器提交请求时采用的编码
- Web 容器(如 Tomcat)的解码配置(如 URIEncoding)
- GET 与 POST 请求处理方式不同(POST 可设置 request.setCharacterEncoding)
因此编码由客户端和服务器共同决定。正确答案:C。
18. 获取 Request 作用域对象的方法
Request 作用域用于在请求转发过程中共享数据:
request.setAttribute(String, Object):存入对象request.getAttribute(String):取出对象
而 getParameter() 用于获取客户端传递的表单或URL参数,与作用域无关。返回 request 范围内对象的方法是:request.getAttribute(),答案为 B。