第一章 java由来、环境搭建
一、Java历史【了解】
1. 1995.5.23 sun推出的一款面向对象的编程语言。
2. Java的发展方向:JavaSE(Java的语言基础)、JavaME(通信方向)、JavaEE(企业级的应用)
二、Java的语言特点[面试题目]
1. 简单性(相对C c++等)
2. 面向对象性
3. 跨平台性(可以在不同的操作系统OS上运行)
三、运行机制【理解】
1. Java的运行机制:先编译后解释运行
将源文件(.java)—>通过编译器生成对应的字节码文件(.class 二进制文件)
---->通过解释器逐行的解释并运行
2. 注意:体现Java的跨平台性的内容为字节码文件。
3. Java的运行特点:一次编译多次运行。(多次运行-》运行的.class文件)
四、名词解释【理解】
1. JVM: Java虚拟机,作用屏蔽不同操作系统之间的差异性。
2. JRE: Java的运行环境(JRE= JVM+解释器)
3. JDK: Java的工具包(JDK= 编译器+JRE+类库+工具)
五、环境变量【理解】
1. JAVA_HOME: JDK的根目录
2. Path: JDK的bin目录
3. ClassPath: 代表的是类路径,告知JVM所需要的类去哪找。
通常的内容为: . 代表在当前目录下查找所有需要的类。
注意:验证JDK的三个环境变量是否配置成功,在DOS命令窗口下输入
javac+回车 和 java + 回车
六、第一个 Java程序【开发应用重点】
1. 源文件:以 .java 结尾
2. class 类名{ -->类是代码容器
//主函数:程序的入口,一个类中最多定义一个主函数
public static void main(String[] args){
System.out.println(“HelloWorld!”);//控制台输出,并且自动换行
System.out.print(“144班牛逼~”);//控制台输出,不自动换行
}
}
3.编译:javac 源文件名.java
4.运行: java 类名
注意:源文件中内容一旦更改,则需要重新编译,再次运行。
5. 注意:在一个源文件中可以定义多个类,但是类之间不能重名,
编译之后,每一个类会生成对应的 .class 文件。
6. public 的应用
① public 修饰符,公开的、公共的
② 被public修饰的类称为公开类、公共类
③ 注意:公开类的类名必须和源文件名完全一致;
一个源文件中最多定义有一个公开类。
七、包(package)【开发应用重点】
1. 作用:类似于文件夹,方便文件管理。
2. 语法:package 包名1.包名2.包名3; ---->多层包结构
3. 注意:
① package 需要定义在源文件第一行有效语句
② 一个源文件中最多有一个package语句
4. 带包的编译和运行:
编译: javac -d . 源文件名.java
运行:java 包名.类名
八、编码规范
1. 良好的格式习惯
① 层级之间要有缩进
② 一行只写一个语句
2. 良好的标识符命名习惯【重点】
① 硬性要求(语法要求):【面试+开发应用重点】
a. Java中的标识符只能以数字、字母、下划线(_)、$ 组成,但是不能以数字开头
b. Java中的标识符严格区分大小写
c. Java中的标识符没有长度限制
d. 不能以Java中关键字、保留字(goto/const)、特殊字符命名 (true/false/null)
注意:Java可以使用汉字作为标识符,但是不建议使用
② 软性要求(建议写法):
a. 望文生义
b. 类名每一个单词的首字母大写
c. 包名全小写
d. 常量名全部大写: PI
e. 变量名、函数名(方法名)首单词的首字母小写,其余单词的首字母大写(驼峰命名 法) 如:studentNameAndAge
3. 良好的注释习惯
① 单行注释: // 解释型的内容…
② 多行注释:/* 解释的内容…*/
注意:单行注释不可以嵌套多行注释,但是多行注释可以嵌套单行注释。
③ 文档注释 /**可以写多行的文档内容… */
javadoc -d dos 源文件名.java ---->生成对应的说明性文档
第二章 变量、数据类型
一、变量
1. 概念:计算中一块内存空间,数据的基本存储单位。【理解】
2. 组成:数据类型、变量名、值(数据)。【理解】
3. 定义:【语法基础】
① 声明:数据类型 变量名;
② 初始化:变量名 = 值;
4. 其他定义方式:【语法基础】
① 声明的同时初始化:数据类型 变量名 = 值;
② 同时声明多个相同数据类型的变量:
数据类型 变量名1,变量名2=值,变量名3;
二、数据类型【基础重点】
1. 基本数据类型(原始数据类型/简单数据类型)(8种)
① 整数类型
关键字
byte 1B -128~127
short 2B -32768~32767
int 4B -2147483648~2147483647
long 8B -922京~922京-1
注意:字节(Byte简称B) 1B = 8bites 位(bite简称为b)
字面值:定义中可以给变量赋的值。
long字面值后面需要加 L 或是 l,建议应用L(区分l 和 数字 1)
② 小数类型:
float 单精度 4B
double 双精度 8B
注意:
a. float字面值后面必须加 F 或是 f
b. double字面值后面可以加D 或是 d ,也可不加。
c. float和double都可以采用科学计数法的形式存储(底层是近似值存储)
面试题目:分析 int 类型的变量和float类型的变量哪一个存储数据更宽泛,说明原因。
③ 字符类型:
char 2B
字面值:
a. 用单引号引起来的一个字符 【重点】
char c = ‘A’;
char c2 = ‘中’;
b. 以整数的形式进行存储:(0~65535)【理解】
char c = 65;
char c2 = 29233;
c. 用 unicode形式存储:
char c = ’ u41’;
转义字符:
t : 水平跳格 n : 换行 : 反斜杠
’ : 单引号 " : 双引号
注意:以上的符号必须都是英文符号。
④ 布尔类型:
boolean 字面值 true/false
注意:Java的布尔类型和 0/1没有任何关系。
- 引用数据类型(对象数据类型)
① 类、数组、接口、集合等都是引用类型。
② 以String(字符串) 为例:
a. 字面值:用双引号引起来的一个或是多个字符。
b. 案例: String s = “abcghgjhsjfysu”;
三、类型转换【应用重点】
1. 数据类型的自动提升
① 当小数据类型的变量赋值给大数据类型的变量时,发生自动类型提升。
(从数据的存储范围来判定数据的大小类型)
② 规则:
a. byte->short -> int -> long -> float - > double
b. char -> int -> long -> float -> double
面试题目:
分析一下代码编译是否通过,不能说明原因。
char c = 65; 和 int i =65; char c2 = i
- 强制类型转换
① 场景:当大数据类型的变量赋值小数据类型的变量时,需要使用强制类型转换。
② 语法:大数据类型 大数据类型的变量名= 值;
小数据类型 变量名 = (小数据类型)大数据类型的变量名;
③ 强制转换的结果
a. 小数据类型强转为整数类型,则直接截取整数部分
double d = 12.7;
int i =(int)d;
b. 大数据类型的整数变量给小数据类型的整数变量赋值,
给的数据合理,则不损失任何内容
int i = 12;
byte b = (byte)i;
c. 大数据类型的整数变量给小数据类型的整数变量赋值,
给的数据不合理,将字节截取
int i = 257;
byte b=(byte)i; —> 打印输出结果1
四、表达式
1. 概念:由变量、字面值、运算符等组成一个式子,通常会产生一个结果。【理解】
2. 当两个数值或是变量参与运算时,如果参与运算的两个变量或是数据类型不一致,
运算过程中,会发生类型转换,转换规律如下:【理解+应用重点】
① 有double结果类型为 double;
② 没有double前提下,有float,结果类型为 float;
③ 没有double/float,有long,结果类型为long;
④ 其余的情况全部为 int 。
面试题目:
分析以下代码编译是否通过,通过写出结果,否则说明原因。
byte b = 1;
b = b + 1;
System.out.println(b);
五、运算符【理解+开发应用基础】
1. 算术运算符
+ - *(乘) /(除) %(取模/取余数)
注意:
① +两端如果为字符串类型的数据,则+为字符串的连接符。–》字符的拼接
② 如果+两端有一个是字符串的数据,则结果自动提升为字符串类型
2. 赋值运算符:= += -= *= /= %=
注意:+= 没有自动类型提升。
面试题目:
分析以下代码编译是否通过,通过写出结果,否则说明原因。
① byte b = 1;
b = b + 1;
System.out.println(b);//编译报错
② byte a= 1;
a+=1;
System.out.println(a); //编译通过,原因:+=没有自动类型提升,打印结果为2
3. 关系运算符
> 大于
>= 大于等于
< 小于
<= 小于等于
== 等于
!= 不等于
表达式的结果类型为布尔类型,这样的表达式称为布尔表达式。
注意:用关系运算符连接的表达式都为布尔表达式,
关系成立-true;关系不成立结果为false.
4. ++(自增) --(自减) —》一元运算符
面试题目:
a++: 先使用a变量原有的数据,然后再将a的内容加1(先使用,再加1)
++a: 先将a的内容加1,再使用 a的数据(先加1,再使用)
int c = a++ + (–a) +(a++);
System.out.println(a);
System.out.println©;
5. 逻辑运算符【基础应用】
① && :逻辑与,两个条件都为 true,则结果才为true.(短路运算符)
② || :逻辑或,两个条件有一个true,结果就为true.(短路运算符)
③ & :逻辑与,两个调价都为 true,则结果为true.(非短路运算符)
④ | : 逻辑或,两个条件只要有一个 true,结果为true.(非短路运算符)
⑤ ! :逻辑非,对结果取反。
6. 条件运算符(三元运算符)[了解]
① 语法:布尔表达式 ? 表达式1: 表达式2;
② 原理:如果布尔表达式的结果为true,则执行表达式1,否则执行表达式2.
第三章 分支结构
一、扫描仪(Scanner)【理解+应用】
1. 应用:java.util.Scanner sc = new java.util.Scanner(System.in);
2. 使用:
① 输入一个整数:int a = sc.nextInt();
② 输入一个小数:double d = sc.nextDouble();
③ 输入一个字符串:String str = sc.next(); // String str sc.nextLine();
④ 输入一个布尔内容:boolean b = sc.nextBoolean();
⑤ 输入一个字符: char c = sc.next().charAt(0);
二、导包(import)【应用重点】
1. 语法:import 包名1.包名2.类名; //导入包中一个类
import 包名1.包名2.*; //导入包中的所有的类
2. 位置:定义在package 的语句后面
3. 注意:
① 一个源文件中可以有多个import语句;
② java.lang包中的内容自动导入,无需导包。
三、if分支结构【开发应用重点】
1. if基本结构
① 语法:
if(布尔表达式/条件){
//语句
}
执行原理:如果布尔表达式的结果为true 则执行{}中的语句。
② 语法:
if(布尔表达式){
//语句1
}else{
//语句2
}
执行原理:如果布尔表达式的结果为true,则执行语句1, 否则执行语句2.
2. 多重的if结构
① 语法:
if(布尔表达式){
//语句1
}else if(布尔表达式){
//语句2
}else if(布尔表达式){
//语句3
}else{
//语句4…
}
② 执行原理:哪一个布尔表达式成立,则执行对应{}中的语句。
3. 嵌套的if结构
① 语法:
if(布尔表达式){
if(布尔表达式){
//语句…
}else{
//…
}
}else{
}
② 执行原理:先判断外层条件,外层条件成立(布尔表达式为true),
则再去判断内层条件。
四、switch…case的分支结构(等值)[通常用于界面设计]
1. 语法:
switch(表达式){
case 值1: 语句1;break;
case 值2: 语句2;break;
case 值3: 语句3;break;
default: 语句n;break;
}
2. 执行的原理:将表达式的结果和case后面的值从上往下依次匹配,哪一个相等,则执行 case后面对应的语句,如果都不相等,则执行default后面的语句。
3. 注意:
① switch后面表达式的结果类型必须是:byte、short、int、char;
JDK7.0版本之后,支持String类型的结果。
② switch…case结构本身没有终止自身结构的能力,需要在语句的后面
添加break语句,用于终止switch…case结构。
③ default没有位置要求,所有后面的break建议不要省略;
switch…case结构中可以没有default语句。
④ case后面的值不允许重复
五、局部变量【语法应用重点】
1. 概念:定义在函数内部的变量。
2. 特点:
① 局部变量必须先赋值后使用。
② 作用范围:从定义位置开始,到定义它的代码块结束。
③ 命名冲突:在重合的作用范围内,不允许命名冲突(不允许有重名的局部变量)
第四章 循环结构
一、循环
1. 概念:通过某一个条件,重复并且有规律的执行一段程序代码。
2. 组成:循环变量的初始化、循环条件、循环变量的改变(递增/递减)、循环体
3. 循环的分类:
① while循环【开发应用重点】
a. while(循环条件/布尔表达式){
//循环体…
}
b. 执行的原理:先判断循环条件是否满足(布尔表达式是为true),如果条件满足则执 行循环体的内容,并且改变循环变量的内容,再次判断条件是否满足,满足继 续执行循环体,同时改变循环变量…直到条件不满足(布尔表达式的结果为false) 为止,跳出循环结构。
c. 执行特点:先判断,再执行,执行次数:0~n次。
d. 注意:开发时,避免出现死循环的现象。
② do…while循环
a. 语法:
do{
//循环体…
}while(循环条件); //注意:此处的分号不能省略
b. 执行原理:先执行循环体,再去判断循环条件,条件成立则继续执行循环体的内 容,直到循环条件不满足为止,跳出循环。
c. 执行的特点:先执行,再判断,执行次数1~n次。
③ for循环【开发应用重点】
a. 语法:
for(循环变量的初始化;循环条件;循环变量的改变){
//循环体…
}
b. 执行的原理:先进行循环变量的初始化,然后判断循环条件,条件成立则执行循 环体,从而循环变量改变;继续判断循环条件…直到循环条件不满 足为止,则跳出循环。
c. 执行特点:先判断,再执行,执行次数:0~n次。
总结:
1. 循环次数确定时,建议使用 for
2. 循环次数不确定时,建议使用 while
二、循环的控制语句
1. break: 终止、结束循环。
2. continue: 跳出、结束本次的循环,从而进入下一次循环。
面试重点:写出 break和 continue.
① break 跳出、终止循环;continue跳出、结束本次循环
② break可以应用于switch…case结构;但是continue不能应用此结构中
三、循环嵌套
1. 概念:在一个循环结构中,定义了另一个循环结构。
2. 循环的次数:外层循环循环的次数*内层循环循环的次数。
3. 图形:通常情况用外层循环控制图形行数,用内层循环控制图形列数。
注意:有些情况下,内层循环会受外层循环的控制。
4. 循环的控制语句:
break:跳出、结束本层循环。
continue:结束本层的本次循环,从而进入本层下一次循环。
5. 循环的Lable标签:对循环做标记,可以通过标记对循环进行操作。[了解]
第五章 函数
一、函数【理解】
1. 概念:实现特定功能的代码组成的一个整体;可以通过名字反复使用。
2. 函数的应用流程:
① 函数的定义:确定函数的功能及函数名。
函数的声明:对函数起名并且声明此函数的功能。
函数的实现:如何实现函数对应的功能。
② 函数的使用:通过函数名使用函数的功能称为函数的调用。
3. 位置:定义在类以内,与main函数并列的位置(其他函数的外面)。
二、函数的定义【应用重点】
1. 语法:public static 返回值类型 函数名(形参列表){
//函数的实现…
}
2. 函数的定义分为:
① 函数的声明:public static 函数的返回值 函数名(形式参数列表)
I. 函数名:望文生义,建议使用驼峰命名法(首单词的首字母小写,其他单词的首字 母 大写)
II. 形式参数:用于约定函数和使用者之间的交互数据类型
a. 语法:(数据类型 参数名,数据类型2 参数名2,数据类型3 参数名3)
b. 应用:形式参数相当于函数内部的局部变量,在函数的内容直接利用参数名 直接使用即可。
c. 形参列表:参数的个数 0~n
III. 函数的返回值:
a. 无返回值类型:返回值类型为void,代表函数没有任何返回值, 即函数没有 return语句。(也可以利用 return;结束当前函数)
b. 有返回值类型:返回值类型为 8种基本数据类型 和 对象数据类型,代表函 数必须有 return XXX;语句
return的细节:
① 函数最多只能定义一个return XXX;语句
② return应用分支结构时,必须保证每一条分支都有return语句return 的作用:
① 将函数的返回值返回
② 结束当前函数的调用
注意:函数的返回值、函数名、形参列表称为函数的三要素。
② 函数的实现:{}
三、函数的调用【应用重点】
1. 函数的调用:函数名();//可以通过函数名反复的使用该函数 --》无参数的调用
2. 有参数的调用:函数名(实际参数列表);
① 实际参数的作用:在函数调用时,给形参赋值.
② 注意:实际参数的个数、顺序、数据类型必须和形参一致。
3. 有返回值的函数的调用:
数据类型 变量名 = 函数名(实际参数);
注意:数据类型决定于函数的返回值类型;
变量的作用是存储函数的返回值。
四、函数的作用【理解】
1. 减少代码的冗余
2. 提高的复用性
3. 提高的可维护性
五、函数的嵌套调用【理解】
1.概念:被调用的函数内部又调用了其他函数。
2.函数调用执行的流程:调用函数时,程序会先执行被调函数内部的代码, 被调函数全部 执行完如果有返回值,则带着返回值返回到调用位置,程序继续往下执行。
六、递归【难点+了解】
1. 概念: 在一个函数的内部调用它自身。
2. 注意:开发时,避免无穷递归的现象;需要给递归设置出口。
第六章 数组
一、数组
1. 概念:可以同时存储多个相同类型的数据,并可以对数组中的数据进行统一操作。
2. 数组的要素:数据类型、长度
3. 使用数组的基本流程:【重点】
① 声明:指定数组的数据类型及数组名;
语法: 数据类型[] 数组名;
例如: int[] a; //建议写法、int []a;、int a[];
② 分配空间:指定数组的长度
数组名 = new 数据类型[长度];
③ 使用数组:
a. 数组的下标:0~长度-1 (0~length-1)
b. 数组中存储的数据称为数组的元素。
c. 操作数组中元素利用数组名+下标:数组名[下标];
d. 如果操作数组过程中,下标超出数组的有效下标范围,则
编译通过,运行报错,错误信息如下:
**java.lang.ArrayIndexOutOfBoundsException(**下标越界)
e. 数组的遍历:将数组中的元素进行一一访问的过程。
for(int i=0;i<数组长度;i++){
//利用 i控制数组的下标,从而操作数组中的元素
}
注意:获取数组的长度–>数组名.length
f. 数组具有默认值,默认值情况如下:
整数类型: 0
小数类型: 0.0
字符类型:空字符(’ u0000’)
布尔类型:false
引用类型:null
4. 数组的其他定义方式:
① 声明的同时分配空间【重点】:
数据类型[] 数组名 = new 数据类型[长度];
② 显示初始化:
数据类型[] 数组名 = new 数据类型[]{值1,值2,值3};
注意:[]中不允许指定长度,数组的长度由{}中数值的个数决定。
③ 显示初始化: 【重点】
数据类型[] 数组名 = {值1,值2,值3};
注意:数组的初始化和声明必须一起进行,{}中数据的个数决定了数组的长度。
二、内存【理解】
1. 数组在内存空间中连续的,数组的空间分配好之后,会获得当前数组的首地址。
2. 数组名中存储数组在内存空间的首地址。
3. 寻址的公式:
首地址+下标*数据类型的字节数
注意:数组的下标从0开始,为了寻址方便。
4. 数组类型的变量之间相互赋值传递的是数组的首地址。
三、数组的扩容【理解】
1.思想:
① 申请一个更大长度的新数组(长度一般为原始数组的长度2倍)
② 将原有数组的元素一一赋值到新数组中
③ 新地址覆盖旧地址
2. 实现方式:
int[] a={1,2,7};
① 申请更大长度的数组
int[] b = new int[a.length*2];
将原有数组的内容赋值到新数组中
for(int i=0;i<a.length;i++){
b[i]=a[i];
}
新地址覆盖旧地址 a=b;
② 利用System.arraycopy(a,0,b,0,a.length)工具实现数组的赋值
参数说明:
a. 第一个参数:原始数组名
b. 第二个参数:赋值起始下标,通常情况下取0
c. 第三个参数:新的数组名
d. 第四个参数:新数组存储的起始下标
e. 第五个参数:赋值的长度
③ 利用 java.util.Arrays.copyOf(a,a.length*2)工具实现数组扩容的两个步骤。
参数说明:
a. 第一个参数:原始数组的名
b. 第二个参数:新数组的长度
注意:当数组的长度不够用时,才需要考虑扩容。
四、可变长的参数【理解+阅读API时应用】
1. 概念:使用函数时,可以给定个数不固定的实参,根据调用者自身决定参数的个数。 (JDK5.0提出.)
2. 语法:
public static 返回值类型 函数名(数据类型…变量名){
//函数体(函数的实现)
}
3. 使用:函数内部使用可变长参数时,将其作为数组使用即可。
4. 注意:一个函数中最多只能定义一个可变长的参数,并且要求可变长的参数必须形式参 数的最后一个。
5. 好处:让函数的调用更加的灵活。
五、排序(小–>大)【面试重点】
1. 冒泡法:相邻的两个元素进行一一比较,最大的元素逐渐往后移。
//外层循环控制比较的轮数
for(int i=1;i<a.length;i++){
//内层循环:控制每一轮具体比较的内容
for(int j=0;j<a.length-i;j++){
if(a[j]>a[j+1]){
int t = a[j];
a[j]= a[j+1];
a[j+1]=t;
}
}
}
2. 选择法:固定一个下标位置元素,和后面的元素进行一一比较,小的元素逐渐往前移。
//外层循环控制比较的轮数
for(int i=0;i<a.length-1;i++){
//内层循环控制每一轮比较内容
for(int j=i+1;j<a.length;j++){
if(a[i]>a[j]){
int t= a[i];
a[i]=a[j];
a[j]=t;
}
}
}
3. 快速排序:java.util.Arrays.sort(数组名);
六、二维数组【了解】
1. 定义:
① 声明:数据类型[][] 数组名;
分配空间:数组名 = new 数据类型[行数/高维][列数/低维];
② 访问二维数组通过行标和列标:
数组名[行下标][列下标]
注意:行标和列标都是从0开始。
a[0][3]代表:第0行第3列的数据
③ 二维数组同一维数组具有默认值。
④ 获取二维数组的行数:数组名.length
获取二维数组的列数:数组名[0].length
⑤ 二维数组就是一维数组的一维数组。
2. 其他的定义方式:
① 声明同时分配空间:
数据类型[][] 数组名= new 数据类型[行数][列数];
② 显示初始化:
数据类型[][] 数组名= new 数据类型[][]{{值1,值2},{值3,值4},{值5,值6}};
注意:[][]中不能指定二维数组的行数和列数。
③ 显示初始化:
数据类型[][] 数组名={{值1,值2,值3},{值4,值5,值6}};
注意:初始化和声明必须一起进行。
3. 不规则的二维数组
① 概念:每一行的列数不相同的二维数组。
② 语法:
a. int[][] a= {{1,2},{2,6,8}};
b. int[][] a = new int[3][];
a[0] = new int[2];
a[1] = new int[5];
a[2] = new int[3];
注意:此种获取不规则二维数组的方式,必须指定行数(高维)。
第七章 面向对象
一、对象【理解】
1. 概念:客观复杂的事物在Java程序中的一种表象形式。(一切客观事物皆是对象)
2. 对象的组成:
① 对象的属性:代表对象有什么的特征(体现对象的静态部分-变量展现)
② 对象的方法:代表对象有什么样功能(体现对象的动态部分-方法展现)
3. 计算机中,用类描述对象,描述对象有哪些属性和哪些方法。
4. 类对象的关系:
① 类是对象的模板
② 对象是类的实例(对象根据类创造)
二、类的组成【语法基础重点】
1. 属性:代表对象有什么特征
① 属性又称为成员变量
② 位置:定义在类以内,方法以外
③ 语法:数据类型 属性名;
数据类型 属性名 = 值;
注意:赋值和声明必须同时进行。
④ 注意:定义属性时,只需保留程序所关注的部分。
⑤ 成员变量具有默认值,默认值同数组:
整数:0
小数:0.0
布尔:false
字符:空字符( u0000)
引用/对象:null
⑥ 成员变量的作用范围:至少在本类中有效。(本类的成员方法可以直接利用成员变量 的名字直接使用)
⑦ 在一个类中,不允许有相同名字的成员变量(属性名);
成员变量可以和局部变量命名相同,命名相同时,在此局部变量所在方法中访问同 名变量时,局部变量优先使用。
总结:成员变量和局部变量的区别?【面试+开发应用重点】
局部变量 成员变量
位置: 定义在方法内部 定义在类以内,方法以外
默认值: 没有默认值(先赋值后使用) 具有默认值
作用范围:从定义位置开始,到定义它 至少本类中有效
的代码块结束
命名冲突:在重合的作用范围内,不允许 成员变量可以和局部变量命名相同,命 命名冲突 名相同时,在此局部变量所在方法中使 用此变量时,局部变量优先
2. 方法:代表对象有什么功能、行为
① 方法称为成员方法。
② 位置:定义在类以内,其他方法以外。
③ 定义:
函数的定义:
public static 返回值类型 函数名(形参列标){
//函数的实现(函数体)
}
方法的定义:
public 返回值类型 方法名(形参列表){
//方法的实现(方法体)
}
注意:方法定义中,不需要加static.
④ 方法的定义分为 方法的声明和方法实现:
a. 方法声明:代表对象能做什么
I. 修饰符 返回值类型 方法名(形参列表)异常
II.一个方法可以有多个修饰符,而且没有位置先后之分
b. 方法实现:代表对象如何做—》
{ //方法的具体实现}
⑤ 方法的重载(overLoad)
a. 概念:在一个类中,定义多个名字相同,但是参数列表不同的方法。
b. 要求:
I. 方法名相同
II. 参数列表不同(类型、个数、顺序)
III. 修饰符、返回值类型、异常没有要求
c. 注意:如果只是形参名不一样,则不能构成方法重载。
d. 使用:编译器在编译的过程中,根据调用者给定实际参数,决定具体调用哪一 个方法。
注意:使用过程中,根据调用者传递的实际参数先进行精确匹配,然后就近向上 匹配,避免出现混淆。
3. 构造方法(构造器 Constructor)
① 位置:定义类以内,其他方法以外
② 特点:
a. 构造方法的方法名必须和类名完全一致(包含大小写)
b. 构造方法没有返回值类型 (连void都没有)
语法:修饰符 类名(形参列表){}
c. 构造方法允许重载
d. 构造方法不允许手动调用
③ 作用:
a. 构造方法用于创建对象
b. 通常给属性赋值
④ 注意:
a. 构造方法不允许手动的调用,用于创建对象时,JVM自动调用1次
b. 如果一个类中没有定义任何的构造方法,则JVM会自动添加一个默认公开、 无参数的构造方法;如果一个类中定义了任何的构造方法,则系统JVM不再提 供默认公开、无参数的构造方法
三、对象的创建
1. 语法:类名 对象名 = new 构造方法(实参);
2. 使用对象:
① 属性:
a. 为属性赋值:对象名.属性名 = 值;
b. 访问属性:对象名.属性名
② 方法:对象名.方法名(实参);
四、对象创建的过程【理解】
1. 分配空间:给所有的属性赋默认值
2. 初始化属性:给属性第二次赋值的机会
3. 调用构造方法:给属性第三次赋值的机会
五、this 的使用【开发应用重点】
1. 第一种应用:this.
① this 代表当前对象,类似于"我",this. 用在类中的成员方法或是构造方法中,调用 当前对象的属性或是成员方法
② this.属性名:代表调用当前对象的属性
this.方法名(实参):代表调用当前对象的成员方法
③ this. 通常可以省略,但是当成员变量和局部变量命名冲突时,必须使用 this. 区分 成员变量
2. 第二种应用:this()
① this():用在本类的构造方法中,调用本类其他构造方法。
② this():代表调用无参数的构造方法
this(实参):调用有参数的构造方法
③ this()的应用必须是构造方法中第一行有效语句
④ 注意:使用 this()/this(实参)时,避免递归调用(回环调用)现象
六、引用【理解】
1. 引用:对象类型的变量。
2. 引用存储对象在堆空间中的首地址。
3. 不同的对象在堆空间相互独立。
4. 引用可以单独声明: 类名 引用名;
5. 引用之间可以相互赋值,传递的是对象在堆空间中的首地址。基本数据类型的变量之间 传递的是数值。
6. 声明引用时,通常给定一个初始数据null(代表空地址)
类名 引用名 = null;
注意:如果引用中存储的为null,用此引用调用属性或是成员方法,则编译通过,但是 运行报错,错误信息为:
**java.lang.NullPointerException(**空指针异常)
第八章 面向对象的三大特性
一、封装
1. private:访问修饰符,私有的,被private修饰的内容只能在本类中使用。
2. 为私有化的属性提供公开的get/set方法:
① 为属性赋值(修改属性值):set方法
public void set属性名(数据类型 变量名){
this.属性名 = 变量名;
}
注意:
a. set属性名–》属性名首字母大写
b. ()中数据类型取决于赋值的属性类型
② 获取属性的值:get方法
public 数据类型 get属性名(){
return this.属性名;
}
注意:
a. 返回值的数据类型取决于 获取的属性数据类型
b. get属性名 --》属性名首字母大写
3. 使用:
① 为属性赋值:对象名.set属性名(实参);
② 获取属性值:对象名.get属性名()
二、继承
1. 概念:【理解】
① 继承体现的是类之间一种 "is-a"关系
语法:class 子类类名 extends 父类类名{}
② 继承是一种机制,通过继承机制可以让子类直接使用父类中属性和方法
③ 开发时,不能强制使用继承机制,继承是两个类本身存在一种"is-a"关系,不能人为、 刻意的使用。
2. 继承的好处:体现代码的可复用性和可扩展性。【理解】
3. 方法的覆盖(override)[重写->将方法的实现部分重写]【应用开发重点】
① 概念:子类中定义了和父类相同的方法。
② 要求:
a. 子类的方法名、形参列表、返回值类型和父类相同
b. 子类的访问修饰符和父类相同或是比父类更宽
③ 使用:子类对象名.方法名(实参);//子类中的方法优先使用
④ 注意:
a. 子类中定义方法和父类中的一个方法,方法名、形参列表相同,但是返回值类 型不同,编译报错。
b. 子类中定义的方法和父类中的一个方法,方法名、返回值类型相同,但是形参 列表不同,编译通过,运行也OK.—>特殊的方法重载
⑤ 应用场景:当父类提供的方法实现部分不足以满足子类需求时,子类可以覆盖父类 中的方法(根据自身功能,重新将方法实现部分写一遍)
面试题目:分别写出overload和override的区别。
4. 将子类的共性抽取为父类中属性和方法。【理解】
父类中的信息是 一般的、抽象的
子类中的信息是 特殊的、具体的
5. Java中继承特点【面试重点】:Java中的类是单继承关系,即一个类只能有一个直接的 父类,但是可以有多个间接地父类(多级继承)–>体现Java语言的简单性
6. 子类可以继承父类中的哪些内容(构造方法、属性、成员方法)?【重点】
① 构造方法不允许被子类继承【面试题目】
a. 语法角度:构造方法的方法名必须和类名一致,子类和父类各有不同的类名
b. 应用角度:子类中的内容多于父类中的内容,所有子类的构造内容比父类复杂, 所以子类需要定义自身的构造方法。
② 属性和成员方法取决于访问修饰符(约束访问权限)【面试重点+应用重点】
本类 同包 不同包的子类 其他(不同的包非子类)
private(私有的) ok
default(默认的) ok ok
protected(受保护的) ok ok ok
public (公开的) ok ok ok ok
***属性和成员方法的继承性如下:
private:不允许被继承
default:同包中的子类允许继承
protected:同包+不同的包的子类都允许继承
public:允许继承
访问修饰符可以修饰的内容:
a. 4个访问修饰符都可以修饰属性、成员方法、构造方法
b. 只有public和 defaule可以修饰类
7. 创建对象的过程(继承体系下)【理解】
① 分配空间(本类+父类):为所有的属性赋默认值
② 递归的构造父类对象:
a. 初始化父类的属性:为属性赋值的第二次机会
b. 调用父类的构造方法:为属性赋值的第三次机会
③ 初始化本类的属性:为本类的属性赋值的第二次机会
④ 调用本类(子类)的构造方法:为本类的属性赋值的第三次机会
8. super的应用【开发应用重点】
① 第一种应用:super()
a. super()/super(实参):用在子类的构造方法中,代表创建子类对象时,JVM需 要先完成父类对象的创建,指示JVM利用父类的哪一个构造方法完成父类对象 的创建。
b. 注意:
I.super()/super(实参)必须是构造方法的第一行有效语句;
II. 如果子类的构造方法的第一行没有定义super()/super(实参),则JVM默认在构 造方法的第一行添加super();语句
III. 一个构造方法中不能同时使用super()/super(实参) 和 this()/this(实参)
IV. 如果子类的构造方法的第一行语句为this()/this(实参),则JVM会放弃在当前 构造方法中查找super()/super(实参),从而转向this所指向构造方法中的第一 行查找super()/super(实参)
② 第二种应用:super.
a. super. :应用在子类的构造方法或是成员方法中,代表调用父类中属性或是成 员方法
b. super.属性名:访问父类的属性
super.方法名(实参):访问父类的成员方法
三、多态
1. 概念【理解+基础重点+开发】
① 多态:父类型的引用 指向 子类的对象。
父类型 引用名 = new 子类类名(实参);
② 如果用父类型的引用调用属性和方法,只能调用父类中声明的属性和方法; —>编译 时检测
③ 运行时,JVM自动检测子类是否覆盖父类中方法,如果子类覆盖了父类中方法,则 运行覆盖之后的方法,否则直接运行父类中方法。
2. 引用之间的转换【应用重点】
① 父类型的引用 赋值给 子类型的引用 必须 通过强制类型转换
子类型 引用名 = (子类型)父类型的引用;
注意:不管父类型引用中存储是哪一种子类型的对象,编译通过;但是运行时将 父类型的引用中实际存储的对象和转换的类型相比较,如果类型匹配,运 行通过;不匹配运行报错,错误信息为:
**java.lang.ClassCastException(**类型转换异常)
instanceof 的应用:
I. 语法: 引用名 instanceof 类名
II.作用:判断引用中存储对象类型是否兼容于 后面的类型,兼容-true;不兼容 -false.
III. 场景:引用之间转换时可以先利用instanceof进行判断,从而避免 类型转 换异常。
② 子类型的引用 赋值给 父类型的引用 直接赋值 (多态的应用)
案例:Dog d = new Dog();
Animal a = d;
③ 转换双方没有继承关系,则不允许相互转换(编译报错)
Animal a = new Dog();
Person p = (Person)a;//编译报错
3. 多态的应用【理解+开发应用重点】
① 多态应用在数组上:本类型+所有子类型的对象都可以作为数组元素存储
② 多态应用在形式参数上:本类型+所有的子类型都可以作为实际参数进行传递
③ 多态应用在返回值上:本类型+所有的子类型都可以作为返回值返回。
4. 多态的好处:屏蔽不同子类之间的差异性,从而可以对不同子类进行统一操作。【理解】
第九章 三个修饰符
一、abstract(抽象的)
1. abstract修饰类
① 被abstract修饰的类称为抽象类
语法:abstract class 类名{}
② 抽象类不能单独创建对象,但是可以声明引用
③ 抽象类中可以定义属性和成员方法
④ 抽象类中有构造方法,但是构造方法是供子类创建对象时先完成父类对象的创建, 应用的。
2. abstract修饰方法
① 被abstract修饰的方法称为抽象方法。
② 抽象方法只有方法的声明部分,没有实现部分(连{}都没有)
语法:访问修饰符 abstract 返回值类型 方法名(形参);
注意:访问修饰符 和 abstract没有位置先后之分。
③ 注意:抽象方法只能定义在抽象类中;抽象类中可以定义抽象方法和非抽象方法。
④ 子类继承抽象类,如果子类不想成为抽象,则需要覆盖父类中所有的抽象方法,否 则子类也必须定义为抽象类。
3. 抽象类的作用:强制使用多态。
二、static(静态的)
1. static 修饰属性
① 被static修饰的属性称为静态属性、类变量、静态变量
② 位置:定义在类以内,方法以外,被static修饰
③ 语法:访问修饰符 static 数据类型 属性名;
注意:访问修饰符 和 static没有位置先后之分
④ 静态属性的特点:类变量,和创建多少对象无关,全类共有。
⑤ 使用:类名.静态属性名
2. static 修饰方法
① 被static修饰的方法称为静态方法。
② 位置:定义在类以内,其他方法以外,被 static修饰
③ 语法:访问修饰符 static 返回值类型 方法名(形参){}
④ 使用:类名.静态方法名(实参); //建议使用
引用名.静态方法名(实参);
⑤ 注意:
a. 静态方法中不能直接访问非静态的成员(非静态属性+成员方法)
b. 静态方法中可以直接方法静态的成员(静态属性+方法)
c. 静态方法中不能使用this/super 关键字
d. 静态方法能被子类继承
e. 静态方法只能被静态方法覆盖,而且没有多态的应用
思考:System.out.println();实现的原理?????【面试题目】
类 静态变量 静态方法
解析:System是类名
out是静态属性,类型是对象类型
println():是一个方法,是out对应的类型中的方法
3. static修饰初始化代码块
① 初始化代码块(动态代码块):【了解】
a. 位置:定义在类以内,方法以外 {}
b. 作用:创建对象时,按照和属性定义的先后顺序,完成对属性的初始化工作(在 创建对象的第二个过程初始化属性时执行).
② 被 static 修饰的初始化代码块称为静态初始化代码块【开发应用重点】
a. 位置:定义在类以内,方法以外,被static修饰的{}
b. 作用:在类加载时,按照和静态属性定义的先后顺序,完成对静态属性的初始 化工作。
c. 类加载:
I. 概念:JVM第一次使用一个类的时候,通过classPath(类路径)找到类对应 的.class文件,对文件进行读取,读取到类的信息(包名、类名、父类、属 性、方法、构造方法等),将读取到的信息保存在JVM内存中,一个类只进 行一次类加载。
II. 类加载的时机:
(1) 第一次创建该类对象,先进行类加载,再完成对象的创建
(2) 第一次访问该类静态成员时,导致类进行类加载
(3) 子类类加载会先加载其父类:
-->第一次访问子类的静态成员
-->第一次创建子类对象
先进行类加载:
先加载父类:
完成对父类静态属性的初始化工作
再加载子类:
完成对子类静态属于的初始化工作
再进行对象的创建:
分配空间(子类+父类)
先创建父类对象:
初始化父类的属性:动态代码块执行
调用父类的构造方法
再创建子类对象:
初始化子类的属性:子类的动态代码块执行
调用子类的构造方法
注意:只是声明引用不会导致类进行类加载。
4. static可以修饰内部类—>静态内部类
三、final(最终的)
1. final可以修饰变量(局部变量、实例变量、静态变量)
① 被final修饰的变量是作用范围内的常量,只允许一次赋值,不允许更改。
② final修饰的实例变量不再分配默认值
对其初始化的时机:
a. 声明的同时对其初始化
b. 在构造方法中对其初始化
注意:必须保证每一个构造方法都对其初始化
③ final修饰的静态变量不具有默认值
对其初始化的时机:
a. 声明的同时对其初始化
b. 在静态代码块中对其初始化
注意:final修饰引用代表引用存储的对象不能改变;
final修饰的变量为基本数据类型,则代表变量中的数值不允许改变。
2. final修饰的方法:可以被继承,但是不允许被覆盖
3. final修饰的类:不能被继承,即没有子类
例如:String、Math、System都被final修饰
第十章 接口
一、概念
1. 接口是一种标准,是接口的使用者和接口的实现者之间的约定。【理解】
2. 接口的语法:【基础重点】
① 关键字:interface
语法:interface 接口名{}
② 接口编译之后生成对应 .class 文件
③ 接口不能创建对象,但是可以声明引用
④ 接口中没有构造方法
⑤ 接口中的属性都是公开、静态、常量(默认的被 public static final 修饰)
⑥ 接口中的方法都是公开、抽象的(默认的被 public abstract修饰)
注意:接口不是类。
二、接口的实现类【基础重点】
1. 语法:
class 类名 implements 接口名{}
2. 注意:实现类如果不想成为抽象,则必须实现(覆盖)接口中所有的方法,而且实现接口 中的方法时,方法的访问修饰符必须是public.
3. 使用:接口名 引用名 = new 实现类类名(实参); ---->多态的应用
三、接口的继承关系【基础重点】
1. 接口之间是多继承关系:
interface 接口名 extends 父接口名1,父接口名2{}
2. 类可以同时实现多个接口:
class 类名 implements 接口名1,接口名2{}
注意:实现类如果不想成为抽象类,则需要实现所有接口中所有的方法。
3.类可以实现多个接口的同时继承一个父类:必须先继承后实现
class 类名 extends 父类名 implements 接口1,接口2{}
四、接口多继承的影响【了解】
1. 引用之间相互强制转换,如果转换的双方有一方为接口类型,则编译一定通过,运行是 否通过,分为以下两种情况:
① 如果引用中存储的实际对象类型和转换的类型相匹配,则运行通过
② 如果引用中存储的实际对象类型和转换的类型不匹配,则运行报错,
错误信息为: java.lang.ClassCastException(类型转换异常)
五、接口的好处【理解】
1. 扩充子类的能力
① Java中类之间是单继承关系,当父类中定义的方法不足以满足子类的能力需求时, 则子类可以利用接口扩充自身的能力。
② 通常将子类的主要功能定义在父类中,次要的功能定义在接口中。
2. 解耦合
接口定义好之后,接口的使用者和接口的实现者进行分离,利用多态,降低各模块之间 的耦合度,从而实现弱耦合性。
六、接口的回调【理解】
1. 接口定义好之后,先有接口的使用者(通常开发人员不参与),再有接口的实现者(开发人 员需要根据接口的规范给予实现)。
注意:接口回调时,只需要关注接口的实现部分。
面试题目:接口和抽象类的区别?
接口 抽象类
关键字 interface abstract class
属性 公开、静态、常量 实例变量、静态属性
成员方法 公开、抽象方法 抽象方法+非抽象方法
构造方法 没有 有
继承关系 多继承 单继承
接口和抽象类的相同点:
① 编译之后都会生成独立.class文件
② 都不能创建对象
第十一章 内部类
一、概念【理解】
1. 内部类:在一个类的内部,定义了一个完整的类。
//外部类
class Outer{
//内部类
class Inner{}
}
2. 内部类编译之后,会生成独立的.class文件,命名方式为:
外部类的类名$内部类的类名.class
3. 内部类可以访问外部类的私有成员,从而不破坏外部类的封装性。
二、内部类分类
1. 分类:成员内部类、静态内部类、局部内部类、匿名内部类【面试题目】
2. 成员内部类(类比于实例变量)【了解】
① 位置:定义在类以内,方法以外。
② 创建成员内部类的对象必须依赖于外部类的对象:
Outer o = new Outer();
Outer.Inner i = o.new Inner();
③ 成员内部类可以直接访问外部类的私有的属性
④ 外部类的类名.this 指向外部类的当前对象
外部类类名.this.属性:访问外部类的属性
外部类类名.this.成员方法名(实参):访问外部类的成员方法
⑤ 成员内部类中不允许定义静态成员
3. 静态内部类(类比于静态变量)【了解】
① 位置:定义在类以内,方法以外,被static修饰
② 静态内部类中可以定义静态成员和非静态成员
③ 创建静态内部类的对象只需要依赖于外部类的类名:
Outer.Inner i = new Outer.Inner();
④ 访问静态内部类的静态成员时,直接利用类名即可:
外部类名.内部类名.静态属性
外部类名.内部类名.方法名(实参);
⑤ 静态内部类中可以直接访问外部类的静态成员(静态的属性和方法);
但是不可以直接访问外部类的非静态成员。
4. 局部内部类(类比局部变量)
① 位置:定义在方法以内
② 创建局部内部类对象必须在定义它的方法内部,并且必须在定义位置后面的地方可 以对其创建对象。
③ 局部内部类中可以访问定义它的方法内部的局部变量,但是要求局部变量必须加 final(java语法规定)
注意:JDK8.0以上版本,JVM默认为 被局部内部类访问的局部变量添加final修 饰符---->语法糖
5. 匿名内部类
① 匿名内部类是特殊的局部内部类
② 特点:
a. 匿名内部类必须实现一个接口或是继承一个父类
b. 基于匿名内部类只能创建该类的一个对象,而且匿名内部类的定义和对象的创 建一起完成
③ 语法:
interface IA{
void m1();
}
方法中定义匿名内部类:
IA ia = new IA(){
public void m1(){
//实现部分…
}
};
注意:直接利用 ia引用操作匿名内部类的对象。
④ 匿名内部类的 优点:简化代码
缺点:可读性差
第十二章 常用类
一、Object类
1. 概念:
① Object是根类、超类,位于java.lang包中,是所有类的父类(直接父类或是间接父 类)
② Object 类中定义的方法是所有类默认具备的
③ Obejct类型的引用可以存储任意类型的对象。
2. Object中常用的方法:
① final Class getClass():返回引用中实际存储的对象类型。
a. 实际开发的应用:判断两个引用中实际存储的对象类型是否一致。
b. 例如:a1.getClass() == a2.getClass(); 【应用重点】
类型一致-true 类型不一致-false
② int hashCode():返回对象的哈希码值(哈希码值是对象十六进制地址转换十进制的 整数结果)
注意:不同的对象具有不同的哈希码值(不同对象的地址不同)
③ String toString():返回值对象的字符串表示形式。【开发应用重点】
a. 应用:开发时通常将toString覆盖,利用对象信息拼凑一个String类型结果
b. 覆盖原则:将对象的所有属性拼凑成一个String结果作为返回值返回。
public String toString(){
return “name=”+this.name+",age="+this.age;//this. 可以省略
}
c. 注意: get方法是获取单个属性的信息,并且不会改变属性的原有类型;
toString方法是以字符串的形式展示所有属性信息,方便编程人员打印 对象所有信息。
④ boolean equals(Object o):判断两个对象的内容是否相同,相同-true;不相同-false a. ==的应用:
I. 如果 == 两端是基本数据类型的变量,则比较变量中存储的数值是否相同
II. 如果 == 两端是引用类型的变量,则比较变量中存储的对象的地址是否相 同
注意:开发时,通常应用 == 判断两个引用是否执行同一个对象:
引用名1 == 引用名2 —》结果为true,代表两个引用指向同一个对象,, 否则,指向不同的对象
b. equals方法的引用:Object中的equals方法默认比较两个引用中地址是否 一致,如果希望它能比较两个对象的内容是否一致,则需要覆盖equals方法, 覆盖的步骤如下:
public boolean equals(Object o){
//将 this 和 o进行比较
//(1) 自反性:判断两个引用是否指向同样一个对象
if(this == o){
return true;
}
//(2)判断 o是否为空
if(o==null){
return false;
}
//(3) 判断两个引用中存储的实际对象类型是否一致
if(this.getClass()!=o.getClass()){
return false;
}
//(4) 强制类型转换–>对下一个步骤准备
当前对象类型 s = (当前对象类型)o;
//(5) 将属性内容进行比较:基本数据类型:==引用:equals比较
if(this.age==s.age && this.name.equals(s.name)){
return true;
}else{
return false;
}
面试题目: 写出 == 和 euqals的区别?
⑤ void finalize(): 垃圾回收器在回收垃圾对象时,JVM自动调用的方法。【面试重点+ 性能调优】
a. 垃圾对象:没有任何引用指向的对象。
b. 垃圾回收器:JVM用于回收垃圾对象,简称GC(gc)
c. 垃圾回收的目的:释放JVM内存空间,保证新创的对象空间可用。
d. 垃圾回收器回收垃圾对象的时机:
I. 自动垃圾回收机制:当JVM内存耗尽,不能再为新创建的对象分配空间时, 垃圾回收器会一次性的将垃圾对象进行回收(垃圾回收回收垃圾对象,自动 调用finalize方法)
II. 手动垃圾回收机制:使用 System.gc() 通知垃圾回收器回收垃圾对象,如 果垃圾回收器(GC)空闲,则立即回收;否则暂不回收。
面试题目:写出 final 和 finalize的区别?
分析:① final是修饰符,
修饰类:没有子类
修饰方法:允许被继承,不能被覆盖
修饰变量(局部变量、实例变量、静态变量):作用范围内的常量
② finalize是方法名,垃圾回收器在回收垃圾对象时调用的方法
二、包装类
1. 概念:8种基本数据类型对应的对象类型,称为基本数据类型的包装类。(8个)【理解】
2. 包装类:(位于 java.lang 包中)【开发应用重点】
基本数据类型 包装类
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean
3. 数据类型之间的转换:
① int 和Integer之间的转换
int --> Integer
a. Integer i1 = new Integer(12);//构造方法
b. Integer i2 = Integer.valueOf(12);//静态方
Integer --> int
a. int a1 = i2.intValue();
② Integer 和 String 之间的转换
String —> Integer
a. Integer i3 = new Integer(“12”);//构造方法
b. Integer i4 = Integer.valueOf(“12”);//静态方法
Integer --> String
a. String s1 = i4.toString();
b. String s2 = i4+"";//利用字符串的拼接
③ int 和 String 之间的转换
int —> String
int a = 12;
a. String s3 = a+"";
String --> int 【开发应用重点】
a. **int n = Integer.parseInt(“128”);//**利用 静态方法
注意:String转换为 int/Integer时,必须保证转换的字符串是纯数字的,否则 运行报错,错误信息如下:
java.lang.NumberFormatException(数字格式转换异常)
4. 自动的装箱和拆箱【理解+应用】
① JDK5.0版本之后,基本数据类型和包装类型之间可以自动完成装箱和拆箱。
② 自动的装箱:将基本的数据类型自动转换为对应的包装类型
自动的拆箱:将包装类型自动的转换为对应的基本数据类型
③ 案例:
Integer i = 12; //自动装箱
int a = i;//自动拆箱
④ 注意:自动的装箱底层原理默认调用 静态方法 Integer.valueOf(int i)【面试重点】
public static Integer valueOf(int i){
if(i>=-128 && i<=127){
return …
}
return new Integer(i);
}
注意:JAVA 为了提高JVM运行效率,对程序中常用的数据做了预先包装处理, 存储在常量池(缓冲区),缓冲的数据范围:-128~127.【面试难点】
5. 实际开发应用【开发应用】
① 场景:将属性由之前的基本数据类型替换为对应的包装类型。
② 作用:区分有效数据和无效数据,例如: 0 和 null/0.0 和 null
三、String类(位于 java.lang 中)
1. 创建字符串对象的两种方式:【面试题目】
① String s1 = “hello”;
注意:这种创建字符串的方式只会产生一个对象,串池中产生(用于共享)
② String s2 = new String(“world”);
注意:这种创建字符串的方式会产生两个对象,一个在堆空间中,另一个在串池 中产生。
2. 常用方法:
① char charAt(int index):根据下标获取对应的字符
注意:String底层本质为 char类型的数组,所以字符串的下标范围:0~字符串的 长度-1
② boolean contains(String s):判断s是否包含在当前字符串中,包含-true, 不包含-false.
③ boolean equals(String str):判断两个字符串内容是否相同
④ int length():获取字符串的长度
注意: 获取数组的长度:数组名.length
遍历字符串:
for(int i=0;i<字符串.length();i++){
char c = 字符串名.charAt(i);
//操作 字符c
}
⑤ String trime():去除字符串前后的空格。
3. 不可变长的字符串【面试题目】
① 字符串是字面值的常量,一旦创建不允许改变,如果实现字符串的拼接,则会在原 文本的基础上拷贝一个副文本,在副文本上进行操作。
4. 可变长的字符串(位于 java.lang 中)
① StringBuffer: JDK1.0版本,线程安全,运行效率慢
StringBuilder: JDK5.0版本,线程不安全,运行效率高
② 字符串的拼接:append 方法
③ StringBuilder的字符串拼接效率高于 String 拼接
面试题目:写出 String 和 StringBuilder的区别?
写出 StringBuilder 和 StringBuffer的区别?
四、BigDecemal类(位于 java.math包中)【了解】
1. 作用:精确、计算浮点数。
2. 常用的构造方法:
BigDecimal(String n)
3. 常用的方法:
① BigDecimal r1 = bd1.add(bd2); //加法
② BigDecimal r2 = bd1.subtract(bd2);// bd1-bd2 减法
③ BigDecimal r3 = bd1.multiply(bd2);//乘法
④ BigDecimal r4 = bd1.divide(bd2,3,BigDecimal.ROUND_HALF_UP);//bd1/bd2
参数说明:
第一个参数:参与运算的除数(分母)
第二个参数:保留到小数点后几位
第三个参数:对小数的取舍模式,通常采用四舍五入BigDecimal.ROUND_HALF_UP
第十三章 集合
**一、**集合【理解即可】
① 概念:是一种工具类,也是一种容器,可以存储数量不等的对象。
② 位置:java.util包中
③ 学习过程中的内容:接口的特点、接口的功能方法、接口的实现类、遍历集合中元素
二、Collection集合(父接口)
① 特点:存储object类型的对象。
② 方法:【重点】
a. add(Object obj):往集合中添加元素。
b. boolean contains(Object obj):判断对象obj是否在当前集合中存在,
存在-true;不存在-false.
c. boolean remove(Object obj):将对象obj从当前集合中移除。
d. int size():获取集合中元素的个数
③ 实现类:没有直接的实现类
④ 遍历方式:详见子接口的实现类。
三、子接口:List集合【重点】
① 特点:存储Object对象,有序、有下标、元素允许重复。
下标范围:0~有效元素的个数-1 (0~size-1)
② 方法:
a. add(int index,Object obj):将对象obj插入到指定位置。
b. Object get(int index):根据下标获取指定集合元素的内容。
c. Object remove(int index):将指定下标元素从当前集合中删除,并返回被删除 的对象
d. Object set(int index,Object obj):将集合中指定元素的内容修改,并返回修改 之前的元素内容。
③ 实现类:ArrayList(底端用数组实现)【开发重点】
面试重点:不同实现类的区别:
ArrayList:底层数组实现,查询快,增删慢。
JDK1.2 版本,线程不安全,运行效率快。
Vector:底层数组实现,查询快,增删慢。
JDK1.0 版本,线程安全,运行效率慢。
LinkedList:底层链表实现,查询效率低,增删快。
④ 遍历:
a. 下标遍历:
for(int i=0;i<list.size();i++){
//根据下标获取对应的元素内容
System.out.println(list.get(i));
}
b. forEach遍历:
语法:
for(数据类型 变量名:集合名字){
}
注意:数据类型取决于集合元素的数据类型
如果集合加了泛型,数据类型取决于泛型的类型。
泛型集合:数据安全的集合。泛型强制约束集合中元素数据类型要一致。
1. 1泛型类:【理解】
① class 类名<泛型标识1,泛型标识2>{
}
注意:泛型标识通常用T/E/K/V
② 泛型类创建对象时,指定泛型标识代表的具体数据类型:
类名<具体数据类型> 对象名=new 类名<具体的数据类型>();
注意:如果创建对象没有指定泛型标识代表的具体数据类型,默认的是Object类型。
1.2 泛型接口:jdk5.0之后可以定义泛型接口。 【理解】
① 语法:
interface 接口名<泛型标识1,泛型标识2>{}
例如:
interface IA{}
② 实现类:
第一种方式:
class ClassA implements IA<具体数据类型>{}
第二种方式:
class ClassB implements IA{}
注意:在创建对象时,指定泛型类型。
1.3 Java提供操作集合的工具类:Collections.【了解】
常用方法:
① public static void reverse(List list):倒置
② public static void shuffle(List list):随机显示
③ public static void sort(List list):排序
注意:如果集合中存储的对象类型是自定义类型的对象,则需要让对应的类实现 Comparable接口,从而实现compareTo方法。
面试题目:区分Collection和Collections。
Collection集合体系中的根接口。
Collections操作集合的工具类。
四、子接口:Set集合【重点】
1. 特点:存储Object类的对象,无序、无下标、元素的内容不允许重复。
2. 方法:方法全部继承于父接口Collection
3. 实现类: HashSet【开发重点】
如果自定义类型的对象存储在HashSet集合中,为了保证元素的内容不重复,必须做到:
① 覆盖hashCode方法
目的:必须保证相同内容的对象返回相同的hashCode码值;为了提高效率,不同 内容的对象尽量返回不同的hashCode码值。
覆盖原则:将所有的属性拼凑为一个int值作为返回值。
例如:
public int hashCode(){
return this.age+this.name.hashCode();
}
② 覆盖equals方法 : 必须保证内容相同的对象结果返回true.
- SortedSet:是Set的子接口【了解】
① 特点:存储Object类型的对象,无序、无下标、元素内容不允许重复。可以 根据元素内容自动排序。
4. 实现类:TreeSet
自定义类型的对象存储在TreeSet集合中,如果compareTo的结果返回值为0,则代 表相同内容的元素,拒绝添加。
5. 遍历:forEach
五、Map集合【开发重点】
1. 特点:【重点】
① 存储任意的键值对(key-value)
② 键:无序、无下标、元素不允许重复(唯一性)
③ 值: 无序、无下标、元素允许重复
2. 方法:
① V put(K key,V value):将一个键值对存储在map集合中。如果键在map中已经存 在,则用新的数值覆盖旧值,将旧值作为返回值返回;如果键在map不存在,值直 接存储,返回null.【重点】
② V remove(K key):根据key删除map中一个键值对,同时将删除值作为返回值返 回。
③ V get(K key):根据键获取值。【开发重点】
④ boolean containsKey(K key):判断map集合中是否包含此键,包含-true;
不包含-false.
⑤ boolean containsValue(V value):判断map集合中是否包含此value,包含-true;
不包含-false.
⑥ int size():获取键值对的个数。
3. 实现类:HashMap【开发应用重点】
① HashMap【重点】:JDK1.2 版本,线程不安全,运行效率快。
允许null作为key或是value.
② Hashtable:JDK1.0 版本,线程安全,运行效率慢。
不允许null作为key或是value.
③ Properties:是Hashtable的子类,键和值必须是String类型。
作用:通常用于读取配置文件。
④ TreeMap:是SortedMap的实现类(SortedMap是Map的子接口)。
作用:可以对键自动排序。
面试重点: HashMap和Hashtable的区别:
HashMap:允许null作为键和值,线程不安全,效率高
HashTable:不允许null作为键值,线程安全,效率低
4. map遍历:
① 键遍历:【开发应用重点】
通过keySet方法获取map中所有的键:Set keySet();
Set<键的数据类型> ks=map.keySet();
for(键的数据类型 key:ks){
//通过键获取值的内容
值的数据类型 value=map.get();
}
② 值遍历:
通过values方法获取map中所有的值:Collection values();
Collection<值的数据类型> vs=map.values();
for(值的数据类型 value:vs){
//…
}
③ 键值对遍历:【开发应用重点】
通过entrySet方法获取map中所有的键值对:
Set<Map.Entry<K,V>> entrySet();
Set<Map.Entry<K,V>> kvs=map.entrySet();
for(Map.Entry<K,V> kv:kvs){
K key=kv.getKey();//获取键
V value=kv.getValue();//获取值
五、总结版Collection集合
1.***集合和数组的区别:(集合是存储对象的容器)
a.长度区别:数组长度固定,集合长度可变
b.存储元素数据类型:数组可以存储基本数据类型和引用数据类型,集合只能存储引 用数据类型
- List的三个实现类:(interface,有下标,有序,不唯一)
①ArrayList:底层数组实现,查询快增删慢,线程不安全,效率高
②Vector:底层数组实现,查询快增删慢,线程安全,效率低
③LinkedList:底层链表实现,查询慢增删快,线程不安全,效率高
- Set(interface,无下标,无序,唯一)的二个实现类:
① HashSet(无序,唯一):如果一个类没有覆盖hashCode和equals方法,会默认 调用Object类中的方法,哈希值会不同,比较的也是两个引用的首地址。
(底层哈希表实现,无序,唯一)
***HashSet如何保证的唯一:
添加底层依靠的两个方法:①hashCode();②equals();
执行步骤:
a.首先执行hashCode(),判断对象的哈希值是否相同。
b.相同–>执行equals(),判断内容是否相同,相同->不存储 不同->存储
覆盖HashCode方法:
public int hashCode(){
return this.name.hashCode()+this.age+this.score;
}
--子类LinkedHashSet:
底层哈希表和链表实现(保证元素的有序和唯一)
② TreeSet:(排序,唯一)
底层:红黑自平衡二叉树
排序方式:自然排序–>必须实现Comparable接口,覆盖compareTo方法
***覆盖compareTo方法
public int compareTo(Student o) {
//主要条件:姓名长度 ,从长到短
int num = o.name.length() - this.name.length();
//次要条件:如果姓名的长度相同,也许姓名不同(按照字典的顺序)
int num2 = num == 0?this.name.compareTo(o.name):num;
//次要条件,如果姓名相同,也许年龄不同
int num3 = num2 == 0?this.age - o.age:num2;
return num3;
}
4.遍历Collection代码:
①toArray()
Object[] obj = list.toArray();
for(Object o:obj){
System.out.println(o);
}
②迭代器
Iterator it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
③普通for(List独有)
for(int i = 0; i<list.size(); i++){
System.out.println(list.get(i));
}
④foreach
for (String s : list) {
System.out.println(s);
}
5.元素去重:***
①遍历旧集合,得到每一个元素
for (int i = 0; i < list.size(); i++) {
String s = (String)list.get(i);//s:集合中的每一个元素
System.out.println(s);
②判断当前元素新集合中是否存在
if(list2.contains(s)){
元素重复
}else{
不重复
list2.add(s);
}
}
System.out.println(list2);
6.Collection中的功能
①.添加功能
boolean add(Object e)
boolean addAll(Collection c): 添加一个集合的元素
②.删除功能:
void clear():移除集合中所有的元素
boolean remove(Object o):删除一个指定的元素
boolean removeAll(Collection c):移除一个集合的元素
③.判断功能:
boolean contains(Object o):判断集合中是否包含指定的元素
boolean isEmpty():判断集合是否为空
④.获取功能:
int size():获取集合的长度
获取数组的长度:数组名.length 获取字符串长度的方法:对象.length()
boolean retainAll(Collection c):交集
Iterator iterator():使用迭代器遍历
⑤.转换功能:
Object[] toArray():将集合转数组
六、总结版Map集合
- Map:存储键值对,键不能重复,值可以重复。(一个键对应一个值)。
***Map和Collection区别:
a.Map存储键值对,健唯一,值可重复
b.Collection存储单个元素,子接口List有序,可重复;无序,唯一。
- Map中的二个实现类:
①.HashMap:唯一,无序
底层哈希表实现
②.TreeMap:排序,唯一
底层:红黑自平衡二叉树(保证键从小到大)
3.LinkedHashMap:唯一,有序
底层:哈希表,链表实现
- HashMap和HashTable的区别:
HashMap:允许null作为键和值,线程不安全,效率高
HashTable:不允许null作为键值,线程安全,效率低
- 遍历Map集合:
问题1:(Map) 给定一个字符串,请输出该字符串由哪些字符组成,每个字符出现几次?
public class Test {
public static void main(String[] args) {
//定义一个字符串
String s = “hheewwwor”;
HashMap<Character, Integer> hm = new HashMap<>();
for(int i = 0; i<s.length(); i++){
char ch = s.charAt(i);
System.out.println(ch);
//判断集合中是否有ch键
if(hm.containsKey(ch)){
//true:集合中存在这个键
Integer value = hm.get(ch);
value += 1;
hm.put(ch, value);
}else{
//false:集合中没有这个键
hm.put(ch, 1);
}
}
System.out.println(hm);
}
}
***遍历Map:
Set keys = hm.keySet();//存储所有的键
for(String key: keys){//key:得到每一个键
//根据键获取值
Student value = hm.get(key);
System.out.println(key +" "+value);
}
- Map中的功能:
1.添加功能:
V put(K key, V value):存储键值对
如果该键第一次被存储,返回null,除第一次以外会返回该键上一次添加的值
2.删除功能:
void clear():删除所有键值对
V remove(Object key):根据键删除键值对,返回该键对应的值
3.判断功能:
boolean containsKey(Object key):是否包含指定的键
boolean containsValue(Object value):是否包含指定的值
boolean isEmpty():集合是否为空
4.获取功能:
*int size():得到集合的长度
*V get(Object key):根据键获取值
*Set keySet():得到集合中所有的键存放在set集合中
*Collection values():得到集合中所有的值
Set<Map.Entry<K,V>> entrySet():得到所有的键值对
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0tZhHZcX-1591751992764)(file:///C:/Users/Shallum/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg)]
第十四章 异常
一、异常【理解】
① 概念:程序运行过程中出现的一些不正常的情况。
② 异常的处理的必要性:减少用户不必要的损失。
二、异常的分类【面试重点】
1. 所有的异常的父类是Throwable类,位于java.lang
常用的方法:
① String getMessage():获取String类型的异常信息。
② void printStackTrace():获取方法调用栈中,异常详细的信息。
2. Throwable具有两个直接的子类:
① Error:表示仅靠程序本身无法恢复的严重错误,例如:内存不足或是方法调用栈溢出
特点:在大多数的情况下,遇到这样的错误,程序无法处理。
② Exception:分类两类
a. RuntimeException:称为运行时异常、未检查异常(RuntimeException+其所有 的子类)
特点:编译器编译时不会检测它,运行时报错。这类异常可以避免,可以 处理也可以不处理。
常见的运行时异常:
I. 数组下标越界:java.lang.ArrayIndexOutOfBoundsException
II. 类型转换异常:java.lang.ClassCastException
III. 空指针异常:java.lang.NullPointerException
IV. 数字格式转换异常:java.lang.NumberFormatException
b. 非RuntimeException:非运行时异常、已检查异常(和RuntimeException异 常没有继承关系的类)
特点:编译器编译时检测它,出现这类异常,编译不通过,必须处理。
三、异常的产生
1. 自动产生异常:【理解】
程序在运行过程中,遇到出错的代码,则自动产生异常,程序自动终止。
2. 手动产生异常【开发重点】
① 语法: throw new 异常类名(实参);
② 位置:手动产生异常,必须定义在方法内部。
③ 结果:相当于return语句,导致程序的终止。
四、异常的传递:【理解】
沿着方法的调用链反向进行传递,最终传递给JVM,导致程序终止。
五、异常的处理:【开发应用重点】
1. 消极处理异常
① 关键字: throws ,声明异常,定义在方法的声明后面。
② 语法:修饰符 返回值类型 方法名(形参列表)throws 异常类名{}
③ 作用:采用消极处理异常的方式只是将异常传递,推卸责任,程序仍然会被终止。 但 是可以让非运行时异常在编译时通过。
2. 积极处理异常
① 语法:
try{
//可能出现的异常的语句
}catch(异常类名 e){ //将捕获到的异常,自动赋值给e引用
//一旦出现异常,执行的语句
}
② 注意:
a. try 后面可以跟多个 catch,try一旦出现异常,从第一个catch依次往下匹配, 直到匹配成功。
b. catch中可以利用多态,通过父类型处理异常,可以处理的异常类型:
本类型+所有的子类的异常。
但是:父类型的catch必须定义在其子类型catch的后面。
c. catch中只能处理try中可能出现的非运行时异常。
catch中可以处理任意的运行时异常,即使在try中没有出现的可能性。【了解】
d. 积极处理异常的同时可以声明抛出异常。
e. finally中的语句是必须执行的语句:
语法:
try{
//…
}catch(异常类名 e){
//…
}finally{
//不管有没有异常,必须执行的语句
}
注意:finally中一般不放return语句,finally一般用于释放资源。
区分:final 、finalize、 finally【面试题目】
final是修饰符:可以修饰变量、方法、类
final修饰的变量是作用范围内常量
final修饰的方法可以被继承,不能被覆盖
final修饰的类不能被继承,即没有子类。
finalize是方法的名字:垃圾回收器回收垃圾对象时,调用的方法
finally是 try…catch…finally结构,finally中的语句不管异常一定被执行; finally一 般用于释放资源。
六、自定义异常类
- 类继承Exception或是其子类;如果自定的异常类想成为运行时异常,它需要继承 RuntimeException或是RuntimeException的子类。
自定义异常类通常定义为:运行时异常。
- 提供两个构造方法:
一个构造方法为无参数的构造方法;
另一个构造方法为带有String类型参数的构造方法:
利用super(message),message描述异常的String信息。
七、方法的覆盖(终结版)【重点】
-
子类的方法名、参数列表、返回值类型必须和父类相同
-
子类的访问修饰符必须和父类相同或是更宽
-
子类不能抛出比父类更多、更宽的异常
第十五章 IO流
一、IO简介(位于java.io包中)
1. 概念:流是内存和其他存储设备中传输数据的通道、管道。
2. 分类
① 按方向分:(以JVM为参照物)【重点】
输入流:将<存储设备>中的数据,读入到<内存>中。
输出流:将<内存>中的数据,写入到<存储设备>中。
② 按单位分:
字节流:以字节为单位,可以操作所有类型的文件。
字符流:以字符为单位,只能操作文本文件。
(可以用记事本打开的文件,例如:.java/.txt/.c/.html)
③ 按功能分:
节点流:具有基本的读写功能。
过滤流:在节点流的基础上,增强新的功能。
二、字节流
1. 字节流的父类(抽象类)
① InputStream:字节输入流—》读操作:read
② OutputStream:字节输出流—》写操作:write
2. 字节节点流【重点】
① FileOutputStream:文件字节输出流
常用的构造方法:
a.FileOutputStream fos = new FileOutputStream(“E:/CoreJava/test/a.txt”);
I. 参数:指定文件的路径E:/CoreJava/test/a.txt或是 E: CoreJava test a.txt
II. 如果指定的文件不存在,系统默认新创建一个文件。
但是如果指定的文件夹不存在,则系统报错,错误信息:
java.io.FileNotFoundException (系统找不到指定的路径。)
III. 绝对路径:盘符:/文件夹名/文件名
b. FileOutputStream fos = new FileOutputStream(“a.txt”);
I.参数:指定文件的路径,默认在当前项目的根目录下查找文件,没有则创建
II. 相对路径:默认在当前项目的根目录下查找文件
c. FileOutputStream fos = new FileOutputStream(“file/a.txt”);【开发应用】
d. FileOutputStream fos = new FileOutputStream(“file/a.txt”,true);
I. 第二个参数:类型是 boolean
true-在原有内容上追加(不覆盖原有内容)
false-覆盖原有的内容(默认)
常用的方法:
a. public void write(int b):将单个字节的内容写入到文件中。
b. public void write(byte[] bs):一次性将多个字节写入到文件中。
c. public void write(byte[] bs,int off,int len):一次性将多个字节写入到文件中,将 bs数组中一部分内容写入文件中,起始下标off,写入长度len
② FileInputStream:文件字节输入流
常用的构造方法:
a. FileInputStream fis = new FileInputStream(“f.txt”);
I. 参数:代表文件的路径,如果指定文件不存在,系统不会自动创建,运行 报错,错误信息:
**java.io.FileNotFoundException(**系统找不到指定的文件。)
常用的方法:
a. public int read():一次性读取一个字节的内容,返回值代表读取的内容,如果达 到文件的尾部,则返回-1.
将文件中内容一次性读取?
while(true){
int r = fis.read();
if(r==-1){
break;
}
System.out.println((char)r);
}
b. public int read(byte[] bs):一次性读取多个字节的内容,将读取的字节内容自 动存储到bs数组中,返回值代表实际读取的字节个数。
c. public int read(byte[] bs,int off,int len):一次性读取多个字节的内容,将读取 的字节内容存储到数组bs中(存储的起始下标off,读取的个数len),返回值代表实 际读取的字节个数。
思考:如何实现文件的拷贝???
while(true){
int r = fis.read();
if(r==-1) break;
fos.write®;
}
3. 过滤流
① BufferedInputStream/BufferedOutputStream
a. 缓冲流,提高IO读写效率,减少访问磁盘的次数。
b. 数据存储在缓冲中,利用flush方法将缓冲区的数据清空,(写入到文件中);
或是直接利用close方法清空缓冲区。
② DataOutputStream/DataInputStream
a. 操作8种基本数据类型
readByte()/readShort()/readInt()/readLong()/readFloat()/readDoubl e()/writeByte(形参)/writeShort(形参)…
b. 可以操作字符串:readUTF() / writeUTF(参数)
③ ObjectOutputStream/ObjectInputStream
a. 具有缓冲作用
b. 可以操作8种基本数据类型/String
c. 可以操作对象
writeObject(Object o):将对象写入到文件中
readObject():从文件中读取一个对象的内容,返回值类型是Object.
④对象序列化:
概念:将对象放在流上进行传输的过程称为对象序列化。【重点】
要求:参与对象序列化的对象是可序列化的,可序列化的要求是
对象的类实现java.io.Serializable接口。【重点】
注意:① 被transient修饰的属性不参与对象序列化。
② 达到文件尾部的标志:java.io.EOFException
③ 如果参与对象序列化的对象中的属性是自定义类型,则该对象也必须是 可序列化的。
④ 如果对集合进行对象序列化,则必须保证集合中所有的元素 都是可序列 化的。
三、字符流
1. 常用编码:
① ISO8859-1 :西欧 ,底端存储占用1B
② GBK 简体中文
GB2312
GB18030
⑤ BIG5 台湾-繁体中文
⑥ UTF-8 万国码,底端采用动态编码,中文占 2 ~ 3个字节,英文符号:1B
如果编码方式和解码方式不一致,会导致乱码。
2. 字符流的父类(抽象类)
① Writer:字符输出流—》写操作
② Reader:字符输入流—》读操作
3. 节点流
① FileWriter:文件字符输出流
a. public void write(int b):将单个字符写入文件中
b. public void write(String str):将多个字符一次性写入到文件中
c. public void write(char[] c):将多个字符一次性写入到文件中
② FileReader:文件字符输入流
a. public int read():一次读取一个字符的内容,达到文件的尾部,返回—1.
b. public int read(char[] c):一次性读取多个字符的内容,并且将读取的字符内容存 储到数组中,返回值代表实际读取的字符个数,达到文件尾部,则返回-1.
c. public int read(char[] c,int off,int len):一次性读取多个字符的内容,将读取的内 容存储到字符数组中,存储下标为off,读取的字符个数为len,达到文件尾部,返 回-1。
4. 过滤流【重点】
BufferedReader/PrintWriter
① BufferedReader:
操作:public String readLine():一次性读取一个文本行的内容。达到文件的尾部, 返回null.
② PrintWriter:
a. 可以操作8种基本数据类型
b. 可以将String写入到文件中
print(参数):将内容写入到文件中不换行
println(参数):将内容写入到文件中,自动换行。
c. 可以将对象的内容写入到文件中:
println(Object o)/print(Object o)
注意:将对象的toString方法的返回的String结果写入到文件中。
- 桥转换流:【重点】
① OutputStreamWriter/InputStreamReader
a. 作用:将字节流转换成字符流,同时可以设置编解码方式。
步骤小结:【重点】
① 创建字节节点流
② 创建桥转换流:字节流–》字符流,同时设置编解码方式
③ 包装过滤流:目的是增强读写操作
④ 读写操作
⑤ 关闭流:关闭最外层流
四、File类
1. File是对文件本身操作,例如:删除文件、改名字等。
IO流是对文件的内容进行操作,读或是写操作。
2. 常用方法:
① File(String pathName):执行操作的文件、文件夹的路径
② String getName():获取文件/文件名字,文件包含扩展名
③ String getAbsolutePath():获取文件、文件夹的绝对路径
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TM2PIVvM-1591751992767)(file:///C:/Users/Shallum/AppData/Local/Temp/msohtmlclip1/01/clip_image004.jpg)]
第十六章 线程
一、进程【理解】
1. 概念: 进程是指操作系统(OS)中并发执行的多个任务。
2. 并发执行的原理:宏观并行,微观串行。
二、线程
1. 概念:线程是一个进程中并发执行的多个程序逻辑(任务);
线程是进程的执行单位。(线程被称为轻量级进程) 【理解】
- 组成:
① CPU:获取OS分配的CPU时间片。
② 数据:堆空间共享,栈空间独立。
堆空间:存储对象,堆空间共享。
栈空间:存储局部变量,栈空间独立。
③ 代码:代码实现多线程【开发应用重点】
a. 第一种实现多线程
I. 自定义类继承Thread类,覆盖run方法
II. 创建自定义类对象
MyThread t=new MyThread();
III. 开启线程:调用start()方法
t.start();//JVM会自动调用run方法
b. 第二种实现多线程:
I. 自定义类实现Runnable接口,同时实现run方法
II. 创建自定义类对象
MyTarget tg=new MyTarget();
III. 创建Thread对象,同时将目标对象作为参数传递
Thread t=new Thread(tg);
IV. 开启线程:调用start方法(t.start()😉
三、线程状态
1. 状态图详见pdf.【理解】
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GpDIfnD7-1591751992770)(file:///C:/Users/Shallum/AppData/Local/Temp/msohtmlclip1/01/clip_image006.jpg)]
2. 常见方法:
① sleep(long ms):让当前线程处于休眠状态,单位是毫秒。处于休眠状态的线程会让 出CPU时间片,但是不释放锁标记。调用sleep方法的线程进入限期等待状态(Timed Waiting)。
② join():加入,合并到自身线程任务中,优先执行。
例如:main函数中调用t.join()//主线程让t线程优先执行。
四、线程同步【重点】
1. 临界资源:多线程并发时,多个线程共享的同一个对象。
- 原子操作:不可分割的多步操作,被视为一个整体,其顺序和步骤不允许被打破。
3. 线程同步:多线程并发时,为了保证临界资源的正确性,从而不破坏程序中原子操作。
4. 线程同步的方式:【开发应用重点】
① 同步代码块:对临界资源对象加锁
a. 位置:定义在方法内部
b. 语法: synchronized(临界资源){
//原子操作…
}
c. 线程必须获取临界资源的锁标记,才能执行同步代码块中{}的内容;而且{}中的 内容全部执行完毕,才释放锁标记。如果线程没有获取临界资源的锁标记,则进 入阻塞状态(Blocked状态),只有获取类锁标记,才能从阻塞状态出来, 同时拥有CPU,才能执行{}中的内容。
② 同步方法:
a. synchronized 修饰方法
b. 修饰符 synchronized 返回值类型 方法名(形参){
//原子操作…
}
相当于:
synchronized(this){
//原子操作…
}
五、线程通信【了解】
1. wait():等待
① 位置:必须使用在该对象的同步代码块中。
② 作用:让当前线程处于等待状态
③ 注意:wait会让当前线程释放拥有的对象的锁标记,同时释放CPU.
2. notify()/notifyAll():通知
① notify:通知一个线程从等待状态出来;
notifyAll:通知所有的线程从等待状态出来。
② 位置:必须使用在该对象操作的同步代码块中。
③ notify/notifyAll:只是通知的作用,不会让当前线程释放锁标记和CPU.
面试重点: sleep(long ms)和wait()方法的区别?????
**六、**什么是ThreadLocal
ThreadLocal是一个本地线程副本变量工具类。主要用于将私有线程和该线程存放的副本对象 做一个映射,各个线程之间的变量互不干扰,在高并发场景下,可以实现无状态的调用,特别 适用于各个线程依赖不通的变量值完成操作的场景。由于ThreadLocalMap的key是弱引用, 而Value是强引用。这就导致了一个问题,ThreadLocal在没有外部对象强引用时,发生GC 时弱引用Key会被回收,而Value不会回收,如果创建ThreadLocal的线程一直持续运行, 那么这个Entry对象中的value就有可能一直得不到回收,发生内存泄露。
总结:每个ThreadLocal只能保存一个变量副本,如果想要上线一个线程能够保存多个副本以 上,就需要创建多个ThreadLocal。ThreadLocal内部的ThreadLocalMap键为弱引用,会 有内存泄漏的风险。适用于无状态,副本变量独立后不影响业务逻辑的高并发场景。如果如果 业务逻辑强依赖于副本变量,则不适合用ThreadLocal解决,需要另寻解决方案。
第十七章 反射
一 、单例
1. 概念:单例是常见的设计模式,在Java中,单例对象必须保证JVM中只有一个该类的 实例对象存在。
2. 单例的代码实现:
//饿汉式:
优点:并发效率高
缺点:空间利用率低
class Single1{
private static final Single1 s=new Single1();
private Single1(){}
public static Single1 getInstance(){
return s;
}
}
//懒汉式:
优点:空间利用率高
缺点:并发效率低
class Single2{
private static Single2 s;
private Single2(){}
public synchronized static Single2 getInstance(){
if(s==null){
s=new Single2();
}
return s;
}
}
二、反射
1. 概念:【理解】
① 类的对象:基于定义好的一个类,创建该类的实例对象。
new出来的对象都是类的对象
② 类对象:类加载的产物,封装了该类的所有的信息
(类名、包名、父类、接口、方法、属性等)。
- 获取类对象的方式:【重点】
① 通过类的对象获取类对象
Student s=new Student();
Class c1=s.getClass();
② 使用类名获取类对象:
Class c2=Student.class;
③ 使用Class中静态方法 forName获取类对象
Class c3=Class.forName(“包名.类名”);
注意:类名必须是全类名:包名.类名
- 反射的特点:
① 缺点:可读性差
② 优点:可以使代码更加灵活通用。一般应用在底层开发,例如框架等。
- 反射:通过.class文件对象,可以操作该类中的成员属性,成员方法,构造方法。
①. 获取.class文件对象
A.Object类中的方法:Class getClass()
B.数据类型.class
C.Class类中有一个静态方法:static Class forName(String className)
注意:className传递类的全路径(包名+类名)
5. 获取构造方法:
Constructor<?>[] getConstructors():所有公共构造方法
Constructor<?>[] getDeclaredConstructors():获取所有的构造方法
Constructor getConstructor(Class<?>… parameterTypes):指定公共构造方法
Constructor getDeclaredConstructor(Class<>parameterTypes)指定构造方法
Constructor类中创建对象的方法:
Object newInstance(Object… initargs):通过构造方法创建对象获取属性:
Field[] getFields():获取所有public修饰的属性
Field[] getDeclaredFields():获取所有的属性
Field getField(String name) :获取单个的public修饰的属性
Field getDeclaredField(String name) :获取指定的属性
Field的类中为属性赋值的方法:
void set(Object obj, Object value)
获取方法:
Method[] getMethods():获取所有public修饰的方法
Method[] getDeclaredMethods() :获取所有的方法
Method getMethod(String name, Class<?>… parameterTypes):获取指定公 共修饰的方法
Method getDeclaredMethod(String name, Class<?>… parameterTypes):获 取指定的方法
Method类中的方法:
Object invoke(Object obj, Object… args):执行当前获取到的方法
三.设计模式
1. 简单工厂设计模式:测试类不必创建对象,通过工厂类创建对象
2. 单例设计模式:保证内存中只有一个对象
A.饿汉式:类一加载就会创建对象
B.懒汉式:什么时候用到在创建对象
如何保证内存中只有一个对象:
1.构造方法私有化
2.类中成员位置创建一个对象
3.提供公开的访问方式
面试题:单例设计模式的思想是什么?请写一段代码体现?(掌握)
思想:保证内存中只有一个对象
开发:饿汉式(多线程环境下不会出现问题)
面试:懒汉式(多线程环境下存在问题)
☆☆☆CoreJava完结☆☆☆