=============================================================== day01复习
计算机的基础知识
软件系统 -- 系统软件 应用软件
操作计算机的方式--图形化 命令行DOS
JAVA的分类 -- SE ME EE
=========================
环境的搭建
1.JDK【1.8】+配置环境变量
TIPS:一台计算机可以安装多个JDK吗?
可以,环境变量配置哪个,哪个就生效
1)新建:JAVA_HOME--JDK安装路径
2)新建:CLASS_PATH--JDK的lib目录
3)不新建:Path--JDK的bin目录
检验:DOS窗口,命令:java -version
2.eclipse
无需安装,解压即可使用
1.切换成Java视图
2.打开package Exploer
****************************************
1.创建了一个项目java project--day01
2.创建了一个包package--cn.tedu.hello
3.创建了一个类class--HelloWorld
4.编写代码
1)创建入口方法/入口函数 main()
2) 创建一个输出语句 syso Alt+/
3) 保存Ctrl+S 执行Ctrl+F11
=============================================================== day02复习
1.标识符
字母 数字 下划线 美元符号
不能以数字开头,区分大小写,见名知意,不能使用关键字
2.关键字
Java预先指定的50个全小写单词,但是有2个保留字,const goto
除了关键字以外,true false null 也不可以用作标识符
3.注释
1)单行注释: //--可以注释单行内容
2)多行注释:/* */--可以注释多行内容
3)文档注释/doc注释: /** */--也可以注释多行内容,作者/版本/时间...
4.变量
可以会发生变化的值,我们需要记录这些会发生变化的值
变量的定义方式:变量的类型 变量的名字 = 变量的值 ;
1)声明 + 赋值 int age = 18 ;
2)先声明,后面再赋值 int age; age = 18;
5.Java的数据类型
1)基本类型-8种 byte1 short2 int4 long8 float4 double8 char2 boolean1
2)引用类型-String字符串类型,用""包裹
3)变量与String的拼接 name+"" ""+name+"" ""+name
6.类型之间的转换
1)是否能够进行类型转换,取决于类型的取值范围,字节数只能做参考
2)小转大,直接转[隐式转换] 大转小
强制转[显式转换] byte a = (byte) x ;--强制类型转换可能会出现溢出的问题
浮变整,小数没--浮点型转换的时候会出现精度丢失的现象
3)boolean类型不参与类型转换
7.字面值的5条规则
1)整数类型的字面值是int类型
2)浮点类型的字面值是double类型
3)byte short char三种比int小的类型,可以使用范围内的值直接赋值
4)字面值后缀 L-long F-float D-double
5)字面值前缀 0b-2进制 0-8进制 0x-16进制
8.运算规则5条
1)计算结果的数据类型与最大类型保持一致
int/int->int double/double->double double/int->double
2)byte short char 三种比int小的类型,运算时会先自动提升成int类型,再运算
3)整数运算溢出的问题--光年的案例--一旦溢出,数据就不正确了,所以要避免
4)浮点数的特殊值 Infinity NaN
5)浮点数运算不精确 1-0.8--后续提供解决方案
****************************************************************************
案例1:
基本类型都提供了与之对应的“工具箱”,MAX_VALUE MIN_VALUE
int类型对应的工具箱是"Integer"
char类型的数据使用''包裹,而且只能保存一个字符(汉字/英文/数字)
97--会去ASCII码表中查询这个数字对应的字符,128-65535 eclipse以?处理
案例2:
double r = new Scanner(System.in).nextDouble();
案例3:
等号右边的值给等号左边
需要第三个变量参与值交换,格式:斜相对,首尾相连
=============================================================== day03复习
% 取余/mod/求模 5%3=2 ,如果一个数对某个数取余,结果为0,表示整除
自增自减运算符:
前缀式:++a --a,先改变变量本身的值,再使用
后缀式: a++ a--,先使用,再改变变量本身的值
注意:自增自减可以改变变量本身的值,但四则运算不可以改变变量本身的值
比较运算符:> < >= <= == != ,结果均为布尔类型的值
位运算符:&单与 |单或 ->也可以参与二进制数的计算,&全1才1,|全0才0
逻辑运算符:&&的判断逻辑与单与相同,&&拥有短路的效果,可以提高效率
||双或/短路或,判断逻辑与单或相同,拥有短路效果,有真则真
字符串与变量的拼接:name+"" ""+name+"" ""+name,使用+进行拼接
!:取反,取非,!true=false , !false=true
三目/元运算符:1 ? 2 : 3
1:代表的是一个表达式
2与3位置代表的是1号表达式的两个结果,1真选2,1假选3
举例子:求两个数的最小值:int min = a < b ? a : b;
=================================================
顺序结构:顺序结构是从上到下依次执行每一条语句。
可以解决输入 输出 计算等的问题
但是不能解决多种情况需要先判断,再根据结果进行选择的问题
分支结构:
单分支结构 :
if(判断条件){
当判断条件成立的时候,执行此代码,如果判断条件不成立,跳过此句
}
多分支结构--适合两种情况时使用
if(判断条件){
判断条件成立时执行的代码
}else{
前一个判断条件不成立时,执行此代码
}
嵌套分支结构--根据多种情况具体决定,想写几个写几个
if(判断条件1){
满足条件1时执行的代码,如果本条件不成立,继续向下判断
}else if(判断条件2){
满足条件3时执行的代码,如果本条件不成立,继续向下判断
}else if(判断条件3){
满足条件3时执行的代码,如果本条件不成立,继续向下判断
}else if(判断条件4){
满足条件4时执行的代码,如果本条件不成立,继续向下判断
}else{
当以上条件都不成立时执行的代码
}
===============================================================
switch(变量){
case value1 : 操作语句1;break;【可选】
case value2 : 操作语句2;break;【可选】
case value3 : 操作语句3;break;【可选】
case value4 : 操作语句4;break;【可选】
case value5 : 操作语句5;break;【可选】
default:保底选项,当上面的case没有匹配上,执行此选项【可选】
}
穿透:没有遇到break时,如果匹配到了某个case,会一直执行所有选项,包括default
==============================================
循环:当我们需要循环多次执行某件事时,可以使用循环结构
for循环:
for(开始条件;循环条件;更改条件){
符合循环条件执行的循环体
}
for(int i = 10 ; i >0 ; i--){
System.out.println(i);
}
列出数据,从哪开始,到哪结束,如何变化
=============================================
=============================================================== day04复习
结构
顺序结构:从头到尾按顺序执行代码,可以完成计算、输入、输出等功能
但是不能先判断,然后选择性的执行代码
===============================================
分支结构:
单分支结构
if(判断条件){
符合判断条件的时候,执行此代码,如果不满足条件,此句跳过
}
多分支结构
if(判断条件){
符合判断条件的时候,执行此代码,如果不满足条件,此句跳过
}else{
不符合上面的判断条件,属于其他情况时,执行此代码
}
嵌套分支结构
if(判断条件1){
满足条件1,执行代码1
}else if(判断条件2){//--条件1不满足时,继续向下判断
满足条件2,执行代码2
}else if(判断条件3){//--条件2不满足时,继续向下判断
满足条件3,执行代码3
}else{
属于保底选项,以上都不满足,执行此选项
}
==============================================
switch--当你有一个值,需要和一系列值做比较执行某个操作时使用
switch(变量名){
case value1 : 操作1;break;
case value2 : 操作2;break;
case value3 : 操作3;break;
case value4 : 操作4;break;
case value5 : 操作5;break;
default : 保底选项;
}
TIPS:case后面值的类型必须与变量名类型一致,支持:byte short int char String
TIPS:一般写的时候需要加break,如果不加会发生穿透的现象
=================================================
循环结构
for-先判断,再执行
for(开始条件;循环条件;更改条件){
满足循环条件,执行的循环体
}
TIPS:开始条件只会在第一轮执行一次,后面轮中,不执行此条件
嵌套for循环
for(开始条件;循环条件;更改条件){//外层循环
for(开始条件;循环条件;更改条件){//内层循环
循环体;
}
}
外层循环执行一次,内层循环执行多次
外层循环控制的是轮数,内层循环控制的是在这一轮中执行的次数
外层循环控制的是行数,内层循环控制的是列数
============================================
while-先判断,再执行
while(判断条件){
符合判断条件后执行的循环体
}
TIPS:while(true)--死循环--必须设置出口!!!
do-while-先执行,再判断
do{
符合判断条件执行的循环体
}while(判断条件);
============================================
变量
成员变量
位置:类里方法外
注意:成员变量不需要手动初始化,会赋予对应类型的默认值
作用域:在整个类中都生效,类消失,成员变量才会消失
局部变量
位置:方法里/局部代码块中
注意:必须手动初始化/赋值
作用域:当方法/局部代码块执行完毕,局部变量也随之释放
tips:当成员变量与局部变量同名时,因为就近原则,会打印近的局部变量
============================================
方法
格式:方法的修饰符 返回值类型 方法名(参数列表){方法体}
TIPS:我们通过方法名+参数列表来确定具体调用哪个方法
TIPS:方法定义时,参数不是必须的,可以有,也可以没有
但是如果设置了参数,使用方法时就必须传参数
TIPS:方法的调用顺序:
先执行入口函数,如果遇到了方法的调用,先执行被调用的方法
然后回到main方法,继续执行main方法中的内容
=============================================================== day05复习老师没有讲
=============================================================== day06复习
1.面向过程:强调的是过程,凡事亲力亲为--是一种思想
面向对象:强调的是结果,从执行者变为了指挥者--是一种思想
2.Java是一门面向对象OOP的语言,万物皆对象
3.类:类型Type,是一类事物的抽象,是设计图纸/模板,用关键字class来描述
对象,是根据抽象设计来具体实现的事物,用关键字new来创建对象
注意:一个类可以创建出多个对象,这些对象各自都占有独立的内存空间
4.对象创建时的内存分析:
1)Cat c = new Cat();--创建了普通对象
1-在栈内存中开辟一块空间,存放引用类型的变量c,并把c压入栈底
2-在堆内存中开辟一块空间,用于存放Cat类的对象
3-完成对象的初始化,并根据属性类型赋予对应的默认值
4-给初始化完毕后的对象生成一个唯一的地址值
5-将对象唯一的地址值交给引用类型变量c来保存
6-后续可以根据变量c中保存的地址值找到对应的对象,进行相关调用
2)new Cat();--创建了匿名对象
1-在堆内存中开辟一块空间,用于存放Cat类的对象
2-完成对象的初始化,并根据属性类型赋予对应的默认值
3-给初始化完毕后的对象生成一个唯一的地址值
4-匿名对象没有名字,只能使用一次,所以调用:new Cat().play();
调用完毕,匿名对象就失去作用了,只适合只使用一次的场景
5.面向对象的三大特性:封装 继承 多态
==============================================
6.面向对象编程思路
1)抽象一类事物的特点,封装形成一个类组件class Dog{}
2)类里有特征/属性/成员变量/字段String name; 行为/功能/方法eat(){}
3)属性可以封装:使用private关键字封装,并提供对应的get&set方法
4)方法可以封装(不常用):使用private修饰,可以在本类的公共方法里调用这个私有方法
5)创建对象--Dog d = new Dog();
6) 可以通过对象使用类中的资源(属性&方法)
1-设置属性的值:d.name="旺财"; d.setName("旺财");
2-查看属性的值:打印输出:(d.name); (d.getName());
3-调用方法:d.eat();
注意:被private修饰的资源无法被外部直接访问,需要提供公共的操作方式
===============================================
IDEA的小贴士:
1.IDEA的结构是Project为根目录的,类似于eclipse的工作空间
2.我们可以在当前Project下创建多个Module模块(如day06)
3.IDEA无需保存,会自动保存
4.运行时直接点击方法左侧的运行绿色小三角即可运行
5.IDEA提供比较良好的提示功能
1)main会自动提示完成的主函数,回车补全即可
2)sout--输出语句
3)Ctrl+D -- 向下复制一行
6.工具不重要,重要的是编程的思维,大家可以选择一个自己喜欢的工具
熟练掌握这个工具的使用
7.IDEA调整字体/大小/颜色/背景。。。面向百度进行开发
=============================================================== day07复习
1.Java是一门面向对象的语言--围绕对象
2.先有类--一类事物的特征与功能抽象封装形成一个类组件
3.可以根据类模板创建本类的对象
4.new Cat();
5.每次创建对象时,都会触发对应的构造函数,创建几次,触发几次
6.默认存在无参构造,如果添加了含参构造,默认的无参构造会被覆盖,所以手动添加无参构造
7.构造方法也存在重载的现象:无参构造/含参构造/全参构造[创建对象+赋值]
注意:全参构造能给对象的属性赋值的前提是要有赋值的语句
=============================================
this : 代表的是本类
1)当本类的成员变量与局部变量同名时,需要使用this.变量名来指定成员变量
2)this还可以实现构造方法的调用
this();--调用无参构造
this(参数);--调用的是对应参数的含参构造
tips:this调用构造方法必须写在第一行,不能互相调用,会死循环
==============================================
代码块:一块代码 { }
构造代码块
位置:类里方法外
执行时机:创建对象时执行,优先于构造方法执行
作用:用于提取所有构造方法的共性内容
局部代码块
位置:方法里
执行时机:调用本局部代码所在的方法时,局部代码块才会执行
作用:用于限制变量的作用范围,范围越小越好
执行顺序:构造代码块->构造方法->对象创建成功->调用方法(局部代码块)
==============================================
继承
1.子类把父类的功能复制了一份,子类可以使用父类的所有非私有功能
2.Java只支持单继承,而且继承可以传递--一脉相传
3.子类可以有自己特有的功能,但是父类不能使用
==============================================
super:代表的是父类
1)当父类的成员变量与子类的变量同名的时候,可以使用super.变量指向父类的成员变量
=============================================================== day08复习
1.面向对象:强调的结果,Java是一门面向对象的语言
2.类:使用关键字class来定义,类是一类事物的抽象,把抽象出来的特点封装成一个类组件
对象:使用new关键字,触发对应参数的构造函数来创建对象
3.编程思路/元素:
属性:成员变量/字段
方法:
1)普通方法:用于完成类中的一些功能
2)构造方法:默认存在无参构造,创建对象时被动触发,用于创建对象
3)静态方法:属于静态资源,与所有静态资源的特性一致
代码块:
1)静态代码块:static{},类里方法外,属于静态资源,优先于对象加载,只加载一次
2)构造代码块:{},类里方法外,优先于构造方法执行,用于提取所有构造的共性功能
3)局部代码块:{},方法里,用于控制变量的作用范围,范围越小越好
4.面向对象的三大特性
1>封装:通过private关键字,对资源的访问进行控制,私有资源只能在本类中访问
私有资源,为了正常使用,需要对外提供公共的全局访问点:
1)属性的封装:提供公共的getXxx()与setXxx();
2)方法的封装:提供公共的方法去调用私有方法
2>继承:通过extends实现继承
继承相当于子类把父类的功能复制了一份,构造方法不能继承
子类可以使用父类的所有非私有资源
Java只支持单继承,一个子类只能有一个父类,继承具有传递性
继承是is a的关系,耦合性非常强
3>多态:
1.多态的前提:继承+重写
2.口诀1:父类引用 指向 子类对象 Animal a = new Dog();
口诀2:编译看左边 运行看右边
3.为了统一调用的标准,统一向父类看齐,父类定义的方法,子类才能使用
强调的是方法,方法的定义看父类,方法体看子类
4.多态对象把自己看做是父类类型,成员变量使用的是父类的,静态资源也是父类的
======================================================
this与super
this代表的是本类
this.变量名指向的是本类的成员变量;this(参数);调用本类的对应参数的构造方法
super代表的是父类
super.变量名指向的是父类的成员变量;super(参数);调用父类的对应参数的构造方法
注意事项:this与super所处的位置必须是第一行
构造方法间不可以互相调用,会死循环
===============================================
static 静态
静态资源属于类资源,随着类的加载而加载,优先于对象进行加载,只加载一次
静态资源可以通过类名直接调用(推荐)
静态资源可以被全局所有对象共享,值只有一份
==============================================
重载:在同一个类中,存在多个方法名相同但参数列表不同的方法
注意:我们通过方法名+参数列表确定调用哪个方法,所以重载看的是参数类型
重写:继承后,子类对父类的方法不满意时,可以重写父类方法的功能
满足OCP原则,在不修改父类代码的情况下,实现功能的拓展与更新
重写的规则:两同 两小 一大
两同:方法名与参数列表相同
一大:子类方法的修饰符 >= 父类方法的修饰符
两小:子类方法的返回值类型 <= 父类方法的返回值类型
子类方法抛出的异常类型 <= 父类方法的异常类型
public void eat(){ 重写后的功能 }
===============================================
=============================================================== day09复习
final
1)可以修饰类,被修饰的类是最终类,不可以被继承
2)可以修饰方法,被修饰的方法是该方法的最终实现,不可以被重写
3)可以修饰"量",被修饰"量"被称作常量,常量的值不可以被修改
注意事项:定义常量时必须赋值
==============================================
异常:
1.组成部分:异常类型 异常信息 报错行号
2.继承结构:
Throwable--异常的顶级父类
--Error--系统异常,目前我们不能解决
--Exception--我们可以通过编程解决的问题
--编译异常--还未运行程序--比如:少写了一个分号
--RuntimeException--运行程序时才报错--比如程序语法没有问题,但运行时出错
--数组下标越界异常 输入不匹配异常 算术异常...
3.异常的解决方案:
方案一:捕获处理--自己解决
try{
可能会发生异常的代码
}catch(异常类型1 异常名){
匹配到小括号的异常类型1时,提供的解决方案1
}catch(异常类型2 异常名){
匹配到小括号的异常类型2时,提供的解决方案2
}catch(异常类型3 异常名){
匹配到小括号的异常类型3时,提供的[通用的]解决方案
}
注意:
1>catch可以嵌套,具体是否嵌套取决于业务,如果不嵌套,提供的都是通用解决方案
2>通用解决方案中,异常类型一般为Exception,也就是把所有的子异常看做父类型
方案二:向上抛出--别人解决/稍后解决/不想把业务与异常解决方案写在同一个方法里
格式:在方法定义的两个括号之间 throws 异常类型1,异常类型2
注意事项:
1>如果一个方法抛出了异常,那么谁来调用这个方法,谁就需要"解决"这个异常
2>我们一定要在main()调用之前解决异常,不能把问题抛给main()
因为调用main()是JVM,已经没人解决,该报错还报错
==============================================
抽象类
1.被abstract修饰的方法是抽象方法,抽象方法没有方法体
2.被abstract修饰的类是抽象类,抽象类中的方法没有限制
3.如果一个类中包含了一个抽象方法,那这个类必须被声明成一个抽象类
4.如果一个类继承了一个抽象父类,有两种方案:
1)作为抽象子类,躺平,不实现/实现部分抽象父类的抽象方法
2)作为普通子类,还债,要全部实现抽象父类中的抽象方法
5.抽象类不可以被实例化(创建对象)
6.抽象类有构造函数,但是是为了子类创建对象时调用super()
7.抽象类中的成员测试
1)抽象类中既可以有成员变量,也可以有成员常量
2)抽象类中既可以全是抽象方法,也可以全是普通方法,还可以混杂
3)如果一个普通类,全是普通方法,但改成abstract修饰
那他一定是不想让外界创建他的对象
=============================================================== day10复习
BASIC OOP API
==============================================
1.面向过程 面向对象
2.类 对象 类与对象的关系
3.创建对象的过程(参见对象创建图) 普通对象与匿名对象
4.类中的一些元素:
1)属性--成员变量
2)方法--构造方法/普通方法
3)代码块--静态代码块/构造代码块/局部代码块
5.面向对象的三大特性
封装:1:封装类组件 2.使用private封装属性与方法
继承:类是单继承的,继承后子类复制父类的所有功能,可以使用所有非私有资源
多态:把子类类型都看做父类型,提供统一解决方案
6.this与super
7.重载与重写
8.异常
9.抽象类与接口
10.static:优先于对象加载,可以通过类名直接调用 全局共享
11.final:不可变
==============================================
接口
接口interface,接口中都是抽象方法,接口中都是静态常量,可以简写
接口不能实例化,也没有构造函数
接口主要用于制定规则
接口可以多继承接口
一个类也可以实现多个接口--"类的多实现" class InterImpl implements I1,I2{}
******************************************************************************
类与类的关系:继承,单继承,如果没有明确指定父类,默认继承顶级父类Object
接口与接口的关系:继承,多继承常用于使用某个接口汇总多个父接口的功能
类与接口的关系:类实现接口,多实现:
1)不实现/实现部分--抽象实现类/抽象子类--不可创建对象
2)全部实现--普通实现类--可以创建对象--常用方式
*****************************************************************************
接口与抽象类的区别
1.抽象类是用abstract修饰的类,而接口不是类,定义接口的关键字是interface
2.抽象类中的方法不做限制,而接口中的方法都是抽象方法,默认拼接public abstract
3.抽象类与接口均不可创建对象,抽象类中有构造方法,而接口中没有构造方法
4.抽象是重构的结果,接口是设计的结果
=================================================
=============================================================== day11复习
API
1.别人制定的规则,我们不得不按照要求来协同开发,如:银行的API,地图的API...
2.一个项目 同事的协同开发
3.Java自带的API,Object String ...
==============================================
Object 顶级父类,所有类都把它当作超类
hashCode()--返回对象对应的哈希码值,不同对象的哈希码值不同
toString()--打印的是对象的地址值,添加默认的重写后,打印的是对象的属性值
equals()--默认使用==比较,比较的是地址值,若地址值不同,返回false
--添加默认的重写后,比较的是类型+属性+属性值
注意:重写以后是什么规则,取决于怎么重写的,后期要测试+翻阅源码
==============================================
String是字符串类型,数据使用“”包裹,底层维护的结构是char[]
String的创建方式:
String s = "abc";--堆中常量池,效率高
String ss = new String(char[] value);--效率低
String API请自行练习
==============================================
StringBuilder 与 StringBuffer
append()拼接效率比+拼接高
=============================================================== day12复习
1. API--应用程序接口--别人写好的功能/制定的规则
===============================================
2. Object 顶级父类,所有类都把Object作为超类
hashCode()--生成对象对应的哈希码值,不同对象的哈希码值不同
toString()--默认实现--打印的是对象的地址值
equals()--默认实现--比较使用的是==比较,比较的是地址值
注意:重写后的效果,取决于是怎么重写的,比如:
我们自定义了一个Student类,重写toString(),可以打印类名+属性与属性的值
我们在使用String的时候,打印的是串的具体内容,原因是String也重写toString()
equlas()比如Student类重写后比较的是属性值,String比较的是串的具体内容
==============================================
3. String 字符串类型 ,使用“”包裹数据,底层维护的结构是char[]
创建方式:
1)String s = "abc"; -- 效率高,第二次使用时不再创建,去堆中常量池去取数据
2)char[] value = {'a','b','c'}; String s = new String(value);--每次新建
常用API:
hashCode()--返回哈希码值
toString()--打印串本身
equals()--比较两个串的具体内容
length()--获取字符串长度
charAt()--获取指定下标处的字符/元素/子串
toUpperCase()--变大写
toLowerCase()--变小写
startsWith()--判断是否以指定元素开头
endsWith()--判断是否以指定元素结尾
indexOf()--判断元素首次出现的索引/下标值
lastIndexOf()--判断元素最后一次出现的索引/下标值
concat()--字符串的拼接,注意不会改变原串
split()--根据指定的规则拆分字符串
trim()--去除首尾的空格
substring()--截取子串,这个方法是重载的方法,可以截取一段或者中间的一部分
valueOf()--把参数类型转为String类型的数据,是静态方法
getBytes()--把参数转为byte[]
================================================
4.字符串的拼接
1)使用+进行拼接,效率非常低
2)StringBuffer/StringBuilder的append()方法进行拼接
==============================================
5. 正则表达式
其实我们制定的一些规则详细规则请见 正则速查表
String regex = "规则";--制定规则
数据.matches(regex);--判断是否符合规则
==============================================
6. 包装类--对基本类型进行包装的类,而且提供了非常丰富的功能
1)基本类型只存值,只能存值,没有别的功能!!!
2)基本类型与包装类型的关系Integer-int Character-char
3) 创建方式:
Integer i1 = new Integer(5);
Integer i2 = Integer.valueOf(5);--高效,但注意范围:-128~127
===============================================
7.自动装箱与自动拆箱
方向:装箱:基本->包装 Integer i = 5;--自动装箱
拆箱:包装->基本 int i2 = i4; --i4是包装类型--自动拆箱
===============================================
8.BigDecimal--浮点数运算不精确解决方案
BigDecimal bd = new BigDecimal(a+"");--把数据交给BigDecimal封装
注意:使用的构造函数必须是String类型的,不能是double,有坑!!
使用对应的加减乘除方法运算即可
注意:除法有可能会出现除不尽的现象,所以需要指定保留位数与舍入规则
===============================================
9. 流 IO
1) 流与管道是抽象处理方便理解的概念,并不是真实存在的
2) 流是有方向的,什么流就做什么事
in/输入流/读取流,方向:磁盘到内存,也就是"数据进到程序中"
out/输出流/写出流,方向:内存到磁盘,也就是"程序生成的数据存储到文件中"
3)流的分类
根据方向:输入流 输出流
根据数据类型:字节流 字符流
组合:字节输入流 字节输出流 字符输入流 字符输出流
4)File--文件--封装的是路径:文件路径/文件夹路径/不存在的路径
注意:路径中不能出现单个\,是转义字符,必须成对出现
File相关的API--详见笔记中速查表与API手册
=============================================================== day13复习
IO流
===================================================
Stream 流
1.流是有方向的,而且是单方向的,什么流就做什么事
2.流只能从头到尾的顺序的读写一次
3.流主要用于内存与磁盘之间的读写操作,由于内存(快)与磁盘(慢)的运行效率差别较大,
所以IO操作会拉慢整体效率,并且IO特别容易发生异常
4.流的方向一定要从程序的角度来考虑,程序读取数据是输入,程序写出数据是输出
===================================================
File 文件类
1.主要由于OOP的原因,我们需要把文件/文件夹/不存在的路径封装成file对象
2.创建好对象后,我们就可以使用File类中的方法
以及把file对象作为参数,参与到流操作当中
3.File相关的API自行复习
===================================================
IO流的继承结构
1.根据流传输方向的不同,可以分为:输入流 输出流
2.根据操作数据单位的不同,可以分为:字节流 字符流
3.抽象父类都是流对应层次结构中的父级,不可以创建对象,一般要学习它的公共方法
4.子类要学习的是如何创建对象(构造函数)
5.流名字中包含前缀为File的,指:可以直接插在文件上,对文件做操作的流
流名字中包含前缀为Buffered的,指:可以插在其他流上,给其他流做加强的缓冲/高效流
字节输入流 InputStream【抽象父类】
FileInputStream【普通子类】操作文件的
BufferedInputStream【普通子类】缓冲/高效
字节输出流 OutputStream【抽象父类】
FileOutputStream【普通子类】
BufferedOutputStream【普通子类】
字符输入流 Reader【抽象父类】
FileReader【普通子类】
BufferedReader【普通子类】
字符输出流 Writer【抽象父类】
FileWriter【普通子类】
BufferedWriter【普通子类】
=====================================================
IO流的入门案例
package cn.tedu.review;
import java.io.*;
/**本类用于复习IO操作*/
public class ReviewIO {
public static void main(String[] args) throws Exception {
//1.复习流对象的创建
//1.1普通字节输入流
InputStream in = new FileInputStream(new File(""));
InputStream in2 = new FileInputStream("");
//1.2高效字节输入流
InputStream in3 = new BufferedInputStream(new FileInputStream(new File("")));
InputStream in4 = new BufferedInputStream(new FileInputStream(""));
//1.3普通字符输入流
Reader in5 = new FileReader(new File(""));
Reader in6 = new FileReader("");
//1.4高效字符输入流
Reader in7 = new BufferedReader(new FileReader(new File("")));
Reader in8 = new BufferedReader(new FileReader(""));
//1.5普通字节流的输出
OutputStream out1 = new FileOutputStream(new File(""));
OutputStream out2 = new FileOutputStream("");
//1.6高效字节流的输出
OutputStream out3 = new BufferedOutputStream(new FileOutputStream(new File("")));
OutputStream out4 = new BufferedOutputStream(new FileOutputStream(""));
//1.7普通字符流的输出
Writer out5 = new FileWriter(new File(""));
Writer out6 = new FileWriter("");
//1.8高效字符流的输出
Writer out7 = new BufferedWriter(
new FileWriter(new File("")));
Writer out8 = new BufferedWriter(
new FileWriter(""));
//2.读取的相关操作
int b;
while((b = in.read())!= -1){
System.out.println(b);
}
//3.写出的相关操作
out1.write(97);
out1.flush();
//4.关流需要写在finally{}中,而且需要继续try-catch
}
}
=============================================================== day14复习
1.流分类的两个维度:
操作的单位:字节流&字符流
方向:输入流&输出流
2.IO的继承结构
字节输入流
InputStream--抽象父级,不可实例化
FileInputStream--文件字节输入流--构造参数:File/路径
BufferedInputStream--缓冲字节输入流--构造参数:InputStream-FIS
ObjectInputStream--反序列化流--构造参数:InputStream--FIS
字节输出流
OutputStream--抽象父级,不可实例化
FileOutputStream--文件字节输出流--构造参数:File/路径
BufferedOutputStream--缓冲字节输出流--构造参数:OutputStream-FOS
ObjectOutputStream--序列化流--构造参数:OutputStream-FOS
字符输入流
Reader--抽象父级,不可实例化
FileReader--文件字符输入流--构造参数:File/路径
BufferedReader--高效字符输入流--构造参数:Reader--FR
InputStreamReader--指定输入流的编码--构造参数:(字节输入流,指定编码)
字符输出流
Writer--抽象父级,不可实例化
FileWriter--文件字符输出流--构造参数:File/路径
BufferedWriter--高效字符输出流--构造参数:Writer-FW
OutputStreamWriter--指定输出流的编码--构造参数:(字节输出流,指定编码)
注意:编辑与打开时需要保证编码的一致,不一致就乱码
如果想要解决流乱码的问题,可以使用编码转换流给流进行编码的设置
================================================
3.序列化与反序列化--为了保证对象的持久存储与传输
序列化:程序中的对象->文件中
反序列化:之前序列化保存在文件中的数据->回复成程序中的对象
注意:要序列化对象所在的类必须实现可序列化接口
反序列化流中的UID要与序列化时的UID保持一致,不一致就报错
==============================================
=============================================================== day15复习
集合
1.集合的继承结构
Collection--接口
--List--接口--序列,元素是有下标有序的,允许存放重复的数据
--ArrayList--底层结构是数组,查快快,增删慢,适合查询场景比较多的情况
--LinkedList--底层结构是链表,查询慢,增删快,适合增删场景比较多的情况
--Set--接口
Map--接口
2.集合的学习方法:学习父级的公共方法,学习子类如何创建对象
注意:我们所说的慢与快是相对而言的,建立在数据量比较大的情况
链表结构针对查询而言,首尾操作比较快,中间操作比较慢
=============================================
3.泛型的作用:为了在编译时就检查数据类型,限制集合中的元素类型
还可以帮我们写出更加通用的代码,比如泛型方法
泛型可以帮我们把报错的时机提前,不会在运行时才报错
注意:如果集合不加泛型,不会报错的,但是集合的元素没有任何限制
注意:使用泛型方法时,有两处位置需要添加泛型,这是语法
注意:<Type> -- Type必须是引用类型, 不可以基本类型
注意:泛型是一颗“语法糖”,泛型只在编译生效,字节码文件中没有泛型
===============================================
4.Collection方法总结
boolean add(E e) 向集合中添加指定的元素
boolean addAll(Collection c) 向集合中添加参数集合中的所有元素
void clear() 清空集合
boolean contains(Object o) 判断集合是否包含指定元素
boolean containsAll(Collection c) 判断集合是否包含参数集合中的所有元素
boolean equals(Object o) 比较此 collection 与指定对象是否相等
int hashCode() 返回此 collection 的哈希码值
boolean isEmpty() 判断集合是否为空,为空返回true
Iterator<E> iterator() 返回用来迭代此集合的迭代器
boolean remove(Object o) 移除集合中的指定元素
boolean removeAll(Collection c) 移除此集合中属于参数集合的所有元素
boolean retainAll(Collection c) 仅保留此集合中属于两个集合交集的公共元素
int size() 返回此集合中的元素的个数
Object[] toArray() 将集合转为数组
===============================================
5.List方法总结
5.1 List自己的方法:
void add(int index, E element) 在指定位置处向列表添加指定元素
boolean addAll(int index, Collection c) 在指定位置处向列表添加参数列表中的所有元素、
E get(int index) 返回列表中指定位置处的元素
int indexOf(Object o) 返回本列表中指定元素第一次出现的索引
int lastIndexOf(Object o) 返回本列表中指定元素最后一次出现的索引
ListIterator<E> listIterator() 返回本列表独有的迭代器
E remove(int index) 移除列表中指定位置上的元素
E set(int index, E element) 用指定元素替换列表中指定位置的元素
List<E> subList(int fromIndex, int toIndex) 指定开始与结束索引,截取子列表【含头不含尾】
5.2继承自Collection的方法
boolean add(E e) 向列表的末尾追加指定元素【继承自Collection】
boolean addAll(Collection c) 向列表的末尾追加参数列表中的所有元素【继承自Collection】
void clear() 移除本列表中的所有元素【继承自Collection】
boolean contains(Object o) 判断本列表中是否包含指定元素【继承自Collection】
boolean containsAll(Collection c) 判断本列表是否包含参数列表的所有元素【继承自Collection】
boolean equals(Object o) 比较指定的对象与列表是否相等【继承自Collection】
int hashCode() 返回列表的哈希码值【继承自Collection】
boolean isEmpty() 判断本列表是否为空
Iterator<E> iterator() 返回迭代本列表的迭代器
boolean remove(Object o) 移除本列表中指定的元素
boolean removeAll(Collection c) 移除本列表中属于参数列表中的所有元素
boolean retainAll(Collection c) 仅保留本列表中与参数列表的公共元素,取交集
int size() 返回列表中的元素的个数
Object[] toArray() 将列表转为数组Object[]
=============================================================== day16复习
集合
1.继承关系
Collection--集合层次的根接口,无法实例化
List--有序,有下标,可重复--子接口,无法实例化
--ArrayList--有下标,结构是数组,连续的内存空间,增删慢
--LinkedList--有下标,结构是链表,不连续的内存空间,查询慢
Set--无序,没有下标,不重复--子接口,无法实例化
--HashSet--常用来给数据去重,但是注意自定义类型需要重写hashCode()&equals()
Map--无序,是键与值的映射关系,而且键不允许重复,结构:数组+链表/红黑树
--Map不是Collection的子接口,无法实例化
--HashMap--数据类型Map.Entry<KEY,VALUE>
2.HashMap存储数据过程
初始容量:16--Entry[]数组的长度
加载因子:0.75f --指数组中的数据存到多满就扩容
扩容方式:约等于2倍进行扩容,注意会发生rehash操作【因为扩容后数组长度改变】
过程:1.我们会拿着当前Entry的Key值做运算,运算约等于hash(Key)%n
2.得到的余数会决定当前Entry存到Entry[]的哪个位置,余数就是数组的下标
如果新来的Entry得到的运算结果
1)余数对应数组位置没有数据,直接存入数组对应下标处
2)余数对应的数组位置已经有Entry了,就会形成链表的结构
3.如果链表的长度>8时,会转成红黑树,<6时会恢复成链表
4.我们的数组是否扩容,取决于数组中数据的存入情况,与链表长度无关
只与数组长度*加载因子的数据有关
3.相关API的总结
集合相关的方法:一查 二试
1)Collection系列中,常用的都是Collection定义了方法
2)List相关的操作大部分与下标有关
3)LinkedList提供了很多首尾操作相关的API
4) Map独有的方法与键和值有关
4.集合的迭代
1)常用迭代器进行迭代
步骤:获取迭代器-判断是否有元素可迭代-获取迭代的元素
2)List有自己独有的迭代器,ListIterator,可以逆序迭代
3)Map没有自己的迭代器,所以需要通过keySet()/EntrySet()转成Set再迭代
注意:keySet()转化的Set集合中存的是Map的key
entrySet()转化的Set集合中存的是一个个的键值对Map.Entry<K,V>
=============================================================== day17复习
进程与线程
1.进程就是正在运行的程序
2.一个进程可以包含一个(单线程程序)或者多个线程
3.线程是OS可以进行运算调度的最小单位
4.我们目前无法控制线程如何被调度,具体时间片分配和调度取决于OS的算法
5.线程的执行具有随机性
6.线程的几种状态
新建状态:new Thread(target目标业务类对象)/ new 自定义线程类对象()
就绪状态:需要调用start()方法才会把线程对象加入到就绪队列当中
阻塞状态:休眠10ms/锁阻塞
执行状态:线程被OS选中,分配时间片正常运行程序,时间片用完挂起
加入到就绪队列当中,等待OS的下一次选中
结束状态:归还PCB,对应的空间清除
7.多线程实现方案:
1)extends Thread
--重写run(),run()当中的是业务
--可以创建多个自定义多线程类的对象,创建几个,就有几个线程干活
2)implements Runnable
--实现run(),run()当中的是业务
--创建一个自定义多线程类的对象,作为目标业务对象target
--将这一个target对象传入多个Thread类的构造中Thread t = new Thread(target);
--执行几次,就创建几个线程对象干活
3)线程池
--Executors--创建线程池对象的工具
-- .newFixedThreadPool(指定线程数)
--ExecutorService--通过工具创建出来的池对象类型
--pool.execute(目标业务对象target)
8.数据安全问题解决方案
1)导致数据安全隐患的原因:多线程程序+有共享数据+多条语句操作共享数据
2)解决方案:排队-加锁-同步代码块
格式:synchronized(唯一的锁对象){ 需要同步的代码块}
1>如果是实现接口的方式:
在可能出现问题的代码上加synchronized同步代码块
锁对象:不限制类型,唯一就行,一般是Object o = new Object();
2>如果是继承的方式:
在可能出现问题的代码上加synchronized同步代码块
由于实现方式是创建多个自定义多线程类的对象
所以,锁对象一般是 类名.class ,目的就是为了锁的唯一
9.synchronized表示同步,可以用来修饰方法,被它修饰的方法称作同步方法
=============================================================== day18复习
设计模式--优秀的编码经验--23种
单例设计模式--只有一个实例--根据业务进行选择
实现方案:
1)饿汉式--不管用户是否要获取对象,都会先创建一个对象出来
1>构造函数私有化
2>创建对象,并把对象私有化
3>提供公共的全局访问点-公共get()供外界获取本类的唯一对象
2)懒汉式--先不创建对象,等用户获取时才创建--延迟加载
1>构造函数私有化
2>创建一个对象类型的成员变量,默认值为null--还未创建对象
3>提供公共的全局访问点-公共get()供外界获取本类的唯一对象
需要在本方法里加判断,判断是否是第一次调用本方法
如果是第一次调用,对象未创建,创建对象,将对象地址交给引用类型变量保存
如果不是第一次调用,对象已创建,直接返回对象即可
===================================================
注解:标记,为了增强程序,简化编码步骤,增强可读性
JDK自带注解:5个,@Override
元注解:用来注解其他注解的注解,5个
1>@Target--标记注解可以加在什么位置,可以多选
2>@Retention--标记注解的声明周期,3选1 SOURCE/CLASS/RUNTIME
自定义注解:
1.@interface来定义,使用注解时,“@注解名”来使用
2.注解还可以定义属性,int age();
3.如果定义了属性,使用时必须给属性赋值:
默认值int age() default 0; / 使用时赋值@Test( age = 10)
4.还可以给注解定义特殊属性value,使用时可以直接赋值@Test("apple")
注意:特殊属性赋予默认值时语法不能简写
注意:如果两个属性均需赋值,格式:@Test(age= 10 , value="apple")
================================================
单元测试方法
好处:只涉及到一个方法,使用比较灵活,比较方便
格式:@Test+public+void+没有参数
注意:使用时需要导包
================================================
反射
1.前提:我们所说的是指别人/外部的资源
2.基石:字节码对象--保存了一个类的所有结构&重要信息
3.获取字节码对象的方式:
Class.forName("类的全路径名-包名.类名")
对象.getClass()
类名.class