Java面试基础(会持续更新)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_43082579/article/details/102744051

Java面试基础

我只是一个练习搬砖的搬运工。。。

1、Java基础

(1)面向对象的特征:继承封装和多态

①继承:

继承实现了IS-A关系,例如Cat和Animal就是一种IS-A关系,因此Cat可以继承Animal,从而获得Animal非private的属性和方法。
Cat可以当做Animal来使用,也就是说可以使用Animal引用Cat对象。父类引用指向对象称为向上转型。

   Animal animal=new Cat()

继承应该遵循里氏替换原则,子类对象必须能够替换掉所有父类对象。

②封装:

利用抽象数据类型将数据和基于数据的操作封装在一起,使其能构成一个不可分割的独立实体。数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系。用户无需知道对象内容的细节,但可以通过对象对外提供的接口来访问该对象。
封装有三大好处:减少耦合;隐藏内部细节,因此内部结构可以自由修改;可以对成员进行更精确的控制。

③多态:

多态分为编译时多态和运行时多态。编译时多态主要指方法的多态,运行时多态指程序中定义的对象引用所指向的具体类型在运行期间才确定。
运行时多态有三个条件:继承;覆盖;向上转型。

(2)final、finally和finalize的区别

final:修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承,因此一个类不能既被声明为abstract的,又被声明为final。将变量和方法声明为final变量的,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取不可以被修改。被声明为final的方法也同样只能使用不能重载。

finall:在异常处理时提供finally块来执行任何清除操作。如果抛出一个异常,那么匹配的catch子句就会执行,然后控制就会进入finally块(如果有的话)。如果同时有多个return,会先执行完finally语句中的代码,再执行finally中的return。

finalize:方法名。Java技术允许finalize()方法在垃圾收集器将对象从内存中清除出去之前做好必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用的情况下对这个对象的调用。它是在object类中定义的,因此所有的类都继承了它。子类覆盖finalize()方法以收集整理系统资源或者执行其他清理工作。finalize()方法是在垃圾收集器删除对象之前对这个对象的调用。

(3)Exception、Error、运行时异常与一般异常有何异同

Throwable可以用来表示任何可以作为异常抛出的类,分为两种:Error和Exception。其中Error用来表示JVM无法处理的错误。
异常类Exception又分为运行时异常和非运行时异常。Java异常又可以分为不受检查异常和检查异常。
Error:Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。
Exception:在Exception分支中有一个重要的子类RuntimeException(运行时异常),该类型的异常自动为你所编写的程序定义ArrayIndexOutOfBoundsException(数组下标越界)、NullPointerException(空指针异常)、ArithmeticException(算术异常)、MissingRescourceException(丢失异常)、ClassNotFoundException(找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以选择不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生;而RuntimeException之外的异常我们统称为非运行时异常,类型上属于Exception类及其子类,从程序的角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。

(4)写出五种常见的runtime Exception

NullPointerException 空指针异常
ClassCastException 类型强制转换异常
IllegalArgumentException 算术异常
IndexOutOfBoundsException 下标越界异常
ArrayStoreException 向数组中存放与声明类型不兼容对象异常
等。。。。

(5)int和Integer区别,Integer的值缓存范围

int是基本数据类型,直接存数值,进行初始化时int类的变量初始为0。
Integer是对象,用一个引用指向这个对象,Integer的变量则初始化为null。
给一个Integer对象赋一个int值的时候,会调用Integer类的静态方法valueOf
JVM会自动维护八种基本的常量池,int常量池中初始化-128~127的范围,所以当为Integer I=127 时,在自动装箱过程中是取自常量池中的数值,而当Integer i=128时,128不在常量池范围类,所以在自动装箱过程中需new 128,所以地址不一样。
①当数值范围为-129~127时:如果两个new出来Integer对象,即使值相同,通过“==”比较结果为false,但两个对象直接赋值,则通过“==”比较结果为true,这一点与String非常相似。
②当数值不在-128~127时,无论通过哪种方式,即使两个对象的值相等,通过“==”比较,结果为false。
③当一个Integer对象直接与一个int基本数据类型通过“==”比较,其结果与第一点相同。
④Integer对象的hash值为数值本身。
Integer对象的范围是-128~127:一个私有的静态内部类IntegerCache,而如果直接将一个基本数据类型的值赋值给Integer对象,则会发生自动装箱,其原理就是通过调用Integer类的public static Integer valueOf()将int类型的值包装到一个对象中。
一个字节占8bit,由于计算机只能识别二进制,即0和1。所以规定第一位是一个符号位,1表示负数,0表示正数,这里涉及到补码。
int的数值范围是-231~231-1(int占4个字节,即32bit)。

(6)包装类、装箱和拆箱

包装类(原始类型对应的类,即Boolean,Byte,Short,Integer,Long,Float,Double,Character)的自动拆、装箱分别是指如下的过程:
装箱:是指基本类型变为包装类型的过程,如Integer a=Integer.valueOf(100);或者int a=100; Integer b=new Integer(a);这里的Integer a=Integer.valueOf(100);new Integer(a);就是装箱,由基本数据类型构造出一个包装的对象。
拆箱:就是装箱的逆过程。如Integer a=Integer.valueOf(100); int b=a.intValue();这里的a.intValue()就是拆箱的过程,由一个包装类对象装换到相应的基本数据类型。
自动装箱、拆箱:指编译器帮助开发人员完成包装类的装箱和拆箱过程,也就是在将*.Java文件编译成*.class文件的过程中完成。
包装类的自动装箱和拆箱规则如下:

  1. 遇到赋值运算符“=”(包括传参数,参数传递属于隐式赋值)时,会将包装类拆箱为相应类型;
  2. 遇到算术运算符、位运算和位移运算符“+,++,–,-,*,/,%,&,|,……,~,<<,>>,>>>”时,对包装类进行拆箱;
  3. 遇到关系运算符“>,<,>=,<=”(不包括“==”和“!=”)是,对包装类进行拆箱
  4. 对关系运算符“==”和“!=”而言,遇到数字常量或者算术表达式时,才对包装进行拆箱。

其余情况下,不进行自动的装箱和拆箱。
包装类的equals方法不支持数据类型的自动转换。

(7)String、StringBuilder和StringBuffer

String,StringBuilder,StringBuffer 三者的区别主要是在两个方面,即运行速度和线程安全这两方面。
5. 运行速度,或者说执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer >String ,String最慢的原因:String为字符串常量,而StringBuild和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的。
6. 线程安全:在线程安全上,StringBuilder 是线程不安全的,而StringBuffer是线程安全的。
如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。
String:适用于少量的字符串操作的情况;
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况;
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况。

(8)重载和重写有什么区别

方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。

① 重载Overloading

  1. 方法重载是让类一统一的方式处理不同类型数据的一种手段。多个同名函数同时存在,具有不同的参数个数/类型。重载是一个类中多态性的一种表现。
  2. Java的方法重载,就是在类中可以创建多个方法。它们具有相同的名字,但具有不同的参数和不同的定义。调用方法时通过传递给他们的不同参数个数和参数类型来决定具体使用哪个方法,这就是多态性。
  3. 重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同也可以不同。但是!不能以返回值类型作为重载函数的区分标准!

② 重写overriding

  1. 父类与子类之间的多态性,对父类的函数进行重新定义。如果在子类中定义某方法与父类有相同的名称和参数,我们说方法被重写(overridiing)。在Java中,子类可继承父类的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就是需要采用方法的重写。方法重写又称方法覆盖。
  2. 若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。
  3. 子类函数的访问修饰权限不能少于父类的。

持续搬砖中。。。

猜你喜欢

转载自blog.csdn.net/weixin_43082579/article/details/102744051