Java基础详细笔记
- JAVA语言概述
- java 基本语法
2.1 关键字和标识符
2.1.1 Unicode 字符集
最多可识别65536个字符 在字符集中 前128个字符刚好是ASCII码。
2.1.2 关键字
Java语言中定义了一些专有词汇,统称为关键字。
2.1.3 标识符
java语言中 类名、对象名、方法名、常量名和变量名
Java标识符具体命名规范如下:
(1)一个标识符可以由几个单词连接而成,以表明他的意思;
(2)标识符由一个或多个字母、数字、下划线(-)和美元符号($)组成,没有长度限制。
(3)标识符不能是关键字;
(4)标识符中的第一个字符不能为数字;
(5)标识符不能是true、flase和null;
(6)对于类名,每个单词的首字母都要大写,其他字母则小写,如RecordInfo;
(7)对于方法名和变量名,除第一个单词首字母小写外,其他单词首字母都大写,如getRecordName();
(8)对于常量名,每个单词的每个字母都要大写,如果由多个单词组成,通常单词之间要用下划线(-)分隔,如MAX_VALUE;
(9)对于包名,每个单词都要的每个字母都要小写,如com.frame。
2.2常量与变量
2.2.1 常量的概念及使用要点
所谓常量,就是值永远不允许被改变的量。如果要声明一个常量,就必须用final关键字修饰。
final int(常量类型) PIE;
注意(对于常量名,每个单词的每个字母都要大写,如果由多个单词组成,通常单词之间要用下划线(-)分隔,如MAX_VALUE;)
声明常量时,通常立即对其赋值,即立即对常量初始化。
final int YOUTH_AGE=18;
final float PIE = 3.14f(F);
注意(在float 型常量赋值时,需要在后面加上一个字母F(f)),说明为float型。
如果要声明多个同一类型的常量。
final int A,B,C;
final int D=4,E=5,F=6;
如果声明常量的时候没有对其初始化,也可以在需要的时候对其初始化。
final float PIE;
PIE=3.14f;
2.2.2 变量的概念及使用要点
所谓变量,就是值可以被改变的量。声明一个变量,不需要任何关键字进行修饰。
String name;
注意(对于方法名和变量名,除第一个单词首字母小写外,其他单词首字母都大写,如getRecordName())
在声明变量的时候,可以对其赋值,即对变量初始化。
String name = “ MWQ”;
Int partyMemberAge=26;
Student s = new Student(); //声明一个student型变量
如果要声明多个同一类型的变量;
Int A,B,C;
Int D=4,E=5,F=6;
变量与常量的区别是 变量的值允许被改变。
String name = “MW”;
name = “QQ”;
2.3数据类型
Java是强类型编程语言
Java数据类型分两大类,分别是基础数据类型和引用数据类型。
基础数据类型由java语言定义,其数据占用内存大小固定,在内存存放的是数值本身
引用数据类型在内存中存放的是引用数据的存放地址,并不是数据本身。
字节型(byte)(1字节)
短整型(short)(2字节)
整数型 整形(int) (4字节)
长整形(long)(8字节)
基本数据类型 单精度(float)(4字节)
浮点型
双精度(double)(8字节)
字符型 (char)(2个字节)
数据类型 逻辑型(Boolean)(1个字节)
数组
引用数据类型 类
接口
2.3.1 基本数据类型
整形注意
所赋的值不能超过对应数据类型允许的取值范围
在为long型变量或常量赋值时,需在所赋值的后面加一个字母”L/l”;如果所赋的值未超出int型的取值范围,也可以省略”L/l”;
浮点型注意
Java默认小数为double类型,在将小数赋值给double型常量或变量时 可以不加”D”(“d”)
如果double ,float 所赋值为整数并且未超出int型取值范围 可以省略”D/d” 或 “F/f”
字符型注意
在为char型常量和变量赋值时,无论所赋的值为字母、符号、还是汉字,都只能为一个字符。
char c = 88;
System .out.println(c); //得到的是 大写字母”X”
逻辑型注意
可以将 逻辑值 ture和flase赋值给boolean型变量
也可以将逻辑表达式赋值给boolean型变量
2.3.2引用数据类型
引用数据类型包括类引用,数组引用,接口引用。
当将引用数据类型的常量或变量初始化为null时,表示引用数据类型的常量或变量不引用任何对象。
2.3.3 基本类型和引用类型的区别。
1.组成
基本数据类型是一个具体的数字、字符或逻辑值。
引用数据类型是一个复杂的数据结构的实例,可以包含基本数据类型的变量,可以包含对这些变量的具体操作行为,可以包含其他引用数据类型的变量。
- java虚拟机的处理方式
基本数据类型,java虚拟机会根据变量的实际类型为其分配实际的内存空间,
引用数据类型,java虚拟机分配内存空间,但在内存空间存放的并不是变量所引用的对象,而是对象在堆区存放的地址,引用变量最终只是指向被引用的对象,不是存储了被引用的对象。因此,两个引用变量之间的赋值,就是将一个引用变量存储的地址复制给另一个引用变量,从而使两个变量指向同一对象
2.3.4 数据类型之间的相互转换
基本数据类型转换分为 自动类型转换和强制类型转换。
- 自动类型转换
程序员无需操作 java 会自动完成从低级向高级类型转换
低Byte<short<char<int<long<float<double高
对于char 不可以将数据类型为byte和short变量赋于char变量,但是可以将char变量赋值给int、long、float、double。
- 强制类型转换
强制把数据类型相对较高的数据或变量赋值给数据类型相对较低的变量
执行强制类型转换,可能会导致溢出或精度降低。
2.4 数组
数组是一种常见的数据结构,通过数组可以保存一组相同数据类型的数据,一旦创建,长度固定。数组可以为基本数据类型,也可以为引用数据类型,可以是一维数组、二维数组,甚至是多维数组。
2.4.1 声明数组
声明一维数组
int[]months;
boolean members[];
声明二维数组
int[][]days;
boolean holidays[][];
2.4.2 创建数组
创建一维数组
int [] months = new int[12];
创建二维数组
Int[][]days = new int[2][3];
2.4.3 初始化数组
int boy[] = {2,3,4,8,6};
等价于
int boy[] = new int[5]
- 运算符与流程控制
3.1运算符
3.1.1赋值运算符
赋值运算符”=”,它的作用是将数据、变量或对象赋值给相应的变量和对象。
3.1.2 算术运算符
算数运算符支持整数型数据和浮点型数据的运算,当整数型数据和浮点型数据进行算数运算时,java会自动完成数据类型的转换,并且计算结果为浮点型。
1.没有小数参与
(1)除法注意
整数型数据和变量之间进行除法运算时,无论是否整除,运算结果都将是一个整数,通过去掉小数部分
(2)求余运算注意
整数型数据和变量之间进行求余运算时,运算结果为数学运算中的余数
- 关于0注意
与数学一样
2.有小数参与的运算
在对浮点型数据或变量进行运算的时候,如果表达式中有double型变量或数据,则运算结果为double 否则为float
如果被除数为浮点型数据或变量,无论是除法运算,还是求余运算,0都可以做除数。
被除数是正数 为infinity 无穷大 被除数是负数 为-infinity 无穷小 如果是求余运算 为NaN
3.1.3关系运算符
关系运算符用于比较大小,运算结果为boolean型。当关系式成立,为true,不成立为false。
3.1.4逻辑云算符
- !逻辑值取反运算
- ^ 逻辑值进行异或运算。当运算符两侧同为true或flase时为flase 否则为true。
- “&&”和”&”均用于逻辑与运算,两侧同为true 为true 否则为flase
- ”&&”(简洁运算符) 只有在左边为true时,才运算右侧,否则直接返回运算结果。
- “&”(非简洁运算符) 无论左侧true或flase都运行右侧。
- ”||”和”|”均属于逻辑或运算。当两侧同为flase时运算为flase,否则为true。
(1)同上(1)
(2)同上(2)
3.1.5 位运算符
位运算符是对操作数以二进制为单位进行的操作和运算,运算结果均为整型。位运算符又分为逻辑位运算符合移位运算符。
- 逻辑运算符
操作数x | 操作数y | ~x | x&y | x|y | X^y |
0 | 0 | 1 | 0 | 0 | 0 |
0 | 1 | 1 | 0 | 1 | 1 |
1 | 0 | 0 | 0 | 1 | 1 |
1 | 1 | 0 | 1 | 1 | 0 |
注意 ~取反。按位与& 都为1 为1。按位或|有一个1就为1。按位异或^ 同时为0或1则为0,否则为1。
- 移位运算
“<<”左移,低位添0补齐、”>>”右移,高位添符号位和”>>>”右移,高位添0补齐。
3.1.6 对象运算符(instanceof)
判断对象是否为某一类型,运算结果为boolean型,是返回true,否则返回flase。
3.1.7 其他运算符
运算符 | 说明 | 运算结果类型 |
++ | 一元运算符,自动递增 | 与操作元的类型相同 |
-- | 一元运算符,自动递减 | 与操作元的类型相同 |
?: | 三元运算符,根据”?”左侧逻辑值,若为true返回”:”左侧否则为右侧 | 与返回值类型相同 |
[] | 用于声明、建立或访问数组的元素 | 用于数组,则为数组;用于访问数组元素,则类型为该数组类型 |
. | 用于访问类的成员变量或对象的实例变量 | 访问成员变量,则与变量相同;访问方法,则与方法返回值相同 |
3.1.8 运算符的优先级别及结合性
略略略。
3.2 if语句
3.2.1 简单的if条件语句
(1)简单的if条件语句;
(2)if...else条语句;
(3)if...else if 多分支条件语句;
3.3 swich语句
swich语句是多分支的开关语句。根据表达式的值来执行输出语句。
swich(){
case ?:
输出语句;
break;
case?:
输出语句;
break;
default:
输出语句;
}
3.4 swich语句和if语句的区别
swich效率更高一点。
if应用广泛和实用。
3.5循环语句
3.5.1 while循环语句
while(表达式){
语句序列
}
while是boolean类型 true则执行循环体,循环到末尾时,会在执行表达式,直到表达式为false,执行循环体外面的。
注意 一定要保证程序正常运行,否则会死循环
3.5.2 do...while 循环语句
do{
语句序列
}while(表达式)
循环至少被执行一次,先执行语句,再判断是否继续执行。
注意 一定要保证程序正常运行,否则会死循环
3.5.3 for循环语句
for语句是最常用的循环语句,一般在循环次数已知的情况下。
For(初始化语句;循环条件;迭代语句){
语句序列
}
3.5.4 for-each风格的for循环
for-each循环在数组中用的多。
for(类型 变量名:要遍历的数组){
语句序列
}
3.5.5 循环的嵌套
1. for循环嵌套
for(;;){
for(;;){
语句序列
}
}
2. while循环语句嵌套
while(条件表达式){
while(条件表达式2){
语句序列
}
}
- “ do....while”循环语句嵌套
do{
do{
语句序列
}while(条件表达式1);
}while(条件表达式2);
3.6跳转语句
3.6.1 break 跳转语句
break语句可以终止循环或其他控制结构。它在for、while或”do...while”循环中,用于强行终止循环。在switch多分支中也适用。
3.6.2 continue跳转语句
Continue语句应用在for、while、”do...while”等循环中,如果循环体中执行了continue语句,那么本循环结束,不再执行continue后面的语句。
3.6.3 return跳转语句
return语句实现从一方法的返回,并把控制权交给调用他的语句
- 面向对象基础
4.1面向对象程序设计
是新一代的程序开发模式,模拟现实世界的事物,把软件系统抽象成各种对象的集合,以对象为最小系统单位,更接近人类的自然思维,给程序员更灵活的空间。
-
-
- 面向对象程序设计概述
- 面向对象程序设计特点
-
- 封装性
将对象的属性和方法封装起来,使用户知道并使用对象提供的属性和方法即可,不需要对象的具体实现。
- 继承性
通过继承原有类的某些特性和或全部特性而产生的类,原类叫父类,产生的新类叫子类。
- 多态性
在父类中定义的属性和方法被子类继承之后,可以具备不同的数据类型或表现不同的行为使得同一个属性或方法在父类及其各个子类中具有不同的语义。
4.2类
类是创建对象的模板,它包含被创建对象的属性和方法的定义。
4.2.1定义类
所有对象都是由类创建的
- 什么是类
同一事物的统称。
类中编写属性和方法,然后通过对象来实现类的行为。
- 类的声明
需要定义类的名称、对该类的访问权限、该类与其他类的关系等
[修饰符]class<类名>[extends 父类名][implements接口列表]{}
修饰符 可选 可选值为 public、abstract和final。
- 类体
类声明部分大括号中的内容为类体。
- 成员变量的定义
- 成员方法的定义
4.2.2 成员变量和局部变量
在类体中变量定义部分所声明的变量为类的成员变量,而在方法体中声明的变量和方法的参数则被称为局部变量。成员变量又可分为实例变量和类变量,在声明成员变量时,用static修饰的称为类变量(static变量或静态变量),否则为实例变量。
- 声明成员变量
用成员变量来表示类的状态和属性,声明如下。
[修饰符][static][final]<变量类型><变量名>;
Static:可选,指定成员变量为类变量,可以直接通过类名访问,如省去则该成员变量为实例变量
final:可选,指定该成员变量为取值不会改变的常量。
类变量和实例变量的区别:在运行时,java虚拟机只为类变量分配一次内存,在加载类过程中完成类变量的内存分配,可以直接通过类名访问类变量。而实例变量不同,每创建一个实例,就会为该实例的变量分配一次内存。
- 声明局部变量
[final]<变量类型><变量名>;
final:可选,指定该局部变量为常量。
- 变量的有效范围
- 成员变量:在类中声明,整个类有效。
- 局部变量:在方法内或方法内的复合代码块({}之间的代码)中声明的变量。在复合代码块声明的变量,只在当前复合代码块中有效;在复合代码块外、方法内声明的变量在整个方法内都有效。
4.2.3 成员方法
Java中类的行为由类的成员方法来实现。
- 方法的声明
- 方法体
格式:[修饰符]<方法的返回值类型><方法名>([参数列表]){
[方法体]
}
注意:在同一类中,不能定义参数和方法名都和已有方法相同的方法。
4.2.4 注意事项
类体由成员变量和成员方法组成。而对成员变量的操作只能放在方法中,方法使用各种语句对成员变量和方法体中声明的局部变量进行操作,声明成员变量是可以赋初值。
4.3构造方法与对象
构造方法用于对对象中的所有成员变量进行初始化。对象的属性通过变量来定义,也就是类的成员变量,而对象的行为通过方法来体现,也就是成员方法。方法可以操作属性形成一定的算法来实现一个具体的功能。类把属性封装成一个整体。
4.3.1 构造方法的概念及用途
构造方法名字必须与它所在类的名字完全相同,并且没有返回值,也不需要void修饰。
- 默认的构造方法和自定义的构造方法
如果类定义了一个或多个构造方法,那么java不提供默认的构造方法。
有无参数的构造函数的区别是,有参数的构造函数可以在new的时候,同时给创建的对象中的数据赋值。
2.构造方法没有类型。
4.3.2对象概述
对象是对类的一个具体描述,是一个客观存在的实体。万物皆对象
一个对象在java语言中的生命周期包括创建、使用、销毁。
- 对象的创建
- 对象的声明。
类名 对象名;
- 实例化对象。
对象名=new 构造函数名([参数列表])
- 对象的使用
创建对象后,就可以访问对象的成员变量,并改变成员变量的值,而且还可以调用对象的成员方法。通过使用运算符 ”.” 实现对成员变量的访问和成员方法的调用。
对象.成员变量
对象.成员方法()
- 对象的销毁
Java中不需要手动释放对象所占用的内存。Java提供的垃圾回收机制可以自动判断对象是否还在使用,并能够自动销毁不再使用的对象,收回对象所占用的资源。
Java提供一个名为finalize()的方法,用于在对象被垃圾回收机制销毁之前执行一些资源回收工作,由垃圾回收系统调用。但垃圾回收系统的运行是不可预测的。finalize()方法没有任何参数和返回值,每个类有且只有一个finalize()方法。
4.4类与程序的结构关系
4.5 参数传值
在Java中,如果声明方法时包含了形参的声明,则调用方法时必须给这些形参指定参数值,调用方法时实际传递给形参的参数值被称为实参。
4.5.1传值机制
Java中参数传递方式只有一种,就是值传递。就是将实际参数的副本传递到方法内,而参数本身不受任何影响。
4.5.2基本数据类型的参数传值
对于基本数据类型的参数,向该参数传递值的级别不能高于该参数的级别。
4.5.3 引用类型的参数传值
当参数是引用数据类型时,传递的值是变量中存放的 ” 引用”,而不是变量所引用的实体。
4.6 对象的组合
如果一个类把某个对象作为自己一个成员变量,使用这样的类创建的对象后,该对象中就会有其他对象,也就是该类对象将其他对象作为自己的一部分。
4.6.1组合与复用
一个对象a组合了另一个对象b,那么对象a就可以委托对象b调用其方法,即对象a以组合的方式复用了对象b的方法。
4.7实例方法与类方法
类中定义的方法分为实例方法和类方法。
4.7.1实例方法和类方法定义
声明方法时,方法类型前面不使用static修饰的是实例方法,使用static修饰的是类方法,也称静态方法。
4.7.2实例方法和类方法区别
- 使用对象调用实例方法
- 使用类名调用类方法
4.8 this关键字
this关键字表示某个对象,this关键字可以出现在实例方法和构造方法中,不可以出现在类方法中。当局部变量和成员变量的名字相同时,成员变量就会被隐藏,这时如果想在成员方法中使用成员变量,必须使用this关键字。
4.9 包
Java要求文件名和类名相同,如果多个类放在一起,可能出现文件冲突,所以需要使用包将类分组。
4.9.1 包的概念
包是java提供的一种区别类的命名空间的机制,是类的组织方式,是一组相关类和接口的集合,提供了访问权限和命名管理机制。
包的三种用途
- 将功能相近的类放在一个包中,方便查找与使用。
- 由于不同包可以存放同名类,使用包一定程度上避免命名冲突。
- 在java中,某些访问权限是以包为单位的。
4.9.2 创建包
4.9.3使用包中类
类可以访问其所在包中的所有类,还可以使用其他包中的所有public类。两种方法
- 使用长名引用包中类。
- 使用import语句引用包中的类。
4.10 import语句
Import关键字用于加载已定义好的类或包,被加载的类可供本类调用其方法和属性。
4.11访问权限
访问权限由访问权限修饰符进行限制,访问权限修饰符有private、protected、public,都是java关键字。
- 什么是访问权限
访问权限是指对象是否能够通过”.”运算符操作自己的变量或”.”运算符调用类中方法。
- 继承与多态
5.1继承简介
通过继承实现代码的重用性,提高程序的可维护性。
5.1.1继承概念
继承是子类拥有父类的成员。
5.1.2子类的设计
通过关键字extends来显示指明其父类
[修饰符]class子类名extends父类名
修饰符:可选,用于指定类的访问权限,可选值为public、abstract、final。
5.1.3继承的使用原则
子类继承父类所有可被子类访问的成员变量和成员方法,但有以下原则:
- 子类能够继承父类中被声明为public和protected的成员变量和成员方法。
- 子类能够继承同一包中的由默认修饰符修饰的成员变量和成员方法。
- 如果子类声明了一个和父类的成员变量同名的成员变量,则子类不能继承父类的成员变量,称子类的成员变量隐藏了父类的成员变量。
- 如果子类声明了一个和父类的成员方法同名的成员方法,则子类不能继承父类的成员方法,称子类的成员方法覆盖了父类的成员方法。
5.1.4使用super关键字
子类中声明的成员方法与父类的成员方法同名,并且参数个数、类型和顺序也相同,称子类的成员方法覆盖了父类的成员方法。这时,想在子类中访问父类中被子类隐藏的成员方法或变量时,就可以使用super关键字。Super两种用途
- 调用父类构造方法
Super([参数列表])
- 操作被隐藏的成员变量和被覆盖的成员方法
Super.成员变量名
Super.成员方法名([参数列表])
5.2子类的继承
子类中一部分成员是子类自己声明、创建的,另一部分是通过它的父类继承的。在java中,Object类是所有类的祖先类,除object类外每个类有且只有一个父类,一个类可以有零个或多个子类。
5.3多态
通常使用方法的重载和覆盖实现类的多态性。
5.3.1方法的重载
一个类中,出现多个方法名相同,但参数个数或参数类型不同的方法。
注意 方法返回值类型不能作为区分方法重载的标志。
5.3.2 方法的覆盖(重写)
当子类继承父类中所有可能被子类访问的成员方法时,如果子类的方法名(参数列表)和父类的方法名(参数列表)相同,那么子类就不能继承父类的方法,称子类的方法覆盖了父类的方法。
注意 在方法覆盖时要注意
- 子类不能覆盖父类中声明为final或者static的方法
- 子类必须覆盖父类中声明为abstract的方法,或者子类也将方法声明为abstract
- 子类覆盖父类中同名方法时,子类方法的声明也必须和父类中被覆盖的方法的声明一样。
5.4抽象类
5.4.1抽象类和抽象方法
抽象类就是只声明方法的存在而不去具体实现它的类。抽象类不能被实例化,也就是不能创建其对象。定义抽象类,在class前面加abstract
Abstract<方法返回值类型>方法名(参数列表);
方法返回值类型:必选
注意 抽象方法不能使用private或static关键字修饰。
包含一个或多个抽象方法的类必须声明为抽象类。
5.4.2抽象类和抽象方法的规则
- 抽象类和抽象方法都必须使用abstract修饰符修饰。
- 抽象类不能被实例化。
- 抽象类可以包含属性、方法(普通方法和抽象方法)。
- 含有抽象方法的类只能被定义成抽象类。
5.4.3抽象类的作用
抽象类不能被实例只能被继承。抽象类作为多个子类的模板,子类在抽象类的基础上进行扩展,但是子类大致保留抽象类的行为。
5.5 final修饰符
final关键字用来修饰类、变量和方法,用于表示它修饰的类、方法和变量不可变。
5.5.1final变量
final可以修饰成员变量、局部变量和形参。
5.5.2final类
final修饰的类为final类,不能被继承
5.5.3final方法
使用final修饰的方法是不可以被重写的。
5.6内部类
Java允许在类中定义内部类,内部类就是在其他类内部定义的子类。
内部类有四种形式
- 成员内部类
- 局部内部类
- 静态内部类
- 匿名内部类
5.6.1成员内部类
成员内部类和成员变量一样,属于类的全局成员。
注意 Java类中只允许存在一个public公共类
5.6.2局部内部类
局部内部类和局部变量一样,都在方法内定义的,有效范围只在方法内部有效。
局部内部类可以访问他的创建类中的所有成员变量和成员方法,包括私有方法。
5.6.3静态内部类
静态内部类和静态变量类似,都使用static修饰
5.6.4匿名内部类
匿名内部类就是没名字的内部类 有以下特点
- 匿名类可以继承父类的方法,也可以重写父类的方法。
- 匿名类可以访问外嵌类中的成员变量和方法,在匿名类中不能声明静态变量和静态方法。
- 使用匿名类时,必须在某个类中直接使用匿名类创建对象。
- 使用匿名类创建对象时,要直接使用父类的构造方法
匿名类格式
new ClassName(){
.....
}
第六章接口
6.1接口简介
Java中的接口是一个特殊的抽象类,接口中的所有方法都没有方法体。
6.2定义接口
使用关键字interface来定义一个接口。分为接口的声明和接口体,其中接口体由常量定义和方法定义两部分组成。
语句格式
[修饰符]interface接口名[extends 父接口名列表]{
[public] [static] [final]常量;
[public][abstract]方法;
}
方法:接口中的方法只有定义而没有被实现。
6.3接口的继承
接口可以实现多继承,当子类继承父类接口时,子类会获得父类接口中定义的所有抽象方法、常量属性等。
6.4接口的实现
接口可以被其他接口继承,也可以被类实现,实现使用关键字implement。
语法格式:
[修饰符]class<类名>[extends 父类名]implements 接口列表{
}
每个类只能实现单继承,而实现接口时。一次则可以实现多个接口。
6.5接口与抽象类
接口与抽象类的共同点:
- 都不能被实例化,能被其他类实现和继承。
- 都包含抽象方法,实现接口或继承抽象类的普通子类都必须实现这些抽象方法。
接口和抽象类的差别:
- 接口中只能有抽象方法,不能有普通方法;抽象类中可以有普通方法。
- 接口不能定义静态方法,抽象类可以
- 接口只能定义常量属性,不能定义普通属性,抽象类都可以
- 接口不包含初始化块,抽象类包含初始化块
- 一个类只能有一个父类,包括抽象类,但可以实现多个接口。
6.6接口与多态
由接口实现的多态就是指不同的类实现同一个接口的时候可能具有不同的表现形式。
第七章 异常处理
7.1异常
异常是指程序在运行时产生的错误。
需程序员捕获处理或声明抛出,称为”受检查异常”;java虚拟机自动进行捕获处理,称为”运行时异常”或不受检查异常。
7.2异常处理
某个方法出现异常时,可以在当前方法中进行捕获,然后处理异常,也可以向上抛出,由方法的调用者处理。
7.2.1使用”try......catch”语句
一般格式
try{
可能产生异常的代码
}catch(异常类 一次对象){
异常处理代码
}
注意 若不知代码抛出哪种异常,可指定他们的父类Throwable或Exception
7.2.2finally子句的用法
不管”try,....catch”是否顺利被执行完,最终都会执行finally语句的代码
7.2.3使用throws关键字抛出异常
若某个方法可能发生异常,但不想在当前方法中处理这个异常,可以将其抛出,然后在调用该方法的代码中捕获该异常进行处理。
7.2.4 使用throw 关键字
Throw 也可以抛出异常,throw用于方法体内,并且抛出一个异常对象,而throws用在方法生命中,指明方法可能抛出多个异常。
7.2.5使用异常注意事项
- try、catch、finally不能单独使用
- Try语句后既可以使用catch语句,也可以使用finally语句。当与catch语句一起使用时,可存在多个catch语句块,而只能有一个finally语句块。当catch与finally同时存在时,finally必须放在catch后。
- 多个catch语句捕获同类型的异常,则捕获子类异常的catch语句块要放在捕获父类异常的catch语句块前面。
- 在try语句中声明的变量是局部变量,只在当前catch中有效。
- 对于发生的异常,必须使用”try...catch ”语句捕获,或使用throws向上抛出,否则编译出错。
- 使用throw抛出一个异常对象时,该语句后面的代码将不会被执行。
7.3异常类
Java提供了一些内置的异常类来描述容易发生的错误,这些类都继承自java.lang.Throwable类。Throwable有两个子类:Error和Exception
7.3.1 Error类
Error类及其子类通常描述java运行系统中的内部错误以及资源耗尽的错误。Error表示的异常是比较严重的,仅靠修改程序本身不能够恢复执行。被称为致命异常类。
7.3.2Exception类
非致命异常类。
Exception类分为runtimeException运行时异常和运行时异常之外的异常。
7.4自定义异常
步骤
- 创建自定义异常类
- 在方法中通过throw抛出异常
- 若在当前抛出异常的方法中处理异常,可使用”try...catch”语句捕获,否则在方法声明处通过throws指明要抛出给方法调用者的异常,继续下一步。
- 在出现异常的方法调用代码中捕获并处理的异常。
7.5异常的使用规则
- 在当前方法声明中使用”try..catch”语句捕获异常。
- 一个方法被覆盖时,覆盖它的方法必须抛出相同的异常或异常子类
- 如果父类抛出多个异常,则覆盖方法必须抛出那些异常的一个子集,不能抛出新异常。
- 常用的实用类、
8.1String 类
8.1.1创建字符串对象
String 字符串标识符=字符串;
注意 一个空字符串并不是它的值等于null,空字符串是有空的“”””符号定义的,它是实例化之后的字符串对象,但是不包含任何字符。
8.1.2连接字符串
用”+”实现,将多个字符串合并到一起生成一个新的字符串。
8.1.3字符串操作
- 比较字符串
- equals()方法
注意equals()方法比较的是字符串对象的内容,而操作符”==”比较的是两个对象的内存地址(即使内容相同,不同对象的内存地址也不相同),所以,在比较两个字符串是否相等时,不能使用操作符”==”。
- equalslgnoreCase()方法
和equals()区别是不分大小写。、
- startWith()和endsWith()方法
分别是来判断是否以指定的字符串开始或结束。
- compareTo()方法
比较字符串是大于还是等于或者小于另一个字符串。
- 获取字符串长度
.length()方法
- 字符串大小转换
ToLowerCase将大写字母转换成小写字母
ToUpperCase将小写字母转换成大写字母
- 查找字符串
IndexOf()搜索字符或字符串首次出现的位置
lastIndexOf()搜索字符或字符串最后一次出现的位置
- 截取字符串
Substring()
- 去掉字符串的首尾空格
Trim()
- 替换字符串中的字符或子串
Replace()
- 分割字符串
Split()
8.1.4格式化字符串
format()方法,最常用的是对日期和时间格式化
8.1.5对象的字符串表示
Object类有一个public String toString()方法,用于获得对象的字符串
字符串形式:
包名.类名@内存的引用地址
8.2日期的格式化
8.2.1Date类
- 无参构造函数
获取当前本机时间
- 有参构造函数
8.3Scanner类
该类用于实现用户的输入,只要有控制台就能实现输入的类。创建Scanner常见方法有两种
- Scanner(InputStream in);
语法:new Scanner(in)
- Scanner(File file)
语法:new Scanner(file)
8.4Math和Random类
- Math类
位于java.lang包中,包含许多进行科学计数法的类方法,可以直接通过类名进行调用
- Random类
位于java.util包中,用于获得随机数的方法
8.5数字格式化
按照规定格式得到一个字符串
8.5.1formatter类
- 格式化模式
方法中一个使用双引号括起来的字符序列,该字符序列由格式符和普通字符构成。
- 值列表
值列表是使用逗号分隔的变量、常量或表达式。
8.6StringBuffer类
8.6.1StringBuffer对象的创建
StringBuffer类和String类都是用来代表字符串的,但内部实现方式不同。String类创建的字符串对象是不可修改的,String字符串不能修改、删除或替换字符串中的某个字符。而StringBuffer类创建的字符串对象是可以修改的。
- StringBuffer对象初始化
StringBuffer s = new StringBuffer();
String和StringBuffer属于不同类型,不能直接强制类型转换。
- StringBuffer的构造方法
- StringBuffer()
- StringBuffer(int size)
- StringBuffer(String s)
8.6.2StringBuffer类的常用方法
- append方法
使用append方法可以将其他java类型数据转化为字符串后,再追加到StringBuffer对象中
8.7包装类
Integer是int的包装类
Character是char的包装类
第九章集合
9.1集合主要接口概述
Java.util包中提供了一些集合,常用的集合有List、Set和Map,List和set实现了Collection接口,集合又被称作容器,与数组不同,数组长度固定,集合长度可变;数组存放基本类型数据,集合存放类对象的引用。
- Collection接口是List和set接口的父接口
- List接口是collection的子接口,存放有序可重复
- Set接口是collection的子接口,存放无序不可重复
- map接口以键值对的形式存放,键对象不可重复,值可以重复
9.2Collection接口
Collection接口定义了一些通用方法,也适合list接口和set接口。
方法名称 | 功能简介 |
Add() | 将指定对象添加到集合中 |
addAll() | 将指定集合中的所有对象添加到该集合中 |
Remove() | 将指定对象从集合中移除 返回boolean类型 |
removeAll() | 从该集合中移除同时包含在指定集合中的对象 |
retainAll() | 仅保留该集合中同时包含在指定集合中的对象 |
Contains() | 查看集合中是否存在指定的对象 |
containsAll() | 查看集合中是否存在指定集合中的所有对象 |
isEmpt() | 查看集合是否为空 |
Size() | 查看集合中存放对象的个数 |
Clear() | 移除集合中所有对象,清空该集合 |
Iterator() | 用来序列化该集合的所有对象 |
toArray() | 用来获得一个包含所有对象的Object型数组 |
toArray(T[] t) | 用来获得一个包含所有对象的指定类型的数组 |
equals(Object obj) | 查看指定的对象与该对象是否为同一个对象 |
9.3List集合
List集合为列表类型,列表的主要特征是以线性方式存储对象。
9.3.1List的用法
方法名称 | 功能简介 |
Set(int index,Object obj) | 将集合中指定索引位置的对象修改为指定对象 |
Get(int index) | 用来获得索引位置的对象 |
Indexof(object obj) | 获得指定对象的索引位置 |
Lastindexof(object obj) | 获得指定对象的索引位置 |
listIterator(int index) | 获得一个包含所有对象的ListIterator实例 |
subList(int fromindex,int toindex) | 通过截取fromIndex(包含)到toindex(不包含)的对象,重新生成一个List集合并返回 |
|
|
9.3.2使用ArrayList类
ArrayList类实现了List接口,采用数组结构保存对象,查询速度快。
9.3.3使用LinkedList类
LinkedList类实现List接口,由LinkedList类实现的List集合采用链表结构保存对象。插入删除快
方法名称 | 功能简介 |
addFirst(E obj) | 将指定对象插入列表的开头 |
addLast(E obj) | 将指定对象插入列表的结尾 |
getFirst() | 获得列表开头的对象 |
getLast() | 获得列表结尾的对象 |
RemoveFirst() | 移除列表开头的对象 |
RemoveLast() | 移除列表结尾的对象 |
9.3.4 ArrayList和LinkedList有什么区别?
ArrayList和LinkedList都实现了List接口,他们有以下的不同点:
ArrayList是基于索引的数据接口,它的底层是数组。它可以以O(1)时间复杂度对元素进行随机访问。与此对应,LinkedList是以元素列表的形式存储它的数据,每一个元素都和它的前一个和后一个元素链接在一起,在这种情况下,查找某个元素的时间复杂度是O(n)。
相对于ArrayList,LinkedList的添加,删除操作速度更快,因为当元素被添加到集合任意位置的时候,不需要像数组那样重新计算大小或者是更新索引。
LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素。
9.4set集合
存放无序不可重复的对象
9.4.1使用HashSet类
HashSet类实现set集合的优点是能够快速定位集合中的元素
由HashSet类实现的set集合中的对象必须是唯一的,需要重新实现equals()方法和hashCode()方法,从而保证插入集合中的对象能够合理的分布在集合中。
9.4.2使用TreeSet类
便利对象时可能按照自然顺序递增排列,存入由TreeSet类实现的set集合的对象时必须实现Comparable接口。
9.5map集合
map集合为映射类型,每个对象都有一个键对象,在检索对象时通过相应的键对象来获取值对象。要求键唯一。
9.5.1map用法
put(K key,V value) | 向集合中添加指定的键—值映射关系 |
PutAll() | 将指定集合中的所有键—值映射关系添加到集合中 |
KeySet() | 将集合中的所有键对象以set集合形式返回 |
Values() | 将集合中所有值对象以Collection集合 |
|
|
9.5.2使用Hashmap类
Hashmap类是线程不安全的,允许存放null键 null值。
9.5.2 使用Hashtable类
hashtable类是线程安全的,不允许存放null键null值。
9.5.4HashMap和Hashtable有什么区别?
HashMap和Hashtable都实现了Map接口,因此很多特性非常相似。但是,他们有以下不同点:
HashMap允许键和值是null,而Hashtable不允许键或者值是null。
Hashtable是同步的,而HashMap不是。因此,HashMap更适合于单线程环境,而Hashtable适合于多线程环境。
HashMap提供了可供应用迭代的键的集合,因此,HashMap是快速失败的。另一方面,Hashtable提供了对键的列举(Enumeration)。
一般认为Hashtable是一个遗留的类。
9.5.5concurrenthashmap的实现原理
分段索思想
HashTable性能差主要是由于所有操作需要竞争同一把锁,而如果容器中有多把锁,每一把锁锁一段数据,这样在多线程访问时不同段的数据时,就不会存在锁竞争了,这样便可以有效地提高并发效率。这就是ConcurrentHashMap所采用的"分段锁"思想。
第10章Java输入与输出
10.1File类
File类是一个与流无关的类,常用构造方法有三种。
- File(String pathname)
通过指定的文件路径字符串来创建一个新file实例对象
- File(String path,String filename)
根据指定的父路径字符串和子路径字符串创建file类的实例对象
(3)File(File file,String filename)
根据指定的File类的父路径和字符串类型的子路径创建file类实例对象
getName() | 获取文件名字 |
getParent() | 获取文件父路径字符串 |
Getpath() | 获取文件的相对路径字符串 |
Exists() | 判断文件或文件夹是否存在 |
IsFile() | 判断文件是否是一个正常的文件,不是目录 |
10.2流
10.2.1流的基本概念
流是一组有序的数据序列,分为输入流和输出流。
10.2.2输入输出流
1.字节输入流
inputStream类是字节输入流的抽象类,所有字节输入流的父类
- 字节输出流
OutputStream
- 字符输入流
Reader
- 字符输出流
Write
第11章多线程
11.1 线程概述
多线程使程序可以同时存在多个执行片段,根据不同的条件和环境同步或异步工作。线程和进程实现原理类似,但服务对象不同,进程代表操作系统平台中运行的一个程序,一个程序中包含多个线程。
- 进程
正在运行的程序
- 线程
一个进程内部也可以执行多任务,可以将进程内部的任务称为线程,线程是进程内部的实体,一个进程可以拥有多个线程。
11.1.1进程和线程的关系:
(1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
(2)资源分配给进程,同一进程的所有线程共享该进程的所有资源。
(3)处理机分给进程,即真正在处理机上运行的是线程。
(4)线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。线程是进程内的一个执行单元,也是进程内的可调度实体.
11.1.2进程与线程的区别:
进程是执行着的应用程序,而线程是进程内部的一个执行序列。一个进程可以有多个线程。线程又叫做轻量级进程。
线程的划分小于进程,线程隶属于某个进程。 进程是程序的一种动态形式,是CPU、内存等资源占用的基本单位,而线程是不能占有这些资源的。 进程之间相互独立,通信比较困难,而线程之间共享一块内存区域,通信比较方便。 进程在执行的过程中,包含比较固定的入口,执行顺序,出口,而线程的这些过程会被应用程序所控制
11.2 线程的创建
11.2.1线程的创建方式
- 继承Thread类;
- 实现Runnable接口;
- Thread类
常用方法start()方法启动线程,run方法为线程主体方法
- runnable接口
Runnable接口只有一个run方法,实现runnable接口后必须覆盖run()方法
11.2.2什么是线程安全?
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
如何保证线程安全呢?:
1使用线程安全的类
2使用synchronized同步代码块,或者用Lock锁
3多线程并发情况下,线程共享的变量改为方法局部级变量
11.3线程的生命周期
JAVA语言定义了五种线程状态:
①新建(New),当你 new 了一个Thread。
2可运行(runable) 线程对象创建后,其他线程调用该线程的start方法。或者该线程位于可运行线程池中等待被线程调用,已获取cpu的使用权。
3.运行(running) 可运行的线程获取了cpu的使用权,执行程序代码
4.阻塞(block) 由于某些原因该线程放弃了cpu的使用权。停止执行。除非线程进入可运行的状态,才会有机会获取cpu的使用权。
1. 等待阻塞:运行中的线程执行wait方法,这时候该线程会被放入等待队列。
2. 同步阻塞:运行中的线程获取同步锁,如果该同步锁被别的线程占用,这个线程会成被放入锁池,等待其他线程释放同步锁。
3. 其他阻塞:运行的线程执行sleep或者join方法这个线程会成为阻塞状态。当sleep超时,join等待线程终止,该线程会进入可运行状态。
5.死亡(dead) 线程run() mian() 执行完毕后,或者因为某些异常产生退出了 run 方法,该线程的生命周期结束
11.4线程的同步
提供synchronized关键字,防止资源冲突提供内置支持。
Java语言中有两种同步形式、同步方法和同步代码块。
- 同步方法
将访问这个资源的方法都标记为synchronized,这样调用这个方法的线程执行完之前,其他调用该方法的线程都会被阻塞。
- 同步代码块
Java语言中同步的设定不只应用于同步方法,也可设置程序的某个代码段块为同步区域。
11.5线程通信
创建多个不相同的线程来完成不相关的任务,然而,有时执行的任务可能有一定联系,就需要使这些线程进行交互。
11.6多线程死锁
所谓死锁是指多个进程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。死锁产生的4个必要条件:
- (1)互斥条件:在一段时间内某 资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。
- (2)不剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能 由获得该资源的进程自己来释放(只能是主动释放)。
- (3)请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源 已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。
(4)循环等待条件:存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被 链中下一个进程所请求。
11.7线程池的实现原理
线程池其实就是预先创建一堆线程对象缓存在一个队列里面,有任务需要执行的时候直接让某个线程去执行,任务执行完成后线程就空闲继续等待新的任务。
这样可以避免线程创建、销毁导致的额外的时间消耗。因为线程的创建和销毁是需要一定时间的,所以线程缓存可以节省时间,提供效率。