Java SE 基础篇大全(Java 入门必看)

第一章 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没有任何关系。

  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

  1. 强制类型转换

​ ① 场景:当大数据类型的变量赋值小数据类型的变量时,需要使用强制类型转换。

​ ② 语法:大数据类型 大数据类型的变量名= 值;

​ 小数据类型 变量名 = (小数据类型)大数据类型的变量名;

​ ③ 强制转换的结果

​ 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.存储元素数据类型:数组可以存储基本数据类型和引用数据类型,集合只能存储引 用数据类型

  1. List的三个实现类:(interface,有下标,有序,不唯一)

①ArrayList:底层数组实现,查询快增删慢,线程不安全,效率高

②Vector:底层数组实现,查询快增删慢,线程安全,效率低

③LinkedList:底层链表实现,查询慢增删快,线程不安全,效率高

  1. 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集合

  1. Map:存储键值对,键不能重复,值可以重复。(一个键对应一个值)。

***Map和Collection区别:

​ a.Map存储键值对,健唯一,值可重复

​ b.Collection存储单个元素,子接口List有序,可重复;无序,唯一。

  1. Map中的二个实现类:

①.HashMap:唯一,无序

底层哈希表实现

②.TreeMap:排序,唯一

​ 底层:红黑自平衡二叉树(保证键从小到大)

3.LinkedHashMap:唯一,有序

底层:哈希表,链表实现

  1. HashMap和HashTable的区别:

HashMap:允许null作为键和值,线程不安全,效率高

HashTable:不允许null作为键值,线程安全,效率低

  1. 遍历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);

​ }

  1. 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一 般用于释放资源。

六、自定义异常类

  1. 类继承Exception或是其子类;如果自定的异常类想成为运行时异常,它需要继承 RuntimeException或是RuntimeException的子类。

​ 自定义异常类通常定义为:运行时异常。

  1. 提供两个构造方法:

​ 一个构造方法为无参数的构造方法;

​ 另一个构造方法为带有String类型参数的构造方法:

​ 利用super(message),message描述异常的String信息。

七、方法的覆盖(终结版)【重点】

  1. 子类的方法名、参数列表、返回值类型必须和父类相同

  2. 子类的访问修饰符必须和父类相同或是更宽

  3. 子类不能抛出比父类更多、更宽的异常

第十五章 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结果写入到文件中。

  1. 桥转换流:【重点】

​ ① 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. 概念:线程是一个进程中并发执行的多个程序逻辑(任务);

​ 线程是进程的执行单位。(线程被称为轻量级进程) 【理解】

  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. 临界资源:多线程并发时,多个线程共享的同一个对象。

  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出来的对象都是类的对象

​ ② 类对象:类加载的产物,封装了该类的所有的信息

​ (类名、包名、父类、接口、方法、属性等)。

  1. 获取类对象的方式:【重点】

​ ① 通过类的对象获取类对象

​ Student s=new Student();

​ Class c1=s.getClass();

​ ② 使用类名获取类对象:

​ Class c2=Student.class;

​ ③ 使用Class中静态方法 forName获取类对象

​ Class c3=Class.forName(“包名.类名”);

​ 注意:类名必须是全类名:包名.类名

  1. 反射的特点:

​ ① 缺点:可读性差

​ ② 优点:可以使代码更加灵活通用。一般应用在底层开发,例如框架等。

  1. 反射:通过.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完结☆☆☆

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值