献给 2018 还在艰苦奋斗的 Java 程序员,Java 常见面试题及答案!

1. 什么是 Java 虚拟机?为什么 Java 被称作是“平台无关的编程语言”?

Java 虚拟机是一个可以执行 Java 字节码的虚拟机进程。Java 源文件被编译成能被 Java 虚拟机执行的字节码文件。

Java 被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。

Java 虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性。

2.JDK 和 JRE 的区别是什么?

JDK: java 开发工具包, 包含了 JRE、编译器和其它工具(如:javaDOc、java 调试器 )

JRE: java 运行环境, 包含 java 虚拟机和 java 程序所需的核心类库。

如果只是想跑 java 程序,那么只需安装 JRE,如果要写 java 程序并且运行,那就需要 JDK 了。

3.”static”关键字是什么意思?Java 中是否可以覆盖一个 private 或者是 static 的方法?

如果一个类的变量或者方法前面有 static 修饰,那么表明这个方法或者变量属于这个类,也就是说可以在不创建对象的情况下直接使用

当父类的方法被 private 修饰时,表明该方法为父类私有,对其他任何类都是不可见的,因此如果子类定了一个与父类一样的方法,这对于子类来说相当于是一个新的私有方法,且如果要进行向上转型,然后去调用该“覆盖方法”,会产生编译错误

class Parent {private fun() {…} }class Child extends Parent {private fun() {…}}class Test {public static void main(String[] args){ Parent c = new Child(); c.fun(); // 编译出错}}

static 方法时编译时静态绑定的,属于类,而覆盖是运行时动态绑定的 (动态绑定的多态), 因此不能覆盖.

4.Java 支持的基本数据类型有哪些?什么是自动拆装箱?

java 支持的基本数据类型有以下 9 种:byte,shot,int,long,float,double,char,boolean,void.

自动拆装箱是 java 从 jdk1.5 引用,目的是将原始类型自动的装换为相对应的对象,也可以逆向进行,即拆箱。这也体现 java 中一切皆对象的宗旨。

所谓自动装箱就是将原始类型自动的转换为对应的对象,而拆箱就是将对象类型转换为基本类型。java 中的自动拆装箱通常发生在变量赋值的过程中,如:

Integer object = 3; // 自动装箱 int o = object; // 拆箱

在 java 中,应该注意自动拆装箱,因为有时可能因为 java 自动装箱机制,而导致创建了许多对象,对于内存小的平台会造成压力。

覆盖和重载是什么?

覆盖也叫重写,发生在子类与父类之间,表示子类中的方法可以与父类中的某个方法的名称和参数完全相同,通过子类创建的实例对象调用这个方法时,将调用子类中的定义方法,这相当于把父类中定义的那个完全相同的方法给覆盖了,这也是面向对象编程的多态性的一种表现。

重载是指在一个类中,可以有多个相同名称的方法,但是他们的参数列表的个数或类型不同,当调用该方法时,根据传递的参数类型调用对应参数列表的方法。当参数列表相同但返回值不同时,将会出现编译错误,这并不是重载,因为 jvm 无法根据返回值类型来判断应该调用哪个方法。

5.Java 支持多继承么?如果不支持,如何实现?

在 java 中是单继承的,也就是说一个类只能继承一个父类。

java 中实现多继承有两种方式, 一是接口,而是内部类.

// 实现多个接口 如果两个接口的变量相同 那么在调用该变量的时候 编译出错 interface interface1 {static String field = “dd”; public void fun1(); }interface interface2 {static String field = “dddd”; public void fun2(); }class child implements interface1,interface2 {static String field = “dddd”; @Override public void fun2() {} @Override public void fun1() {}}// 内部类 间接多继承 class Child {class Father { private void strong() {System.out.println(“父类”); }}class Mother {public void getCute() {System.out.println(“母亲”); }}public void getStrong(){ Father f = new Father(); f.strong();}public void getCute(){ Mother m = new Mother(); m.getCute();}}

6. 什么是值传递和引用传递?java 中是值传递还是引用传递,还是都有?

值传递 就是在方法调用的时候,实参是将自己的一份拷贝赋给形参,在方法内,对该参数值的修改不影响原来实参,常见的例子就是刚开始学习 c 语言的时候那个交换方法的例子了。

引用传递 是在方法调用的时候,实参将自己的地址传递给形参,此时方法内对该参数值的改变,就是对该实参的实际操作。

在 java 中只有一种传递方式,那就是值传递. 可能比较让人迷惑的就是 java 中的对象传递时,对形参的改变依然会意向到该对象的内容。

下面这个例子来说明 java 中是值传递.

public class Test {public static void main(String[] args){ StringBuffer sb = new StringBuffer("hello"); getString(sb); System.out.println(sb); } public static void getString(StringBuffer s) {//s = new StringBuffer(“ha”); s.append(“world”); }}

在上面这个例子中, 当前输出结果为:hello world。这并没有什么问题,可能就是大家平常所理解的引用传递,那么当然会改变 StringBuffer 的内容。但是如果把上面的注释去掉,那么就会输出:hello. 此时 sb 的值并没有变成 ha hello. 假如说是引用传递的话,那么形参的 s 也就是 sb 的地址,此时在方法里 new StringBuffer(),并将该对象赋给 s,也就是说 s 现在指向了这个新创建的对象. 按照引用传递的说法,此时对 s 的改变就是对 sb 的操作,也就是说 sb 应该也指向新创建的对象,那么输出的结果应该为 ha world. 但实际上输出的仅是 hello. 这说明 sb 指向的还是原来的对象,而形参 s 指向的才是创建的对象, 这也就验证了 java 中的对象传递也是值传递。

7. 接口和抽象类的区别是什么?

不同点在于:

接口中所有的方法隐含的都是抽象的。而抽象类则可以同时包含抽象和非抽象的方法。

类可以实现很多个接口,但是只能继承一个抽象类

类如果要实现一个接口,它必须要实现接口声明的所有方法。但是,类可以不实现抽象类声明的所有方法,当然,在这种情况下,类也必须得声明成是抽象的。

抽象类可以在不提供接口方法实现的情况下实现接口。

Java 接口中声明的变量默认都是 final 的。抽象类可以包含非 final 的变量。

Java 接口中的成员函数默认是 public 的。抽象类的成员函数可以是 private,protected 或者是 public 。

接口是绝对抽象的,不可以被实例化 (java 8 已支持在接口中实现默认的方法)。抽象类也不可以被实例化,但是,如果它包含 main 方法的话是可以被调用的。

8. 构造器(constructor)是否可被重写(override)?

构造方法是不能被子类重写的,但是构造方法可以重载,也就是说一个类可以有多个构造方法。

9.Math.round(11.5) 等于多少? Math.round(-11.5) 等于多少?

Math.round(11.5)==12 Math.round(-11.5)==-11 round 方法返回与参数 最接近的长整数,参数加 1/2 后求其 floor.

10. String, StringBuffer StringBuilder 的区别。

tring 的长度是不可变的;

StringBuffer 的长度是可变的,如果你对字符串中的内容经常进行操作,特别是内容要修改时,那么使用 StringBuffer,如果最后需要 >String,那么使用 StringBuffer 的 toString() 方法;线程安全;

StringBuilder 是从 JDK 5 开始,为 StringBuffer 该类补充了一个单个线程使用的等价类;通常应该优先使用 StringBuilder 类,因 > 为它支持所有相同的操作,但由于它不执行同步,所以速度更快。

使用字符串的时候要特别小心,如果对一个字符串要经常改变的话,就一定不要用 String, 否则会创建许多无用的对象出来.

来看一下比较

String s = “hello”+“world”+“i love you”;StringBuffer Sb = new StringBuilder(“hello”).append(“world”).append(“i love you”);

这个时候 s 有多个字符串进行拼接,按理来说会有多个对象产生,但是 jvm 会对此进行一个优化,也就是说只创建了一个对象,此时它的执行速度要比 StringBuffer 拼接快. 再看下面这个:

String s2 = “hello”; String s3 = “world”; String s4 = “i love you”; String s1 = s2 + s3 + s4;

上面这种情况,就会多创建出来三个对象,造成了内存空间的浪费.

java 常见面试题及答案 21-30,请看下篇,欢迎转发加关注.

1、具有 1-5 工作经验的,面对目前流行的技术不知从何下手,需要突破技术瓶颈的可以进群学习。

2、在公司待久了,过得很安逸,但跳槽时面试碰壁。需要在短时间内进修、跳槽拿高薪的可以进群学习。

3、如果没有工作经验,但基础非常扎实,对 java 工作机制,常用设计思想,常用 java 开发框架掌握熟练的,可以进群学习。

4、觉得自己很牛 B,一般需求都能搞定。但是所学的知识点没有系统化,很难在技术领域继续突破的可以进群学习。

5. 阿里 Java 高级架构师直播讲解知识点,分享知识,多年工作经验的梳理和总结,带着大家全面、科学地建立自己的技术体系和技术认知!

群号:685167672