1 面向对象的特点有哪些?
抽象、继承、封装、多态
2 抽象类和普通类的区别?
- 抽象方法的访问修饰符必须为 public 和 protected。
- 抽象类不能被实例化。
- 如果一个类继承于抽象类,则子类必须实现父类的抽象方法,如果子类没有实现父类的抽象方法,则子类必须也一个抽象类。
3 抽象类和接口的区别?
- 一个类只能继承一个抽象类,而一个类可以实现多个接口。
- 抽象类可以有构造方法,接口中不能有构造方法。
- 抽象类中可以有成员变量,接口中没有成员变量。(被 final 修饰变成了常量)
- 抽象类中可以有普通方法,接口中所有方法都必须是抽象的。(1.8后允许接口定义非抽象方法)
- 抽象类中抽象方法的访问类型可以是 public,protected,但接口中抽象方法的访问类型只能是public,并且默认为 public abstract(省略则自动默认补全)。
- 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的;
- 抽象类中可以有静态代码块和静态方法,接口中不能含有静态代码块以及静态方法
4 重载(Overload)的特点
- 在使用重载时只能通过不同的参数样式。例如,不同的参数类型,不同的参数个数,不同的参数顺序(当然,同一方法内的几个参数类型必须不一样,例如可以是fun(int,float), 但是不能为fun(int, int));
- 不能通过访问权限、返回类型、抛出的异常进行重载;
- 方法的异常类型和数目不会对重载造成影响;
- 对于继承来说,如果某一方法在父类中是访问权限是 priavte,那么就不能在子类对其进行重载,如果定义的话,也只是定义了一个新方法,而不会达到重载的效果。
5 重写(Override)的特点
- 覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配,才能达到覆盖的效果;
- 覆盖的方法的返回值必须和被覆盖的方法的返回一致;
- 覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其子类;
- 被覆盖的方法不能为 private,否则在其子类中只是新定义了一个方法,并没有对其进行覆盖。
- 子类方法不能缩小父类方法的访问权限。
- 方法被定义为 final 不能被重写。
6 基本类型
java 的基本类型如下:
- 整型:byte(1字节)、short(2字节)、int(4字节)、long(8字节)
- 浮点型:float(4字节)、double(8字节)
- 字符型:char(2字节)
- 布尔类型:boolean(1字节)
其中数据类型转换(自动),即较小的类型转换为一个更大的类型,为: byte -> short -> char -> int -> long -> float ->double
7 自动拆箱和自动装箱
在 Java SE5 中,为了减少开发人员的工作,Java 提供了自动拆箱与自动装箱功能。自动装箱就是将基本数据类型自动转换成对应的包装类,自动拆箱就是将包装类自动转换成对应的基本数据类型。
哪些场景会发生装箱与拆箱?
- 将基本数据类型放入集合类
- 包装类型和基本类型的大小比较
- 包装类型的运算
- 三目运算符的使用
- 函数参数与返回值
8 Java 类的实例化顺序?
其顺序为:
- 父类静态成员和静态代码块
- 子类静态成员和静态代码块
- 父类非静态成员和非静态代码块
- 父类构造方法
- 子类非静态成员和非静态代码块
- 子类构造方法
9 值传递与引用传递
关于值传递与引用传递,这个问题一般是相对函数而言的,即 java 中的方法参数。值传递指的是方法接收的是调用着提供的值,引用传递指的是方法接收的是调用者提供的变量地址(C 语言的指针)。值传递与引用传递的根本区别是一个方法可以修改传递引用所对应的变量值,而不能修改传递值调用所对应的变量值。在 java 中并不存在引用调用,方法得到的是所有参数值的一个拷贝,方法并不能修改传递给它的任何参数变量的内容。
- 一个方法不能修改一个基本数据类型的参数(数值型和布尔型),这里使用的是值传递。
- 一个方法可以修改一个引用所指向的对象状态,但这仍然是值传递而非引用传递。
10 final 修饰符的作用
final 表示无法改变。
- final 类不能被继承,没有子类,final 类中的方法默认是 final 的。
- final 方法不能被子类的方法覆盖,但可以被继承。
- final 成员变量表示常量,只能被赋值一次,赋值后值不再改变。
- final 不能用于修饰构造方法。
11 String,StringBuilder,StringBuffer 的区别?
- String 是不可变的,而 StringBuilder 和 StringBuffer 是可变的。
- 运行速度快慢为:StringBuilder > StringBuffer > String。
- StringBuilder 是线程不安全的,而 StringBuffer,String 是线程安全的。
12 Error 与 Exception 的区别?
事实上,Java 的异常可以分为以下三类:
- 错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
- 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
- 运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
所有异常类型都是内置类 Throwable 的子类,因而 Throwable 在异常类的层次结构的顶层。接下来 Throwable 分成了两个不同的分支,一个分支是 Error,它表示不希望被程序捕获或者是程序无法处理的错误。另一个分支是 Exception,它表示用户程序可能捕捉的异常情况或者说是程序可以处理的异常。其中异常类 Exception 又分为运行时异常( RuntimeException )和非运行时异常。
- Error:Error 类对象由 Java 虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。例如,Java虚拟机运行错误(Virtual MachineError),当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java 虚拟机(JVM)一般会选择线程终止;还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError)、链接错误(LinkageError)。这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。在 Java 中,错误通常是使用 Error 的子类描述。
- Exception:在 Exception 分支中有一个重要的子类 RuntimeException(运行时异常),该类型的异常自动为你所编写的程序定义 ArrayIndexOutOfBoundsException(数组下标越界)、NullPointerException(空指针异常)、ArithmeticException(算术异常)、MissingResourceException(丢失资源)、ClassNotFoundException(找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生;而 RuntimeException 之外的异常我们统称为非运行时异常,类型上属于 Exception 类及其子类,从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如 IOException、SQLException 等以及用户自定义的 Exception 异常,一般情况下不自定义检查异常。
13 throw 和 throws 的区别?
- throw 语句用在方法体内,表示抛出异常,由方法体内的语句处理。 throws 语句用在方法声明后面,表示抛出异常,由该方法的调用者来处理。
- throws 主要是声明这个方法会抛出这种类型的异常,使它的调用者知道要捕获这个异常。 throw 是当程序出现某种逻辑错误时由程序员主动抛出某种特定类型的异常是,具体向外抛异常的动作,所以它是抛出一个异常实例。
- throws 表示出现异常的一种可能性,并不一定会发生这些异常;throw 则是抛出了异常,执行 throw 则一定抛出了某种异常对象。
- 两者都是消极处理异常的方式(这里的消极并不是说这种方式不好),只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。
14 JDK、JRE、JVM 的区别?
14.1 什么是 JDK?
JDK (Java Development Kit) 是整个 JAVA 的核心,是 Java 语言的软件开发工具包 (SDK),包括了 Java 运行环境(Java Runtime Envirnment),一堆Java工具(javac/java/jdb 等)和 Java 基础的类库(即 Java API 包括 rt.jar )。
JDK 是 java 开发工具包,基本上每个学 java 的人都会先在机器 上装一个 JDK,那它都包含哪几部分呢?在目录下面有六个文件夹、一个 src 类库源码压缩包、和其他几个声明文件。其中,真正在运行 java 时起作用的是以下四个文件夹:bin(最主要的是编译器)、include( java 和 JVM 交互用的头文件)、lib(类库)、 jre(java 运行环境)。有这样一个关系,JDK 包含 JRE,而 JRE 包含 JVM。
jre 目录里面有两个文件夹 bin 和 lib,在这里可以认为 bin 里的就是 jvm,lib 中则是 jvm 工作所需要的类库,而 jvm 和 lib 合起来就称为 jre。
总的来说 JDK 是用于 java 程序的开发,而 jre 则是只能运行 class 而没有编译的功能。
14.2 什么是 JRE?
JRE(Java Runtime Environment,Java 运行环境),包含 JVM 标准实现及 Java 核心类库。JRE 是 Java 运行环境,并不是一个开发环境,所以没有包含任何开发工具(如编译器和调试器)。
JRE 是指 java 运行环境。光有 JVM 还不能完成 class 的执行,因为在解释 class 的时候 JVM 需要调用解释所需要的类库 lib。 (jre 里有运行.class 的 java.exe)。
JRE 是运行 Java 程序必不可少的(除非用其他一些编译环境编译成 .exe 可执行文件),JRE 的地位就象一台 PC 机一样,我们写好的 Win64 应用程序需要操作系统帮我们运行,同样的,我们编写的 Java 程序也必须要 JRE 才能运行。
14.3 什么是 JVM?
JVM(Java Virtual Machine),即 java 虚拟机,是 java 运行时的环境,JVM 是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。针对 java 用户,也就是拥有可运行的.class 文件包(jar 或者 war)的用户。里面主要包含了 jvm 和 java 运行时基本类库(rt.jar)。rt.jar 可以简单粗暴地理解为:它就是 java 源码编译成的 jar 包。Java 虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是 Java 的能够“一次编译,到处运行”的原因。
14.4 JDK、JRE、JVM 三者的联系?
JVM 不能单独搞定 class 的执行,解释 class 的时候 JVM 需要调用解释所需要的类库 lib。在 JDK 下面的的 jre 目录里面有两个文件夹 bin 和 lib,在这里可以认为 bin 里的就是 jvm,lib 中则是 jvm 工作所需要的类库,而 jvm 和 lib 和起来就称为 jre,jvm + lib = JRE。总体来说就是,我们利用 JDK(调用 JAVA API)开发了属于我们自己的 JAVA 程序后,通过 JDK 中的编译程序(javac)将我们的文本 java 文件编译成 JAVA 字节码,在 JRE 上运行这些 JAVA 字节码,JVM 解析这些字节码,映射到 CPU 指令集或 OS 的系统调用。
14.5 JDK、JRE 的区别?
在 bin 文件夹下会发现,JDK 有 javac.exe 而 JRE 里面没有,javac 指令是用来将 java 文件编译成 class 文件的,这是开发者需要的,而用户(只需要运行的人)是不需要的。JDK 还有 jar.exe, javadoc.exe 等等用于开发的可执行指令文件。这也证实了一个是开发环境,一个是运行环境。
14.6 JRE、JVM 的区别?
JVM 并不代表就可以执行 class 了,JVM 执行 .class 还需要 JRE 下的 lib 类库的支持,尤其是 rt.jar。
参考:接口和抽象类有什么联系和区别?
【面试题】重载和重写的区别
Java的基本数据类型详解
【Java面试官】史上最全的JAVA专业术语面试100问
java中throw和throws的区别.