1、JDK 、JRE、JVM是什么?有什么区别与联系?

JDK:java Development Kit 是一种java开发工具,主要提供了java运行环境和开发环境
JRE:java Resourse Environment 是一种java运行时的环境。
jvm:java virtual machine java虚拟机,java的字节码会存储在jvm中

JDK=JRE+java开发工具(javac等)
JRE=JVM+lib(解释jvm的类库)
JVM是Java实现跨平台最核心的部分,所有的Java程序会首先被编译为.class的类文件,JVM的主要工作是解释自己的指令集(即字节码)并映射到本地的CPU的指令集或OS的系统调用。

2、大小端字节序,java是属于哪一种字节序

大端字节序:以二进制进行存储,其中高位存储在低位地址上,低位存储在高位地址上;
小端字节序:以二进制进行存储,其中高位存储在高位地址上,低位存储在低位地址上;
网络字节序:网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian(大端)排序方式。

3、数组相关面试题?八大排序算法

1、冒泡排序:遍历数组,两两进行比较,按照升序/降序的要求进行交换。
2、插入排序:将数组分为有序数组和无序数组,遍历无序数组,然后将当前元素从后往前和有序数组依次进行比较,根据升序/降序的要求插入到指定的位置,直至遍历完所以的无序数组。
3、选择排序:遍历数组,根据升序/降序的要求从当前序列中找到最小值/最大值放到序列的最前面,然后再对未排序的序列进行选择排序。
4、快速排序:选择一个基准元素,将数组中所有小于基准元素都放在左边,所有大于基准元素的值都放在右边,然后将左边和右边序列的数组按照同样的规则进行排序,直至整个数组有序。
5、分治排序:将长度为n的数组拆分成长度为1的子序列,然后将子序列按照要求进行两两合并,形成n/2个长度为2的子序列,然后将子序列两两合并,形成长度为4的子序列,依次将子序列进行合并,直至长度为n
6、桶排序:创建一个代表0-9的桶,以数组形式表示,按照数组的位数大小依次进行排序,根据数组元素的位数大小放入到桶的对应位置,然后依次将其取出,重复操作,直至数组有序。
7、希尔排序:将整个原始数组拆分为若干个子序列(以相隔*个增量组成),然后对子序列依次进行插入排序。依次缩短增量,进行插入排序,直至数组有序。
8、基于二叉树的堆排序:将数组以二叉树的形式进行构建,首先根据升序/降序要求构建大顶堆/小顶堆,其中大顶堆是指当前节点的值大于其任一子节点,然后将根元素沉积到数组的末尾后,对剩下序列再构建大/小顶堆,将根元素沉积到数组的末尾。重复操作,直至数组有序。
image.png

4、Java语言的特点

1、Java语言是面向对象的语言,可以直接反映我们的对象的特征;
2、Java语言具有平台无关性,Java运行时首先将源文件编译成.class字节码文件,然后利用jvm虚拟机进行字节码文件的运行,所以无论是在再windows、mac、linux系统中都能实现java代码的编译
3、Java为解释性语言,编译器将java代码编译成字节码文件在虚拟机上进行解释运行,具有很好的可移植性。
4、Java内部提供了很对内置类库,例如多线程的支持、网络编程的支持,此外还提供了垃圾回收机制
5、Java内部提供了垃圾回收机制,使其具有安全性和健壮性
6、Java语言还支持对web应用的开发。

面向对象编程相关面试题

5、Java面向对象的特点

1、区分面向过程和面向对象
面向过程更加注重解决问题的过程,面向对象更加强调对象,易于拓展维护。
2、面向对象三大特性(继承、封装、多态)
封装性:提供了四种修饰符修饰类及其内部结构,体现了类及其内部结构被外部调用时其可见性的大小,内部细节对外部调用透明,外部调用时无需修改和关注具体的实现内容。例如我们利用mybatis操作数据库时,无需关心数据库连接是怎么建立,sql语句是怎么执行的,只需要调用方法即可。
继承性:子类继承基类,可以对继承的属性和方法进行适当改变和拓展,满足不同的需求,提高了代码的复用性,同时也加强了类与类之间的联系。
多态性:基于对象所属的类不同,外部对同一个方法的调用,实际执行的逻辑不同。

6、四种权限修饰符

private:在同一类中可见,不能用来修饰类
protected:在同一包内的所有类和子类可见,不能用来修饰类
default:在同一包内可见
public:对所有类可见。

7、属性的赋值及其先后顺序

按照先后顺序排列,可分为:
成员变量默认初始化—>代码块进行属性赋值/显示初始化(局部变量直接赋值)->构造器赋值->通过调用对象·方法或者对象·属性调用。

8、非静态变量、静态变量、静态代码块的执行顺序

父类静态变量->父类静态代码块->子类静态变量->子类静态代码块->父类非静态变量->父类非静态代码块->父类构造方法->子类非静态变量->子类非静态代码块->子类构造方法

9、方法的重写和重载的联系与区别?

重载:发生在同一类中,方法名必须不同,参数类型不同、个数不同、顺序不同,方法的重载与返回值的类型和访问修饰符无关,重载发生在编译时。
如 private int add(int a ,int b)和private String add(int a,int b)不属于方法的重载
重写:重写一般发生在父类的子类中,方法名和参数列表必须相同,但是父类的方法如果是用private修饰的,那么子类将无法对该方法进行重写,方法的重写了体现了面向对象的多态性。此外,子类重写的方法返回值范围小于等于父类,抛出的异常小于等于父类的方法。

10、接口和抽象类的区别?

相同点:
1、两者都不能被实例化
2、接口的实现类和继承抽象类的子类必须重写接口和抽象类当中的方法才能被实例化。
不同点:
1、抽象类中可以存在普通成员函数,而接口中都是public abstract函数
2、抽象类只能继承一个,接口可以实现多个
3、抽象类的成员变量可以是多种类型的,而接口中的成员变量默认就说public static final静态常量
从设计目的来看:
1、接口的设计目的是为了对类有一个约束,也就是提供一种机制,要求不同的类具有相同的行为,但是只关心行为的有无,不关心具体行为的内容。
2、抽象类的设计目的是为了代码复用,是对类本质的抽象,当不同类具有相同的行为时,且其实现方式一致时,可以让这些类都继承于一个抽象类,在这个抽象类中实现类某些方法,避免让所有子类来实现B,达到代码复用的功能。而且由于抽象类中还存在一些抽象方法,供子类自己去实现,也因此抽象类不能实例化。

11、Java为什么不支持多重继承?

1、为了维护java代码结构更加清晰且易于维护,比如说子类C多重继承了父类A和父类B,且父类A和父类B中都定义了成员方法f(),那么子类C调用该方法时,不知道执行哪一个方法,造成混乱。因此,Java代码通过实现多个接口来支持多重继承,接口中只包含方法的定义,不包含方法具体的实现,子类C需要自己重写接口的方法,这样调用时就不会产生歧义。
2、多重继承会导致类型转换、构造方法的调用顺序变得复杂,影响运行的性能。

12、final、finally、finalize的区别分别是什么?

1、final可以用来修饰类、方法和属性,其中:
1)当final修饰类时,表示该类不可以被继承。
2)final修饰方法时,表示该方法不能被重写,但可以被重载。
3)final修饰变量时,表示变量一旦被赋值就不能被修改:
final修饰成员变量时:
final修饰静态变量时,那么只能在声明的时候或者静态代码块中对变量进行赋值
final修饰成员变量时,可以在非静态代码块、声明该变量或者构造器中对该变量进行赋值。
当final修饰局部变量时:
系统不会对该变量进行初始化,该局部变量必须由程序员显示初始化,或者在后面的代码中对final修饰的变量进行赋值(只能进行依次赋值)。
4)如果final修饰数据类型时:
如果final修饰基本数据类型时,则其数值一旦赋值就不能再被修改
如果final修饰的引用数据类型时,则其引用的地址一旦被确定就不能再被改变。
2、finally作为异常处理的一部分,通常与try catch配合使用,finally附带一个语句块表示该部分的语句一定会被执行,通常使用finally来执行资源的释放。
3、finalize是在垃圾收集器执行是会调用的一个方法,finalize()方法,当垃圾回收期准备好释放对象内存时,首先会调用finalize()方法,并在下一次垃圾回收动作发生时真正回收对象的内存。

13、匿名内部类和局部内部类只能访问局部final变量。

  1. public static void test(final String s){
  2. //或final String s = "axman";
  3. ABSClass c = new ABSClass(){
  4. public void m(){
  5. int x = s.hashCode();
  6. System.out.println(x);
  7. }
  8. };
  9. //其它代码.
  10. }
  1. 局部内部类(包含匿名内部类)的生命周期和局部变量的生命周期是不一致的,内部类的生命周期是和外部类的生命周期是一致的,当方法运行结束,局部变量也一同被销毁,那么内部类该如何访问到不存在的局部变量呢?<br />其实是将局部变量复制了一份作为内部类的成员变量,这样当局部变量销毁时,内部类还可以访问这个局部变量,实际访问的是它的copy值,但是为了保证在复制过程中两个变量一致,所以将该局部变量设置为final,当对变量赋值后,就无法再进行修改,保证了内部类访问的变量和局部变量的一致,本质是一种内部类为了访问局部变量的妥协。

14、static关键词

主要是为某种特定数据类型或对象分配与创建与对象创建个数无关的单一存储空间。
具体而言,static关键字可以修饰成员变量、成员方法、修饰代码块、修饰内部类,其中:
static修饰成员变量时,该变量在内存中只占一个副本,随着类的加载而加载,创建了类的多个对象时,多个对象共享一个静态变量,当某个对象修改这个变量时,会导致其他对象的该变量也进行修改,例如Math.PI表示为静态变量。
static修饰成员方法时,表示该方法为静态方法,随着类的加载而创建。静态方法中只能调用静态的属性和静态方法。例如工具类的方法常声明为static,
static修饰代码块:静态代码块,会在类加载的时候进行加载,通常是用于静态变量的初始化,只会被执行依次
static修饰的内部类:静态内部可以不依赖于外部类的对象而进行实例化,静态内部类不能与外部类有同样的名字,静态内部类不能访问普通成员变量,只能访问外部类中的静态成员变量和静态方法。

15 ==和equals()方法的区别

1) ==
如果==比较的是基本数据类型,那么==比较的是两个变量保存的数据值是否相等,
如果==比较的是引用数据类型,那么比较的是两个变量的引用地址是否相等。
2) equals()方法,只能用来比较引用类型数据
如比较的数据没有重写euqals()方法,那么比较的是引用的地址是否相等;
如果比较的的数据重写了euqals()方法,如String类型、Date类型等重写了equals()方法,那么就会比较重写以后两个变量的”实体内容”是否相等。

16、内部类是什么?内部类设计的好处?

在类的内部定义另一个类,在类里面的这个类就是内部类,类的外面就说外部类。
内部类的好处在于能够1、隐藏不想让别人知道的操作,也就是我们所说的封装性;2、一个内部类可以访问创建它的外部类的对象的内容,包括私有的成员变量。
一般我们在采用事件监听器时候会用到内部类。

异常处理相关面试题

17、简述异常的分类

Java异常主要可以分为Error(表示不可处理的错误)和Exception(可以处理的异常),均继承于Throwable。
其中Error错误主要有StackOverFlowError 和OutofMemoryError等错误
Exception可以分为运行时异常和非运行时异常,其中运行时异常可以用try catch来处理,也可以不处理;但是非运行时异常必须处理,否则就会编译错误。
异常的处理方式主要有两种,throw一般用于方法体内部,由程序员发现异常后出动抛出一个异常;throws一般在方法声明中,代表该方法可能会抛出异常。

18、finally语句一定会被执行吗?

不一定,当程序进入try语句之前若已经发生了异常,那么就会直接结束;当代码在try块中强制退出,若System.exit(0)时,就会直接结束,也不会执行finally中的语句。
一般情况下,try/catch/finally语句执行后,try块先执行,发现异常,然后catch和finally进行处理后程序就结束了,当没有异常发生时,finally语句执行完成后,会继续执行下面的代码。注:当try/catch中有return返回值时,finally中的语句会在return前执行;当try/catch/finally中都有return值时,finally语句中的return值会覆盖掉前面的return值。

String字符串类相关面试题

19、String、StringBuilder和StringBuffer的区别及其使用场景

String其底层源码是用final修饰字符数组进行字符串的保存,一经创建就不可变,每次操作都会产生一个新的String对象。
StringBuilder和StringBuffer都是在原对象的基础上进行操作的,其中StringBuilder是线程不安全的,StringBuffer是线程安全的,其方法是用synchronized进行修饰的。
性能方面,StringBuilder>StringBuffer>String,一般我们需要对字符串进行频繁的操作时,优先考虑使用StringBuilder,在多线程操作共享变量时,采用StringBuffer。

20、String字符串为什么设计成不变的

1、节省空间:字符串被存放在JVM堆空间中的字符串常量池,可以被用户共享
2、提高效率:String字符串会被不同线程共享,是线程安全的,涉及多线程时可以不用同步操作
3、安全性:由于String字符串不可修改,一般用来存储账号、密码等信息,可以防止被恶意篡改。