小豹子的 Java 面试知识点(一)基本功 Part 1

1,395 阅读7分钟

鸣谢:本文中 Java 知识点题目来源于微信公众号“服务端思维”,经作者授权后,作答并发布至掘金。

1 基本功

1.1 面向对象的特征

封装、继承、多态。

  • 封装:把客观事物封装成抽象的类,对调用者屏蔽细节,控制数据和方法的权限。
  • 继承:使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
    继承概念的实现方式有三类:实现继承接口继承可视继承
    实现继承是指使用基类的属性和方法而无需额外编码的能力;
    接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力;
    可视继承是指子窗体(类)使用基窗体(类)的外观和实现代码的能力。
  • 多态:计算机程序运行时,相同的消息可能会送给多个不同的类别之对象,而系统可依据对象所属类别,引发对应类别的方法,而有不同的行为。简单来说,所谓多态意指相同的消息给予不同的对象会引发不同的动作称之。
    多态可分为变量多态与函数多态。变量多态是指:基类型的变量(对于 Java 是引用)可以被赋值基类型对象,也可以被赋值派生类型的对象。函数多态是指,相同的函数调用界面(函数名与实参表),传送给一个对象变量,可以有不同的行为,这视该对象变量所指向的对象类型而定。因此,变量多态是函数多态的基础。

1.2 final, finally, finalize 的区别

  • final:用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。
  • finally:是异常处理语句结构的一部分,表示总是执行。
  • finalize:是 Object 类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。JVM 不保证此方法总被调用。

PS:除了长得像,还有啥相似之处么?

1.3 int 和 Integer 有什么区别

项目 int Integer
是否为对象
位于内存
默认值 0 null
何时回收 随执行栈弹出而回收 由 gc 回收
判断值相等 == equals

扩展:

a. int 与 Integer 的应用场景分别是什么

在阿里巴巴 Java 开发手册的第一章第四项第八条中,有如下规定:

关于基本数据类型与包装数据类型的使用标准如下:
1)【强制】所有的 POJO 类属性必须使用包装数据类型。
2)【强制】 RPC 方法的返回值和参数必须使用包装数据类型。
3)【推荐】所有的局部变量使用基本数据类型。
说明:POJO 类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何 NPE 问题,或者入库检查,都由使用者来保证。
正例:数据库的查询结果可能是 null,因为自动拆箱,用基本数据类型接收有 NPE 风险。
反例:比如显示成交总额涨跌情况,即正负 x%,x 为基本数据类型,调用的 RPC 服务,调用不成功时,返回的是默认值,页面显示为 0%,这是不合理的,应该显示成中划线。所以包装数据类型的 null 值,能够表示额外的信息,如:远程调用失败,异常退出。

因此我们得出,在业务逻辑上 null 值具有一定意义的,应该使用 Integer;否则使用 int 效率高。

b. 为什么 Integer 在 -128 至 127 范围内时可以用 == 判断值相等

对于 Integer var = ? 在-128 至 127 范围内的赋值,Integer 对象是在 IntegerCache.cache 产生,会复用已有对象,这个区间内的 Integer 值可以直接使用 == 进行 判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑, 推荐使用 equals 方法进行判断。

摘自阿里巴巴 Java 开发手册。

1.4 重载和重写的区别

重载(Overload)

重载是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。

重载规则:

  • 被重载的方法必须改变参数列表(参数个数或类型或顺序不一样);
  • 被重载的方法可以改变返回类型;
  • 被重载的方法可以改变访问修饰符;
  • 被重载的方法可以声明新的或更广的检查异常;
  • 方法能够在同一个类中或者在一个子类中被重载。
  • 无法以返回值类型作为重载函数的区分标准。

重写(Override)

重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。

方法的重写规则

  • 参数列表必须完全与被重写方法的相同;
  • 返回类型必须完全与被重写方法的返回类型相同;
  • 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public ,那么在子类中重写该方法就不能声明为 protected。
  • 父类的成员方法只能被它的子类重写。
  • 声明为 final 的方法不能被重写。
  • 声明为 static 的方法不能被重写,但是能够被再次声明。
  • 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。
  • 子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。
  • 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
  • 构造方法不能被重写。
  • 如果不能继承一个方法,则不能重写这个方法。

1.5 抽象类和接口有什么区别

  • 抽象类可以有方法实现,也可以不实现方法;接口根本不存在方法的实现(Java 1.8 中添加了接口默认方法)。
  • 抽象类的子类使用 extends 来继承抽象类,一个子类只能继承一个父类(包括抽象类);接口的实现类使用 implements 来实现接口,实现类可以实现多个接口。
  • 抽象类可以有构造器;接口不能有构造器
  • 抽象方法可以有public、protected和default这些修饰符;接口方法默认修饰符是public。你不可以使用其它修饰符(Java 1.8 中允许在接口中使用 default)。

1.6 说说反射的用途及实现

反射,个人通俗的理解是:通过某种方式在运行期任意类进行操作(查找方法、字段,获取方法参数表,执行方法,修改方法等),这种方式称为反射。 反射最大的应用就是框架,通过传递一个字符串值 去调用某一个类的方法。例如 Web框架中的路由器,绝大多数基于反射。另外注解操作、动态代理也要基于反射。

反射的实现在 Java 应用层面上讲,是通过对 Class 对象的操作实现的,Class 对象为我们提供了一系列方法对类进行操作。在 Jvm 这个角度来说,Class 文件是一组以 8 位字节为基础单位的二进制流,各个数据项目按严格的顺序紧凑的排列在 Class 文件中,里面包含了类、方法、字段等等相关数据。通过对 Claas 数据流的处理我们即可得到字段、方法等数据。