Java基础
# 基础概念与常识
# Java语言的特点
1、简单易学
2、面向对象(封装、继承、多态)
3、平台无关性
4、支持多线程
....
# JVM JDK JRE
JVM:Java虚拟机,只要满足JVM规范,任何人都能够开发专属JVM,JVM更多是一种规范
JDK:Java语言工具包
JRE: Java运行环境
# 字节码
JVM 可以理解的代码就叫做字节码(即扩展名为 .class
的文件),它不面向任何特定的处理器,只面向虚拟机。
# 基本语法
# 注解形式
- 单行注释 :通常用于解释方法内某单行代码的作用。
- 多行注释 :通常用于解释一段代码的作用。
- 文档注释 :通常用于生成 Java 开发文档。
# 变量
成员变量
- 成员变量是属于类的
- 成员变量可以被
public
,private
,static
等修饰符所修饰 - 成员变量是对象的一部分,它随着对象的创建而存在
局部变量
- 局部变量是在代码块或方法中定义的变量或是方法的参数
- 局部变量不能被访问控制修饰符及
static
所修饰 - 而局部变量随着方法的调用而自动生成,随着方法的调用结束而消亡。
静态变量
静态变量可以被类的所有实例共享。无论一个类创建了多少个对象,它们都共享同一份静态变量。
通常情况下,静态变量会被
final
关键字修饰成为常量。
字符型常量和字符串常量的区别
形式 :字符常量是单引号引起的一个字符,字符串常量是双引号引起的 0 个或若干个字符。
含义 :字符常量相当于一个整型值( ASCII 值),可以参加表达式运算; 字符串常量代表一个地址值(该字符串在内存中存放位置)。
占内存大小 :字符常量只占 2 个字节; 字符串常量占若干个字节。
# 重载和重写有什么区别
- 重载就是同样的一个方法能够根据输入数据的不同,做出不同的处理
- 重写就是当子类继承自父类的相同方法,输入数据一样,但要做出有别于父类的响应时,你就要覆盖父类方法
# 基本数据类型
Java 中有 8 种基本数据类型,分别为:
- 6 种数字类型:
- 4 种整数型:
byte
、short
、int
、long
- 2 种浮点型:
float
、double
- 4 种整数型:
- 1 种字符类型:
char
- 1 种布尔型:
boolean
# 包装类型的缓存机制
享元模式
Java 基本数据类型的包装类型的大部分都用到了缓存机制来提升性能。
Byte
,Short
,Integer
,Long
这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character
创建了数值在 [0,127] 范围的缓存数据,Boolean
直接返回 True
or False
。
# 基本类型和包装类型区别
成员变量包装类型不赋值就是
null
,而基本类型有默认值且不是null
。包装类型可用于泛型,而基本类型不可以。
基本数据类型的局部变量存放在 Java 虚拟机栈中的局部变量表中,基本数据类型的成员变量(未被
static
修饰 )存放在 Java 虚拟机的堆中。包装类型属于对象类型,我们知道几乎所有对象实例都存在于堆中。相比于对象类型, 基本数据类型占用的空间非常小。
# 自动装箱与拆箱
什么是自动拆装箱?
- 装箱:将基本类型用它们对应的引用类型包装起来;
- 拆箱:将包装类型转换为基本数据类型;
# String-StringBuffer-StringBuilder
# 接口和抽象类有什么共同点和区别
共同点 :
- 都不能被实例化。
- 都可以包含抽象方法。
- 都可以有默认实现的方法(Java 8 可以用
default
关键字在接口中定义默认方法)。
区别 :
- 接口主要用于对类的行为进行约束,你实现了某个接口就具有了对应的行为。抽象类主要用于代码复用,强调的是所属关系。
- 一个类只能继承一个类,但是可以实现多个接口。
- 接口中的成员变量只能是
public static final
类型的,不能被修改且必须有初始值,而抽象类的成员变量默认 default,可在子类中被重新定义,也可被重新赋值。
# 深拷贝和浅拷贝区别了解
浅拷贝:浅拷贝会在堆上创建一个新的对象(区别于引用拷贝的一点),不过,如果原对象内部的属性是引用类型的话,浅拷贝会直接复制内部对象的引用地址,也就是说拷贝对象和原对象共用同一个内部对象。
深拷贝 :深拷贝会完全复制整个对象,包括这个对象所包含的内部对象。
# 异常
# Exception和Error有什么区别
他们都有一个共同的祖先Throwable类:
- exception:程序本身可以处理的异常,可以通过catch来进行捕获。
- Error:属于程序无法处理的错误,比如Java 虚拟机运行错误(
Virtual MachineError
)、虚拟机内存不够错误(OutOfMemoryError
)、类定义错误(NoClassDefFoundError
)等 。
# Checked Exception 和 Unchecked Exception
checked exception:受检查异常 ,Java 代码在编译过程中,如果受检查异常没有被 catch
或者throws
关键字处理的话,就没办法通过编译。
Unchecked Exception :即不受检查异常 ,Java 代码在编译过程中 ,我们即使不处理不受检查异常也可以正常通过编译。比如空指针错误,参数错误
# try-catch-finally
try
块 : 用于捕获异常。其后可接零个或多个catch
块,如果没有catch
块,则必须跟一个finally
块。catch
块 : 用于处理 try 捕获到的异常。finally
块 : 无论是否捕获或处理异常,finally
块里的语句都会被执行。当在try
块或catch
块中遇到return
语句时,finally
语句块将在方法返回之前被执行
finally中的代码一定会执行吗
不一定,就比如说 finally 之前虚拟机被终止运行的话,finally 中的代码就不会被执行。
另外,在以下 2 种特殊情况下,finally
块的代码也不会被执行:
- 程序所在的线程死亡。
- 关闭 CPU。
# 泛型
使用泛型参数,可以增强代码的可读性以及稳定性。
使用方式
- 泛型类
- 泛型接口
- 泛型方法
使用场景
- 集合
- 自定义接口通过返回结果
- 数据处理类
作用
- 类型安全
- 消除强制类型转换
- 更好的代码复用性
限定通配符和非限定通配符
限定通配符对类型进行了限制。有两种限定通配符:
- <? extends T>它通过确保类型必须是T及T的子类来设定类型的上界;
- <? super T>它通过确保类型必须是T及T的父类设定类型的下界;
表示了非限定通配符,因为可以用任意类型来替代。
# 反射
# 定义
反射之所以被称为框架的灵魂,主要是因为它赋予了我们在运行时分析类以及执行类中方法的能力。
通过反射你可以获取任意一个类的所有属性和方法,你还可以调用这些方法和属性。
# 反射的应用场景
Spring/Spring Boot、MyBatis 等等框架中都大量使用了反射机制。
spring中的xml,之前就是通过反射去加载。
# 序列化和反序列化
- 序列化: 将数据结构或对象转换成二进制字节流的过程
- 反序列化:将在序列化过程中所生成的二进制字节流转换成数据结构或者对象的过程
常见应用场景:
对象在进行网络传输(比如远程方法调用 RPC 的时候)之前需要先被序列化,接收到序列化的对象之后需要再进行反序列化;
将对象存储到文件之前需要进行序列化,将对象从文件中读取出来需要进行反序列化;
将对象存储到数据库(如 Redis)之前需要用到序列化,将对象从缓存数据库中读取出来需要反序列化;
将对象存储到内存之前需要进行序列化,从内存中读取出来之后需要进行反序列化。