500+ 精选 Java 面试题大放送
Posted CSDN
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了500+ 精选 Java 面试题大放送相关的知识,希望对你有一定的参考价值。
Java程序是怎么执行的?
先把 Java 代码编译成字节码,也就是把 .java 类型的文件编译成 .class 类型的文件。这个过程的大致执行流程:Java 源代码 -> 词法分析器 -> 语法分析器 -> 语义分析器 -> 字符码生成器 -> 最终生成字节码,其中任何一个节点执行失败就会造成编译失败;
把 class 文件放置到 Java 虚拟机,这个虚拟机通常指的是 Oracle 官方自带的 Hotspot JVM;
Java 虚拟机使用类加载器(Class Loader)装载 class 文件;
类加载完成之后,会进行字节码效验,字节码效验通过之后 JVM 解释器会把字节码翻译成机器码交由操作系统执行。但不是所有代码都是解释执行的,JVM 对此做了优化,比如,以 Hotspot 虚拟机来说,它本身提供了 JIT(Just In Time)也就是我们通常所说的动态编译器,它能够在运行时将热点代码编译为机器码,这个时候字节码就变成了编译执行。
Java 程序执行流程图如下:
Java 虚拟机是如何判定热点代码的?
基于采样的热点判定:主要是虚拟机会周期性的检查各个线程的栈顶,若某个或某些方法经常出现在栈顶,那这个方法就是“热点方法”。这种判定方式的优点是实现简单;缺点是很难精确一个方法的热度,容易受到线程阻塞或外界因素的影响。
基于计数器的热点判定:主要就是虚拟机给每一个方法甚至代码块建立了一个计数器,统计方法的执行次数,超过一定的阀值则标记为此方法为热点方法。
Hotspot 虚拟机使用的基于计数器的热点探测方法。它使用了两类计数器:方法调用计数器和回边计数器,当到达一定的阀值是就会触发 JIT 编译。
方法调用计数器:在 client 模式下的阀值是 1500 次,Server 是 10000 次,可以通过虚拟机参数:-XX:CompileThreshold=N 对其进行设置。但是JVM还存在热度衰减,时间段内调用方法的次数较少,计数器就减小。回边计数器:主要统计的是方法中循环体代码执行的次数。
以下 Integer 代码输出的结果是?
Integer age = 10;
Integer age2 = 10;
Integer age3 = 133;
Integer age4 = 133;
System.out.println((age == age2) + ","+ (age3 == age4));
以下 StringBuffer 传值修改后的执行结果是什么?
publicstaticvoid main(String[] args) {
StringBuffer sf = newStringBuffer("hi");
changeStr(sf);
System.out.println(sf);
}
publicstaticvoid changeStr(StringBuffer sf){
sf.append("laowang");
}
hilaowang
题目解析:String 为不可变类型,在方法内对 String 修改的时候,相当修改传递过来的是一个 String 副本,所以 String 本身的值是不会被修改的,而 StringBuffer 为可变类型,传递过来的参数相当于对象本身,所以打印的结果就为
hilaowang
。
以下数组比较的结果分别是什么?
String[] strArr = {"dog", "cat", "pig", "bird"};
String[] strArr2 = {"dog", "cat", "pig", "bird"};
System.out.println(Arrays.equals(strArr, strArr2));
System.out.println(strArr.equals(strArr2));
System.out.println(strArr == strArr2);
答:true
、 false
、 false
。题目解析:strArr == strArr2 为引用比较,因此结果一定是 false,而数组本身的比较也就是 strArr.equals(strArr2) 为 false 的原因是因为数组没有重写 equals 方法,因此也是引用比较。数组 equals 源码实现如下:
publicboolean equals(Object obj) {
return(this== obj);
}
publicstaticboolean equals(Object[] a, Object[] a2) {
if(a==a2)
returntrue;
if(a==null|| a2==null)
returnfalse;
int length = a.length;
if(a2.length != length)
returnfalse;
for(int i=0; i<length; i++) {
Object o1 = a[i];
Object o2 = a2[i];
if(!(o1==null? o2==null: o1.equals(o2)))
returnfalse;
}
returntrue;
}
常用的序列化方式都有哪些?
答:常用的序列化方式有以下三种:1) Java 原生序列化方式请参考以下代码:
// 序列化和反序列化
classSerializableTest{
publicstaticvoid main(String[] args) throwsIOException, ClassNotFoundException{
// 对象赋值
User user = newUser();
user.setName("老王");
user.setAge(30);
System.out.println(user);
// 创建输出流(序列化内容到磁盘)
ObjectOutputStream oos = newObjectOutputStream(newFileOutputStream("test.out"));
// 序列化对象
oos.writeObject(user);
oos.flush();
oos.close();
// 创建输入流(从磁盘反序列化)
ObjectInputStream ois = newObjectInputStream(newFileInputStream("test.out"));
// 反序列化
User user2 = (User) ois.readObject();
ois.close();
System.out.println(user2);
}
}
classUserimplementsSerializable{
privatestaticfinallong serialVersionUID = 5132320539584511249L;
privateString name;
privateint age;
@Override
publicString toString() {
return"{name:"+ name + ",age:"+ age + "}";
}
publicString getName() {
return name;
}
publicvoid setName(String name) {
this.name = name;
}
publicint getAge() {
return age;
}
publicvoid setAge(int age) {
this.age = age;
}
}
2) JSON 格式,可使用 fastjson 或 GSONJSON 是一种轻量级的数据格式,JSON 序列化的优点是可读性比较高,方便调试。我们本篇以 fastjson 的序列化为例,请参考以下代码:
// 序列化和反序列化
classSerializableTest{
publicstaticvoid main(String[] args) throwsIOException, ClassNotFoundException{
// 对象赋值
User user = newUser();
user.setName("老王");
user.setAge(30);
System.out.println(user);
String jsonSerialize = JSON.toJSONString(user);
User user3 = (User) JSON.parseObject(jsonSerialize, User.class);
System.out.println(user3);
}
}
classUserimplementsSerializable{
privatestaticfinallong serialVersionUID = 5132320539584511249L;
privateString name;
privateint age;
@Override
publicString toString() {
return"{name:"+ name + ",age:"+ age + "}";
}
publicString getName() {
return name;
}
publicvoid setName(String name) {
this.name = name;
}
publicint getAge() {
return age;
}
publicvoid setAge(int age) {
this.age = age;
}
}
3) Hessian 方式序列化:Hessian 序列化的优点是可以跨编程语言,比 Java 原生的序列化和反序列化效率高。请参考以下示例代码:
// 序列化和反序列化
classSerializableTest{
publicstaticvoid main(String[] args) throwsIOException, ClassNotFoundException{
// 序列化
ByteArrayOutputStream bo = newByteArrayOutputStream();
HessianOutput hessianOutput = newHessianOutput(bo);
hessianOutput.writeObject(user);
byte[] hessianBytes = bo.toByteArray();
// 反序列化
ByteArrayInputStream bi = newByteArrayInputStream(hessianBytes);
HessianInput hessianInput = newHessianInput(bi);
User user4 = (User) hessianInput.readObject();
System.out.println(user4);
}
}
classUserimplementsSerializable{
privatestaticfinallong serialVersionUID = 5132320539584511249L;
privateString name;
privateint age;
@Override
publicString toString() {
return"{name:"+ name + ",age:"+ age + "}";
}
publicString getName() {
return name;
}
publicvoid setName(String name) {
this.name = name;
}
publicint getAge() {
return age;
}
publicvoid setAge(int age) {
this.age = age;
}
}
有哪些方法可以解决哈希冲突?
-
建立公共溢出区:将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表。
JVM 内存布局是怎样的?
程序计数器(Program Counter Register)
Java 虚拟机栈(Java Virtual Machine Stacks)
本地方法栈(Native Method Stack)
Java 堆(Java Heap)
-
方法区(Methed Area)
通过这门课拿到 Offer 的同学:
这门课所包含的知识点:
专栏作者:王磊
你将获得
1. 收获 Java 技术栈的核心知识点
这个课程几乎涵盖了 Java 技术栈的大部分内容,不止对于面试,在日常的工作中也可以发挥很大的作用。
2. 500 多道实用、权威、高频 Java 面试题详解
3. 理解技术背后的实现原理
点击阅读原文,了解 Java 面试题。
以上是关于500+ 精选 Java 面试题大放送的主要内容,如果未能解决你的问题,请参考以下文章
Java 面试题目最全集合1000+ 大放送,能答对70%就去BATJTMD试试~