java后端开发面试题(java)

记录一下自己看的,方便以后用,很多都是来自各个博客。

1. 解释下什么是面向对象?面向对象和面向过程的区别?
感觉有点像雕版印刷术和活字印刷术的区别
面向对象:简称oop : object oriented programming,简单来说就是根据类创建对象,每个对象都有自己的属性和方法,而这些属性和方法都是围绕对象服务的,你会发现用到的属性和方法都是对象。
优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护

缺点:性能比面向过程低

面向过程:简称POP,Procedure Oriented,面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。

缺点:没有面向对象易维护、易复用、易扩展

2. 面向对象的三大特性?分别解释下?

封装
封装是把客观事物抽象成类,并且把自己的属性和方法让可信的类或对象操作,对不可性的隐藏。

继承
继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。

多态
多态性(polymorphism)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。这就意味着虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。

3. JDK、JRE、JVM 三者之间的关系?
java后端开发面试题(java)_第1张图片

JDK(Java Development Kit)是针对Java开发员的产品,是整个Java的核心,包括了Java运行环境JRE、Java工具和Java基础类库。JDK中包含JRE,在JDK的安装目录下有一个名为jre的目录。

JRE 是Java运行环境,并不是一个开发环境,所以没有包含任何开发工具(如编译器和调试器),只是针对于使用Java程序的用户。

JVM(java virtual machine)就是我们常说的java虚拟机,它是整个java实现跨平台的最核心的部分,所有的java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行。

4. 重载和重写的区别?

Java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义。

调用方法时通过传递给它们的不同参数个数和参数类型来决定具体使用哪个方法, 这就是多态性。
重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同也可以不相同。无法以返回型别作为重载函数的区分标准。

重写是对函数内容的修改,返回值,名字等不可修改。并且访问修饰符要不小于重写方法的访问修饰符。重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常。

方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型。

总结:

override(重写)

1、方法名、参数、返回值相同。

2、子类方法不能缩小父类方法的访问权限。

3、子类方法不能抛出比父类方法更多的异常(但子类方法可以不抛出异常)。

4、存在于父类和子类之间。

5、方法被定义为final不能被重写。

overload(重载)

1、参数类型、个数、顺序至少有一个不相同。

2、不能重载只有返回值不同的方法名。

3、存在于父类和子类、同类中。
  
5. Java 中是否可以重写一个 private 或者 static 方法?

Java中static方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而static方法是编译时静态绑定的。static方法类的任何实例都不相关,所以概念上不适用。
Java中也不可以覆盖private的方法,因为private修饰的变量和方法只能在当前类中使用,如果是其他的类继承当前类是不能访问到private变量或方法的,当然也不能覆盖。

6. 构造方法有哪些特性?
a… 名字与类名相同;

b… 没有返回值,但不能用void声明构造函数;

c…生成类的对象时自动执行,无需调用。

7. 在 Java 中定义一个不做事且没有参数的构造方法有什么作用?
因为在父类存在有参构造方法的时候,子类会去调用无参的构造方法,那么就会发生编译错误。

8. Java 中创建对象的几种方式?
a.使用new关键字
b.使用Class类的newInstance方法
c.使用Constructor类的newInstance方法
d.使用clone方法
e.使用反序列化

9. 抽象类和接口有什么区别?
1.抽象类中可以没有抽象方法,可以有非抽象方法,接口中全都是抽象方法。
b.抽象类子类用implements来实现接口,需要实现接口中的所有方法了。接口中用extends来继承实现。
c.抽象类可以有构造器,接口没有构造器。
d.抽象方法可以用public、protected、default修饰。接口默认是public、不能用别的修饰符去修饰。
e.抽象类可以多实现,接口只能单继承,但是接口可以多层继承。

10. 静态变量和实例变量的区别?
1)在语法定义上的区别:静态变量前要加 static 关键字,而实例变量(成员变量)前则不加。
2)在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。

11. short s1 = 1;s1 = s1 + 1;有什么错?那么 short s1 = 1; s1 += 1;呢?有没有错误?
s1 = s1 + 1有错,1是int类型,和short类型所占字节不同,大传小需要强制转换。而 s1 += 1等于 s1 = (short) (s1 + 1)

13. Integer 和 int 的区别?
int与integer的区别从大的方面来说就是基本数据类型与其包装类的区别:
int 是基本类型,直接存数值,而integer是对象,用一个引用指向这个对象

14. 装箱和拆箱的区别

Integer i = 10;  //装箱
int n = i;   //拆箱
简单一点说,装箱就是自动将基本数据类型转换为包装器类型;拆箱就是  自动将包装器类型转换为基本数据类型。

15. switch 语句能否作用在 byte 上,能否作用在 long 上,能否作用在 String 上?
switch 语句中的变量类型可以是: byte、short、int 或者 char。从 Java SE 7 开始,switch 支持字符串 String 类型了,同时 case 标签必须为字符串常量或字面量。

16. final、finally、finalize 的区别

在java中,final可以用来修饰类,方法和变量(成员变量或局部变量)。

finally
在异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。
finally不会执行到的几种情况
1)未执行到try模块。
2)在 try 语句块中执行了 System.exit (0) 语句,终止了 Java 虚拟机的运行
3)当一个线程在执行 try 语句块或者 catch 语句块时被打断(interrupted)或者被终止(killed),与其相对应的 finally 语句块可能不会执行

finalize()是在java.lang.Object里定义的,也就是说每一个对象都有这么个方法。这个方法在gc启动,该对象被回收的时候被调用。其实gc可以回收大部分的对象(凡是new出来的对象,gc都能搞定,一般情况下我们又不会用new以外的方式去创建对象),所以一般是不需要程序员去实现finalize的。
特殊情况下,需要程序员实现finalize,当对象被回收的时候释放一些资源,比如:一个socket链接,在对象初始化时创建,整个生命周期内有效,那么就需要实现finalize,关闭这个链接。
  使用finalize还需要注意一个事,调用super.finalize();
  一个对象的finalize()方法只会被调用一次,而且finalize()被调用不意味着gc会立即回收该对象,所以有可能调用finalize()后,该对象又不需要被回收了,然后到了真正要被回收的时候,因为前面调用过一次,所以不会调用finalize(),产生问题。 所以,推荐不要使用finalize()方法,它跟析构函数不一样。
17. == 和 equals 的区别?
基本数据类型种 == 是比较值,引用数据类型是比较引用地址是否相同,本质上 == 和equals是相同的,都是引用比较,只是String、Integer等重写了他的equals方法。

18. 两个对象的 hashCode() 相同,则 equals() 也一定为 true 吗?
java后端开发面试题(java)_第2张图片

可以看到,这两个字符串的hashCode()是相同的,但是equals()方法返回为false。

这是因为hash表本身是一种散列表,而在散列表中,hashCode()相等即两个键值对的哈希值相等;然而哈希值相等,并不一定能得出键值对相等。

所以根据上述的情况以及设计要求,可以得到结论:

两个对象equals返回true,那么hashcode一定相等;两个对象的hashcode相等,那么equals不一定为true。
重写equals()方法,则hashCode()方法也必须重写,这样才能保证equals()方法返回true时,hashcode的值相等。

19. 为什么重写 equals() 就一定要重写 hashCode() 方法?
答案见上一题

20. & 和 && 的区别?
1.&

(1)按位运算符; (2)逻辑运算符

作为逻辑运算符时,&左右两端条件式有一个为假就会不成立,但是两端都会运行,比如(1+2)=4 &(1+2)=3;1+2=4即使为假也会去判断1+2=3是否成立。

2.&&——逻辑运算符

&&也叫做短路运算符,因为只要左端条件式为假直接不成立,不会去判断右端条件式

相同点:只要有一端为假,则语句不成立

21. Java 中的参数传递时传值呢?还是传引用?
a、基本类型作为参数传递时,是传递值的拷贝,无论你怎么改变这个拷贝,原值是不会改变的
b、对象作为参数传递时,是把对象在内存中的地址拷贝了一份传给了参数。
具体看这篇博客 https://www.cnblogs.com/huanghuanghui/p/9386047.html
22. Java 中的 Math.round(-1.5) 等于多少?
结果是:-1
round()是Math类中的一个四舍五入的方法.
-1.5+0.5=-1.0,然后-1.0向下取整结果为-1,最后的结果就是-1
问题的点就是计算规则中的+0.5,如果将-1.5换成+1.5的话结果就是
1.5+0.5=2.0,然后2.0向下取整结果为2

23. 如何实现对象的克隆?
有两种方式:
1). 实现Cloneable接口并重写Object类中的clone()方法;
2). 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。
24. 深克隆和浅克隆的区别?

public class Student implements Cloneable{
    private String name;
    private Integer age;
    private Grade grade;
    }

浅克隆只克隆基本数据属性,不会克隆对象属性引用的对象(也就是不会克隆Student对象引用的Grade对象),克隆前后两个对象的引用指向同一个对象。

25. 什么是 Java 的序列化,如何实现 Java 的序列化?
a.序列化形象的说就是将对象**“打碎”**了方便网络传输。打个比方,显示生活中如果想要自行车寄到另外一个地方,并不好寄,只有将自行车拆成多个零件进行寄。
b.只需要将需要序列化的对象实现Serializabel接口

26. 什么情况下需要序列化?
当 Java 对象需要在网络上传输 或者 持久化存储到文件中时,就需要对 Java 对象进行序列化处理。

27. Java 的泛型是如何工作的 ? 什么是类型擦除 ?
Java 泛型(Generic)的引入加强了参数类型的安全性,减少了类型的转换,但有一点需要注意:Java 的泛型在编译器有效,在运行期被删除,也就是说所有泛型参数类型在编译后都会被清除掉。

类型擦除
Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节代码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会被编译器在编译的时候去掉。这个过程就称为类型擦除。如在代码中定义的List和List等类型,在编译之后都会变成List。JVM看到的只是List,而由泛型附加的类型信息对JVM来说是不可见的。Java编译器会在编译时尽可能的发现可能出错的地方,但是仍然无法避免在运行时刻出现类型转换异常的情况。类型擦除也是Java的泛型实现方式与C++模板机制实现方式之间的重要区别。

28. 什么是泛型中的限定通配符和非限定通配符 ?

限定通配符对类型进行了限制。

  有两种限定通配符,一种是它通过确保类型必须是T的子类来设定类型的上界,另一种是它通过确保类型必须是T的父类来设定类型的下界。泛型类型必须用限定内的类型来进行初始化,否则会导致编译错误。另一方面表示了非限定通配符,因为可以用任意类型来替代。

即:限定通配符包括两种:

  1. 表示类型的上界,格式为:<? extends T>,即类型必须为T类型或者T子类
  2. 表示类型的下界,格式为:<? super T>,即类型必须为T类型或者T的父类
    非限定通配符:类型为,可以用任意类型来替代。

30. Java 中的反射是什么意思?有哪些应用场景?
反射比较重要,建议看视频或者看书好好学。
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的以及动态调用对象的方法的功能称为Java的反射机制。
应用场景:spring, java框架几乎都用到了
31. 反射的优缺点?
.反射的优点:
反射提高了程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创和控制任何类的对象,无需提前硬编码目标类

.反射的缺点
性能问题,使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用

32. Java 中的动态代理是什么?有哪些应用?
动态代理就是,在程序运行期,创建目标对象的代理对象,并对目标对象中的方法进行功能性增强的一种技术。在生成代理对象的过程中,目标对象不变,代理对象中的方法是目标对象方法的增强方法。可以理解为运行期间,对象中方法的动态拦截,在拦截方法的前后执行功能操作。
应用:aop,连接池

33. 怎么实现动态代理?
Java 中实现动态的方式:JDK 中的动态代理 和 Java类库 CGLib。

34. static 关键字的作用?
static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。
static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。
35. super 关键字的作用?
a.在子类的成员方法中,访问父类的成员变量。
b.在子类的成员方法中,访问父类的成员方法。
c.在子类的构造方法中,访问父类的构造方法。
36. 字节和字符的区别?
字节(Byte)是一种计量单位,表示数据量多少,它是计算机信息技术用于计量存储容量的一种计量单位。
在java中
1:char“字符”,byte“字节”,bit“位”;

2:1 byte = 8 bit;

3:char 在Java中是2个字节。java采用unicode,2个字节(16位)来表示一个字符。

  1. String 为什么要设计为不可变类?

1、便于实现字符串池(String pool)
在Java中,由于会大量的使用String常量,如果每一次声明一个String都创建一个String对象,那将会造成极大的空间资源的浪费。Java提出了String pool的概念,在堆中开辟一块存储空间String pool,当初始化一个String变量时,如果该字符串已经存在了,就不会去创建一个新的字符串变量,而是会返回已经存在了的字符串的引用。
2、使多线程安全

38. String、StringBuilder、StringBuffer 的区别?
String 字符串常量
StringBuffer 字符串变量(线程安全)
StringBuilder 字符串变量(非线程安全)

  1. String 字符串修改实现的原理?
    每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。

40. String str = “i” 与 String str = new String(“i”) 一样吗?

不一样,不是同一个对象, String是final类型的所以 str = "i"是常量,是放在常量池中的,而String str = new String(“i”) 是在堆中新new的对象。
41. String 类的常用方法都有那些?
1、和长度有关:

返回类型 方法名 作用
int length() 得到一个字符串的字符个数
2、和数组有关:

返回类型 方法名 作用
byte[] getByte() 将一个字符串转换成字节数组
char[] toCharArray() 将一个字符串转换成字符数组
String split(String) 将一个字符串按照指定内容劈开
3、和判断有关:

返回类型 方法名 作用
boolean equals() 判断两个字符串的内容是否一样
boolean equalsIsIgnoreCase(String) 忽略太小写的比较两个字符串的内容是否一样
boolean contains(String) 判断一个字符串里面是否包含指定的内容
boolean startsWith(String) 判断一个字符串是否以指定的内容开头
boolean endsWith(String) 判断一个字符串是否以指定的内容结尾
4、和改变内容有关:

返回类型 方法名 作用
String toUpperCase() 将一个字符串全部转换成大写
String toLowerCase() 将一个字符串全部转换成小写
String replace(String,String) 将某个内容全部替换成指定内容
String replaceAll(String,String) 将某个内容全部替换成指定内容,支持正则
String repalceFirst(String,String) 将第一次出现的某个内容替换成指定的内容
String substring(int) 从指定下标开始一直截取到字符串的最后
String substring(int,int) 从下标x截取到下标y-1对应的元素
String trim() 去除一个字符串的前后空格
5、和位置有关:

返回类型 方法名 作用
char charAt(int) 得到指定下标位置对应的字符
int indexOf(String) 得到指定内容第一次出现的下标
int lastIndexOf(String) 得到指定内容最后一次出现的下标

原文链接:https://blog.csdn.net/sinat_41920065/article/details/107439921

42. final 修饰 StringBuffer 后还可以 append 吗?

可以。final 修饰的是一个引用变量,那么这个引用始终只能指向这个对象,但是这个对象内部的属性是可以变化的。

final StringBuffer s = new StringBuffer();
final修饰的是变量,与对象如何改变一点关系都没有。
比如上面,final修饰的是变量s
后面你不能再赋值给变量s了,如:s = new StringBuffer();
但是s指向的对象还是可以改变的,如:s.append(“xxxx”);//
s.reverse()生成的是String对象

43. Java 中的 IO 流的分类?说出几个你熟悉的实现类?
(1)按流向分类:
输入流
输出流
(2)按处理数据不同分类:
字节流:二进制,可以处理一切文件,包括:纯文本、doc、音频、视频等。
字符流:文本文件,只能处理纯文本。
(3)按功能不同分类:
节点流:包裹源头。
处理流:增强功能,提高性能。

java后端开发面试题(java)_第3张图片

44. 字节流和字符流有什么区别?

实际上字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操作文件,如下图所示。
java后端开发面试题(java)_第4张图片
下面以两个写文件的操作为主进行比较,但是在操作时字节流和字符流的操作完成之后都不关闭输出流。

范例:使用字节流不关闭执行

package org.lxh.demo12.byteiodemo;    
import java.io.File;    
import java.io.FileOutputStream;    
import java.io.OutputStream;    
public class OutputStreamDemo05 {    
public static void main(String[] args) throws Exception {   // 异常抛出,  不处理    
// 第1步:使用File类找到一个文件    
     File f = new File("d:" + File.separator + "test.txt"); // 声明File  对象    
// 第2步:通过子类实例化父类对象    
     OutputStream out = null;            
// 准备好一个输出的对象    
     out = new FileOutputStream(f);      
// 通过对象多态性进行实例化    
// 第3步:进行写操作    
     String str = "Hello World!!!";      
// 准备一个字符串    
     byte b[] = str.getBytes();          
// 字符串转byte数组    
     out.write(b);                      
// 将内容输出    
 // 第4步:关闭输出流    
    // out.close();                  
// 此时没有关闭    
        }    
    } 

程序运行结果:
在这里插入图片描述
此时没有关闭字节流操作,但是文件中也依然存在了输出的内容,证明字节流是直接操作文件本身的。而下面继续使用字符流完成,再观察效果。

范例:使用字符流不关闭执行

package org.lxh.demo12.chariodemo;    
import java.io.File;    
import java.io.FileWriter;    
import java.io.Writer;    
public class WriterDemo03 {    
    public static void main(String[] args) throws Exception { // 异常抛出,  不处理    
        // 第1步:使用File类找到一个文件    
        File f = new File("d:" + File.separator + "test.txt");// 声明File 对象    
        // 第2步:通过子类实例化父类对象    
        Writer out = null;                 
// 准备好一个输出的对象    
        out = new FileWriter(f);            
// 通过对象多态性进行实例化    
        // 第3步:进行写操作    
        String str = "Hello World!!!";      
// 准备一个字符串    
        out.write(str);                    
// 将内容输出    
        // 第4步:关闭输出流    
        // out.close();                   
// 此时没有关闭    
    }    
}   

程序运行结果:
在这里插入图片描述
程序运行后会发现文件中没有任何内容,这是因为字符流操作时使用了缓冲区,而 在关闭字符流时会强制性地将缓冲区中的内容进行输出,但是如果程序没有关闭,则缓冲区中的内容是无法输出的,所以得出结论:字符流使用了缓冲区,而字节流没有使用缓冲区。
转载自:https://blog.csdn.net/cynhafa/article/details/6882061
字节流:二进制,可以处理一切文件,包括:纯文本、doc、音频、视频等。
字符流:文本文件,只能处理纯文本。

45. BIO、NIO、AIO 有什么区别?

你可能感兴趣的:(java,java,后端,开发语言)