java基础大全
2021-03-27 16:16:20 0 举报
AI智能生成
知识点比较全面、详细。
作者其他创作
大纲/内容
基础语法
Java的跨平台
基于JVM,每一个系统都有对应的JVM
Java语言是跨平台的,但是JVM不是跨平台的
JDK/JRE/JVM
JDK:Java开发工具包,包含了JRE和开发工具
JRE:Java运行环境,包含了JVM和核心类库
JVM:Java虚拟机,是Java实现可移植性的前提
入门程序
编译命令:javac -d 文件的存放路径 要编译的Java文件
运行命令:java -cp class文件的存放路径 包名.类名
每一个Java文件中可以存放多个类,但是只能有一个公共类
每一个类在编译完成之后都会产生一个class文件,所以class文件名和类名对应
关键字
一共是53个关键字
2个目前没有使用---保留字
所有的关键字都是小写的
标识符
命名规则
由字母、数字、_、$组成
数字不能开头
不能使用关键字
大小写敏感
见名知意
驼峰命名法
类名/接口名:每个单词的首字母都需要大写,其余字母小写
方法名/变量名:第一个单词的首字母小写,其余单词的首字母大写
常量名:所有的字母都要大写,多个单词之间用_隔开
包名:所有的字母都要小写,多个单词之间用 . 隔开
注释
单行注释 // 注释文字
多行注释 /*注释文字*/
文档注释 /**注释文字*/
可以利用javadoc命令将注释文字提取出来形成文档
只能提取公共类
字面量
整数常量
所有的整数
小数常量
所有的小数
字符常量
将一个字母、数字、符号用 ''标志起来
字符串常量
将一个或者多个字符用""标志起来
布尔常量
true/false,用于表示逻辑值
空常量
null
进制
二进制
0-1两个基本元素
满2进1, 1+1=10
从JDK1.7开始,用0b/0B开头作为标志
八进制
0-7八个基本元素
满8进1,7+1=10
用0开头作为标志
十进制
0-9十个基本元素
满10进1,9+1=10
代码中,数字默认就是十进制
十六进制
0-9,A-F十六个基本元素
满16进1,9+1=a, a+1=b f+1=10
用0x开头作为标志
进制的转换
十进制->二进制
将数字除以2,取余数,将余数倒排
二进制->十进制
从低位次开始,按位次乘以2的位次次幂,然后求和
十进制->任何进制
将数字除以对应的进制,取余数,将余数倒排
任何进制->十进制
从低位次开始,按位次乘以赌赢的进制次幂,然后求和
八进制->二进制
每一位八进制产生三位二进制,如果不足三位,补0
二进制->八进制
从低位开始,每三位二进制产生一位八进制,如果不足三位,补0
十六进制->二进制
每一位十六进制产生四位二进制,如果不足四位,补0
二进制->十六进制
从低位开始,每四位二进制产生一位十六进制,如果不足四位,补0
变量
要素:数据类型、变量名、变量值
变量先定义后使用
变量必须先赋值后使用
变量在哪儿定义在哪儿使用
数据类型
基本数据类型
数值型
整数型
字节型 byte
1个字节
-2^7~2^7-1 --- -128~127
短整型 short
2个字节
-2^15~2^15-1 --- -32768~32767
整型 int
4个字节
-2^31~2^31-1 --- 大概-10^10~10^10
Java中,整数默认为int
长整型 long
8个字节
-2^63~2^63-1 --- 大概-10^18~10^18
需要以L/l作为结尾
浮点型
单精度 float
4个字节
大概-10^38~10^38
需要以f/F作为结尾
双精度 double
8个字节
大概-10^308~10^308
Java中,小数默认为double
注意:科学计数法
十进制科学计数法:aeb表示a*10^b
十六进制科学计数法:0xapb表示a*2^b
注意:Java中的数值型都是有符号
字符型
char
2个字节
0-65535
Java中,char类型的数据是以UTF-16的编码来进行存储
布尔型
boolean
值:true/false
表示逻辑值
boolean的内存是不确定,随着系统和JDK的版本来确定
引用数据类型
数组 []
类 class
接口 interface
数据类型的转换
隐式转换
自动类型转换
小类型转化为大类型
整数转化为小数会产生精度损失
char类型可以自动提升为int
显式转换
强制类型转换
大类型转化为小类型
小数转化为整数会舍弃小数部分
大的数字转化为小的类型的时候会产生精度损失
运算符
算术
+ - * / % ++ --
整数运算完成之后的结果一定是整数
小的类型和大的类型运算,结果应该是大的类型
byte/short/char在运算之后的结果自动提升为int
对于小数而言,运算结果是不精确
除以0
整数/0 --- ArithmeticException
非零小数/0 非零数字/0.0 Infinity
0.0/0 0/0.0 0.0/0.0 NaN
取余运算的结果的符号看的是%左边的数字的符号
++/--
如果在变量之前,先自增/自减,然后参与后续运算
如果在变量之后,先将值取出来参与后续运算,然后自增/自减
byte/short/char可以参与自增运算,而且结果类型是原来的类型
赋值
= += -= *= /= %= &= |= ^= <<= >>= &>>>=
除了=以外,其余的符号都要求变量先有值,才能使用
byte/short/char可以参与赋值运算
注意:赋值运算的连等
关系
== != > < <= >=
运算结果一定是boolean类型
比较值的关系
逻辑
& | ! ^ && ||
^的运算规则:相同为假,不同为真
&&和||的短路特性
如果前边为false,&&后边的表达式就不再运算
如果前边为true,||后边的表达式就不再运算
||在前可以把后边的&&给短路掉
位
& | ^ << >> >>> ~
针对的整数的补码进行运算,那么运算结果也一定是补码
数据在计算机中是以补码形式存在
任何一个数据都有原码、反码、补码形式
对于正数而言,原反补三码一致
对于负数而言,反码是在原码的基础上最高位不变,其余位1<->0;补码是在反码的基础上+1
& | ^:将数据转化为补码之后进行按位运算
&: 0&a=0 a&1=1或0
|: 0|a=a
^:a^a=0 0^a=a a^b^b=a
交换值
追尾法
利用第三方变量来交换两个变量的值
局限性比较小,可以适用于任何类型
额外耗费空间,运行效率相对较低
加减法
只能运算数值型
效率高于追尾而低于亦或
尽量减少对小数使用加减法交换值
亦或法
效率最高
只能适用于整数交换,局限性最大
<<:在一定范围内,左移几位就是乘以2的几次方
>>:在一定范围内,右移几位就是除以2的几次方
正数:右移越移越小,最小到0
负数:右移越移越大,最大到-1
>>>:无论正负,空出的最高位一律补0
实际上移动的(位数%32)
~:~i = -i-1
三元
逻辑值?表达式1:表达式2;
执行顺序:如果逻辑值为true,则执行表达式1;反之执行表达式2
表达式1和表达式2的结果类型要一致或者能够自动转化
运算完成之后一定有一个结果---这个结果可以用一个变量来接住
运算符的优先级:一元>二元>三元>赋值
() ~ ++ -- ! 算术 << >> >>>; 关系 逻辑 & | ^ 三元 赋值
流程控制
顺序结构
代码从上到下从左到右依次编译运行
分支结构
判断结构
if
适合于单个条件的判断
if-else
if-else if
多个条件分部筛选
选择结构
switch-case
switch()的值类型:byte/short/char/int,从JDK1.5开始允许使用枚举,从JDK1.7开始允许使用String
如果每一个case之后都有break,那么case的顺序不影响结果
如果有一个或者多个case之后没有break,那么从匹配的选项开始依次往下执行,直到遇到break或者是switch结束才会停止执行,所以此时case的顺序会影响结果
循环结构
while
适用于次数不固定或者变化不规律的场景
do-while
循环体至少执行一次
for
使用次数固定或者步长有规律的场景
循环的要素:定义循环变量,控制循环条件,改变循环变量
注意:循环的嵌套
break和continue
break:可以用于选择结构和循环结构中,用于终止当前的一层结构
continue:只能用于循环结构,表示跳过本次的一层循环继续下次循环
支持标号形式
数组
格式
数据类型[] 数组名 = new 数据类型[数组的大小];
数据类型[] 数组名 = new 数据类型[]{元素1, 元素2...};
数据类型[] 数组名 = {元素1, 元素2...};
数组的内存
数组是存储在堆内存中
在堆内存中会自动赋予默认值
栈内存存储的是这个数组的地址
数组的应用
获取数组的元素
数组名[下标]
获取数组的长度
数组名.length
遍历数组
通过下标遍历
获取最值
定义变量记录最大值
记录最大值的下标
数组元素的排序
冒泡排序
时间复杂度:O(n^2)
空间复杂度:o(1)
选择排序
时间复杂度:O(n^2)
空间复杂度:o(1)
Arrays.sort
时间复杂度:O(nlogn)
元素的查找
元素无序---遍历
元素有序---二分查找
时间复杂度:O(logn)
空间复杂度:o(1)
数组的反转
首尾互换
数组的复制
System.arraycopy(原数组, 复制的起始位置, 目标数组, 存放的起始位置, 复制的元素的个数);
Arrays.copyOf(原数组, 变化之后的长度);
底层实际上是调用了System.arraycopy
数组的扩容之后的地址一定发生了改变
时间复杂度:程序中必然会执行的代码的执行时间认为是单位1,执行这个单位1所需要的次数
空间复杂度:程序执行过程中,额外开辟的内存空间
二维数组
格式
数据类型[][] 数组名 = new 数据类型[包含的一维数组的个数][每个一维数组的长度];
数据类型[][] 数组名 = new 数据类型[包含的一维数组的个数][];
数据类型[][] 数组名 = {{}, {}, {}...};
二维数组的内存
二维数组存储在堆内存中
二维数组的每一个位置上存储的是一维数组的地址
如果一个位置上没有指定一维数组,那么默认值为null
方法
格式
修饰符 返回值类型 方法名(参数列表){方法体; return 返回值;}
如果一个方法没有返回值,返回值类型定义为void
意义
提高代码的复用性
便于团队的合作开发
使代码的结构更加清晰
方法的传参
形参:定义方法的时候()定义的变量
实参:调用方法的时候传入的数据
对于基本类型而言,传参传递的是实际值,所以在另一个方法中改变这个参数的值不会影响原来方法的数据
对于引用类型尔雅,传参传递的是地址。如果地址不发生改变,则影响原来方法中的对象;如果地址放生改变,则不影响原来的对象
方法的重载
在同一个类中,存在方法名一致而参数列表不同的方法
参数列表不同指的是参数的个数或者是对应位置上的参数类型
和修饰符、返回值类型、异常没有关系
方法的重写
在父子类中存在了方法签名一致的非静态方法
如果返回值类型是基本类型或者是void,则子类在重写方法的时候的返回值类型要一致
如果返回值类型是引用类型,那么子类重写的方法的返回值类型是父类方法的方法返回值类型的子类,或者与父类方法的返回值类型一致
如果父类的方法抛出了异常,那么子类在重写的时候的异常不能超过父类异常的范围,而且指的是编译时异常
子类重写的方法的权限修饰符的范围要大于等于父类方法的权限修饰符的范围
方法的递归
在方法中调用了方法本身
如果递归次数过多会出现栈溢出错误---StackOverFlowError
面向对象
面向对象与面向过程的比较
面向过程注重流程中的每一步
面向对象注重的对象,只要有了对象,就可以获取对象身上的一切功能
对于简单事务,适合于用面向过程;对于复杂事务,建议使用面向对象
面向对象是基于面向过程
类和对象的关系
类是对象的概括
对象是类的实例化
在类中,属性是一种特征,方法是一种行为
成员变量和局部变量
定义位置
成员变量定义在类内;局部变量定义在代码块中
作用范围
成员变量作用在整个类内;局部变量作用在当前的代码块/语句中
内存位置
成员变量存储在堆内存中,并且堆内存中有默认值;局部变量是存储在栈内存中,没有默认值
生命周期
成员变量是在对象被创建的时候出现,在对象被回收的时候被销毁;局部变量是在语句执行的时候创建,在代码块执行完成之后被释放
构造方法
特点:与类同名而没有返回值类型
作用:创建对象,初始化属性
可以写return,用于规避不合法的情况
this关键字
代表当前在活动的对象的引用,可以认为是一个虚拟对象
用于在本类中调用本类中的非静态方法和非静态属性
this语句
在本类的构造方法中调用本类对应形式的构造方法
必须放在构造方法的首行
代码块
局部代码块
定义方法中用{}包起来的代码
构造代码块
定义在类中用{}包起来的代码
在创建对象的时候先于构造方法执行
面向对象的特征
封装
体现形式:方法、属性的私有化、内部类
优势
提高代码的服用
保证数据的合法性
继承
类用extends来继承另一个类
类和类之间是单继承
单继承和多继承的比较
单继承明确调用的方法
多继承能够更好的提高代码的复用性
通过继承,子类可以继承父类所有的方法和属性,但是子类只能使用父类中的一部分方法和属性
意义
提高代码的复用性
避免调用方法产生混乱
多态
根据时期
编译时多态
方法的重载
运行时多态
向上造型
用父类/接口声明,用子类/实现类来创建
对象能干什么看的是父类,怎么干看的是子类
方法的重写
基于继承
根据形式
行为多态
方法的重载
方法的重写
对象多态
向上造型
意义
使代码的调用形式更加的灵活和统一
配合反射实现解耦
super关键字
在子类中代表父类对象的引用
在子类中调用父类中的方法和属性
在创建子类对象的时候必然先创建父类对象
super语句
如果子类的构造方法中没有手动指定super语句,那么默认添加无参的super
利用super语句调用父类中对应形式的构造方法
如果父类中没有提供无参构造,那么子类的构造方法就必须提供对应形式的superu语句
super语句必须放在子类构造方法的第一行
权限修饰符
public
本类中、子类中、同包类中、其他类中
protected
本类中、子类中、同包类中
默认
本类中、同包类中
private
本类中
在子类中使用的时候,使用哪个子类对象,就必须是在对应的子类中使用
static
静态变量
在类加载的时候加载到方法区
在方法区中赋予了默认值
静态变量先于对象出现,习惯上通过类名来调用
对象存的是静态变量的地址,所以所有的对象共享这个静态变量
静态变量只能定义在类中
静态方法
随着类的加载而加载到方法区
在方法区中没有执行只是存储
在调用的时候到栈内存中执行
静态方法是先于对象存在,习惯上通过类名来调用
静态方法可以重载
静态方法可以被继承
静态方法不能重写
父子类中可以存在方法签名一致的静态方法---隐藏
如果父子类中存在方法签名一致的方法,要么都是静态方法,要么都是非静态方法
静态代码块
在类中用static{}包起来的代码
在类第一次被真正使用的时候执行一次
执行顺序
父类的静态
子类的静态
父类的非静态
子类的非静态
静态内部类
final
常量
对于基本类型,指的是实际值不可变
对于引用类型,指的是地址不可变,属性值可以改变
成员常量
在对象创建完成之前给值
静态常量
在类加载完成之前给值
最终方法
可以重载
可以被继承
不能被重写/隐藏
最终类
不能被继承
abstract
抽象类
不一定有抽象方法
不能被实例化
有构造方法
抽象类中可以定义一切的属性和方法
子类继承抽象类之后需要重写所有的抽象方法,除非这个子类也是抽象类
抽象类一定不是最终类
抽象方法
可以被重载
必然被继承,必然被重写
不能用static/final/private修饰
如果抽象类的权限修饰符是默认的,那么要求父子类同包
interface
一个类用implements关键字来实现一个类
一个类可以实现多个接口
接口和接口之间是多继承的关系
接口中所有的方法都是抽象方法,抽象方法默认使用public abstract修饰
接口中没有构造方法
类实现接口之后需要重写所有的抽象方法
接口中定义的属性默认是使用public static final修饰
内部类
方法内部类
定义在方法中的类
只能在定义它的方法中使用
方法内部类中不可以静态变量和静态方法,但是可以定义静态常量
方法内部类在使用当前方法中的数据的时候,要求这个数据是一个常量
方法内部类可以使用当前外部类中的属性和方法
成员内部类
定义在类内方法外
不可以定义静态变量和静态方法,但是可以定义静态常量
可以使用外部类中的一切属性和方法
静态内部类
用static修饰的内部类
可以定义静态变量和静态方法
不可以使用当前外部类中的非静态属性和非静态方法
只能外部类中的静态属性和静态方法
匿名内部类
匿名内部类本质上是继承了对应的类或者是实现了对应的接口
任何一个类,只要不是最终类,一定可以存在匿名内部类形式
任何一个接口一定可以产生匿名内部类形式
包
声明包用package
导入包用的import
在Java文件中只能有1个package语句,而且这句话必须放在Java文件的第一行
* 表示导入当前包下的所有的类而不包括子包下的类
如果使用的是java.lang或者是同包中的类,可以不用导包
垃圾分代回收机制
针对的是堆内存
堆内存在不确定的某个时刻被GC扫描进行对象的回收
对象创建的时候是放到新生代
在新生代中的伊甸园区经过一次扫描如果依然存在,则挪到幸存区
在幸存区经过多次扫描如果依然存在,则挪到老生代
老生代的扫描频率要远低于新生代
初代回收(minor gc):发生在新生代的回收
完全回收(full gc):发生在老生代的回收
API
Object
是java中的顶级父类
任何一个对象都可以用Object对象来接住
重要方法
getClass:获取对象的实际类型,返回是一个Class对象
equals:比较两个对象是否相等。在比较的时候默认比较的是地址,一般需要重写equals方法
toString:将对象转化为字符串形式。打印一个对象的时候一般默认是调用了对象的toString方法
String
代表字符串的类
是一个最终类,不可以被继承
字符串是一个常量,是存储在常量池的,被共享的
注意字符串的拼接运算:+默认使用的是StringBuilder中的append方法
字符串在Java底层是以字符数组形式来进行存储
字符串的哈希码是固定不变的
StringBuilder/StringBuffer
底层是以字符数组形式来存储数据
StringBuilder是一个线程不安全的类,StringBuffer是一个线程安全的类
StringBuffer之所以能保证线程安全是因为底层采用了同步方法的机制
Pattern
用于指定规则的类
匹配格式
[abc] 表示a或者b或者c
[^abc] 除了a/b/c
预定义字符
. 任意字符
\d 任意数字
\D 非数字
\s 空白字符
\S 非空白字符
\w 单词字符-字母、数字、_
\W 非单词字符
数量词
+ >=1
? <= 1
* >= 0
{n} =n
{n,} >= n
{n,m} n <= x <= m
注意:每一个字符或者捕获组之后只能使用一个数量词
捕获组
将一个或者多个符号看作一个整体进行匹配
捕获组的编号:从(出现的位置开始计算
\\n 表示引用编号为n的捕获组
包装类
对于每种基本类型都提供了对应的类形式
byte-Byte
short-Short
int-Integer
long-Long
float-Float
double-Double
char-Character
boolean-Boolean
void-Void
注意:所有的数值型的包装类都有一个对应父类是Number
所有的数值型以及Boolean都提供了将字符串转化为对应的类型的方法
所有的包装类对象的哈希码是固定不变的
自动封箱拆箱
数学类
Math
最终类,构造方法私有化,不可创建对象
提供了大量的静态方法,允许对基本类型进行初等的数据运算
在计算小数的时候不精确
BigDecimal
用于精确计算的类
在精确计算的时候要求参数以字符串形式传入
BigInteger
用于存储任意大小的整数的类
在存储的时候需要以字节数组或者是字符串形式来传递
日期类
Date
表示日期的类
提供了大量的方法,但是大部分已过时
掌握字符串和日期之间的转换:SimpleDateFormat
parse:将字符串转化为日期
format:将日期转化为字符串
在转化的时候需要指定转化格式
Calendar
表示日历的类
提供了大量的属性和方法来操作时间
异常
是java中一套用于问题的反馈和处理的机制
Throwable
Error
表示错误
一旦出现不可处理
Exception
编译时异常(已检查异常)
在编译的时候就已经出现,要求必须处理
运行时异常(未检查异常)
继承RuntimeException
在运行的时候才会出现,出现之后可以处理可以不处理
自定义异常
继承一个异常类
如果继承的是Exception或者是其他的编译时异常,那么这个自定义异常就是一个编译时异常
如果继承的是RuntimeException或者是其子类,那么就是一个运行时异常
异常的处理方式
继续向上抛出-在方法中用throw抛出该异常对象,在方法签名上利用throws来生命
进行捕获处理
如果每一个异常的处理方式都不一样,利用多个catch来分别捕获分别处理
如果所有异常的处理方式都一样,捕获父类异常统一处理
如果不同异常的处理方式进行了分组,那么将同一组的异常用|隔开,这种方式是从JDK1.7开始
finally
无论出现异常与否,都必须执行一次
集合
是Java中用于存储多个数据的容器,该容器的大小是不固定
顶级接口Collection
列表List
保证元素的存储顺序,允许存储重复元素
顺序表ArrayList
底层基于数组
默认初始容量是10
每次默认增加一半,底层基于右移
内存空间连续
增删相对复杂,查询相对简单
线程不安全
链表LinkedList
底层基于节点(双向链表)
内存空间不连续
增删相对简单,查询相对复杂
线程不安全
向量Vector
底层基于数组(jdk1.0出现,现在一般不用)
默认初始容量是10
默认增加一倍,底层是基于三元运算
内存空间连续
增删相对复杂,查询相对简单
线程安全
栈Stack
遵循先进后出
入栈:将元素放入栈中
出栈:将元素从栈中取出
栈顶元素:最后放入栈中的元素
栈底元素:最先放入栈中的元素
散列集合Set
元素不可重复,底层存储是无序的
HashSet
底层基于哈希码来存储元素
不保证元素存入顺序
底层基于HashMap存储
线程不安全
LinkedHashSet
基于哈希码加链表结构
TreeSet
在存储元素的时候会进行排序
要求存储的元素对应的类必须实现Comparable接口
队列Queue
先进先出
常用实现类:LinkedList
比较器
Comparable
需要重写compareTo方法,实现它的类产生的对象可以实现自然排序
Comparator
如果需要对某一个集合或者数组单独排序,需要重写Comparator中的compre方法
迭代器
Iterable
实现这个接口的类产生的对象可以被增强for循环遍历
Iterator
在迭代遍历集合的时候,是将该集合做一个复制,然后在复制过程中对每一个元素进行标记,表示该元素是否存在。
在迭代过程中不允许增删原集合
Enumeration
最古老的迭代器
现在一般是利用Vector类中的elements方法来产生
映射
顶级接口Map
HashMap
底层是基于键的哈希码来进行存储
底层结构是用的数组+链表(数组+单向链表,在jdk1.7之前),jdk1.8之后链表数据超过8个会转换为红黑树排列
底层数组的默认大小是16(底层大小一定是2的整数次幂)
数组的每一个位置称之为是一个桶
每一个桶中维持一个链表结构
在存储元素的时候是先计算键的哈希码,然后根据哈希码分配到不同的桶中,根桶中的键一一比较,如果一致则舍弃,如果不一致,则插到这个链表的最前面
在元素个数比较多的情况下,每一个桶中维持的链表会比较长,会导致效率降低,所以需要扩容
是否扩容依赖的是加载因子
默认加载因子是0.75f
当使用的桶的个数超过桶的总数*加载因子,就需要扩容
每次默认增加一倍
扩容之后,需要重新计算所有元素的哈希码重新进行分布,这一步称之为rehash
如果桶数量较小会导致频繁发生扩容和rehash
如果加载因子过小,也会导致频繁扩容和rehash,同时还会浪费空间
如果加载因子过大,会导致每一个桶中的链表过长从而降低效率
允许键或者值为null
异步式线程不安全
Hashtable
不允许键或者值为null
默认初始容量是11
默认加载因子是0.75f
同步式线程安全
Properties
是一个可以持久化的映射
键和值默认是String
可以store方法存储到硬盘上
Properties对象一定要存到.properties文件中
properties文件作为配置文件使用
properties文件中不存储中文,一旦放入中文会转化为对应的编码
Properties文件默认编码是西欧编码
可以通过load方法反持久化回来
键不可重复
每一个键对应一个值 - 键值对
Map.Entry:代表键值对的接口
遍历映射的方式
先获取所有的键,然后根据键获取值 - keySet()
直接获取所有的键值对 - entrySet()
File
代表文件或者目录的类
所表示的文件后者目录在计算机中不一定真实存在
文件操作的时候大多数情况下需要使用递归
IO
是java中一套用于数据传输的机制
传输方向
输入流:数据从外部流向程序
输出流:数据从程序流向外部
传输形式
字节流
字符流
四个基本流
InputStream
FileInputStream
System.in
ObjectIntputStream
OutputStream
FileOutputStream
System.out
System.err
PrintStream
ObjectOutputSteam
Reader
InputStreamReader
将字节转化为字符
FileReader
BufferedReader
Writer
OutputStreamWriter
将字符转化为字节
FileWriter
BufferedWriter
PrintWriter
来源/目的地
硬盘
内存
网络
输入设备
流的异常处理
流对象需要在try之外声明并且赋值为null,然后再try之内初始化
在关流之前需要判断流对象是否为空
为了防止关流失败占用资源,需要将刘对象设置为null
如果是字符输出流,那么为了关流失败以防有数据死在缓冲区中,所以在关流之前需要手动flush
序列化/反序列化
序列化:将对象转化为字节数组的过程
持久化是指对象保存到硬盘上
反序列化:将字节数组转化为对象的过程
注意问题
一个对象要想被序列化必须实现Serializable接口,这个接口中没有任何的方法和属性,仅仅用于标记
用static/transient修饰的属性不会被序列化
每一个可以被序列化的类中有一个版本号-serialVersionUID,如果没有手动版本号会根据当前类中的方法和属性自动计算一个版本号,所以类中每发生一次变动就会重新计算版本号。如果手动指定版本号,则不会发生变化。对象在反序列化的时候需要比较对象持有的版本号和类中定义的版本号是否一致,如果一直才允许反序列化。所以版本号的作用是用于防止类在产生变动的情况下已经序列化的对象无法反序列化回来
线程
进程
是计算机的CPU在执行的任务
是进程的子任务
顶级父类Thread
定义线程
继承Thread类,重写run方法,然后通过start方法启动
实现Runnable接口,重写run方法,然后创建Thread对象,利用Thread对象来启动线程
实现Callable接口,重写call方法
线程并发安全
多个线程同时执行,由于线程之间的执行是相互抢占并且抢占是发生在线程执行的每一步,所以会导致出现不符合实际的情况
synchronized
同步代码块
需要锁对象
共享资源
类的字节码
this
同步
同一时间内某段代码只允许一个线程执行
异步
同一时间内某段代码允许多个线程同时执行
同步方法
非静态方法的锁对象是this
静态方法的所对象是当前类
死锁
锁对象不统一并且多个锁之间形成了嵌套
等待唤醒
通过wait方法让当前线程陷入等待
通过notify唤醒等待的线程,每次只能唤醒一个
通过notifyAll唤醒所有的线程
线程的状态
创建
就绪
执行/活跃
挂起/阻塞
结束/消亡
状态转化
就绪->;执行
执行->阻塞
阻塞->就绪
就绪->阻塞
守护线程
当被守护的线程接收,守护线程无论完成与否都要结束
以最后一个被守护的线程作为标准
线程的优先级
1~10
理论上数字越大优先级越高,意味着抢占CPU的概率越大
相邻两个优先级的差异性非常不明显
如果优先级相差到5个单位及以上,才略微明显
套接字
用于网络进行通信的机制
UDP
不建立连接
不可靠
传输速率相对较快
会对数据进行封包,每个包不超过64KB
DatagramSocket:用于发送端和接收端
发送端
创建套接字对象
准备数据包,将数据封包
绑定地址,发送数据
关流
接收端
创建套接字对象,绑定监听的端口号
准备数据包
接受数据
关流
解析数据包
DatagramPacket:数据包
TCP
建立连接
可靠
三次握手
传输速率相对较慢
不封包,理论上不限制数据大小
客户端Socket
创建套接字对象
发起连接
获取输出流,写出数据
禁用输出流
关流
服务器端ServerSocket
创建套接字对象,绑定端口号
接受连接,获取Socket对象
获取输入流,读取数据
禁用数据流
关流
JDK1.5的特性
自动封箱拆箱
自动封箱
将基本类型直接赋值给对应的引用类型
自动封箱调用的是对应类身上的valueOf方法
对于正数类型,在自动封箱的时候有一个范围判断 - -128~127
自动拆箱
将引用类型直接赋值给对应的基本类型
自动拆箱调用的对应对象身上的***Value方法
增强for循环
要求遍历的对象对应的类必须实现Iterable接口
本质上是一种迭代遍历
在遍历过程中不允许增删原集合
泛型
参数化类型-ParameterizedType
泛型的擦除
用具体类型替换泛型
发生在编译期
自定义泛型
泛型的边界
上限
? extends 类/接口
下限
? super 类/接口
静态导入
imprt static 包名.类名.静态方法名
可以提高加载效率
降低可读性
可变参数
用 ... 定义
本质上是一个数组
可以传入任意个数的参数
定义的时候必须放在参数列表的末尾
枚举
用enum定义
在取值情况相对固定并且能够一一列举的情况下使用
枚举常量必须定义在枚举类的第一行
枚举类中的构造方法只能是私有的
枚举类中可以定义任意的属性和方法,也可以定义抽象方法
从JDK1.5开始,switch-case支持枚举
顶级父类java.lang.Enum
反射
获取类的字节码,从而分析类的信息
获取Class的方式
类名.class
对象.getClass()
Class.forName(类的全路径名)
Class
代表字节码的类
Field
代表属性的类
Method
代表方法的类
Constructor
代表构造方法的类
Package
代表包的类
Annotation
代表注解的类
动态代理
利用Proxy产生对象的代理对象
在代理对象中可以对一些进行修改
注解
顶级父类Annotation
用@interface定义
属性:数据类型 属性名() default 默认值
可以使用的数据类型
基本类型
String
Class
枚举
注解
以上类型对应的一维数组
在赋值的时候如果属性名为value并且只有一个属性,那么在赋值的时候可以省略名称
元注解
@Target
定义注解的使用位置
@Retention
定义注解的生命周期
@Documented
控制注解是否生成到文档中
@Inherited
表示该注解能否被继承
内省
内存
栈内存
执行代码块
每一个线程独有的
堆内存
存储对象
划分
新生代
伊甸园区
幸存区
老生代
所有线程共享的
方法区
存储类信息
划分
静态常量池
存储类信息
运行时常量池
存储字面量和自定义常量
所有线程所共享
本地方法栈
执行本地方法
每一个线程所独有的
寄存器
用于控制程序的执行指令的
每一个线程所独有的
意义:限制变量的使用范围以及生命周期,以提高栈内存的利用率
0 条评论
下一页