经典Java面试题及答案(146道企业真题)_Java编程面试题-极悦
第一部分 Java基础
第二部分 Java进阶

经典Java面试题及答案(1~41企业真题)

1、下面程序的运行结果是

public static void main(String[] args) {
    String str1 = "hello";
    String str2 = "he" + new String("llo");
    String str3 = "he" + "llo";
    System.err.println(str1 == str2);
    System.err.println(str1 == str3);
}

运行结果:

false

true

2、HashSet 里的元素是不能重复的, 那用什么方法来区分重复与否呢?

往集合在添加元素时,调用 add(Object)方法的时候,首先会调用Object的 hashCode()方法判断hashCode 是否已经存在,如不存在则直接插入元素;如果已存在则调用Object对象的 equals()方法判断是否返回 true,如果为true则说明元素已经存在,如为false则插入元素。

3、List ,Set, Map是否继承来自Collection接口? 存取元素时, 有何差异?

● List、Set 是继承 Collection 接口; Map不是。

● List:元素有放入顺序,元素可重复,通过下标来存取。

● Map:元素按键值对存取,无放入顺序。

● Set:元素无存取顺序,元素不可重复(注意:元素虽然无放入顺序,但是元素在 set 中的位置是有该元素的 hashCode 决定的,其位置其实是固定的)。

4、简述 Java 中的值传递和引用传递?

按值传递是指的是在方法调用时,传递的参数是按值的拷贝传递。按值传递重要特点:传递的是值的拷贝,也就是说传递后就互不相关了示例如下:

class TempTest {
    private void test1(int a) {
        a = 5;
        System.out.println("test1 方法中的 a=" + a);
    }

    public static void main(String[] args) {
        TempTest t = new TempTest();
        int a = 3;
        //传递后,test1 方法对变量值的改变不影响这里的 a
        t.test1(a);
        System.out.println("main 方法中的 a =" + a);
    }
}

运行结果是:

test1 方法中的 a=5

main 方法中的 a =3

按引用传递是指的是在方法调用时,传递的参数是按引用进行传递,其实传递的是引用的地址,也就是变量所对应的内存空间的地址。传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。示例如下:

class TempTest {
    private void test1(A a) {
        a.age = 20;
        System.out.println("test1 方法中的 age=" + a.age);
    }

    public static void main(String[] args) {
        TempTest t = new TempTest();
        A a = new A();
        a.age = 10;
        t.test1(a);
        System.out.println("main 方法中的 age =" + a.age);
    }
}

class A {
    public int age = 0;
}

运行结果:

test1 方法中的 age=20

main 方法中的 age =20

5、请写出几个常见的运行时异常?

NullPointerException - 空指针引用异常

ClassCastException - 类型强制转换异常。

IndexOutOfBoundsException - 下标越界异常

NumberFormatException - 数字格式异常

6、简述数据库事务和实际工作中的作用?

所谓事务是用户定义的一个数据库操作序列,这些操作要么全做要么全不做,是一个不可分割的工作单位。

例如在关系数据库中,一个事务可以是一条 SQL 语句、一组 SQL 语句或整个程序。简单举个例子就是你要同时修改数据库中两个不同表的时候,如果它们不是一个事务的话,当第一个表修改完,可是第二表改修出现了异常而没能修改的情况下,就只有第二个表回到未修改之前的状态,而第一个表已经被修改完毕。而当你把它们设定为一个事务的时候,当第一个表修改完,可是第二表改修出现了异常而没能修改的情况下,第一个表和第二个表都要回到未修改的状态!这就是所谓的事务回滚。

例如,在将资金从一个帐户转移到另一个帐户的银行应用中,一个帐户将一定的金额贷记到一个数据库表中,同时另一个帐户将相同的金额借记到另一个数据库表中。由于计算机可能会因停电、网络中断等而出现故障,因此有可能更新了一个表中的行,但没有更新另一个表中的行。如果数据库支持事务,则可以将数据库操作组成一个事务,以防止因这些事件而使数据库出现不一致。如果事务中的某个点发生故障,则所有更新都可以回滚到事务开始之前的状态。如果没有发生故障,则通过以完成状态提交事务来完成更新。

7、已知一棵二叉树,如果先序遍历的节点顺序是:ADCEFGHB ,中序遍历是:CDFEGHAB ,则后序遍历结果为:(D)

A.CFHGEBDA

B.CDFEGHBA

C.FGHCDEBA

D. CFHGEDBA

原因:对于二叉树的遍历方式一般分为三种先序、中序、后序三种方式:

先序遍历(根左右)若二叉树为空,则不进行任何操作,否则

● 访问根结点。

● 先序方式遍历左子树。

● 先序遍历右子树。

中序遍历 (左根右)若二叉树为空,则不进行任何操作,否则

● 中序遍历左子树。

● 访问根结点。

● 中序遍历右子树。

后序遍历 (左右根)若二叉树为空,则不进行任何操作,否则

● 后序遍历左子树。

● 后序遍历右子树。

● 访问根结点。

因此,根据题目给出的先序遍历和中序遍历,可以画出二叉树:

8、下列哪两个数据结构,同时具有较高的查找和删除性能?

A.有序数组

B.有序链表

C.AVL 树

D.Hash 表

看下图:

平衡二叉树的查找,插入和删除性能都是 O(logN)  ,其中查找和删除性能较好;哈希表的查找、插入和删除性能都是 O(1) ,都是最好的。所以最后的结果选择:CD。

9、下列排序算法中,哪些时间复杂度不会超过 nlogn?(BC)

A.快速排序

B.堆排序

C.归并排序

D.冒泡排序

看下图:

根据上图,观察平均情况,最好最差情况的时间复杂度基本可以知道答案了,最后结果选择: BC。

10、初始序列为 1 8 6 2 5 4 7 3 一组数采用堆排序,当建堆(小根堆)完毕时,堆所对应的二叉树中序遍历序列为:( A )

A. 8 3 2 5 1 6 4 7

B. 3 2 8 5 1 4 6 7

C. 3 8 2 5 1 6 7 4

D. 8 2 3 5 1 4 7 6

初始化序列:1 8 6 2 5 4 7 3,小根堆就是要求结点的值小于其左右孩子结点的值,左右孩子的大小没有关系,那么小根堆排序之后为:1 2 4 3 5 6 7 8;中序遍历:左根右,故遍历结果为:8 3 2 5 1 6 4 7,故最后选择的结果:A

11、当 n = 5 时,下列函数的返回值是:(A)

int foo(int n) {
    if (n < 2) return n;
    return foo(n - 1) + foo(n - 2);
}

A.5

B.7

C.8

D.1

12、S市 A ,B 共有两个区,人口比例为 3:5 ,据历史统计 A 区的犯罪率为 0.01% ,B 区为 0.015% ,现有一起新案件发生在 S 市,那么案件发生在A 区的可能性有多大?

A.37.5%

B.32.5%

C.28.6%

D.26.1%

做这道题首先得了解犯罪率是什么?犯罪率就是犯罪人数与总人口数的比。因此可以直接得出公式:( 3 0.01% ) / ( 30.01% + 5 * 0.015% ) = 28.6%,当然如果不好理解的话,我们可以实例化,比如B区假设 5000 人,A区 3000 人,A 区的犯罪率为 0.01%,那么 A 区犯罪人数为 30 人,B 区的犯罪率为 0.015% ,那么 B 区的犯罪人数为 75 人 ,求发生在 A 区的可能性,就是说 A 区的犯罪人数在总犯罪人数的多少,也就是 30/(30+75)=0.2857,当然,也可以回归到我们高中遗忘的知识:

假设 C 表示犯案属性

在 A 区犯案概率:P(C|A)=0.01%

在 B 区犯案概率:P(C|B)=0.015%

在 A 区概率:P(A)=3/8

在 B 区概率:P(B)=5/8

犯案概率:P(C)=(3/80.01%+5/80.015%)

根据贝叶斯公式:P(A|C) = P(A,C) / P(C) = [P(C|A) P(A)] / [ P(C|A) P(A)+ P(C|B) P(B) ] 也可以算出答案来,最后结果选择为: C

13、Linux系统中,哪些可以用于进程间的通信?(ABCD )

A.Socket

B.共享内存

C.消息队列

D.信号量

管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;

信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux 除了支持 Unix 早期信号语义函数 sigal 外,还支持语义符合 Posix.1 标准的信号函数 sigaction(实际上,该函数是基于 BSD 的,BSD 为了实现可靠信号机制,又能够统一对外接口,用 sigaction 函数重新实现了 signal 函数);

报文(Message)队列(消息队列):消息队列是消息的链接表,包括 Posix 消息队列 system V 消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。

共享内存:使得多个进程可以访问同一块内存空间,是最快的可用 IPC 形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。

信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。

套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由 Unix 系统的 BSD分支开发出来的,但现在一般可以移植到其它类 Unix 系统上:Linux 和 System V 的变种都支持套接字。

故最后选择的结果为: ABCD

14、静态变量通常存储在进程哪个区?( C )

A.栈区

B.堆区

C.全局区

D.代码区

原因:静态变量的修饰关键字:static,又称静态全局变量。故最后选择的结果为: C

15、如何提高查询 Name 字段的性能( B )

A.在 Name 字段上添加主键

B.在 Name 字段上添加索引

D.在 Age 字段上添加索引

16、IP地址 192.168.14.69 是一个(B)类 IP 地址

17、浏览器访问某页面,HTTP协议返回状态码为 403 时表示:( B )

A.找不到该页面

B.禁止访问

C.内部服务器访问

D.服务器繁忙

18、TCP 和 IP 分别对应了 OSI 中的哪几层?(CD)

A.Application layer

B.Presentation layer

C.Transport layer

D.Network layer

19、一个栈的入栈序列是 A,B,C,D,E,则栈的不可能的输出序列是?(C)

A.EDCBA

B.DECBA

C.DCEAB

D.ABCDE

堆栈分别是先进后出,后进先出,选项 a 是 abcde 先入栈,然后依次出栈,正好是 edcba。选项 b 是 abcd 先依次入栈,然后d出栈, e再入栈, e出栈选项c是错误的,不可能a先出栈。选项 d 是 a 入栈,然后 a 出栈;b 再入栈, b 出栈。依此类推。最后的结果选择 C。

20、同一进程下的线程可以共享以下?(BD)

A.stack

B.data section

C.register set

D.file fd

● 线程共享的内容包括:

进程代码段

进程的公有数据(利用这些共享的数据,线程很容易的实现相互之间的通讯)

进程打开的文件描述符

信号的处理器

进程的当前目录和进程用户 ID 与进程组 ID

● 线程独有的内容包括:

线程 ID

寄存器组的值

线程的堆栈

错误返回码

线程的信号屏蔽码

所以选择为 BD。

21、递归函数最终会结束,那么这个函数一定?(B)

A.使用了局部变量

B.有一个分支不调用自身

C.使用了全局变量或者使用了一个或多个参数

D.没有循环调用

22、编译过程中,语法分析器的任务是(BCD)

A.分析单词是怎样构成的

B.分析单词串是如何构成语言和说明的

C.分析语句和说明是如何构成程序的

D.分析程序的结构

● 词法分析(lexical analysis)词法分析是编译过程的第一个阶段。这个阶段的任务是从左到右的读取每个字符,然后根据构词规则识别单词。词法分析可以用 lex 等工具自动生成。

● 语法分析(syntax analysis)语法分析是编译过程的一个逻辑阶段。语法分析在词法分析的基础上,将单词序列组合成各类语法短语,如“程序”,“语句”,“表达式”等等。语法分析程序判断程序在结构上是否正确。

● 语义分析(semantic analysis)属于逻辑阶段。对源程序进行上下文有关性质的审查,类型检查。如赋值语句左右端类型匹配问题。

所以 BCD 都属于词法分析,选择结果为 BCD。

23、同步机制应该遵循哪些基本准则?(ABCD)

A.空闲让进

B.忙则等待

C.有限等待

D.让权等待

24、进程进入等待状态有哪几种方式?(D)

A.CPU 调度给优先级更高的线程

B.阻塞的线程获得资源或者信号

C.在时间片轮转的情况下,如果时间片到了

D.获得 spinlock 未果

25、设计模式中,属于结构型模式的有哪些?(BC)

A.状态模式

B.装饰模式

C.代理模式

D.观察者模式

26、下面代码的运行结果是(C)

public class Test {
    public static void main(String[] args) {
        List<String> a = null;
        test(a);
        System.out.println(a.size());
    }

    public static void test(List<String> a) {
        a = new ArrayList<String>();
        a.add("abc");
    }
}

A.0

B.1

C.java.lang.NullPointerException

D.以上都不正确

27、Linux下查看进程占用的 CPU 的百分比,使用工具(A)

A.ps

B.cat

C.more

D.sep

28、JVM 内存里哪个区域不可能发生OutOfMerncyError( A)

A.程序计数器

B.堆

C.方法区

D.本地方法栈

29、下面关于阻塞队列(java.util.concurrent.BlockingQueue)的说法不正确的是(C)

A.阻塞队列是线程安全的

B.阻塞队列的主要应用场景是“生产者-消费者”模型

C.阻塞队列里的元素不能为 null

D.阻塞队列的实现必须显示地设置容量

30、如果现在需要创建一组任务,他们并行的执行工作,然后进行下一个步骤之前等待,直至所有的任务都完成,而去这种控制可以重用多次, 这种情形使用 java.util.concurrent包中引入哪种同步工具最适合(B)

A.CountDownLatch

B.CyclicBarrier

C.Semaphore

D.FutureTask

31、java 中, 为什么基类不能做为 HashMap 的键值, 而只能是引用类型,把引用类型作为 HashMap 的键值,需要注意哪些地方?

引用类型和原始类型的行为完全不同,并且它们具有不同的语义。引用类型和原始类型具有不同的特征和用法,它们包括:大小和速度问题,这种类型以哪种类型的数据结构存储,当引用类型和原始类型用作某个类的实例数据时所指定的缺省值。对象引用实例变量的缺省值为 null,而原始类型实例变量的缺省值与它们的类型有关。

32、编写一个工具类 StringUtil, 提供方法 int compare(char[] v1 ,char[] v2)方法,比较字符串v1,v2 ,如果按照字符顺序 v1>v2 则 return 1 ,v1=v2 则 return 0, v1<v2 则 return-1 。

class StringUtil {
    int compare(char[] v1, char[] v2) {
        String str1 = new String(v1);
        String str2 = new String(v2);
        int result = str1.compareTo(str2);
        return result == 0 ? 0 : (result > 0 ? 1 : -1);
    }
}

33、Java 出现 OutOfMemoryError(OOM)的原因有那些?出现 OOM 错误后,怎么解决?

触发 java.lang.OutOfMemoryError:最常见的原因就是应用程序需要的堆空间是大的,但是 JVM 提供的却小。这个的解决方法就是提供大的堆空间即可。

除此之外还有复杂的原因:内存泄露:特定的编程错误会导致你的应用程序不停的消耗更多的内存,每次使用有内存泄漏风险的功能就会留下一些不能被回收的对象到堆空间中,随着时间的推移,泄漏的对象会消耗所有的堆空间,最终触发java.lang.OutOfMemoryError: Java heap space 错误。

解决方案:你应该确保有足够的堆空间来正常运行你的应用程序,在 JVM 的启动配置中增加如下配置:-Xmx1024m,流量/数据量峰值:应用程序在设计之初均有用户量和数据量的限制,某一时刻,当用户数量或数据量突然达到一个 峰 值 , 并 且 这 个 峰 值 已 经 超 过 了 设 计 之 初 预 期 的 阈 值 , 那 么 以 前 正 常 的 功 能 将 会 停 止 , 并 触 发java.lang.OutOfMemoryError: Java heap space 异常解决方案,如果你的应用程序确实内存不足,增加堆内存会解决 GC overhead limit 问题,就如下面这样,给你的应用程序 1G 的堆内存:java -Xmx1024m com.yourcompany.YourClass。

​​​​​​​34、下列关于栈的描述错误的是(B)

A.栈是先进后出的线性表

B.栈只能顺序存储

C.栈具有记忆功能

D.对栈的插入和删除操作中,不需要改变栈底指针

​​​​​​​35、对于长度为 n 的线性表,在最坏的情况下,下列个排序法所对应的比较次数中正确的是(D)

A.冒泡排序为 n/2

B.冒泡排序为 n

C.快速排序为 n

D.快速排序为 n(n-1)/2

36、阅读下列代码后,下列正确的说法是(A)

class Person {
    int arr[] = new int[10];
    public static void main(String args[]) {
        System.out.println(arr[1]);
    }
}

A.编译时将产生错误

B.编译时正确,运行时将产生错误

C.输出空

D .输 出 0

​​​​​​​37、执行以下程序后输出的结果是(D)

public class Test {
    public static void main(String[] args) {
        StringBuffer a = new StringBuffer("A");
        StringBuffer b = new StringBuffer("B");
        operator(a, b);
        System.out.println(a + "," + b);
    }

    public static void operator(StringBuffer x, StringBuffer y) {
        x.append(y);
        y = x;
    }
}

A.A,A

B.A,B

C.B,B

D.AB,B

​​​​​​​38、下列不属于持久化的是(A)

A.把对象转换成为字符串的形式通过网络传输,在另一端接收到字符串把对象还原出来

B.把程序数据从数据库中读出来

C.从 XML 配置文件中读取程序的配置信息

D.把程序数据保存为文件

39、​​​​​​​下列代码输出的结果是(C)

int x = 0;
int y = 10;
do {
    y--;
    ++x;
} while (x < 6);
System.out.println(x + "," + y);

A. 5,6

B. 5,5

C. 6,4

D. 6,6

40、下列程序段输出的结果是(B)​​​​​​​

public static void complicatedexpression_f() {
    int x = 20, y = 30;
    boolean j;
    j = x > 50 && y > 60 || x > 50 && y < -60 || x < -50 && y > 60 || x < -50 && y < -60;
    System.out.println(j);
}

A.true

B.false

C.1  

D.001

41、​​​​​​​一个栈的输入序列为123,则下列序列中不可能是栈输出的序列的是(C)

A. 2 3 1

B. 3 2 1

C. 3 1 2

D. 1 2 3​​​​​​​​​​​​​​​​​​​​​

全部教程