面试宝典

460道Java后端面试高频题答案版【模块一:Java基础】

由于之前分享的 460道Java后端高频面试题 中只分享了题目,大家都建议附有答案。所以最近根据题目整理了下答案,因为题目比较多,所以按照原文中的模块陆续发出。因为个人水平有限,仅供参考,如有错误,可与我交流,再改正。可扫描文末二维码加我的微信(微信号:kaigejava),备注:面试题说明:答案来自于我的秋招复习笔记,但是答案都是我复习过程中参考“别人”的以及面试过程中不断总

由于之前分享的 460道Java后端高频面试题 中只分享了题目,大家都建议附有答案。所以最近根据题目整理了下答案,因为题目比较多,所以按照原文中的模块陆续发出。因为个人水平有限,仅供参考,如有错误,可与我交流,再改正。可扫描文末二维码加我的微信(微信号:kaigejava),备注:面试题

说明:答案来自于我的秋招复习笔记,但是答案都是我复习过程中参考“别人”的以及面试过程中不断总结和整理的,并非完全原创。

1、解释下什么是面向对象?面向对象和面向过程的区别?

面向对象是一种基于面向过程的编程思想,是向现实世界模型的自然延伸,这是一种“万物皆对象”的编程思想。由执行者变为指挥者,在现实生活中的任何物体都可以归为一类事物,而每一个个体都是一类事物的实例。面向对象的编程是以对象为中心,以消息为驱动。


区别: (1)编程思路不同:面向过程以实现功能的函数开发为主,而面向对象要首先抽象出类、属性及其方法,然后通过实例化类、执行方法来完成功能。 (2)封装性:都具有封装性,但是面向过程是封装的是功能,而面向对象封装的是数据和功能。 

(3)面向对象具有继承性和多态性,而面向过程没有继承性和多态性,所以面向对象优势很明显。

2、面向对象的三大特性?分别解释下?1)封装:通常认为封装是把数据和操作数据的方法封装起来,对数据的访问只能通过已定义的接口。


(2)继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类/基类),得到继承信息的被称为子类(派生类)。(3)多态:分为编译时多态(方法重载)和运行时多态(方法重写)。要实现多态需要做两件事:一是子类继承父类并重写父类中的方法,二是用父类型引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为。


关于继承的几点补充:



(1)子类拥有父类对象所有的属性和方法(包括私有属性和私有方法),但是父类中的私有属性和方法子类是无法访问,只是拥有。因为在一个子类被创建的时候,首先会在内存中创建一个父类对象,然后在父类对象外部放上子类独有的属性,两者合起来形成一个子类的对象;


(2)子类可以拥有自己属性和方法;(3)子类可以用自己的方式实现父类的方法。(重写)


3、JDK、JRE、JVM 三者之间的关系?

JDK(Java Development Kit):是 Java 开发工具包,是整个 Java 的核心,包括了 Java 运行环境 JRE、Java 工具和 Java 基础类库。


JRE( Java Runtime Environment):是 Java 的运行环境,包含 JVM 标准实现及 Java 核心类库。JVM(Java Virtual Machine):是 Java 虚拟机,是整个 Java 实现跨平台的最核心的部分,能够运行以 Java 语言写作的软件程序。所有的 Java 程序会首先被编译为 .class 的类文件,这种类文件可以在虚拟机上执行。


4、重载和重写的区别?

(1)重载:编译时多态、同一个类中同名的方法具有不同的参数列表、不能根据返回类型进行区分【因为:函数调用时不能指定类型信息,编译器不知道你要调哪个函数】;


(2)重写(又名覆盖):运行时多态、子类与父类之间、子类重写父类的方法具有相同的返回类型、更好的访问权限。


5、Java 中是否可以重写一个 private 或者 static 方法?限  

Java 中 static 方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而 static 方法是编译时静态绑定的。static 方法跟类的任何实例都不相关,所以概念上不适用。 


Java 中也不可以覆盖 private 的方法,因为 private 修饰的变量和方法只能在当前类中使用, 如果是其他的类继承当前类是不能访问到 private 变量或方法的,当然也不能覆盖。


静态方法的补充



静态的方法可以被继承,但是不能重写。如果父类和子类中存在同样名称和参数的静态方法,那么该子类的方法会把原来继承过来的父类的方法隐藏,而不是重写。通俗的讲就是父类的方法和子类的方法是两个没有关系的方法,具体调用哪一个方法是看是哪个对象的引用;这种父子类方法也不在存在多态的性质。

6、构造器是否可以被重写?

在讲继承的时候我们就知道父类的私有属性和构造方法并不能被继承,所以 Constructor 也就不能被 Override(重写),但是可以 Overload(重载),所以你可以看到一个类中有多个构造函数的情况。

7、构造方法有哪些特性?

(1)名字与类名相同;


(2)没有返回值,但不能用 void 声明构造函数;
(3)成类的对象时自动执行,无需调用。

8、在 Java 中定义一个不做事且没有参数的构造方法有什么作用?

Java 程序在执行子类的构造方法之前,如果没有用 super() 来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用 super() 来调用父类中特定的构造方法,则编译时将发生错误,因为 Java 程序在父类中找不到没有参数的构造方法可供执行。解决办法是:在父类里加上一个不做事且没有参数的构造方法。 

9、Java 中创建对象的几种方式?1、使用 new 关键字;


2、使用 Class 类的 newInstance 方法,该方法调用无参的构造器创建对象(反射):Class.forName.newInstance();3、使用 clone() 方法;4、反序列化,比如调用 ObjectInputStream 类的 readObject() 方法。


10、抽象类和接口有什么区别?(1)抽象类中可以定义构造函数,接口不能定义构造函数;


(2)抽象类中可以有抽象方法和具体方法,而接口中只能有抽象方法(public abstract);(3)抽象类中的成员权限可以是 public、默认、protected(抽象类中抽象方法就是为了重写,所以不能被 private 修饰),而接口中的成员只可以是 public(方法默认:public abstrat、成员变量默认:public static final);(4)抽象类中可以包含静态方法,而接口中不可以包含静态方法;


JDK8中的改变:



1、在 JDK1.8中,允许在接口中包含带有具体实现的方法,使用 default 修饰,这类方法就是默认方法。

2、抽象类中可以包含静态方法,在 JDK1.8 之前接口中不能包含静态方法,JDK1.8 以后可以包含。之前不能包含是因为,接口不可以实现方法,只可以定义方法,所以不能使用静态方法(因为静态方法必须实现)。现在可以包含了,只能直接用接口调用静态方法。JDK1.8 仍然不可以包含静态代码块。

11、静态变量和实例变量的区别?静态变量:是被 static 修饰的变量,也称为类变量,它属于类,因此不管创建多少个对象,静态变量在内存中有且仅有一个拷贝;静态变量可以实现让多个对象共享内存。


实例变量:属于某一实例,需要先创建对象,然后通过对象才能访问到它。


12、short s1 = 1;s1 = s1 + 1;有什么错?那么 short s1 = 1; s1 += 1;呢?有没有错误?

对于 short s1 = 1; s1 = s1 + 1; 来说,在 s1 + 1 运算时会自动提升表达式的类型为 int ,那么将 int 型值赋值给 short 型变量,s1 会出现类型转换错误。


对于 short s1 = 1; s1 += 1; 来说,+= 是 Java 语言规定的运算符,Java 编译器会对它进行特殊处理,因此可以正确编译。


13、Integer 和 int 的区别?(1)int 是 Java 的八种基本数据类型之一,而 Integer 是 Java 为 int 类型提供的封装类;


(2)int 型变量的默认值是 0,Integer 变量的默认值是 null,这一点说明 Integer 可以区分出未赋值和值为 0 的区分;(3)Integer 变量必须实例化后才可以使用,而 int 不需要。


关于 Integer 和 int 的比较的延伸:



1、由于 Integer 变量实际上是对一个 Integer 对象的引用,所以两个通过 new 生成的 Integer 变量永远是不相等的,因为其内存地址是不同的;

2、Integer 变量和 int 变量比较时,只要两个变量的值是相等的,则结果为  true。因为包装类 Integer 和基本数据类型 int 类型进行比较时,Java 会自动拆包装类为 int,然后进行比较,实际上就是两个 int 型变量在进行比较;

3、非 new 生成的 Integer 变量和 new Integer() 生成的变量进行比较时,结果为 false。因为非 new 生成的 Integer 变量指向的是 Java 常量池中的对象,而 new Integer() 生成的变量指向堆中新建的对象,两者在内存中的地址不同;

4、对于两个非 new 生成的 Integer 对象进行比较时,如果两个变量的值在区间 [-128, 127] 之间,则比较结果为 true,否则为 false。Java 在编译 Integer i = 100 时,会编译成 Integer i = Integer.valueOf(100),而 Integer 类型的 valueOf 的源码如下所示:

public static Integer valueOf(int var0) {    
        return var0 >= -128 && var0 <= Integer.IntegerCache.high ? Integer.IntegerCache.cache[var0 + 128] : new Integer(var0);
}

从上面的代码中可以看出:Java 对于 [-128, 127] 之间的数会进行缓存,比如:Integer i = 127,会将 127 进行缓存,下次再写 Integer j = 127 的时候,就会直接从缓存中取出,而对于这个区间之外的数就需要 new 了。

包装类的缓存:

Boolean:全部缓存


Byte:全部缓存Character:<= 127 缓存Short:-128 — 127 缓存Long:-128 — 127 缓存Integer:-128 — 127 缓存Float:没有缓存Doulbe:没有缓存


14、装箱和拆箱

自动装箱是 Java 编译器在基本数据类型和对应得包装类之间做的一个转化。比如:把 int 转化成 Integer,double 转化成 Double 等等。反之就是自动拆箱。


原始类型:boolean、char、byte、short、int、long、float、double封装类型:Boolean、Character、Byte、Short、Integer、Long、Float、Double


15、switch 语句能否作用在 byte 上,能否作用在 long 上,能否作用在 String 上?

在 switch(expr 1) 中,expr1 只能是一个整数表达式或者枚举常量。而整数表达式可以是 int 基本数据类型或者 Integer 包装类型。由于,byte、short、char 都可以隐式转换为 int,所以,这些类型以及这些类型的包装类型也都是可以的。而 long 和 String 类型都不符合 switch 的语法规定,并且不能被隐式的转换为 int 类型,所以,它们不能作用于 switch 语句中。不过,需要注意的是在 JDK1.7 版本之后 switch 就可以作用在 String 上了。

16、字节和字符的区别?字节是存储容量的基本单位;


字符是数字、字母、汉字以及其他语言的各种符号;


1 字节 = 8 个二进制单位,一个字符由一个字节或多个字节的二进制单位组成。17、String 为什么要设计为不可变类?

在 Java 中将 String 设计成不可变的是综合考虑到各种因素的结果。主要的原因主要有以下三点:


(1)字符串常量池的需要:字符串常量池是 Java 堆内存中一个特殊的存储区域, 当创建一个 String 对象时,假如此字符串值已经存在于常量池中,则不会创建一个新的对象,而是引用已经存在的对象;(2)允许 String 对象缓存 HashCode:Java 中 String 对象的哈希码被频繁地使用, 比如在 HashMap 等容器中。字符串不变性保证了 hash 码的唯一性,因此可以放心地进行缓存。这也是一种性能优化手段,意味着不必每次都去计算新的哈希码;(3)String 被许多的 Java 类(库)用来当做参数,例如:网络连接地址 URL、文件路径 path、还有反射机制所需要的 String 参数等, 假若 String 不是固定不变的,将会引起各种安全隐患。


18、String、StringBuilder、StringBuffer 的区别?String:用于字符串操作,属于不可变类;【补充:String 不是基本数据类型,是引用类型,底层用 char 数组实现的】


StringBuilder:与 StringBuffer 类似,都是字符串缓冲区,但线程不安全;StringBuffer:也用于字符串操作,不同之处是 StringBuffer 属于可变类,对方法加了同步锁,线程安全。


StringBuffer的补充:

说明:StringBuffer 中并不是所有方法都使用了 Synchronized 修饰来实现同步:



    @Override
    public StringBuffer insert(int dstOffset, CharSequence s) {
      // Note, synchronization achieved via invocations of other StringBuffer methods
      // after narrowing of s to specific type
      // Ditto for toStringCache clea

    原创不易,完成人机校验,阅读全文

    相关推荐