面试3.1_Java_基础
一、JAVA概述
1.1面向过程、面向对象、面向切面
-
面向过程编程OPP,是一种以事物为中心的编程思想。主要关注
“怎么做”
,即完成任务的具体细节
。 -
面向对象编程OOP,是一种以对象为基础的编程思想。主要关注
“谁来做”
,即完成任务的对象
。 -
面向切面编程AOP,基于OOP延伸出来的编程思想。主要实现的目的是
针对业务处理过程中的切面进行提取
,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。
1.2 JVM、JRE和JDK的关系
- JVM:Java虚拟机
- JRE:Java虚拟机、核心类库等
- JDK:Java的开发工具,包括JRE、编译工具,打包工具等
二、基础语法
2.1 数据类型
基本类型
包装类、自动拆箱、自动装箱
Byte、Short、Integer、Long、Float、Double、Character、Boolean
switch作用的数据类型
- Java 5 以前,switch(expr)中,expr 只能是
byte、short、char、int
。 - Java 5 开始,引入了
枚举类型
- Java 7 开始,引入了
字符串
float f=3.4 是否正确
- 不正确。 3.4 是双精度数,
下转型
会造成精度损失
已知short s1 = 1;问s1 = s1 + 1;与 s1 += 1;的区别
s1 = s1 + 1;
由于1
是int
类型,因此s1+1
运算结果也是 int型,需要强制转换类型
才能赋值给 short 型。s1 += 1;
可以正确编译,因为s1+= 1;
相当于s1 = (short(s1 + 1);
其中有隐含的强制类型转换
。
2.2 访问修饰符
2.3 运算符
&、&&区别
- &运算符:(1)
按位与
;(2)逻辑与
。 - &&运算符:
短路与
2.4 关键字
static
- 【修饰变量】: 静态变量
随着类加载时被完成初始化
,内存中只有一个,且JVM也只会为它分配一次内存
,所有类的实例对象共享静态变量
。 - 【修饰方法】: 在
类加载的时候就存在
,不依赖任何实例;static方法必须实现
,不能用abstract修饰。 - 【修饰代码块】: 在
类加载完之后就会执行
代码块中的内容。 - 【静态内部类】
final
- 【修饰类】:不能被继承。
- 【修饰方法】:不能被继承,不能被子类修改。
- 【修饰变量】:被final修饰不可变的是变量的引用,
引用指向的内容是可以改变的
- 编译期常量:类加载的过程完成初始化,编译后带入到任何计算式中。只能是基本类型。
- 运行时常量:基本数据类型或引用数据类型。引用不可变,但引用的对象内容可变。
- 【修饰形参】:final形参不可在方法中更改
final、finally、finalize区别
- final可以修饰类、变量、方法
- finally一般作用在
try-catch
代码块中,表示不管是否出现异常,该代码块都会执行 - finalize是
Object
类的一个方法,该方法一般由垃圾回收器来调用- 当我们调用System.gc() 方法的时候,由垃圾回收器调用finalize(),回收垃圾,一个对象是否可回收的最后判断。
this用法
-
普通的直接引用,this相当于是指向
当前对象本身
。 -
形参与成员名字重名,用this来区分
-
引用本类的构造函数
super用法
-
普通的直接引用,指向
当前对象的父类的引用
-
子类中的成员变量或方法与父类中的成员变量或方法同名时,用super进行区分
-
引用父类构造函数
this、super的区别
this是指向本对象的指针
, 然而super是Java关键字
。- this()和super()都指的是对象,所以,
均不可以在static环境中使用
- this()和super()
不能同时出现在一个构造函数里面
- super()和this()均需放在构造方法内第一行
2.5 流程控制
跳出多重嵌套循环
循环语句前定义一个标志
三、面向对象
3.1 面向对象特性
封装:把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法
继承:使用已存在的类的定义作为基础建立新类
- 子类拥有父类
非 private 的属性和方法
。 - 子类可以拥有自己属性和方法。
- 子类可以
重写父类的方法
。
多态:继承、接口
方法重载
( overload )实现的是编译时的多态性
(也称为前绑定)。方法重写
( override )实现的是运行时的多态性
(也称为后绑定)。要实现多态需要做两件事:方法重写
(子类继承父类并重写父类中已有的或抽象的方法) ;对象造型
(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。
3.2 类与接口
抽象类、接口的对比
-
抽象类
- 抽象类
不能被实例化
只能被继承; - 包含
抽象方法
(只被abstract修饰
)的一定是抽象类,但是抽象类不一定含有抽象方法; - 抽象类中的抽象方法的修饰符只能为
public
或protected
,默认为public; - 一个子类继承一个抽象类,则
子类必须实现父类抽象方法
,否则子类也必须定义为抽象类; - 抽象类可以包含属性(
默认default
)、方法、构造方法,但是构造方法不能用于实例化
,主要用途是被子类调用。
- 抽象类
-
接口
- 变量被隐式指定为
public static final
,必须赋初值
; - 方法被隐式指定为
public abstract
(JDK1.8之前),不能被实现
; - 一个
接口
可以继承多个接口
,间接的解决了Java中类的单继承问题; - 一个
类
可以实现多个接口
;
- 变量被隐式指定为
普通类、抽象类区别
- 普通类不能包含抽象方法,抽象类可以包含抽象方法。
- 抽象类不能直接实例化,普通类可以直接实例化。
抽象类不能使用 final 修饰
对象实例、对象引用区别
-
对象实例在
堆内存
-
一个对象可以有n个引用指向它
-
对象引用指向对象实例(对象引用存放在
栈内存
中) -
一个对象引用可以指向0个或1个对象
3.3 overload、override
-
overload
- 重载发生在同一个类中
- 方法名相同,
参数列表不同
(参数类型不同、个数不同、顺序不同) 与方法返回值和访问修饰符无关
,即重载的方法不能根据返回类型进行区分
-
override
- 重写发生在子类与父类之间
- 方法名、
参数列表必须相同
返回值
小于等于父类抛出的异常
小于等于父类访问修饰符
大于等于父类(里氏代换原则)- 如果父类方法访问修饰符为private则子类中就不是重写。
3.4 对象相等判断
==、equals 的区别
- == : 判断两个对象的地址是不是相等。
- 基本类型则表示
值相等
- 引用类型则表示
地址相等
即是同一个对象。
- 基本类型则表示
- 类
未重写equals()
方法,等价于 ==
,比较两个对象的的内存地址 - 类
重写equals()
方法,内容相等
为什么重写equals时必须重写hashCode方法
为了保证是同一个对象,在 equals 比较相同的情况下 hashcode值必定相同。
-
按照规定:
- 如果两个对象相同(即:用 equals 比较返回true),那么它们的 hashCode 值一定要相同;
- 如果两个对象的 hashCode 相同,它们并不一定相同(即:用 equals 比较返回 false);
-
重写前:hashcode比较的是对象的物理地址经过hash算法后得到的值,可以计算得到对象在hash表中的位置
属性相等的两个对象,放入HashMap中时先计算hashcode来获取加入的位置,同时也会与其他已经加入的对象的 hashcode 值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 equals()方法来检查 hashcode 相等的对象是否真的相同。
3.5 深拷贝、浅拷贝区别
- 基本数据类型:数据直接
存储在栈
中; - 引用数据类型:存储在栈中的是
对象的引用地址
,真实的对象数据存放在堆内存
里。
- 浅拷贝
- 对于基础数据类型:直接复制数据值
- 对于引用数据类型:只是
复制了对象的引用地址
,新旧对象指向同一个内存地址,修改其中一个对象的值,另一个对象的值随之改变。
- 深拷贝
- 对于基础数据类型:直接复制数据值;
- 对于引用数据类型:
开辟新的内存空间
,在新的内存空间里复制一个一模一样的对象,新老对象不共享内存,修改其中一个对象的值,不会影响另一个对象。
深拷贝相比于浅拷贝速度较慢并且花销较大。
3.6 静态变量、成员变量区别
- 成员变量:堆内存;对象创建时初始化;被【对象】所调用 ;与对象共存亡。
- 静态变量:方法区;类加载时初始化;被【对象 / 类名】调用;与类共存亡。
3.7 IO流
BIO、NIO、AIO区别
-
参考资料
-
BIO:面向流
连接数目较小
且固定
的架构同步阻塞
IO,数据的读取写入必须阻塞在一个线程内等待其完成。- 服务器实现模式:
一个连接一个线程
- 客户端有连接请求时服务器就需要启动一个线程进行处理
- 并发处理能力低。
-
NIO:面向缓冲区
连接数目多
且连接较短
(轻操作)的架构同步非阻塞
IO,提供SocketChannel
和ServerSocketChannel
两种不同的套接字通道实现- 服务器实现模式:
一个请求一个线程
- 客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有IO请求时才启动一个线程进行处理。
- 支持
面向缓冲、基于通道
的I/O操作方法 - 客户端和服务器端通过 Channel(通道)通讯
- 实现了
多路复用
。
-
AIO:
连接数目多
且连接较长
(重操作)的架构- NIO 的升级,也叫 NIO2
异步非堵塞
IO- 异步 IO 的操作
基于事件和回调机制
。 - 服务器实现模式:
一个有效请求一个线程
- 客户端的IO请求之后会直接返回,不会堵塞在那里,当操作系统先完成了再通知服务器用其启动线程进行处理。
四、String相关
String、StringBuffer、StringBuilder区别
-
都是
final类
,都不允许被继承; -
String
长度是不可变
的, -
StringBuffer. StringBuilder长度是
可变
的; -
StringBuffer是线程安全
的,StringBuilder不是线程安全的,但它们两个中的所有方法都是相同的。 -
StringBuffer在StringBuilder的方法之.上添加了
synchronized
修饰,保证线程安全。
-如果一个String类型 的字符串,在编译时就可以确定是一个字符串常量,则编译完成之后,字符串会自动拼接成一个常量。
此时String的連度比StringBuffer和StringBuilder的性能好的多。
String不可变
- String类利用了
private
访问权限、final
修饰的char数组
存储字符private final char value[];
- 通过反射是可以修改所谓的“不可变”对象