从本篇起,Java基础篇的整理主要偏向于面试题
面向对象和面向过程的区别
- 面向过程性能高,因为类调用时需要实例化,开销比较大,比较消耗资源
- 面向过程没有面向对象易维护、易复用、易扩展(封装、继承、多态)
JVM
- Java虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。字节码和不同系统的 JVM 实现是 Java 语言“一次编译,随处可以运行”的关键所在。
构造器Constructor 是否可被 override?
- 继承的时候我们就知道父类的私有属性和构造方法并不能被继承,所以 Constructor 也就不能被 override(重写),但是可以 overload(重载),所以你可以看到一个类中有多个构造函数的情况。
Java面向对象三大特性:封装、继承、多态
- 封装:封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果属性不想被外界访问,我们大可不必提供方法给外界访问。但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了。
String StringBuffer 和 StringBuilder 的区别是什么? String 为什么是不可变的?
- String类中:private final char value[] --->不可变
- StringBuilder 与 StringBuffer 的构造方法都是调用父类构造方法也就是 AbstractStringBuilder 实现的
- StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁(synchronized),所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的
接口和抽象类区别
- 接口的方法默认是 public,所有方法在接口中不能有实现(Java 8 开始接口方法可以有默认实现),而抽象类可以有非抽象的方法。
- 接口中除了static、final变量,不能有其他变量,而抽象类中则不一定。
- 一个类可以实现多个接口,但只能实现一个抽象类。接口自己本身可以通过extends关键字扩展多个接口。
- 在JDK8中,接口也可以定义静态方法,可以直接用接口名调用。实现类和实现是不可以调用的。如果同时实现两个接口,接口中定义了一样的默认方法,则必须重写,不然会报错。
对象实体和对象引用有何区别?
- new创建对象实例(对象实例在堆内存中),对象引用指向对象实例(对象引用存放在栈内存中)。一个对象引用可以指向0个或1个对象(一根绳子可以不系气球,也可以系一个气球);一个对象可以有n个引用指向它(可以用n条绳子系住一个气球)。
实例方法和静态方法有何不同?
- 浅层次:在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。(静态方法的调用不依赖于对象)
- JVM深层次:类的静态方法,静态变量是在类装载的时候装载的,这时候还没有产生对象**。静态变量 存放在 Java 内存区域的方法区**
- static关键字使用场景
- 修饰成员变量和成员方法: 被 static 修饰的成员属于类,不属于单个这个类的某个对象,被类中所有对象共享,可以并且建议通过类名调用。被static 声明的成员变量属于静态成员变量,静态变量 存放在 Java 内存区域的方法区。调用格式:
类名.静态变量名
类名.静态方法名()
- 静态代码块: 静态代码块定义在类中方法外, 静态代码块在非静态代码块之前执行(静态代码块—>非静态代码块—>构造方法)。 该类不管创建多少对象,静态代码块只执行一次.
- 静态内部类(static修饰类的话只能修饰内部类): 静态内部类与非静态内部类之间存在一个最大的区别: 非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围类,但是静态内部类却没有。没有这个引用就意味着:1. 它的创建是不需要依赖外围类的创建。2. 它不能使用任何外围类的非static成员变量和方法。
- 静态导包(用来导入类中的静态资源,1.5之后的新特性): 格式为:
import static
这两个关键字连用可以指定导入某个类中的指定静态资源,并且不需要使用类名调用类中静态成员,可以直接使用类中静态成员变量和成员方法。
- 修饰成员变量和成员方法: 被 static 修饰的成员属于类,不属于单个这个类的某个对象,被类中所有对象共享,可以并且建议通过类名调用。被static 声明的成员变量属于静态成员变量,静态变量 存放在 Java 内存区域的方法区。调用格式:
final关键字
-
可作用在变量、方法、类
-
final作用在基本数据类型上:数值一旦初始化便不能随意更改;final作用在引用型变量:初始化之后不能再指向其他的对象
-
final作用在类上-->该类不能被继承,所有的成员方法默认为final
-
final作用在方法上:
- 把方法锁定,防止任何继承类修改它的含义
-
类中的private修饰的方法默认添加有final关键字
Java中异常
层次
![image-20191217165252832](https://tva1.sinaimg.cn/large/006tNbRwly1g9ztjy5yx9j31a20py7nz.jpg)
- Error(错误):是程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。
- Exception(异常):是程序本身可以处理的异常。Exception 类有一个重要的子类 RuntimeException。RuntimeException 异常由Java虚拟机抛出。NullPointerException(要访问的变量没有引用任何对象时,抛出该异常)、ArithmeticException(算术运算异常,一个整数除以0时,抛出该异常)和 ArrayIndexOutOfBoundsException (下标越界异常)。
- 异常和错误的区别:异常能被程序本身处理,错误是无法处理。
try/catch/fianlly
- try 块: 用于捕获异常。其后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块。
- catch 块: 用于处理try捕获到的异常。
- finally 块: 无论是否捕获或处理异常,finally块里的语句都会被执行。当在try块或catch块中遇到return 语句时,finally语句块将在方法返回之前被执行。
- finally语句块不会被执行的情况:
- 在finally语句块第一行发生了异常。 因为在其他行,finally块还是会得到执行
- 在前面的代码中用了System.exit(int)已退出程序。 exit是带参函数 ;若该语句在异常语句之后,finally会执行
- 程序所在的线程死亡。
- 关闭CPU。
深拷贝/浅拷贝
浅拷贝:对基本数据类型进行值传递,引用类型的属性复制,复制栈中的变量 和 变量指向堆内存中的对象的指针,不复制堆内存中的对象。
![image-20191217170403217](https://tva1.sinaimg.cn/large/006tNbRwly1g9ztvk9ybgj30u00uyack.jpg)
深拷贝:对基本数据类型进行值传递,引用类型的属性复制,复制栈中的变量 和 变量指向堆内存中的对象的指针和堆内存中的对象。(在堆中创建了新的对象)
![image-20191217170540653](https://tva1.sinaimg.cn/large/006tNbRwly1g9ztxcys4pj30u00v5gnt.jpg)
反射
对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。--->反射就是把java类中的各种成分映射成一个个的Java对象
![image-20191217172633390](https://tva1.sinaimg.cn/large/006tNbRwly1g9zuj06enpj31gm0lkn56.jpg)
- 反射优势:运行期类型的判断,动态加载类,提高代码灵活度。
应用:
- JDBC 连接数据库时使用
Class.forName()
通过反射加载数据库的驱动程序 - Spring XML配置方法进行装在Bean