Java基础知识
第一章、Java基础入门
1、JDK的组成

2、什么是注释,注释有哪些,字面量,什么是变量
注释是写在程序中对代码进行解释说明的文字,方便自己和其他人查看,以便理解程序的。单行注释。多行注释。文档注释: 文档注释的内容是可以提取到一个程序说明文档中去的。计算机是用来处理数据的,字面量就是告诉程序员:数据在程序中的书写格式。变量就是内存中的一块区域,用来存储一个数据的,且存储的数据可以被替换。变量是什么,有什么作用?内存中的一块区域。用来存储一个数据的,且存储的数据可以被替换。变量的格式:数据类型 变量名称 = 初始值;变量的基本特点:变量中只能存一个值。变量中存的值是可以替换的。
3、定义变量需要注意的几个问题,关键字,标识符
变量要先声明再使用,变量声明后,不能存储其他类型的数据,变量的有效范围是从定义开始到“}”截止,且在同一个范围内部不能定义2个同名的变量。变量定义的时候可以没有初始值,但是使用的时候必须给初始值。Java语言自己用到的一些词,有特殊作用的,我们称之为关键字。 java用了,我们就不能用了,否则会报错!如定义:类名或者是变量名称时,就不能用这些词。注意:关键字很多,不用刻意去记。标志符就是名字。我们写程序时会起一些名字,如类名、方法名、变量名,取名时要遵守一定的规则。标识符的要求:基本要求:由数字、字母、下划线(_)和美元符($)等组成。强制要求:不能以数字开头、不能是关键字、区分大小写。命名指导规范变量名称:满足标识符规则,建议全英文、有意义、首字母小写,满足“驼峰模式”,例如:int studyNumber = 59。类名称: 满足标识符规则,建议全英文、有意义、首字母大写,满足“驼峰模式”,例如:HelloWorld.java。
4、总结:什么是关键字,标识符(取名字的注意事项)
关键字就是Java自己要用到的词,并且有特殊含义的一些词。标识符取名字的规则,数字,字母,下划线,美元符等组成。取名字不能数字开头,不能是关键字。
第二章、类 型转换、常用运算符
5、 二进制,十进制转二进制的算法
只有0、1,按照逢2进1的方式表示数据。除二取余法。计算机中数据最小的组成单元:使用8个二进制位为一组,称之为一个字节(byte,简称B)。字节中的每个二进制位就称为 位(bit,简称b), 1B = 8b。数据在计算机底层都是怎么存储的?都是采用二进制:使用0、1,按照逢2进1的规则表示数据来存储。如何快速的算出一个数据的二进制形式?
除二取余法。数据在计算机底层存储的最小单位是什么?字符在计算机中是如何存储的呢?ASCII编码表:即美国信息交换标准编码,规定了现代英语、数字字符、和其他西欧字符对应的数字编号。二进制如何计算成八进制?每3位二进制作为一个单元,最小数是0,最大数是7,0-7有8个数字。二进制如何计算成十六进制?每4位二进制作为一个单元,最小数是0,最大数是15,0-15有16个数字,依次用: 0~9 A B C D E F 代表。
6、数据类型的作用
数据类型就是约束变量存储数据的形式。 数据类型 变量名称 = 初始值;数据类型的分类
引用数据类型(除基本数据类型之外的,如String 。)。基本数据类型:4大类8种。
7、数据类型分为几种?
引用数据类型:String,基本数据类型:4大类8种。byte short int(默认) long 整型,float double(默认) 浮点型,char 字符型,boolean 布尔型,随便写的整数、小数字面值默认什么类型?23 ,默认是int类型 , 加上L/l就是long类型的数据了。23.8,默认是double类型,加上F/f就是float类型了。
8、什么是自动类型转换,为什么要学习自动类型转换?
类型范围小的变量,可以直接赋值给类型范围大的变量。

9、为什么要进行类型转换?
存在不同类型的变量赋值给其他类型的变量。自动类型转换是什么样的?类型范围小的变量,可以直接赋值给类型范围大的变量。
10、表达式的自动类型转换
在表达式中,小范围类型的变量会自动转换成当前较大范围的类型再运算。注意事项:表达式的最终结果类型由表达式中的最高类型决定。在表达式中,byte、short、char 是直接转换成int类型参与运算的。
11、表达式的自动类型转换是什么样的?
小范围的类型会自动转换成大范围的类型运算。表达式的最终结果类型是由谁决定的?
最终类型由表达式中的最高类型决定。表达式的有哪些类型转换是需要注意的?byte short char是直接转换成int类型参与运算的。强制类型转换:可以强行将类型范围大的变量、数据赋值给类型范围小的变量。
12、什么是强制类型转换?
可以强行将类型范围大的变量、数据赋值给类型范围小的变量。强制类型转换有哪些需要注意的?可能出现数据丢失。小数强制转换成整数是直接截断小数保留整数。
13、运算符
运算符:对字面量或者变量进行操作的符号。

14、“+” 做连接符
“+”符号与字符串运算的时候是用作连接符的,其结果依然是一个字符串。自增自减运算符
++ 和 – 既可以放在变量的后边,也可以放在变量的前边。++ 、-- 只能操作变量,不能操作字面量的。自增自减的使用注意事项。++、–如果不是单独使用(如在表达式中、或者同时有其它操作),放在变量前后会存在明显区别。关系运算符: 是对数据进行条件判断的符号,最终会返回一个比较的布尔结果(false,true)。逻辑运算符概述:可以把多个条件的布尔结果放在一起运算,最终返回一个布尔结果。三元运算符介绍
执行流程:首先计算关系表达式的值,如果值为true,返回值1,如果为false,返回值2。
运算符优先级: 在表达式中,哪个运算符先执行后执行是要看优先级的,例如 “*、/” 的优先级高于”+、-”。
第三章、 流程控制
15、程序执行的几种常见形式

16、If分支
根据判定的结果(真或假)决定执行某个分支的代码。If分支有三种格式

if 第一种格式
执行流程:首先判断条件表达式的结果,如果为true执行语句体,为 false 就不执行语句体。注意事项:if 语句中,如果大括号控制的只有一行代码,则大括号可以省略不写。

if 第二种格式
执行流程:
首先判断条件表达式的结果,如果为true执行语句体1,为 false 就执行语句体2。

if 第三种格式
执行流程:
先判断条件1的值,如果为true则执行语句体1,分支结束;如果为false则判断条件2的值,如果值为true就执行语句体2,分支结束;如果为false则判断条件3的值,如果没有任何条件为true,就执行else分支的语句体n+1。

17、switch分支
也是匹配条件去执行分支, 适合做值匹配的分支选择,结构清晰,格式良好。执行流程:
先执行表达式的值,拿着这个值去与case后的值进行匹配。匹配哪个case的值为true就执行哪个case,遇到break就跳出switch分支。如果case后的值都不匹配则执行default代码。

18、总结
switch分支的格式、执行流程是怎么样的?if、switch分支各自适合做什么业务场景?if其实在功能上远远强大于switch。if适合做区间匹配。switch适合做:值匹配的分支选择、代码优雅。图同上。
19、switch分支注意事项:
表达式类型只能是byte、short、int、char,JDK5开始支持枚举,JDK7开始支持String、不支持double、float、long。case给出的值不允许重复,且只能是字面量,不能是变量。不要忘记写break,否则会出现穿透现象。switch的穿透性: 如果代码执行到没有写break的case块,执行完后将直接进入下一个case块执行代码(而且不会进行任何匹配),直到遇到break才跳出分支,这就是switch的穿透性。
20、for 循环
控制一段代码反复执行很多次。

for 循环案例详细流程说明
执行的流程:
循环一开始,执行int i = 0 一次。
然后判断循环条件:0 < 3 返回true ,进入到循环体中执行输出 :helloWorld ,然后执行迭代语句i++ , 此时i=1了。
然后判断循环条件:1 < 3 返回true ,进入到循环体中执行输出 :helloWorld ,然后执行迭代语句i++ , 此时i=2了。
然后判断循环条件:2 < 3 返回true ,进入到循环体中执行输出 :helloWorld, 然后执行迭代语句i++ , 此时i=3了。
然后判断循环条件:3 < 3 返回false, 循环立即结束!!
21、while 循环格式与执行流程

22、总结
while循环的格式,执行流程是怎么样的?什么时候用for循环,什么时候用while循环?
功能上是完全一样的,for能解决的while也能解决,反之亦然。使用规范是:知道循环几次:使用for;不知道循环几次建议使用:while。
23、三种循环的区别小结
for循环 和 while循环(先判断后执行),do…while (第一次先执行后判断),for循环和while循环的执行流程是一模一样的。如果已知循环次数建议使用for循环,如果不清楚要循环多少次建议使用while循环。for循环中,控制循环的变量只在循环中可以使用。While循环中,控制循环的变量在循环后还可以继续使用。死循环一直循环的执行下去,如果没有干预不会停止下来。循环嵌套:循环中又包含循环。嵌套循环的特点:外部循环每循环一次,内部循环全部执行完一次。跳转控制语句介绍:break : 跳出并结束当前所在循环的执行。continue: 用于跳出当前循环的当次执行,进入下一次循环。
第四章、数组
24、数组是什么
数组就是用来存储一批同种类型数据的容器。数组适合做一批同种类型数据的存储。静态初始化数组:定义数组的时候直接给数组赋值。

数组的基本原理:数组变量名中存储的是数组在内存中的地址,数组是引用类型。
数组的静态初始化的写法和特点什么样的?

数组是属于什么类型,数组变量名中存储的是什么?
引用数据类型,存储的数组在内存中的地址信息。
2、数组的访问

25、总结
如何访问数组的元素?数组名称[索引],如何访问数组的长度?数组名称.length
数组的最大索引怎么获取?数组名. length – 1 // 前提:元素个数大于0

26、数组的几个注意事项:
“数据类型[] 数组名”也可以写成 “数据类型 数组名[] ”。
什么类型的数组存放什么类型的数据,否则报错。
数组一旦定义出来,程序执行的过程中,长度、类型就固定了。
27、数组的动态初始化
定义数组的时候只确定元素的类型和数组的长度,之后再存入具体数据。
数组的动态初始化格式:
数据类型[] 数组名 = new 数据类型[长度];
int[] arr = new int[3];
// 后赋值
arr[0] = 10;
System.out.println(arr[0]); // 10
28、总结
1、动态初始化的写法是什么样的?
数据类型[] 数组名 = new 数据类型[长度];
int[] ages = new int[4];
2、两种数组定义时的特点和场景有什么区别
当前已经知道存入的元素值,用静态初始化。
当前还不清楚要存入哪些数据,用动态初始化。
29、元素默认值规则:

两种初始化的的使用场景总结、注意事项说明:
动态初始化:只指定数组长度,后期赋值,适合开始知道数据的数量,但是不确定具体元素值的业务场景。
静态初始化:开始就存入元素值,适合一开始就能确定元素值的业务场景。
两种格式的写法是独立的,不可以混用。
30、数组遍历介绍
遍历:就是一个一个数据的访问。
为什么要遍历?

数组元素求最大值如何实现的?
数据拿到程序中去,用数组装起来。定义一个变量用于记录最大值,这个变量建议默认存储第一个元素值作为参照。遍历数组的元素,如果该元素大于变量存储的元素,则替换变量存储的值为该元素。循环结束后输出最大值变量即可。

Java 内存分配介绍

数组使用常见问题
问题1:如果访问的元素位置超过最大索引,执行时会出现ArrayIndexOutOfBoundsException(数组索引越界异常)
问题2:如果数组变量中没有存储数组的地址,而是null, 在访问数组信息时会出现NullPointerException(空指针异常)
第五章、方法
31、方法是什么
方法是一种语法结构,它可以把一段代码封装成一个功能,以方便重复调用。使用方法的好处是?提高了代码的复用性。让程序的逻辑更清晰。
32、方法定义的完整格式

方法的调用格式
方法必须调用才可以跑起来,调用格式:

33、方法的调用流程 - Debug

方法格式的注意点
方法的修饰符:暂时都使用public static 修饰。
方法申明了具体的返回值类型,内部必须使用return返回对应类型的数据。
形参列表可以有多个,甚至可以没有; 如果有多个形参,多个形参必须用“,”隔开,且不能给初始化值。如果方法不需要返回结果,不需要接收参数,应该怎么办,要注意什么?
方法不需要返回结果,则申明返回值类型为void;方法不需要参数,则形参列表可以不写。
方法没有申明返回值类型,内部不能使用return返回数据。
方法如果没有形参列表,调用的时候则不能传入参数值,否则报错。
34、方法常见问题
方法的编写顺序无所谓。
方法与方法之间是平级关系,不能嵌套定义。
方法的返回值类型为void(无返回值),方法内则不能使用return返回数据,如果方法的返回值类型写了具体类型,方法内部则必须使用return返回对应类型的数据。
return语句下面,不能编写代码,因为永远执行不到,属于无效的代码。
方法不调用就不执行, 调用时必须严格匹配方法的参数情况。
有返回值的方法调用时可以选择定义变量接收结果,或者直接输出调用,甚至直接调用;无返回值方法的调用只能直接调用。
35、方法定义的技巧说明
修饰符:public static (暂时固定的)。返回值类型到底写什么是需要分析的。方法名称:自己取名,有意义,英文小写,驼峰模式。(有意义的名字即可)。形参列表到底写什么也是需要分析的。方法体代码:完成自己需要写的功能代码即可。结论:定义方法时真正需要关注的就两点:1、分析方法是否需要申明返回值类型;2、分析方法是否需要接收参数。
36、定义方法重点关注的是哪两点?
方法是否需要申明返回值类型。方法是否需要定义形参列表。
37、方法的调用流程 – 内存图解
方法是放在方法区中的,被调用的时候,需要进入到栈内存中运行。方法的运行区域在哪里?栈内存。
38、Java的参数传递机制:值传递
在传输实参给方法的形参的时候,并不是传输实参变量本身, 而是传输实参变量中存储的值,这就是值传递。注意:实参:如在方法内部定义的变量。形参:如在定义方法时,“()”中所声明的参数。
39、形参和实参各指什么?
形参:以方法为例,就是方法定义时的变量。实参:在方法内部定义的变量。Java的参数传递机制是什么样的?值传递,传输的是实参存储的值。
40、基本类型和引用类型的参数在传递的时候有什么不同?
都是值传递。基本类型的参数传输存储的数据值。引用类型的参数传输存储的地址值。
41、方法重载
同一个类中,出现多个方法名称相同,但是形参列表是不同的,那么这些方法就是重载方法。方法重载的作用:可读性好,方法名称相同提示是同一类型的功能,通过形参不同实现功能差异化的选择,这是一种专业的代码设计。
42、方法重载的作用
可读性好,方法名称相同提示是同一类型的功能,通过形参不同实现功能差异化的选择,这是一种专业的代码设计。方法重载是什么样的?同一个类中,多个方法的名称相同,形参列表不同。使用方法重载的好处 ?对于相似功能的业务场景:可读性好,方法名称相同提示是同一类型的功能,通过形参不同实现功能差异化的选择,这是一种专业的代码设计。方法重载的识别技巧:只要是同一个类中,方法名称相同、形参列表不同,那么他们就是重载的方法,其他都不管!(如:修饰符,返回值类型都无所谓)。形参列表不同指的是:形参的个数、类型、顺序不同,不关心形参的名称。
43、方法重载的关键要求是什么样的?
同一个类中,多个方法的名称相同,形参列表不同,其他无所谓。形参列表不同指的是什么?形参的个数、类型、顺序不同。不关心形参的名称。如果要直接结束当前方法的执行,怎么解决?return; 跳出并立即结束所在方法的执行。break; 跳出并结束当前所在循环的执行。
continue; 结束当前所在循环的当次继续,进入下一次执行。
44、类和对象是什么?拿到对象后怎么访问对象的信息?
类:是共同特征的描述(设计图);对象:是真实存在的具体实例。对象.成员变量;对象.成员方法(…)。

45、定义类的补充注意事项
类名首字母建议大写,且有意义,满足“驼峰模式”。
一个Java文件中可以定义多个class类,但只能一个类是public修饰,而且public修饰的类名必须成为代码文件名。
实际开发中建议还是一个文件定义一个class类。
成员变量的完整定义格式是:修饰符 数据类型 变量名称 = 初始化值; 一般无需指定初始化值,存在默认值。
46、成员变量的默认值规则

47、总结
类名首字母建议大写、英文、有意义,满足驼峰模式,不能用关键字,满足标志符规定
一个代码文件中可以定义多个类,但是只能一个类是public修饰的,public修饰的类名必须是Java代码的文件名称。
成员变量的完整格式是:修饰符 数据类型 变量名称 = 初始化值;
一般无需为成员变量指定初始化值,存在默认值。
对象到底是放在哪个位置的?
堆内存中
Car c = new Car(); c变量名中存储的是什么?
存储的是对象在堆内存中的地址。
成员变量(name、price)的数据放在哪里,存在于哪个位置?
对象中,存在于堆内存中。
48、垃圾回收
注意:当堆内存中的对象,没有被任何变量引用(指向)时,就会被判定为内存中的“垃圾”。
49、构造器的作用
定义在类中的,可以用于初始化一个类的对象,并返回对象的地址。
构造器的格式

构造器的分类和作用
无参数构造器(默认存在的):初始化对象时,成员变量的数据均采用默认值。
有参数构造器:在初始化对象的时候,同时可以接收参数为对象进行赋值。
50、构造器的注意事项
任何类定义出来,默认就自带了无参数构造器,写不写都有。一旦定义了有参数构造器,那么无参数构造器就没有了,如果还想用无参数构造器,此时就需要自己手写一个无参数构造器了。
51、总结
构造器的作用?
初始化类的对象,并返回对象的地址。
构造器有几种,各自的作用是什么?
无参数构造器:初始化对象时,成员变量的数据均采用默认值。
有参数构造器:在初始化对象的时候,同时可以接收参数为对象进行赋值。
构造器有哪些注意事项?
任何类定义出来,默认就自带了无参数构造器,写不写都有。
一旦定义了有参数构造器,无参数构造器就没有了,此时就需要自己写无参数构造器了。
52、this关键字是什么
可以出现在构造器、方法中
代表当前对象的地址。
this关键字的作用
可以用于指定访问当前对象的成员变量、成员方法。
封装
面向对象的三大特征:封装,继承,多态。
53、String简单介绍
String类定义的变量可以用于存储字符串,同时String类提供了很多操作字符串的功能,我们可以直接使用。
54、ArrayList 简单介绍
ArrayList代表的是集合类,集合是一种容器,与数组类似,不同的是集合的大小是不固定的。
通过创建ArrayList的对象表示得到一个集合容器,同时ArrayList提供了比数组更好用,更丰富的API (功能)给程序员
购物车使用集合对象来存储商品对象更合适
随时可能添加新商品对象进来(个数不确定)
也随时可能删除商品对象
55、String 概述
java.lang.String 类代表字符串,String类定义的变量可以用于指向字符串对象,然后操作该字符串。
Java 程序中的所有字符串文字(例如“abc”)都为此类的对象。
String类的特点详解
String其实常被称为不可变字符串类型,它的对象在创建后不能被更改。
56、字符串对象存在哪里?
以“”方式给出的字符串对象,在字符串常量池中存储。

57、总结
String是什么,可以做什么?
字符串类型,可以定义字符串变量指向字符串对象。
String是不可变字符串的原因?
String变量每次的修改其实都是产生并指向了新的字符串对象。
原来的字符串对象都是没有改变的,所以称不可变字符串。
58、创建字符串的2种方式
方式一:直接使用“”定义。(推荐方式)
方式二:通过String类的构造器创建对象。
59、如果是字符串比较应该使用使用什么方式进行比较,为什么?
使用String提供的equals方法。
只关心内容一样就返回true。
开发中什么时候使用==比较数据
基本数据类型比较时使用。
60、数组和集合的元素存储的个数问题?
数组定义后类型确定,长度固定
集合类型可以不固定,大小是可变的。
数组和集合适合的场景
数组适合做数据个数和类型确定的场景
集合适合做数据个数不确定,且要做增删元素的场景
61、集合概述
集合是与数组类似,也是一种容器,用于装数据的。
数组的特点
数组定义完成并启动后,类型确定、长度固定。
问题:在个数不能确定,且要进行增删数据操作的时候,数组是不太合适的。
62、集合的特点
集合的大小不固定,启动后可以动态变化,类型也可以选择不固定。
集合非常适合做元素个数不确定,且要进行增删操作的业务场景。
集合还提供了许多丰富、好用的功能,而数组的功能很单一。
62、总结
数组和集合的元素存储的个数问题?
数组定义后类型确定,长度固定
集合类型可以不固定,大小是可变的。
数组和集合适合的场景:
数组适合做数据个数和类型确定的场景
集合适合做数据个数不确定,且要做增删元素的场景
63、泛型概述
ArrayList:其实就是一个泛型类,可以在编译阶段约束集合对象只能操作某种数据类型。
举例:
ArrayList :此集合只能操作字符串类型的元素。
ArrayList:此集合只能操作整数类型的元素。
注意:泛型只能支持引用数据类型,不支持基本数据类型。
64、怎么去统一ArrayList集合操作的元素类型,泛型需要注意什么?
使用泛型:<数据类型>
创建集合对象都应该使用泛型。
ArrayList list1 = new ArrayList();
泛型只能支持引用数据类型,不支持基本数据类型。
65、static是什么
static是静态的意思,可以用来修饰成员变量、成员方法。
static修饰成员变量之后称为静态成员变量(类变量),修饰方法之后称为静态方法(类方法)。
static修饰后的成员变量,可以被类的所有对象共享(访问、修改)。
66、总结
static是什么 ?
静态的意思,可以修饰成员变量、成员方法
static修饰的成员变量是什么? 有什么特点?
静态成员变量(有static修饰,属于类、加载一次,内存中只有一份),访问格式

实例成员变量(无static修饰,属于对象),访问格式:
两种成员变量各自在什么情况下定义?
静态成员变量:表示在线人数等需要被类的所有对象共享的信息时。
实例成员变量:属于每个对象,且每个对象的该信息不同时(如:name,age,money…)
67、成员方法的分类:
静态成员方法(有static修饰,归属于类),建议用类名访问,也可以用对象访问。
实例成员方法(无static修饰,归属于对象),只能用对象触发访问。表示对象自己的行为的,且方法中需要访问实例成员的,则该方法必须申明成实例方法。
如果该方法是以执行一个共用功能为目的,则可以申明成静态方法。
67、总结
成员方法的分类和访问分别是什么样的?
静态成员方法(有static修饰,属于类和对象共享)访问格式:
类名.静态成员方法。
对象.静态成员方法。(不推荐)
实例成员方法(无static修饰,属于对象)的访问格式:
对象.实例成员方法。
每种成员方法的使用场景是怎么样的?
表示对象自己的行为的,且方法中需要直接访问实例成员,则该方法必须申明成实例方法。
如果该方法是以执行一个通用功能为目的,或者需要方便访问,则可以申明成静态方法
68、static访问注意事项:
静态方法只能访问静态的成员,不可以直接访问实例成员。
实例方法可以访问静态的成员,也可以访问实例成员。
静态方法中是不可以出现this关键字的。
69、工具类是什么,有什么好处?
内部都是一些静态方法,每个方法完成一个功能
一次编写,处处可用,提高代码的重用性。
工具类有什么要求?
建议工具类的构造器私有化处理。
工具类不需要创建对象。
70、代码块概述
代码块是类的5大成分之一(成员变量、构造器,方法,代码块,内部类),定义在类中方法外。
在Java类下,使用 { } 括起来的代码被称为代码块 。
代码块分为
静态代码块:
格式:static{}
特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发、只执行一次
使用场景:在类加载的时候做一些静态数据初始化的操作,以便后续使用。
构造代码块(了解,见的少):
格式:{}
特点:每次创建对象,调用构造器执行时,都会执行该代码块中的代码,并且在构造器执行前执行
使用场景:初始化实例资源。
71、什么是设计模式(Design pattern)
开发中经常遇到一些问题,一个问题通常有n种解法的,但其中肯定有一种解法是最优的,这个最优的解法被人总结出来了,称之为设计模式。
设计模式有20多种,对应20多种软件开发中会遇到的问题。
学设计模式主要是学2点:
第一:这种模式用来解决什么问题。
第二:遇到这种问题了,该模式是怎么写的,他是如何解决这个问题的。
72、单例模式
可以保证系统中,应用该模式的这个类永远只有一个实例,即一个类永远只能创建一个对象。
例如任务管理器对象我们只需要一个就可以解决问题了,这样可以节省内存空间。
单例的实现方式很多
饿汉单例模式。
懒汉单例模式。
饿汉单例设计模式
用类获取对象的时候,对象已经提前为你创建好了。
设计步骤:
定义一个类,把构造器私有。
定义一个静态变量存储一个对象。
73、什么是继承?
Java中提供一个关键字extends,用这个关键字,我们可以让一个类和另一个类建立起父子关系。
Student称为子类(派生类),People称为父类(基类 或超类)。
作用:当子类继承父类后,就可以直接使用父类公共的属性和方法了
使用继承的好处
可以提高代码的复用性。
74、总结
什么是继承? 继承的好处是啥?
继承就是java允许我们用extends关键字,让一个类和另一个类建立起一种父子关系。
提高代码复用性,减少代码冗余,增强类的功能扩展性。
继承的格式
子类 extends父类
继承后子类的特点?
子类 继承父类,子类可以得到父类的属性和行为,子类可以使用。
Java中子类更强大
75、继承设计规范:
子类们相同特征(共性属性,共性方法)放在父类中定义,子类独有的的属性和行为应该定义在子类自己里面。
为什么?
如果子类的独有属性、行为定义在父类中,会导致其它子类也会得到这些属性和行为,这不符合面向对象逻辑。
76、继承需要满足什么样的设计规范?
子类们相同特征(共性属性,共性方法)放在父类中定义。
子类独有的的属性和行为应该定义在子类自己里面。

77、继承的特点
子类可以继承父类的属性和行为,但是子类不能继承父类的构造器。
Java是单继承模式:一个类只能继承一个直接父类。
Java不支持多继承、但是支持多层继承。
Java中所有的类都是Object类的子类。
78、子类是否可以继承父类的构造器?
不可以的,子类有自己的构造器,父类构造器用于初始化父类对象。
子类是否可以继承父类的私有成员?
可以的,只是不能直接访问。
79、子类是否可以继承父类的静态成员?
有争议的知识点。
子类可以直接使用父类的静态成员(共享)
但个人认为:子类不能继承父类的静态成员。(共享并非继承)
Java只支持单继承,不支持多继承。
Java支持多层继承:
子类 A 继承父类 B ,父类B 可以 继承父类 C
Object特点:
Java中所有类,要么直接继承了Object , 要么默认继承了Object , 要么间接继承了Object, Object是祖宗类。
80、在子类方法中访问成员(成员变量、成员方法)满足:就近原则
先子类局部范围找
然后子类成员范围找
然后父类成员范围找,如果父类范围还没有找到则报错。
如果子父类中,出现了重名的成员,会优先使用子类的,此时如果一定要在子类中使用父类的怎么办?
可以通过super关键字,指定访问父类的成员。
80、总结
在子类方法中访问成员(成员变量、成员方法)满足:
就近原则,子类没有找子类、子类没有找父类、父类没有就报错!
如果子父类中出现了重名的成员,此时如果一定要在子类中使用父类的怎么办?
格式:super.父类成员变量/父类成员方法
81、什么是方法重写?
在继承体系中,子类出现了和父类中一模一样的方法声明,我们就称子类这个方法是重写的方法。
方法重写的应用场景
当子类需要父类的功能,但父类的该功能不完全满足自己的需求时。
子类可以重写父类中的方法。
案例演示:
旧手机的功能只能是基本的打电话,发信息
新手机的功能需要能够:基本的打电话下支持视频通话。基本的发信息下支持发送语音和图片。
82、@Override重写注解
@Override是放在重写后的方法上,作为重写是否正确的校验注解。
加上该注解后如果重写错误,编译阶段会出现错误提示。
建议重写方法都加@Override注解,代码安全,优雅!
方法重写注意事项和要求
重写方法的名称、形参列表必须与被重写方法的名称和参数列表一致。
私有方法不能被重写。
子类重写父类方法时,访问权限必须大于或者等于父类 (暂时了解 :缺省 < protected < public)
子类不能重写父类的静态方法,如果重写会报错的。
83、总结
方法重写是什么样的?
子类写一个与父类申明一样的方法覆盖父类的方法。
方法重写建议加上哪个注解,有什么好处?
@Override注解可以校验重写是否正确,同时可读性好。
重写方法有哪些基本要求?
重写方法的名称和形参列表应该与被重写方法一致。
私有方法不能被重写。
子类重写父类方法时,访问权限必须大于或者等于父类被重写的方法的权限。
84、子类继承父类后构造器的特点:
子类中所有的构造器默认都会先访问父类中无参的构造器,再执行自己。
为什么?
子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据。
子类初始化之前,一定要调用父类构造器先完成父类数据空间的初始化。
怎么调用父类构造器的?
子类构造器的第一行语句默认都是:super(),不写也存在。
85、this和super详情
this:代表本类对象的引用;super:代表父类存储空间的标识。
实际上,在以上的总结中,唯独只有this调用本类其他构造器我们是没有接触过的。

86、什么是包?
包是用来分门别类的管理各种不同类的,类似于文件夹、建包利于程序的管理和维护。
建包的语法格式:package 公司域名倒写.技术名称。报名建议全部英文小写,且具备意义
建包语句必须在第一行,一般IDEA工具会帮助创建

导包
相同包下的类可以直接访问,不同包下的类必须导包,才可以使用!导包格式:import 包名.类名;
假如一个类中需要用到不同类,而这个两个类的名称是一样的,那么默认只能导入一个类,另一个类要带包名访问。
87、什么是权限修饰符?
权限修饰符:是用来控制一个成员能够被访问的范围。
可以修饰成员变量,方法,构造器,内部类,不同权限修饰符修饰的成员能够被访问的范围将受到限制。
权限修饰符的分类和具体作用范围:
权限修饰符:有四种作用范围由小到大(private -> 缺省 -> protected - > public )

88、final的作用
final 关键字是最终的意思,可以修饰(类、方法、变量)
修饰类:表明该类是最终类,不能被继承。
修饰方法:表明该方法是最终方法,不能被重写。
修饰变量:表示该变量第一次赋值后,不能再次被赋值(有且仅能被赋值一次)。
final修饰变量的注意:
final修饰的变量是基本类型:那么变量存储的数据值不能发生改变。
final修饰的变量是引用类型:那么变量存储的地址值不能发生改变,但是地址指向的对象内容是可以发生变化的。
89、常量
常量是使用了public static final修饰的成员变量,必须有初始化值,而且执行的过程中其值不能被改变。
常量名的命名规范:英文单词全部大写,多个单词下划线连接起来。
常量做信息配置的原理、优势
在编译阶段会进行“宏替换”:把使用常量的地方全部替换成真实的字面量。
维护系统容易,可读性更好。
90、枚举的概述
枚举是Java中的一种特殊类型
枚举的作用:“是为了做信息的标志和信息的分类”。
定义枚举类的格式:

91、反编译后观察枚举的特征:
枚举的特征:
枚举类都是继承了枚举类型:java.lang.Enum
枚举都是最终类,不可以被继承。
构造器都是私有的,枚举对外不能创建对象。
枚举类的第一行默认都是罗列枚举对象的名称的。
枚举类相当于是多例模式。
92、抽象类
在Java中abstract是抽象的意思,可以修饰类、成员方法。
abstract修饰类,这个类就是抽象类;修饰方法,这个方法就是抽象方法。
注意事项
抽象方法只有方法签名,不能声明方法体。
一个类中如果定义了抽象方法,这个类必须声明成抽象类,否则报错。
抽象的使用场景:
抽象类可以理解成不完整的设计图,一般作为父类,让子类来继承。
当父类知道子类一定要完成某些行为,但是每个子类该行为的实现又不同,于是该父类就把该行为定义成抽象方法的形式,具体实现交给子类去完成。此时这个类就可以声明成抽象类。
93、总结
抽象类、抽象方法是什么样的?
都是用abstract修饰的;抽象方法只有方法签名,不能写方法体。
一个类中定义了抽象方法,这个类必须声明成抽象类。
抽象类基本作用是啥?
作为父类,用来被继承的。
继承抽象类有哪些要注意?
一个类如果继承了抽象类,那么这个类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。
94、特征和注意事项
类有的成员(成员变量、方法、构造器)抽象类都具备
抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
一个类继承了抽象类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。
不能用abstract修饰变量、代码块、构造器。
最重要的特征:得到了抽象方法,失去了创建对象的能力(有得有失)
final和abstract是什么关系?
互斥关系
abstract定义的抽象类作为模板让子类继承,final定义的类不能被继承。
抽象方法定义通用功能让子类重写,final定义的方法子类不能重写。
95、什么时候使用模板方法模式
使用场景说明:当系统中出现同一个功能多处在开发,而该功能中大部分代码是一样的,只有其中部分可能不同的时候。
模板方法模式实现步骤:
1、定义一个抽象类。2、定义2个方法,一个是模板方法:把相同代码放里面去,不同代码定义成抽象方法
3、子类继承抽象类,重写抽象方法。

96、什么是多态?
指对象可以有多种形态。
多态的常见形式
父类类型 对象名称 = new 子类构造器;
多态中成员访问特点
方法调用:编译看左边,运行看右边。
变量调用:编译看左边,运行也看左边。(注意)
多态的前提
有继承/实现关系;有父类引用指向子类对象;有方法重写(多态侧重行为多态)。
优势
在多态形式下,右边对象可以实现解耦合,便于扩展和维护。
Animal a = new Dog();
a.run(); // 后续业务行为随对象而变,后续代码无需修改
定义方法的时候,使用父类型作为参数,该方法就可以接收这父类的一切子类对象,体现出多态的扩展性与便利。
多态下会产生的一个问题:
多态下不能使用子类的独有功能
97、多态下的类型转换
自动类型转换(从子到父):
强制类型转换(从父到子)
从父到子( 必须进行强制类型转换,否则报错): 子类 对象变量 = (子类)父类类型的变量
作用:可以解决多态下的劣势,可以实现调用子类独有的功能。
注意: 有继承/实现关系的类就可以在编译阶段进行强制类型转换;但是,如果转型后的类型和对象真实对象的类型不是同一种类型,那么在运行代码时,就会出现ClassCastException
Java建议强转转换前使用instanceof判断当前对象的真实类型,再进行强制转换
98、总结
引用数据类型的类型转换,有几种方式?
自动类型转换、强制类型转换。
强制类型转换能解决什么问题?
可以转换成真正的子类类型,从而调用子类独有功能。
强制类型转换需要注意什么?
有继承关系/实现的2个类型就可以进行强制转换,编译无问题。
运行时,如果发现强制转换后的类型不是对象真实类型则报错(ClassCastException)
强制类型转换前最好做什么事情,如何进行?
使用instanceof判断当前对象的真实类型,再进行强制转换
对象变量名 instanceof 真实类型
99、接口的定义与特点
接口的格式如下:
接口用关键字interface来定义
public interface 接口名 {
// 常量
// 抽象方法
}

JDK8之前接口中只能是抽象方法和常量,没有其他成分了。
接口不能实例化。
接口中的成员都是public修饰的,写不写都是,因为规范的目的是为了公开化。
100、接口的用法:
接口是用来被类实现(implements)的,实现接口的类称为实现类。实现类可以理解成所谓的子类。
修饰符 class 实现类 implements 接口1, 接口2, 接口3 , … {
}
实现的关键字:implements
从上面可以看出,接口可以被类单实现,也可以被类多实现。

接口实现的注意事项:
一个类实现接口,必须重写完全部接口的全部抽象方法,否则这个类需要定义成抽象类。
基本小结
类和类的关系:单继承。
类和接口的关系:多实现。
接口和接口的关系:多继承,一个接口可以同时继承多个接口。
接口多继承的作用
规范合并,整合多个接口为同一个接口,便于子类实现。
类似之前写的普通实例方法:必须用default修饰
默认会public修饰。需要用接口的实现类的对象来调用
101、接口的注意事项
1、接口不能创建对象
2、一个类实现多个接口,多个接口的规范不能冲突
2、一个类实现多个接口,多个接口中有同样的静态方法不冲突。
3、一个类继承了父类,同时又实现了接口,父类中和接口中有同名方法,默认用父类的。
4、一个类实现了多个接口,多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可。
5、一个接口继承多个接口,是没有问题的,如果多个接口中存在规范冲突则不能多继承。
102、内部类
内部类就是定义在一个类里面的类,里面的类可以理解成(寄生),外部类可以理解成(宿主)。
public class People{
// 内部类
public class Heart{
}
}
内部类的使用场景
场景:当一个事物的内部,还有一个部分需要一个完整的结构进行描述时。
基本作用
内部类通常可以方便访问外部类的成员,包括私有的成员。
内部类提供了更好的封装性,内部类本身就可以用private ,protectecd等修饰,封装性可以做更多控制
内部类的分类
静态内部类[了解]
成员内部类(非静态内部类) [了解]
局部内部类[了解]
匿名内部类(重点)
103、什么是静态内部类?
有static修饰,属于外部类本身。
它的特点和使用与普通类是完全一样的,类有的成分它都有,只是位置在别人里面而已
public class Outer{
// 静态成员内部类
public static class Inner{
}
}
静态内部类创建对象的格式:
格式:外部类名.内部类名 对象名 = new 外部类名.内部类构造器;
静态内部类的访问拓展:
1、静态内部类中是否可以直接访问外部类的静态成员?
可以,外部类的静态成员只有一份可以被共享访问。
2、静态内部类中是否可以直接访问外部类的实例成员?
不可以的,外部类的实例成员必须用外部类对象访问。
静态内部类的使用场景、特点、访问总结。
如果一个类中包含了一个完整的成分,如汽车类中的发动机类。
特点、使用与普通类是一样的,类有的成分它都有,只是位置在别人里面而已。
访问总结:可以直接访问外部类的静态成员,不能直接访问外部类的实例成员。
注意:开发中实际上用的还是比较少。
104、什么是成员内部类?
无static修饰,属于外部类的对象。
JDK16之前,成员内部类中不能定义静态成员,JDK 16开始也可以定义静态成员了。
public class Outer {
// 成员内部类
public class Inner {

}

}
成员内部类创建对象的格式:
格式:外部类名.内部类名 对象名 = new 外部类构造器.new 内部类构造器();
范例:Outer.Inner in = new Outer().new Inner();
成员内部类的访问拓展:
成员内部类中是否可以直接访问外部类的静态成员?
可以,外部类的静态成员只有一份可以被共享访问。
成员内部类的实例方法中是否可以直接访问外部类的实例成员?
可以的,因为必须先有外部类对象,才能有成员内部类对象,所以可以直接访问外部类对象的实例成员。
成员内部类是什么样的、有什么特点?
无static修饰,属于外部类的对象。
可以直接访问外部类的静态成员,实例方法中可以直接访问外部类的实例成员。
成员内部类如何创建对象?
外部类名.内部类名 对象名 = new 外部类构造器.new 内部类构造器();
105、匿名内部类:
本质上是一个没有名字的局部内部类。
作用:方便创建子类对象,最终目的是为了简化代码编写。
格式:
new 类|抽象类名|或者接口名() {
重写方法;
};

特点总结:
匿名内部类是一个没有名字的内部类,同时也代表一个对象。
匿名内部类产生的对象类型,相当于是当前new的那个的类型的子类类型。
106、Object类的作用:
一个类要么默认继承了Object类,要么间接继承了Object类,Object类是Java中的祖宗类。
Object作为所有类的父类,提供了很多常用的方法给每个子类对象拿来使用。
Object类的常用方法:

106、Object的toString方法:
问题引出
开发中直接输出对象,默认输出对象的地址其实是毫无意义的。
开发中输出对象变量,更多的时候是希望看到对象的内容数据而不是对象的地址信息。
toString存在的意义
父类toString()方法存在的意义就是为了被子类重写,以便返回对象的内容信息,而不是地址信息!!
Object的toString方法的基本作用是什么,存在的意义是什么?
基本作用:给子类继承,子类对象调用可以返回自己的地址。
意义:让子类重写,以便返回子类对象的内容。
Object的equals方法:
问题思考
直接比较两个对象的地址是否相同完全可以用“==”替代equals。
同时,开发中很多业务情况下,更想判断2个对象的内容是否一样。
equals存在的意义
为了被子类重写,以便子类自己来定制比较规则(比如比较对象内容)。
107、Objects概述
Objects是一个工具类,提供了一些方法去完成一些功能。
官方在进行字符串比较时,没有用字符串对象的的equals方法,而是选择了Objects的equals方法来比较。
使用Objects的equals方法在进行对象的比较会更安全。
108、StringBuilder概述
StringBuilder是一个可变的字符串的操作类,我们可以把它看成是一个对象容器。
使用StringBuilder的核心作用:操作字符串的性能比String要更高(如拼接、修改等)。
StringBuilder 构造器
109、正则表达式在字符串方法中的使用

110、Arrays类概述
数组操作工具类,专门用于操作数组元素的。

111、包装类
其实就是8种基本数据类型对应的引用类型。

为什么提供包装类?
Java为了实现一切皆对象,为8种基本类型提供了对应的引用类型。
后面的集合和泛型其实也只能支持包装类型,不支持基本数据类型。
112、自动装箱和拆箱
自动装箱:基本类型的数据和变量可以直接赋值给包装类型的变量。
自动拆箱:包装类型的变量可以直接赋值给基本数据类型的变量。
包装类的特有功能
包装类的变量的默认值可以是null,容错率更高。
可以把基本类型的数据转换成字符串类型(用处不大)
调用toString()方法得到字符串结果。
调用Integer.toString(基本类型的数据)。
可以把字符串类型的数值转换成真实的数据类型(真的很有用)
Integer.parseInt(“字符串类型的整数”)
Double.parseDouble(“字符串类型的小数”)。
113、包装类是什么,作用是什么?
基本数据类型对应的引用类型,实现了一切皆对象。
后期集合和泛型不支持基本类型,只能使用包装类。
包装类有哪些特殊功能?
可以把基本类型的数据转换成字符串类型(用处不大)
可以把字符串类型的数值转换成真实的数据类型(真的很有用)
114、常见的算法
冒泡排序的思想:
每次从数组中找出最大值放在数组的后面去。
实现冒泡排序的关键步骤分析:
确定总共需要做几轮: 数组的长度-1.
每轮比较几次:
当前位置大于后一个位置则交换数据
选择排序的思想:
每轮选择当前位置,开始找出后面的较小值与该位置交换
选择排序的关键
确定总共需要选择几轮: 数组的长度-1.
控制每轮从以前位置为基准,与后面元素选择几次。
基本查找:

结论:在数据量特别大的时候,基本查找从前往后寻找的性能是很差的!
二分查找:
二分查询性能好,二分查找的前提是必须是排好序的数据。
二分查找相当于每次去掉一半的查找范围
结论:二分查找正常的检索条件应该是开始位置min <= 结束位置max
115、总结
数组的二分查找的实现步骤是什么样的?
定义变量记录左边和右边位置。
使用while循环控制查询(条件是左边位置<=右边位置)
循环内部获取中间元素索引
判断当前要找的元素如果大于中间元素,左边位置=中间索引+1
判断当前要找的元素如果小于中间元素,右边位置=中间索引-1
判断当前要找的元素如果等于中间元素,返回当前中间元素索引。
116、Lambda概述
Lambda表达式是JDK 8开始后的一种新语法形式。
作用:简化匿名内部类的代码写法。
Lambda表达式的简化格式
(匿名内部类被重写方法的形参列表) -> {
被重写方法的方法体代码。
}
注:-> 是语法形式,无实际含义
注意:Lambda表达式只能简化函数式接口的匿名内部类的写法形式
什么是函数式接口?
首先必须是接口、其次接口中有且仅有一个抽象方法的形式
117、总结
Lambda表达式的基本作用?
简化函数式接口的匿名内部类的写法。
Lambda表达式有什么使用前提?
必须是接口的匿名内部类,接口中只能有一个抽象方法
118、Lambda表达式的省略写法(进一步在Lambda表达式的基础上继续简化)
参数类型可以省略不写。
如果只有一个参数,参数类型可以省略,同时()也可以省略。
如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写,同时要省略分号!
如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写。此时,如果这行代码是return语句,必须省略return不写,同时也必须省略";"不写
119、数组的特点
数组定义完成并启动后,类型确定、长度固定。不适合元素的个数和类型不确定的业务场景,更不适合做需要增删数据操作。数组的功能也比较的单一,处理数据的能力并不是很强大。集合的大小不固定,启动后可以动态变化,类型也可以选择不固定。集合更像气球。集合非常适合元素个数不能确定,且需要做元素的增删操作的场景。同时,集合提供的种类特别的丰富,功能也是非常强大的,开发中集合用的更多。
120、集合类体系结构
Collection单列集合,每个元素(数据)只包含一个值。Map双列集合,每个元素包含两个值(键值对)。注意:前期先掌握Collection集合体系的使用。
121、Collection集合特点
List系列集合:添加的元素是有序、可重复、有索引。ArrayList、LinekdList :有序、可重复、有索引。Set系列集合:添加的元素是无序、不重复、无索引。HashSet: 无序、不重复、无索引;LinkedHashSet: 有序、不重复、无索引。TreeSet:按照大小默认升序排序、不重复、无索引。

122、泛型
集合都是泛型的形式,可以在编译阶段约束集合只能操作某种数据类型
注意:集合和泛型都只能支持引用数据类型,不支持基本数据类型,所以集合中存储的元素都认为是对象。
123、Collection集合
Collection是单列集合的祖宗接口,它的功能是全部单列集合都可以继承使用的。
Collection API如下:

124、迭代器遍历概述
遍历就是一个一个的把容器中的元素访问一遍。
迭代器在Java中的代表是Iterator,迭代器是集合的专用的遍历方式。
Collection集合获取迭代器

Iterator中的常用方法

125、增强for循环
for(元素数据类型 变量名 : 数组或者Collection集合) {
//在此处使用变量即可,该变量就是元素
}
增强for循环:既可以遍历集合也可以遍历数组。
126、Lambda表达式遍历集合
得益于JDK 8开始的新技术Lambda表达式,提供了一种更简单、更直接的遍历集合的方式。
Collection结合Lambda遍历的API
127、数据结构概述
数据结构是计算机底层存储、组织数据的方式。是指数据相互之间是以什么方式排列在一起的。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。常见的数据结构:栈,队列,数组,链表,二叉树,二叉查找树,平衡二叉树,红黑树。栈数据结构的执行特点:后进先出,先进后出。常见数据结构之数组:数组是一种查询快,增删慢的模型
查询速度快:查询数据通过地址值和索引定位,查询任意数据耗时相同。(元素在内存中是连续存储的)。删除效率低:要将原始数据删除,同时后面每个数据前移。添加效率极低:添加位置后的每个数据后移,再添加元素。链表的特点:链表中的元素是在内存中不连续存储的,每个元素节点包含数据值和下一个元素的地址。链表中的元素是在内存中不连续存储的,每个元素节点包含数据值和下一个元素的地址。链表查询慢。无论查询哪个数据都要从头开始找。链表增删相对快。二叉树概述:只能有一个根节点,每个节点最多支持2个直接子节点。节点的度: 节点拥有的子树的个数,二叉树的度不大于2 叶子节点 度为0的节点,也称之为终端结点。高度:叶子结点的高度为1,叶子结点的父节点高度为2,以此类推,根节点的高度最高。层:根节点在第一层,以此类推兄弟节点 :拥有共同父节点的节点互称为兄弟节点。
128、红黑树概述
红黑树是一种自平衡的二叉查找树,是计算机科学中用到的一种数据结构。1972年出现,当时被称之为平衡二叉B树。1978年被修改为如今的"红黑树"。每一个节点可以是红或者黑;红黑树不是通过高度平衡的,它的平衡是通过“红黑规则”进行实现的。红黑规则
:每一个节点或是红色的,或者是黑色的,根节点必须是黑色。如果某一个节点是红色,那么它的子节点必须是黑色(不能出现两个红色节点相连的情况)。对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。红黑树不是高度平衡的,它的平衡是通过"红黑规则"进行实现的。规则如下:每一个节点或是红色的,或者是黑色的,根节点必须是黑色。如果一个节点没有子节点或者父节点,则该节点相应的指针属性值为Nil,这些Nil视为叶节点,每个叶节点(Nil)是黑色的;如果某一个节点是红色,那么它的子节点必须是黑色(不能出现两个红色节点相连的情况)。对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。
129、List系列集合特点
ArrayList、LinekdList :有序,可重复,有索引。有序:存储和取出的元素顺序一致。有索引:可以通过索引操作元素可重复:存储的元素可以重复。List集合因为支持索引,所以多了很多索引操作的独特api,其他Collection的功能List也都继承了。ArrayList底层是基于数组实现的,根据查询元素快,增删相对慢。LinkedList底层基于双链表实现的,查询元素慢,增删首尾元素是非常快的。ArrayList集合底层原理:ArrayList底层是基于数组实现的:根据索引定位元素快,增删需要做元素的移位操作。第一次创建集合并添加第一个元素的时候,在底层创建一个默认长度为10的数组。LinkedList的特点:底层数据结构是双链表,查询慢,首尾操作的速度是极快的,所以多了很多首尾操作的特有API。
130、泛型类的概述
定义类时同时定义了泛型的类就是泛型类。泛型类的格式:修饰符 class 类名<泛型变量>{ }。此处泛型变量T可以随便写为任意标识,常见的如E、T、K、V等。作用:编译阶段可以指定数据类型,类似于集合的作用。泛型类的原理: 把出现泛型变量的地方全部替换成传输的真实数据类型。泛型方法的概述;范例: public void show(T t) { }。定义方法时同时定义了泛型的方法就是泛型方法。泛型方法的格式:修饰符 <泛型变量> 方法返回值 方法名称(形参列表){}。作用:方法中可以使用泛型接收一切实际类型的参数,方法更具备通用性。泛型方法的原理:把出现泛型变量的地方全部替换成传输的真实数据类型。泛型接口的概述使用了泛型定义的接口就是泛型接口。泛型接口的格式:修饰符 interface 接口名称<泛型变量>{}。范例: public interface Data{}。作用:泛型接口可以让实现类选择当前功能需要操作的数据类型。泛型接口的原理:实现类可以在实现接口的时候传入自己操作的数据类型,这样重写的方法都将是针对于该类型的操作。
131、Set系列集合特点
无序:存取顺序不一致,不重复:可以去除重复,无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素。HashSet : 无序、不重复、无索引。LinkedHashSet:有序、不重复、无索引。TreeSet:排序、不重复、无索引。Set集合的功能上基本上与Collection的API一致。
132、HashSet底层原理
HashSet集合底层采取哈希表存储的数据。哈希表是一种对于增删改查数据性能都较好的结构。哈希表的组成:JDK8之前的,底层使用数组+链表组成。JDK8开始后,底层采用数组+链表+红黑树组成。在了解哈希表之前需要先理解哈希值的概念,哈希值:是JDK根据对象的地址,按照某种规则算出来的int类型的数值。Object类的API:public int hashCode():返回对象的哈希值。对象的哈希值特点,同一个对象多次调用hashCode()方法返回的哈希值是相同的,默认情况下,不同对象的哈希值是不同的。HashSet1.7版本原理解析:数组 + 链表 +(结合哈希算法):创建一个默认长度16的数组,数组名table,根据元素的哈希值跟数组的长度求余计算出应存入的位置(哈希算法),判断当前位置是否为null,如果是null直接存入。底层结构:哈希表(数组、链表、红黑树的结合体)。当挂在元素下面的数据过多时,查询性能降低,从JDK8开始后,当链表长度超过8的时候,自动转换为红黑树。
133、哈希表的详细流程
创建一个默认长度16,默认加载因为0.75的数组,数组名table,根据元素的哈希值跟数组的长度计算出应存入的位置,判断当前位置是否为null,如果是null直接存入,如果位置不为null,表示有元素,则调用equals方法比较属性值,如果一样,则不存,如果不一样,则存入数组。当数组存满到16*0.75=12时,就自动扩容,每次扩容原先的两倍。
134、LinkedHashSet集合概述和特点
有序、不重复、无索引。这里的有序指的是保证存储和取出的元素顺序一致。原理:底层数据结构是依然哈希表,只是每个元素又额外的多了一个双链表的机制记录存储的顺序。
135、TreeSet集合概述和特点
不重复、无索引、可排序,可排序:按照元素的大小默认升序(有小到大)排序。TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好。注意:TreeSet集合是一定要排序的,可以将元素按照指定的规则进行排序。TreeSet集合默认的规则:对于数值类型:Integer , Double,官方默认按照大小进行升序排序。对于字符串类型:默认按照首字符的编号升序排序。对于自定义类型如Student对象,TreeSet无法直接排序。结论:想要使用TreeSet存储自定义类型,需要制定排序规则。自定义排序规则:TreeSet集合存储对象的的时候有2种方式可以设计自定义比较规则。方式一:让自定义的类(如学生类)实现Comparable接口重写里面的compareTo方法来定制比较规则。方式二:TreeSet集合有参数构造器,可以设置Comparator接口对应的比较器对象,来定制比较规则。两种方式中,关于返回值的规则:如果认为第一个元素大于第二个元素返回正整数即可。如果认为第一个元素小于第二个元素返回负整数即可。如果认为第一个元素等于第二个元素返回0即可,此时Treeset集合只会保留一个元素,认为两者重复。
136、可变参数
可变参数用在形参中可以接收多个数据。可变参数的格式:数据类型…参数名称,可变参数的作用接收参数非常灵活,方便。可以不接收参数,可以接收1个或者多个参数,也可以接收一个数组,可变参数在方法内部本质上就是一个数组。可变参数的注意事项:一个形参列表中可变参数只能有一个,可变参数必须放在形参列表的最后面。
137、Map集合概述和使用
Map集合是一种双列集合,每个元素包含两个数据。Map集合的每个元素的格式:key=value(键值对元素)。Map集合也被称为“键值对集合”。Map集合整体格式:Collection集合的格式: [元素1,元素2,元素3…]。Map集合的完整格式:{key1=value1 , key2=value2 , key3=value3 , …}
Map集合体系

说明
使用最多的Map集合是HashMap。
重点掌握HashMap , LinkedHashMap , TreeMap。其他的后续理解。
138、Map集合体系特点
Map集合的特点都是由键决定的。Map集合的键是无序,不重复的,无索引的,值不做要求(可以重复)。Map集合后面重复的键对应的值会覆盖前面重复键的值。Map集合的键值对都可以为null。Map集合实现类特点:HashMap:元素按照键是无序,不重复,无索引,值不做要求。(与Map体系一致),LinkedHashMap:元素按照键是有序,不重复,无索引,值不做要求。TreeMap:元素按照建是排序,不重复,无索引的,值不做要求。
139、Map集合
Map是双列集合的祖宗接口,它的功能是全部双列集合都可以继承使用的。Map集合的遍历方式有:3种。方式一:键找值的方式遍历:先获取Map集合全部的键,再根据遍历键找值。方式二:键值对的方式遍历,把“键值对“看成一个整体,难度较大。方式三:JDK 1.8开始之后的新技术:Lambda表达式。Map集合的遍历方式一:键找值,先获取Map集合的全部键的Set集合。遍历键的Set集合,然后通过键提取对应值。Map集合的遍历方式二:键值对。先把Map集合转换成Set集合,Set集合中每个元素都是键值对实体类型了。遍历Set集合,然后提取键以及提取值。Map集合的遍历方式三:Lambda
得益于JDK 8开始的新技术Lambda表达式,提供了一种更简单、更直接的遍历集合的方式。
140、HashMap的特点
HashMap是Map里面的一个实现类。特点都是由键决定的:无序、不重复、无索引没有额外需要学习的特有方法,直接使用Map里面的方法就可以了。HashMap跟HashSet底层原理是一模一样的,都是哈希表结构,只是HashMap的每个元素包含两个值而已。实际上:Set系列集合的底层就是Map实现的,只是Set集合中的元素只要键数据,不要值数据而已。
141、TreeMap集合概述和特点
由键决定特性:不重复、无索引、可排序,可排序:按照键数据的大小默认升序(有小到大)排序。只能对键排序。注意:TreeMap集合是一定要排序的,可以默认排序,也可以将键按照指定的规则进行排序。TreeMap跟TreeSet一样底层原理是一样的。TreeMap集合自定义排序规则有2种。类实现Comparable接口,重写比较规则。集合自定义Comparator比较器对象,重写比较规则。
142、Map集合实现类特点
HashMap:元素按照键是无序,不重复,无索引,值不做要求,基于哈希表(与Map体系一致)。LinkedHashMap:元素按照键是有序,不重复,无索引,值不做要求,基于哈希表
TreeMap:元素只能按照键排序,不重复,无索引的,值不做要求,可以做排序。
143、什么是不可变集合?
不可变集合,就是不可被修改的集合。集合的数据项在创建的时候提供,并且在整个生命周期中都不可改变。否则报错。为什么要创建不可变集合?如果某个数据不能被修改,把它防御性地拷贝到不可变集合中是个很好的实践。或者当集合对象被不可信的库调用时,不可变形式是安全的。如何创建不可变集合?在List、Set、Map接口中,都存在of方法,可以创建一个不可变的集合。这个集合不能添加,不能删除,不能修改。
144、什么是Stream流?
在Java 8中,得益于Lambda所带来的函数式编程,引入了一个全新的Stream流概念。
目的:用于简化集合和数组操作的API。Stream流式思想的核心:先得到集合或者数组的Stream流(就是一根传送带)。把元素放上去,然后就用这个Stream流简化的API来方便的操作元素。Stream操作集合或者数组的第一步是先得到Stream流,然后才能使用流的功能。集合获取Stream流的方式。可以使用Collection接口中的默认方法stream()生成流
数组获取Stream流的方式。Stream流的三类方法:获取Stream流:创建一条流水线,并把数据放到流水线上准备进行操作。中间方法:流水线上的操作。一次操作完毕之后,还可以继续进行其他操作。终结方法:一个Stream流只能有一个终结方法,是流水线上的最后一个操作。
145、什么是异常?
异常是程序在“编译”或者“执行”的过程中可能出现的问题,注意:语法错误不算在异常体系中。 比如:数组索引越界、空指针异常、 日期格式化异常,等。为什么要学习异常?异常一旦出现了,如果没有提前处理,程序就会退出JVM虚拟机而终止。研究异常并且避免异常,然后提前处理异常,体现的是程序的安全, 健壮性。异常体系。

Exception:java.lang包下,称为异常类,它表示程序本身可以处理的问题。RuntimeException及其子类:运行时异常,编译阶段不会报错。 (空指针异常,数组索引越界异常) 。除RuntimeException之外所有的异常:编译时异常,编译期必须处理的,否则程序不能通过编译。 (日期格式化异常)。
Error:系统级别问题、JVM退出等,代码无法控制。
146、编译时异常和运行时异常
编译时异常,是在编译成class文件时必须要处理的异常,也称之为受检异常,运行时异常,在编译成class文件不需要处理,在运行字节码文件时可能出现的异常。简单来说:编译时异常就是在编译的时候出现的异常,运行时异常就是在运行时出现的异常。运行时异常直接继承自RuntimeException或者其子类,编译阶段不会报错,运行时可能出现的错误。
运行时异常示例

运行时异常:一般是程序员业务没有考虑好或者是编程逻辑不严谨引起的程序错误,
147、编译时异常
不是RuntimeException或者其子类的异常,编译阶就报错,必须处理,否则代码不通过。
编译时异常的作用是什么:是担心程序员的技术不行,在编译阶段就爆出一个错误, 目的在于提醒不要出错!默认会在出现异常的代码那里自动的创建一个异常对象:ArithmeticException。异常会从方法中出现的点这里抛出给调用者,调用者最终抛出给JVM虚拟机。虚拟机接收到异常对象后,先在控制台直接输出异常栈信息数据。直接从当前执行的异常点干掉当前程序。后续代码没有机会执行了,因为程序已经死亡。编译时异常是可遇不可求。遇到了就遇到了呗。编译时异常是编译阶段就出错的,所以必须处理,否则代码根本无法通过。编译时异常的处理形式有三种:出现异常直接抛出去给调用者,调用者也继续抛出去。出现异常自己捕获处理,不麻烦别人。前两者结合,出现异常直接抛出去给调用者,调用者捕获处理。
148、异常处理方式1 —— throws
throws:用在方法上,可以将方法内部出现的异常抛出去给本方法的调用者处理。这种方式并不好,发生异常的方法自己不处理异常,如果异常最终抛出去给虚拟机将引起程序死亡。代表可以抛出一切异常,异常处理方式2 —— try…catch…。监视捕获异常,用在方法内部,可以将方法内部出现的异常直接捕获处理。这种方式还可以,发生异常的方法自己独立完成异常的处理,程序可以继续往下执行。异常处理方式3 —— 前两者结合:方法直接将异通过throws抛出去给调用者,调用者收到异常后直接捕获处理。运行时异常的处理形式运行时异常编译阶段不会出错,是运行时才可能出错的,所以编译阶段不处理也可以。 按照规范建议还是处理:建议在最外层调用处集中捕获处理即可。 自定义异常的必要?Java无法为这个世界上全部的问题提供异常类。如果企业想通过异常的方式来管理自己的某个业务问题,就需要自定义异常类了。自定义异常的好处:可以使用异常的机制管理业务问题,如提醒程序员注意。同时一旦出现bug,可以用异常的形式清晰的指出出错的地方。
149、自定义异常的分类
自定义编译时异常:定义一个异常类继承Exception,重写构造器。在出现异常的地方用throw new 自定义对象抛出,作用:编译时异常是编译阶段就报错,提醒更加强烈,一定需要处理。自定义运行时异常:定义一个异常类继承RuntimeException,重写构造器。在出现异常的地方用throw new 自定义对象抛出!作用:提醒不强烈,编译阶段不报错!!运行时才可能出现!!
150、File类概述
File类的对象代表操作系统的文件(文件、文件夹),File类在java.io.File包下。File类提供了诸如:创建文件对象代表文件,获取文件信息(大小、修改时间)、删除文件、创建文件(文件夹)等功能。File类创建对象

注意:File对象可以定位文件和文件夹,File封装的对象仅仅是一个路径名,这个路径可以是存在的,也可以是不存在的。
150、什么是方法递归?
递归做为一种算法在程序设计语言中广泛应用。方法调用自身的形式称为方法递归( recursion)。递归的形式:直接递归:方法自己调用自己。间接递归:方法调用其他方法,其他方法又回调方法自己。方法递归存在的问题?递归如果没有控制好终止,会出现递归死循环,导致栈内存溢出现象。
151、IO流概述
I表示intput,把硬盘文件中的数据读入到内存的过程,称之输入,负责读。O表示output,把内存中的数据写出到硬盘文件的过程,称之输出,负责写。IO流的分类:输入流和输出流。总结流的四大类:字节输入流:以内存为基准,来自磁盘文件/网络中的数据以字节的形式读入到内存中去的流称为字节输入流。字节输出流:以内存为基准,把内存中的数据以字节写出到磁盘文件或者网络中去的流称为字节输出流。字符输入流:以内存为基准,来自磁盘文件/网络中的数据以字符的形式读入到内存中去的流称为字符输入流。字符输出流:以内存为基准,把内存中的数据以字符写出到磁盘文件或者网络介质中去的流称为字符输出流。
152、try-catch-finally
finally:放在try-catch后面的,无论是正常执行还是异常执行代码,最后一定要执行,除非JVM退出。作用:一般用于进行最后的资源释放操作(专业级做法)
153、什么是线程?
线程(thread)是一个程序内部的一条执行路径。我们之前启动程序执行后,main方法的执行其实就是一条单独的执行路径。程序中如果只有一条执行路径,那么这个程序就是单线程的程序。多线程是什么?多线程是指从软硬件上实现多条执行流程的技术。
154、Thread类
Java是通过java.lang.Thread 类来代表线程的。 按照面向对象的思想,Thread类应该提供了实现多线程的方式。多线程的实现方案一:继承Thread类,定义一个子类MyThread继承线程类java.lang.Thread,重写run()方法,创建MyThread类的对象,调用线程对象的start()方法启动线程(启动后还是执行run方法的),方式一优缺点:优点:编码简单,缺点:线程类已经继承Thread,无法继承其他类,不利于扩展。
155、总结
方式一是如何实现多线程的?继承Thread类,重写run方法,创建线程对象,调用start()方法启动。优缺点是什么?优点:编码简单。缺点:存在单继承的局限性,线程类继承Thread后,不能继承其他类,不便于扩展。多线程的实现方案二:实现Runnable接口:定义一个线程任务类MyRunnable实现Runnable接口,重写run()方法,创建MyRunnable任务对象
把MyRunnable任务对象交给Thread处理。调用线程对象的start()方法启动线程。方式二优缺点:优点:线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强。多线程的实现方案三:利用Callable、FutureTask接口实现。缺点:编程多一层对象包装,如果线程有执行结果是不可以直接返回的。得到任务对象定义类实现Callable接口,重写call方法,封装要做的事情。用FutureTask把Callable对象封装成线程任务对象。把线程任务对象交给Thread处理。调用Thread的start方法启动线程,执行任务。线程执行完毕后、通过FutureTask的get方法去获取任务执行的结果。
156、Thread常用API说明
Thread常用方法:获取线程名称getName()、设置名称setName()、获取当前线程对象currentThread()。至于Thread类提供的诸如:yield、join、interrupt、不推荐的方法 stop 、守护线程、线程优先级等线程的控制方法,在开发中很少使用,这些方法会在高级篇以及后续需要用到的时候再为大家讲解。线程安全问题:多个线程同时操作同一个共享资源的时候可能会出现业务安全问题,称为线程安全问题。取钱模型演示需求:小明和小红是一对夫妻,他们有一个共同的账户,余额是10万元。如果小明和小红同时来取钱,而且2人都要取钱10万元,可能出现什么问题呢?
157、线程同步
为了解决线程安全问题。加锁,把共享资源进行上锁,每次只能一个线程进入访问完毕以后解锁,然后其他线程才能进来。同步代码块:
synchronized(同步锁对象) {
操作共享资源的代码(核心代码)
}
作用:把出现线程安全问题的核心代码给上锁。原理:每次只能一个线程进入,执行完毕后自动解锁,其他线程才可以进来执行。
同步方法
修饰符 synchronized 返回值类型 方法名称(形参列表) {
操作共享资源的代码
}

作用:把出现线程安全问题的核心方法给上锁。原理:每次只能一个线程进入,执行
158、同步方法底层原理
同步方法其实底层也是有隐式锁对象的,只是锁的范围是整个方法代码。如果方法是实例方法:同步方法默认用this作为的锁对象。但是代码要高度面向对象!如果方法是静态方法:同步方法默认用类名.class作为的锁对象。Lock锁:为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock,更加灵活、方便。Lock实现提供比使用synchronized方法和语句可以获得更广泛的锁定操作。Lock是接口不能直接实例化,这里采用它的实现类ReentrantLock来构建Lock锁对象。
159、什么是线程通信、如何实现?
所谓线程通信就是线程间相互发送数据,线程间共享一个资源即可实现线程通信。线程通信常见形式:通过共享一个数据的方式实现。根据共享数据的情况决定自己该怎么做,以及通知其他线程怎么做。线程通信实际应用场景。生产者与消费者模型:生产者线程负责生产数据,消费者线程负责消费生产者产生的数据。要求:生产者线程生产完数据后唤醒消费者,然后等待自己,消费者消费完该数据后唤醒生产者,然后等待自己。
160、总结
线程通信的三个常见方法

注意
上述方法应该使用当前同步锁对象进行调用。
161、什么是线程池?
线程池就是一个可以复用线程的技术。不使用线程池的问题 ,如果用户每发起一个请求,后台就创建一个新线程来处理,下次新任务来了又要创建新线程,而创建新线程的开销是很大的,这样会严重影响系统的性能。谁代表线程池?JDK 5.0起提供了代表线程池的接口:ExecutorService,如何得到线程池对象,方式一:使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象,方式二:使用Executors(线程池的工具类)调用方法返回不同特点的线程池对象。线程池常见面试题。临时线程什么时候创建啊?新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程。什么时候会开始拒绝任务?核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始任务拒绝。
162、并发与并行
正在运行的程序(软件)就是一个独立的进程, 线程是属于进程的,多个线程其实是并发与并行同时进行的。并发的理解:CPU同时处理线程的数量有限。CPU会轮询为系统的每个线程服务,由于CPU切换的速度很快,给我们的感觉这些线程在同时执行,这就是并发。
并行的理解:在同一个时刻上,同时有多个线程在被CPU处理并执行。