一、格式规范

手动编写一个java后缀名的文件
打开控制台 win+r
通过指令找到源文件存储地址
cd 文件名称 打开某个文件
cd.. 跳回上一级文件
cd/ 回到根目录
dir 展示当前目录下的所有文件
cls 清屏
通过javac Test.java进行编译操作会产生一个.class文件
通过java Test执行当前文件
关键字keywords
public static 。。
标识符
起名规范:
类名规范:首字母大写 后面每个单词首字母大写StudentsAge
方法名规范:首字母小写后面每个单词首字母大写showAge()
变量名:首字母小写

1、程序:

为了解决问题实现一定的目的编写的一系列指令按照一定顺序排序执行
数据的存储:0 1 1bit 比特位
二进制 十进制

常用存储单位:
1字节B=8bit
1KB=1024B
1MB=1024KB

常量 程序中不变化的量就是常量
字符串常量
小数常量
整数常量
字符常量
布尔常量

变量 程序中会变化的量
分类 基本数据类型:
整型 :字节(byte) 短整型(short) 整型(int) 长整型(long)
浮点型:单精度浮点型(float) 双精度浮点型(double)
字符型(char)
布尔型(boolean)
引用数据类型:类 数组。。

  1. 声明:定义类型 标识符;
  2. 赋值:标识符 = ;
  3. 边声明边赋值: 定义类型 标识符 = 值;
  1. 数据溢出
  2. //数据溢出
  3. int max = 2147483647;
  4. int min = -2147483648;
  5. System.out.println(max+1);//最大值+1-》最小值 最大值+2-》次小值
  6. System.out.println(min-1);//最小值-1-》最大值
  7. //自动类型转换
  8. //方案二:
  9. System.out.println(max+1L);
  10. System.out.println(min-1L);
  11. //方案一:
  12. long max1 = 2147483647;
  13. long min1 = -2147483648;
  14. System.out.println(max1+1);
  15. System.out.println(min1-1);
  • 数值类型 byte short int long
  • 自动类型转换:
    范围小的数据类型转换为范围大的数据类型
    运算过程中 结果会保存为范围比较大的类型
    double num = 10;
  • 强制类型转换:
    范围大的数据类型转换为范围小的数据类型
    int num = (int)9.8;
  • 程序中 整数值默认int类型 小数值默认double类型
    //对char类型数据操作
    char c = ‘A’;
    System.out.println((int)c);
  • 运算符
    赋值运算符 = += -=
    算数运算符 + - * / % ++ —
    比较运算符 > < >= <= == != 返回真或者假
    三元运算符 =(放返回真假的表达式或者变量)?值1 :值2
    逻辑运算符 && || ! 最终返回真假 一般和包含比较运算符的表达式一起使用
    短路与:使用&&时 第一个条件为假 后续不再执行
    短路或:使用||时 第一个条件为真 后续不再执行
    使用&、| 会执行完所有的判断
    !>算术运算符>比较运算符>&&>||

byte b1=3,b2=4,b3;
b3=3+4;//常量优化机制 自动识别运行
b3=b1+b2;//会转向int类型,编译错误

二、程序逻辑

if选择语句的嵌套

1.嵌套与被嵌套的if模块都是可以单独执行的完整语句
2.一定是嵌套在一对大括号中
3.只执行一次以后就不再执行

switch(判断条件){
case 值1:
执行语句;
break;
case值2:
break;
default:
其余情况执行的代码
}
可判断类型/;byte short int char string enum(枚举);
case 后跟的值 必须是常量 且各不相同
使用break跳出switch 或者执行default
如果几个值共享一个结果,代码如下:

if与switch使用场景的区别
if更多拿来做区间判断,也可做等值判断
switch拿来做等值判断 一些特定区间判断可用

int num=(int)(Math.random()*10);产生1到10的随机数
Random random=new Random();
int num=random.nextInt(10);产生1到10的随机数
hasNextInt();验证数据是否为int类型

while(先判断){
如果条件为真则执行;
}
执行完后会重新返回判断条件,直到判断条件为假时则退出循环向下执行。

Debug模式

1.预估错误代码处,提前左侧双击打出判断点
2.点击臭虫,进入debug模式
3.F5:跳入内部 F6:单步执行注意查看右侧界面观察变量变化情况
颜色加深行是即将执行的代码

while循环特点:

1.观察题目中是否有重复执行的操作(循环体)
2.找出结束条件 编写判断标准 编写变量变化情况 保证循环能正常退出
3.先判断再执行

先执行再判断
do{
循环体
变量变化情况 迭代情况
}while(判断);
至少执行一次;

break;
结束当前循环,执行下面代码
switch当中必须有
单独的其他选择语句 不能使用
嵌套在循环中的选择内可使用

continue:
结束本次循环 执行下一次循环
必须使用在循环中的选择模块内
使用时要求当前选择后还有待执行的循环语句

for循环

for(参数初始化;条件判断;更新循环变量){
循环体;
}

鸡兔同笼,共有30个头,88只脚,求笼中鸡兔各有几只;

方法(method function)
概念:在很多语言中 也叫做“函数”指的是一段可以被重复调用的代码块,他是一种实现代码重用的
技术手段;就是将一个功能抽离出来,把代码单独定义在一对大括号中,形成一个可单独调用使用的
方法。
语法:
例如:public static void mian(String[] args){ 方法体 }
方法的修饰符 在现阶段 我们定义的方法用public static 代表公开静态
方法的返回值 没有返回值的方法 要写void
有返回值的方法 要写返回值的类型 public static int add(){ return int类型的值}
如果有返回值 方法体的最后一定要通过return 返回同类型的值

方法名 命名规范 小驼峰命名法:首字母小写 第二个单词首字母大写 showAge_1();
方法的参数
有参方法 比喻成榨汁机
参数:会影响方法执行结果的一些因素 都以变量的形式放在方法的参数位
无参方法 方法名后是一对空的小括号、
方法体
注意事项:
编写的方法 不能嵌套在另一个的方法内部,只可以通过方法名互相调用方法
在方法名前一定要根据返回值类型 定义好类型
方法体最后一定要通过return 返回同类型的变量、值
return加强版break 遇到return结束当前模块、同时返回一个值
调用:
使用同类型变量去接收方法
可以直接使用输出语句输出方法
根据返回值的特性直接参与逻辑运算

编写一个带参方法:
参数列表项:
有多个参数使用,隔开
每个参数应定义出类型 而且各个参数的类型可以不同
参数列表有顺序性
形参,实参
实参出现在调用有参方法时 应该在调用前就准备好 在调用方法时应根据形参的类型及顺序
依次补入实参 不需要标明类型
实参名称和形参名称不需要一致

方法的重载
定义:在同一个类中,方法名相同 但是参数不同
方法的重载是实现重用的一种技术形式
参数数量不同
参数类型不同
参数顺序不同
跟返回值类型或者是否有返回值无关
注意事项:
重载与参数类型无关
为了保证标准形式 一般都建议统一返回类型

注意事项:
如果参数为基本数据类型 形参与实参只是一个值的传递 不会互相影响
如果参数为引用数据类型 传递的是内存地址,形参和实参指向的是同一个内存地址 就会导致改变
其一 另一个参数也会变化
为了防止引用传递导致实参的变化 创建一个新的数组接收实参

方法的递归
注意事项:
实际开发中 尽量少使用,如果没有执行停止条件栈的溢出
必须有结束条件,且最终必须执行,每次运行注意改变参数的值

面向对象的特点:
以对象作为编码的核心,不再以功能,对象来自于类

System.out.println(Arrays.toString(nums));
创建类
class关键字
描述类所具备的特性和方法
以变量形式描述特性称之为成员变量不用赋值
以方法来表述功能

优势:
更符合人们的思考习惯(类和对象)
面向过程体现执行者,面向对象体现指挥者
面向对象可将复杂问题简单化

类:具备相同属性和方法的一类对象的集合
对象:具体存在的真实事物
关系:类是对象的抽象化 对象是类的实例化

成员变量&局部变量
定义的位置不同
成员变量在类中,局部变量在方法中或者{}中
初始化不同
成员变量会有默认的初始值,局部变量必须赋值才能使用
在内存当中的位置不同
成员变量储存在内存的对象中
局部变量存储在内存的方法中
生命周期
成员变量是随着对象的创建出现在堆中,随着对象的消失而从堆中消失;
局部变量是随着方法的执行出现在栈中,随着方法的出栈而消失。
可取类型 基本数据类型 和引用数据类型,布尔默认为false;
byte short int long 0;
double float 0.0;
Boolean flase;
char ‘\u0000’;
引用数据类型 null;

从编译成功开始
类文件进入方法区(Method Area)成员变量 成员方法
执行,必然先执行main()执行任何方法都要进栈(压栈)
main()进栈
new自定义类型的对象,只要new就会在堆内存中开辟空间保存当前对象的信息;
会把堆内存地址给回当前对象
对象保存的是对象在堆内存中的地址
对象,成员变量=值 先根据对象找到堆内存覆盖修改成员变量
对象,方法 先根据对象 找到堆内存,在根据堆内存中保存的方法所在方法区中的
地址,最终得到方法体(在方法区中)
执行完成后 方法出栈(弹栈)

引用数据类型的扩充
在之前了解的引用数据类型之上 增加了自定义类型
自定义类型一样可以作为方法的参数 方法的返回值使用

三、面向对象三大特性

封装:

是面向对象三大特性之一
优点:
提升开发效率,提高代码扩展性能 提高代码复用性
隐藏了实现细节 提升了代码的安全性
表现:
方法就是一个基本的封装体
类也是一个封装体

使用:对于实体类的成员变量进行封装操作
将访问修饰符改为private(私有的)
Alt+shift+s->getter setter
getxx()获取值的方法
setxx()赋值的方法
使用时使用 对象.getxxx() 对象.setxxx();
使用重写toString();

this关键字

作用:调用当前类中的属性 区分本类中的成员变量和接收形参
在哪个类中使用就代表当前类对象
调用普通方法可以省略不写
构造方法中调用其他构造方法,直接使用this(可有可无)但是一定要放在构造方法的第一行
多个构造方法互相调用时 一定要保证有一个构造方法没有去调用其他构造方法,作为程序的出口

编码思想
根据业务需求判断研究的对象-》抽离出类(实体类)
根据业务需求(实现的功能)判断需要哪些方法 设计方法
方法名 需不需要返回值 返回值类型 需不需要参数 参数类型
实现方法
测试类调用

Stu[0]=new Students();每一个元素都是引用数据类型(在堆内存以地址形式保存),一定要单独开辟空间

构造方法

执行时机:new对象的时候执行
语法:
public 类名(可有可无){
}
概念:当一个对象被创建的时候,构造方法用来初始化对象,给对象的成员变量赋初始值
注意:无论是否自定义构造方法,所有类都有自己默认的无参构造方法,一旦我们自定义了构造方法,
这个由java提供的默认构造方法就失效了。构造方法主要作用是简化赋初始值的过程
一个类中至少存在一个构造方法;
构造方法可以重载,按照参数从少到多的顺序编辑构造方法
在实体中首先定义成员变量 再定义构造方法 最后定义普通方法

  1. 构造方法和普通方法的区别:
  2. 普通方法可以有返回值 构造方法无返回值
  3. 普通方法名按照标识符规范取名 构造方法方法名要和类名相同
  4. 普通方法在方法被调用时执行 构造方法在new对象的时候执行

匿名对象

概念:没有声明对象名,没有指向引用,直接new开辟堆空间的对象称为匿名对象。
特点:因为没有再栈内存的引用,所以该对象再使用一次以后就成为了垃圾空间。
new Student().方法名或者属性;

引用数据类型作为构造方法的参数

标准的实体类 JavaBean
概念:java语言编写类的一种标准规范
类的名称一定要有意义 可以描述一类事务
类中的所有属性都必须使用private,给出get和set方法
类中不允许出现任何输出语句,所有的内容获取都通过返回值
可以提供一个获取对象详细信息的方法String toString();

static 关键字 静态

可以用于全局属性和全局方法的声明 可以避免对象实例化的限制(每个普通属性都必须使用对象调用
在不同对象的堆内存中 有不同的值 使用static修饰的属性 所有对象共享)这样的属性是保存在全局数据区中
特点:
由static修饰的属性所有对象都可访问;可以通过类名直接访问。
可以通过任何对象包括类直接访问
注意事项:
static修饰的方法内不能有this关键字
由static修饰的方法不能调用非static修饰的属性和方法
非static修饰的方法可以调用static修饰的属性和方法
static修饰的方法可以调用static修饰的属性和方法

代码块

概念:在程序之中使用{}定义起来的一段程序
分类:
普通代码块:可解决重复变量的问题 代码块内部的变量属于局部变量
构造代码块:在实体类中使用 且执行顺序优于构造方法 每次实例都会执行一次
静态代码块:在非主类中使用 优先于构造代码块,多次实例化只会执行一次

  1. 利用静态代码块可以实现公共的初始化操作
  2. static{
  3. }
  4. 在主类中使用则优先于main()执行(有趣的bug jdk1.7之前,可以用静态代码块替代mian())
  5. 执行顺序:
  6. 主类中的静态代码块 一定先执行 但是必须存在main();
  7. 实体类中的静态代码块 一定在创建对象的时候执行 只执行一次

java三大特性之二——继承

概念:描述类之间的所属关系 被抽取的类称之为子类 生成的新类称之为父类 使之子类具备父类相同
的属性和方法
特点:用来判定是否是继承关系 是否满足 is-a的关系
在创建子类对象时 堆内存中会先开辟父类的内存空间再开辟子类的内存空间 并且父类内存空间
包含在子类内存空间中(子类内存空间中还会有属于自己的特有属性和方法)
一个类可以有无数多个子类 但是只有一个父类
如果希望继承多个类 方案一:可以向上继续继承 方案二:可以使用接口(更优先)
优点:第一 提高了代码的复用性 第二 让类与类之间产生了关系 是实现多态的前提
语法:
public class 子类 extends 父类{
}
super指代父类
注意事项:
当子类和父类的成员变量重名时 测试类中通过子类对象调用的是子类自己的成员变量
如果需要使用父类的成员变量 只能再子类中使用super关键字调用父类的成员变量

  1. 不重名 子类对象可直接调用父类的成员变量
  2. 可以使用protected(受保护的)修饰父类的方法和成员变量
  3. 如果重名 参数列表相同 称之为子类对于父类方法的重写 在通过子类对象调用该方法时调用的是子类重写后的父类方法

重写后的父类方法
成员变量 成员方法 子类当中 测试类中 是否重名

重写:存在与继承关系中 子类对父类方法的重写 方法名称相同 参数列表也相同

子类的方法返回值类型 小于等于 父类的返回值类型
子类的方法访问权限必须大于等于父类的方法访问权限
子类挎包访问父类使用protected及以上权限
动态调用 通过子类,先找子类中是否有当前方法,如果没有再向上一层查找
重写的结果 父类方法依然存在 只是调用的是子类的方法
方法都是存在方法区中

重载:在同一个类中 方法名相同 参数列表不同 与返回值无关

静态调用

继承中的构造方法
在子类构造方法中调用父类构造方法使用super(可选参数列表);一定放在第一条
this()和super()不能同时出现在同一个构造方法中
子类必须调用父类的构造方法(不写会默认调用父类的无参构造方法);

抽象类 abstract
从逻辑意义上来说 不应该去new成实例化对象的类 称之为抽象类
抽象方法 加上abstract关键字 去掉方法体包括大括号

  1. 必须用一个类来继承抽象父类
  2. 一旦一个类继承了抽象类就必须去实现抽象类中的所有抽象方法
  3. 通过子类对象去实现调用
  4. 抽象类中可以有抽象方法 正常方法
  5. 普通类中不能有抽象方法
  6. 抽象类可以作为子类继承普通类
  7. abstract不能和privatefinalstatic使用

继承————-接口
抽象方法——抽象方法

当出现多个同等级,同时他们具有相同的属性和方法 可以使用继承来提升代码重用率
方案一:普通类:本身可以被new成对象
方案二:抽象类 不可以new成对象 主要功能就是作为继承中的父类

多态

java三大特性之三(封装 继承 多态)同一行为 不同表现形式

  1. 1.继承关系中(或者接口)
  2. 2.方法重写
  3. 3.父类的引用指向子类的对象
  4. 语法:父类类型 变量名=new 子类类型();
  5. 变量名.(当前子类重写之后的)父类方法 成员变量
  6. 方法访问过程 先找父类中是否有这个方法 如果有 再找子类中是否有重写后的该方法 如果有,则执行

否则执行父类的该方法
如果父类中找不到该方法,哪怕子类中有 也会报错
结论 多态只能访问父类存在的方法
如果需要访问子类特有的方法 需要将父类引用强转回对应子类的对象

  1. if(父类引用变量名 instanceof 可能的子类类型){
  2. 子类类型 变量名=(子类类型)待强转父类引用变量名
  3. }
  4. 优势:
  5. 实际开发中 父类类型作为方法的形式参数 传递子类的对象给方法 进行方法的调用
  6. 引用类型的转换
  7. 在多态当中使用
  8. 向上转型
  9. 多态本身子类类型向父类类型向上的转换的过程 这个过程是默认的
  10. 父类类型 变量名 = new 子类类型();
  11. 向下转型
  12. 父类类型向子类类型向下转型的过程 这个过程是强制的
  13. 注意:实现向下转型的要求 父类类型变量必须是由子类类型对象向上转型而来 而不能是直接创建

的父类对象 也就是 先执行向上转型 如果需要调用子类特有的方法再执行向下转型

  1. 转型的异常
  2. 父类的引用对象和预备接收的子类类型 不匹配
  3. 编译通过 执行报错
  4. 避免转型异常 转型前先判断

接口 一个类 使用interface关键字
一种定义好的标准、规范
一种抽象方法的集合(jdk7以前)
特点:
不能创建接口类的对象 只能被实现(implements)
一个实现接口的类可以看成是接口的子类 需要实现接口中的所有抽象方法
调用过程一 创建实现类的对象 过程二 通过多态创建接口的引用指向实现类的对象
对象:

  1. public interface 接口名{
  2. public abstract void 方法名();//abstract 可省略 默认就是抽象方法
  3. }
  4. public class 实现类名 implements 接口名{
  5. 实现接口中的各种抽象方法
  6. }

接口中可放入的内容
JDK8及以上 可以放入默认方法和静态方法 添加default和static public default void show(){ }
static直接使用接口类类名调用 default可以被实现类的对象调用,也可以通过多态创建接口类的引用调用
JDK9及以上 可以放入私有方法
私有静态方法

  1. 接口中不存在变量 都是默认的静态常量 ,可以通过本类名调用,可以通过实现类对象调用,可以通过多态

使用接口类对实现类对象的引用调用,只能查看或者展示 不能修改

  1. 一个普通类
  2. 可以实现多个接口
  3. 可以继承一个父类 再实现多个接口

public class A extends B implements C{}
一个接口类
可以同时实现多个接口
可以同时继承多个接口类作为父类

final关键字

和abstract相对(修饰的类必须被继承,抽象方法要被重写)
有一些类不需要被继承或者类中的成员信息不希望被修改或者重写 都可以使用final来修饰

native关键字

native关键字告诉JVM调用的是该方法在外部定义,也就是我们会用 C 语言(或者其他语言)去实现。
native语法:
1、修饰方法的位置必须在返回类型之前,和其余的方法控制符前后关系不受限制。
2、不能abstract修饰,也没有方法体,也就没有左右大括号。
3、返回值可以是任意类型。

JNI:一般情况下,我们完全可以使用java语言编写程序,但某些情况下,java可能会不满足应用程序的需求,或者是不能更好的满足需求,比如:
1、标准的java类库不支持应用程序平台所需的平台相关功能。
2、我们已经用另一种语言编写了一个类库,但是需要用java代码调用。
3、某些运行次数特别多的方法代码,为了加快性能,我们需要用更接近硬件的语言(比如汇编)编写。
上面这三种需求,其实说到底就是如何使用Java代码调用不同语言编写的代码,那么JNI应运而生了。

Java Native Interface标准就成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定支持就可以了。使用java与本地已编译的代码交互,通常会丧失平台可移植性,但是,有些情况下这样做是可以接受的,甚至是必须的,比如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少保证本地代码能工作在任何Java虚拟机实现下。
v2-c2e96d708acda51b92f644c90be3fdc9_720w.jpg
JNI 的缺点:
①、程序不再跨平台。要想跨平台,必须在不同的系统环境下重新编译本地语言部分。
②、程序不再是绝对安全的,本地代码的不当使用可能导致整个程序崩溃。一个通用规则是,你应该让本地方法集中在少数几个类当中。这样就降低了JAVA和C之间的耦合性。
目前来讲使用 JNI 的缺点相对于优点还是可以接受的,可能后面随着 Java 的技术发展,我们不在需要 JNI,但是目前 JDK 还是一直提供对 JNI 标准的支持。

修饰类

此类不能有任何子类继承,内部的方法必须具备完整的方法体,再final修饰的类中不能存在抽象方法
可以继承或实现其他的类、接口 final修饰引用数据类型,需要赋值且不能再new
修饰成员变量
就是常量 关注赋值
书写规范,全部大写
赋值过程:
方式一:直接赋值
方式二:构造方法
方法三:对于静态的常量赋值,可以使用静态块
引用数据类型变量不能有第二个内存地址,但是内部的成员变量可以继续随意赋值
如果数组对象使用了final,内部的元素一样可以赋值或者是new
修饰成员方法
不能被重写 子类重写后的方法可以添加final

内部类
在一个类的内部又定义了一个完整的类
在一个类的内部成员方法中 定义了一个完整的类

  1. 编码规范:
  2. 尽量单独定义类 如果需要包含 可以使用当前类声明的变量
  3. 如果这个单独的类确实只被一个类所拥有 可以把这个单独的类直接写在所有类的内部
  4. 成员内部类的调用 new 外部类.new 内部类.成员变量或者方法

原则:
内部类访问外部类 可以直接访问
外部类访问内部类 需要创建内部类的对象

  1. 通过接口类名调用静态方法得到内部类的对象 调用内部类的方法
  2. Outer.getInner().show();
  3. Outer.Inner oi=new Outer.Inner();
  4. oi.show();

常用的API
API:Application Programming Interface
就是jdk提供给我们的各种类 使用封装的特性 我们直接使用封装后的类及方法
Object超级类
Java语言中的根类 所有类的父类 所有类创建对象的时候 最终都会参照Object类作为模板
toString()
在自定义类中重写Object

String类
程序当中所有“”字符串 都是String对象 无论有没有new
new是新空间
“”是存储在常量池中的
特点:
1.字符串本身的内容永不改变
2.字符串是可以共享使用的
3.字符串从效果上看 相当于char[] 但是底层原理是byte[]字节数组
对于引用数据类型来说 ==判断的就是地址
如果是基本数据类型 ==判断的是值

StringBuffer类 初始化为大小16字符数组 可序列化 线程安全但效率低
StringBuilder类 与StringBuffer继承自同一个类 但是线程不安全
面试题:
String、StringBuffer和StringBuilder的区别
String是不可变字符序列
StringBuffer可变字符序列 线程安全 效率低
StringBuilder可变字符序列 线程不安全 效率高

Math类
执行基本的数字运算的方法 指数 对数 三角函数等
BigDecimal:float和double并不能表示精确的小数 用于处理金钱和精度要求高的数据类创建对象
不能使用传统的“+ - * /”方法的参数及返回值都是BigDecimal类型的对象
DecimalFormat:只负责控制结果的精度 通过创建模板 最终通过对象调用format(double num)
Math.random() [0,1)

  1. System.out.println(Math.PI);
  2. DecimalFormat de=new DecimalFormat("0.000");//定义输出格式,四舍五入
  3. //“#”直接取整 “#.##%”把源数据*100% 保留两位小数
  4. System.out.println(de.format(Math.PI));

先通过创建对应的format对象 定义输出的格式
通过对象.format(待操作的数据)

Date 日期类
java.util.Date 表示特定的时刻 精确到毫秒
按照标准格式输出 先创建SimpleDateFormat对象同时定义格式 通过对象使用format() 传入要格式
化的时间日期
Date date=new Date();
System.out.println(date.getTime());
SimpleDateFormat sd=new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
Date date2=sd.parse(“1998-01-28 14:57:30”);
Date常用方法
long getTime();//获取1970年到现在的毫秒数
String formate(Date date); //时间转字符串
Date Parse(String scource);//字符串转时间

calendar类 日历类
//日历类是抽象类 保持当时时间信息
calendar c=calendar.getInstance();
//设置值
c.set(calendar.MONTH,2);
//获取值
c.get(calendar.YEAR)//获取Date类型

  1. //增加值(减就用-)信息
  2. c.add(待修改属性,增加量)

包装类
这对8个基本数据类型 Java提供了8个对应的引用类型被称之为包装类(封装类)有了包装类
就可以以面向对象的方式来操作数据(方法和属性)
装箱:基本数据类型包装类的实例
拆箱:获取到包装类对象中包装的基本数据类型变量
JDK1.5之后 支持自动装箱和拆箱

  1. byte--------Byte
  2. short-------Short
  3. int----------Integer
  4. long--------Long
  5. float--------Float
  6. double------Double
  7. Boolean-----Boolean
  8. char---------Character
  9. String类型的值存入对应的包装类
  10. Byte对象.parseByte(String)
  11. 其余类型转String
  12. 基本类型(值)+“”
  13. //拆箱
  14. int num=i.intValue();
  15. System.out.println(num);
  16. //装箱
  17. Integer i=new Integer(4);
  18. Integer i1=Integer.valueOf(5);
  19. //自动装箱
  20. Integer i=4;
  21. String count="44";
  22. Integer i3=Integer.parseInt(count);
  23. //自动拆箱
  24. int num1=i

四、集合框架

数组:同类型的数据 限定固定的长度
集合保存:不同类型 不限定长度 保存的都是对象
暂时性的数据存储空间(内存) 数据持久化——数据库技术
Collection接口
定义了所有单列集合中共性的方法,没有带索引的方法
Collection中定义了单列集合(List\Set)通用的方法
boolean add(对象) 添加元素的操作
void clear() 清空集合中所有的元素
boolean remove(对象) 从当前集合中删除
boolean contatins(对象) 判断当前集合中是否包含给定对象
boolean isEmpty() 判断当前集合是否为空
int size() 返回集合中元素的个数
Object[] toArray() 使用方式:Object[] obj=对象名.toArray() 把集合中的元素 存储到数组中

List集合(接口)

  1. List<Object> list=new ArrayList<>();
  2. 1list.add(Object o);//新增元素
  3. 或者list.add(int index,Object o);//在指定位置插入元素,后面的元素都往后移一个元素。
  4. 2list.get(int index);//返回list集合中指定索引位置的元素
  5. 3list.indexOf(Object o);//返回list集合中第一次出现o对象的索引位置,如果list集合中没有o对象,那么就返回-1
  6. 4list.remove(int index);//删除指定索引对象
  7. 5list.set(int index,Object o);//在索引为index位置的元素更改为o元素
  8. 6list.subList(int fromIndex,int toIndex);//返回从索引fromIndex到toIndex的元素集合,包左不包右
  9. 7list.retainAll(Collection<?> c);//retainAll的返回值并不能用于判断两个集合是否存在交集,只能用于判断集合大小是否发生改变;
  10. 应该通过集合的大小判断两个集合是否有交集。

1.有序的集合(存储和取出的顺序相同)
2.允许存储重复的元素
3.可以通过普通的for循环遍历
ArrayList集合
底层以数组实现 查询快 增删慢
LinkedList集合
以链表的形式实现 查询慢 增删快

Set接口

  1. Set<String> set = new HashSet<>();
  2. 1set.add("元素");//指定的元素添加到该集合中
  3. 2set.addAll(new ArrayList());//将指定集合的所有元素添加到该集合中
  4. 3set.clear();//从这个集合中移除所有的元素
  5. 4set.contains("元素");//是否包含指定的元素
  6. 5set.containsAll(new ArrayList());//是否包含指定集合的所有元素
  7. 6set.equals(new Object());//将指定的对象与此设置的相等性进行比较
  8. 7set.hashCode();//返回哈希代码
  9. 8set.isEmpty();//集合是否含有元素
  10. 9set.remove(Object o);//从该集合中移除指定的元素
  11. 10set.removeAll(Collection<?> c);//从这个集合中移除包含在指定集合中的所有元素

1.无序存储
2.不允许存储重复数据
3.不可用普通的for循环遍历
TreeSet集合
底层以二叉树实现,一般用于排序,存取无序
HashSet集合
底层是哈希表+红黑数实现,存取无序
LinkedHashSet集合
底层以哈希表+链表实现,保证存取的顺序

泛型:
一情况:为了防止因为集合中各元素类型不一致 导致后续操作中的转换类型出现异常
二情况:在定义类的时候使用泛型

  1. class 类名<泛型一,泛型二,...>{
  2. //代码中将泛型一 泛型二 当正常类型使用
  3. }
  4. 当创建对象时 要根据设计类泛型个数 一次赋上真正的类型
  5. Students<String,Integer> stu=new Students<>();
  6. 在创建方法时定义泛型
  7. public<泛型一,泛型二,...> 返回值可以用泛型 方法名(可以使用泛型){
  8. }
  9. 在接口中定义泛型
  10. public interface StuInterface{
  11. public void show(I i);
  12. }
  13. 实现方式一:同实现类的泛型
  14. public class Student<E,T> implements StuInterface{
  15. public void show(E e){}
  16. }
  17. 实现方式二:直接给接口具体的类型
  18. public class Student implements StuInterface{
  19. public void show(String str){}
  20. }

泛型通配符
不知道使用什么类型来接收的时候,可以使用? 表示未知通配符
在定义泛型时要给的是泛型名称
在调用具有泛型的类、方法时可以使用通配符来标识泛型
在最终调用执行时 必须给泛型具体的类

  1. 通配符高级使用---受限泛型
  2. 即可以放大泛型的类型,也可以限制泛型的范围
  3. public void show(Collection<? extends Pet> cp){
  4. //设置泛型上限
  5. }
  6. public void show(Collection<? super Pet> cp){
  7. //设置泛型下限
  8. }

迭代器Iterator接口
针对于集合的遍历问题(util) 归纳为Collection集合的一员
Collection接口和Map接口主要是存储元素 Iterator接口主要遍历元素
接口中的两个方法:
boolean hasNext();判断下一个元素是否有值
E next()返回迭代的下一个元素
//通过集合本身对象创建迭代器对象,集合内数据类型就是迭代器类型
Iterator it=cs.iterator();
注意事项:
如果在迭代器循环过程中 使用Collection父接口的remove()进行元素删除,会导致发生并
访问异常。

  1. ListIterator双向迭代是Iterator的子接口
  2. List list = new ArrayList<>();
  3. while(it.hasPrevious()) {//反向取值输出
  4. String n=it.previous();
  5. System.out.print(n+"\t");
  6. }
  1. Enumeration枚举输出 只针对Vector集合使用,用法与迭代器一样

ArrayList查询快 增删慢 线程不安全

源码中默认大小
private static final int DEFAULT_CAPACITY = 10;
默认最大值:
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

扩容思路
先创建一个新数组 新数组的大小是原数组的1.5倍(增长了原数组一半)
再将老数组中的数据复制给新数组
老数组被当作垃圾回收
(两个数组地址不同)
无参构造方法 首次执行 无参模式
特点:数据保存的顺序就是添加的顺序 展示的顺序都是一致的
希望在使用前尽量估算好长度 避免因为修改和增加 导致内存垃圾的产生

LinkedList双向链表 增删效率高 查询效率低

封装实现了一个链表结构 基于node节点实现数据的存储关系
链表与数组的区别:链表实现不需要频繁的进行空间的开辟 但数组实现查询可直接访问到索引 而链表需要从头开始
一个一个查找 数组查询时可以直接通过下标索引查找。
单向链表:只有一条链 不能保证元素的顺序性 存储元素与取出元素顺序不一定一致
双向链表:一条链专门保证元素的顺序使之成为一个有序的集合
查询慢:因为链表中的地址不是连续的 每次都必须从头开始
增删快:新增和删除并没有操作整个链表结构
offer()添加到尾部
poll()删除首位 pollLast() 删除末尾
pop()移除首个元素 同时返回这个元素
push()放入

Set集合 不存在get()方法

哈希值:是一个十进制的整数 是由系统随机给出(对象的地址,是一个逻辑地址 非物理地址)
在Object类中有public native[本地操作系统执行] int hashCode()返回对象的哈希值

HashSet散列无序存放 通过hashCode()确定唯一值
LinkedHashSet新增了一条链 可使集合有序输出(先进先出)但是依然不允许重复
TreeSet
基本数据类型 直接存 使用Comparable接口实现的排序 通过CompareTo()判断重复元素
自定义类型 必须使用以上接口 重写CompareTo()方法
引用数据类型 必须使用Comparable接口实现的排序 通过重写Comparable()判断顺序结构
如果不使用不能正确输出集合内容

Map集合

通过查看文档 可以发现Map具有两个泛型 存储及查询方式与Collection接口下的实现过程是不同的
Collection是保存单列数值 Map是独立于collection的一种数据存储模式(键值对)
Collection中的元素是孤立存在的存储是针对一个一个的值
Map集合中的元素成对存在每个元素都是由唯一和对应的值构成
Collection中的集合称为单列集合Map中的集合称为双列集合
HashTable 不可以保存null 线程安全 效率低 比较古老的表结构
HashMap:存储数据采用的是哈希表结构 元素的存取顺序不能保证一致

  1. 1map.isEmpty();//判断map是否为空
  2. 2map.containsKey("key值");//判断map中是否存在这个key
  3. 3map.containsValue(value值);//判断map中是否存在这个value
  4. 4map.put("key值",value值);//map存值
  5. 5map.get("key值");//map取值
  6. 6map.values();//显示所有的value值
  7. 7map.size();//显示map里的值的数量
  8. 8map.keySet();//显示map所有的key
  9. 9map.entrySet();//显示map所有的key和value;
  10. 10map.remove("key值");//删除这个键值对
  11. 11map.replace("key值",value值);//替换这个key的value
  12. 12map.clear();//清空这个map
  13. 13Object clone = ((HashMap<String, Object>) map).clone();//hashmap的克隆
  14. 14hmap.putIfAbsent("key值",value值);//如果所指定的 key 已经在 HashMap 中存在,返回和这个 key 值对应的 value, 如果所指定的 key 不在 HashMap 中存在,则返回 null。
  15. 注意:如果指定 key 之前已经和一个 null 值相关联了 ,则该方法也返回 null
  16. Map<K,V> map=new HashMap<>();
  17. map.put(K,V);
  18. Collections集合工具类
  19. sort(List<> list); 按升序排列
  20. shuffle(List<> list); 打乱集合中的元素顺序
  21. 引用数据类型 必须使用Comparable接口实现排序 通过重写comparaTo()判断返回的值进行大小比较,
  22. 如果不使用,不能正确输出集合内容,sort()直接报错
  23. 方式一:
  24. //比较器
  25. public int compareToStudent stu){
  26. ifthis.age<stu.age){
  27. return -1;
  28. }else if(this.age>stu.ag){
  29. return 1;
  30. }else{
  31. return this.name.compareTo(stu.name);
  32. }
  33. }
  34. 方式二:通过单独设置比较规则 后期通过调用实现
  35. public int compareTo(Object obj) {//重写
  36. ifthis.age!=obj.age){
  37. return user.age-obj.age;
  38. }else{
  39. return this.name.compareTo(obj.name);
  40. }
  41. }
  42. public class MemeberCom implements Comparator{
  43. Member m=new Member();
  44. public int compare(Member o1, Member o2) {
  45. if(o1.getAge()!=o2.getAge()) {
  46. return o1.getAge()-o2.getAge();
  47. }else {
  48. return m.getAge();
  49. }
  50. }
  51. }
  52. //测试类中 调用比较规则
  53. 类中只有一个方法时调用类可以直接调用方法
  54. Arrays.sort(n,new MemberCom());
  55. System.out.println(Arrays.toString(u));
  56. 如果比较对象是集合中的元素 ,则使用collections.sort();

异常

指的是程序在运行过程中出现的非正常的情况 最终会导致JVM非正常的停止
错误
编译不能通过 不会产生字节码文件 不能运行
4
错误(Error)和异常(Exception)有一个共同的父类java.lang.Throwable(可抛出的)
Exception:编译期异常,进行编译程序出现的问题
RuntimeException:运行期异常 程序运行过程中发生异常
相当于程序出了小问题 把异常处理掉 程序可以继续执行
Error:相当于程序出了无法治愈的毛病,除非修改源代码l
编译无法通过的异常处理方式

方式一:
try{
//可能会出现异常的代码 一般都是编译无法通过的
}catch(ParseException){
e.printStackTrace;
}finally{
//无论try内代码是否正常执行 都一定要执行的代码放入此处
//资源的关闭 释放
}
方式二:
在方法后面添加throws异常类型

关键字throw
可以使用当前关键字在指定的方法中抛出指定的异常
语法:throw new xxxException(“提示信息”);
注意:
1.关键字必须写在方法的内部
2.此关键字后面new的对象必须是Exception或者是Exception的子类对象
3.throw关键字抛出了指定的异常对象,就必须去处理这个异常对象
如果是运行时异常或者运行时异常的子类对象 无需处理默认最终交给JVM处理(打印异常信息
中断程序)
如果是编译异常 则必须处理此类异常 通过try或者throws

可以包含多组catch模块 但是注意子类异常放前面 Exception父类异常放最后
try、finally这两个模块在同一次异常处理中 只能出现一次

如何获取异常的信息

String getMEssage() 获取异常描述信息
String toString() 获取异常的类型和描述信息(不用)
void printStackTrace() 打印异常的跟踪栈信息并输出到控制台
包含异常的类型 异常的原因 出现的位置,

异常在继承关系中
父类的方法中抛出了异常 子类重写方法时可以抛出同类异常 或者是此类异常的子类异常 或者是不
抛出任何异常
父类的方法中没有抛出异常 子类重写该方法时也不可以抛出异常 如果子类重写的方法中确实有编译
异常,可以通过try catch去捕获这个异常

自定义异常
在开发中根据自己的业务可能的异常情况 定义异常类
自定义一个业务逻辑异常类:RegisterException 一个注册异常类
创建异常类 继承自Exception 或者 RuntimeException
如果继承自Exception属于编译异常,就一定要处理
如果继承自RuntimeException属于运行时异常,可以不处理

throw和throws异同点
都可以抛出异常
throws用在方法外部 后面跟的是异常的类型名称 同时可以解决编译异常
throw用在方法内部 后面跟的是异常类的对象 不能解决编译异常,编译异常必须通过try…catch或者throws
处理

try…catch throws异同点
try模式 有反馈(catch模块)同时还能添加finally模块执行必要的后续操作被throws抛出异常
的方法 被调用时 调用他的方法也有抛出同类异常或者父类异常,建议使用try…catch

五、线程

进程:正在运行的程序
线程:进程中的一个执行小单元
关系:进程中至少有一个线程 线程一定属于某一个进程
如果某一个进程中包含了多个线程 多线程的应用程序

单线程配置 当执行多线程的任务时 是通过在各个线程中切换来实现的 时间非常短
举例:迅雷通过增加下载任务的线程来提高下载的速度
CPU线程调度
分时调度:所有线程轮流使用CPU的使用权 平均分配给每个线程CPU的时间
抢占式调度:优先级高的线程使用CPU 如果优先级相同则随机选择一个线程(线程随机性)
多核处理器:相当于在单核的线程切换中 效率翻倍 并没有提高程序运行速度 只是提高了效率让
CPU使用效率更高

主线程:

从输入java命名 回车后 启动JVM就会去找操作系统开辟线程 从mian方法执行程序代码,CPU
有了一个执行的路径 这个路径就是当前的线程,路径名就是“main”,这个线程是主线程,会一直把当前
线程执行完毕(都是顺序执行 包括循环或选择结构)

使用线程方案一:
Thread父类
创建多线程业务 需要继承Thread父类 重写里面的run()方法
public void run() {
   for(int i=0;i<100;i++) {
       System.out.println(this.getName()+":"+i);
   }
}
线程同时执行,数据交叉展示 都在争取CPU的时间片
//测试类中代表主线程的业务
for(int i=0;i<100;i++) {
   System.out.println(Thread.currentThread().getName()+"主线程:"+i);
}
run()和start()的区别
使用run()不开启线程 只是普通的方法调用
如果开启线程 必须使用start()会让JVM去调用run()
使用线程方案二:(推荐方案,接口可以多继承)
创建多线程业务也可以实现Runnable接口 实现里面的run()方法
public void run() {
  for(int i=0;i<100;i++) {
      System.out.println(Thread.currentThread().getName()+":"+i);
  }
}
//测试类中 要创建Thread通过构造方法 传入Runable实现类的对象

RunnableTest rt=new RunnableTest();
Thread t1=new Thread(rt,"线程一");
t1.start();
Thread t2=new Thread(rt,"线程二");
t2.start();

程序就是一个进程 至少包含两个线程 一个是主线程 一个是垃圾回收线程
java命令开始执行main()由JVM为主线争取时间片段 开始执行主程序
start()申请JVM争取时间片段 在栈空间中开辟独立的线程空间 执行run()执行完后弹栈
线程在栈内中释放空间 当所有线程执行完毕后 进程结束

Thread和Runnable区别:
1.接口更适合资源的共享
2.可以避免java单继承的约束
3.增加程序的健壮性 实现解耦操作 代码可以被多个线程共享 代码和线程的独立
4.线程池只能放入实现Runnable或是Callable类的线程不能放入继承Thread的类

常用方法:
线程对象.getName()
线程对象.start();
线程对象.run();
Thread.currentThread();返回当前调用此方法的线程对象,当前对象
Thread.sleep(毫秒数);线程休眠然后执行
Thread.getPriority();获取线程优先等级

使用匿名内部类创建线程
场景:当某个线程要完成的功能是这个线程特有的,而不与其他线程共享,那么可以使用匿名内部类的方式实现线程


new Thread(new Runnable() {
    public void run() {
    }
},"线程一").start();

线程池:

能够容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作
步骤:
先定义功能类 需要实现Runnable或是Callable类的接口
创建线程池 规定线程数量
取出线程,提交线程任务

ExecutorService es=Executors.newFixedThreadPool(2);
//取出线程 提交任务
es.submit(tc);
如果方法中需要抛出异常 或者有返回值 可以使用Callable接口替代Runnable接口
ExecutorCalleable ec=new ExecutorCalleable();
//需要使用Future<V>来接收callable接口定义方法的返回值
Future<String> submit=es.submit(ec);
//通过.get()获取线程的返回值
System.out.println(submit.get());
可以通过线程池 或者创建普通线程来执行call()方法
setName();设置名字
释放线程
es.shutdown();

线程安全

多个线程同时操作同一段代码 并且其中有对于数据的修改操作 大概率出现数据异常 这就属于线程安全问题
前者修改了数据 内存并没有及时的保存 后者直接访问了没有修改前的数据 等后者拿到这个重复数据,系统
才进行了修改操作
类似前面的案例 多人同时购票 或者多窗口存储
解决思路:把操作过程上锁 在某个线程操作完成前 其他线程不允许操作 效率低
(线程同步机制)

方案一:添加同步代码块
synchronized(锁的对象){
  可能会出现线程安全问题的代码(访问操作了共同的数据)
}
注意:1.通过代码中锁的对象,可以使用任意的对象
2.要保证多个线程使用的锁的对象是同一个
3.锁的对象的作用,把同步代码块中的代码锁住,只让一个线程在同步代码块中执行
方案二:添加同步方法
步骤:
1.提取同步代码内容 生成一个方法,该方法由synchronized关键字修饰
2.在run()方法中调用以上同步方法
步骤:
1.生成一个方法 在该方法中提取同步代码内容 使用synchronized代码块包裹
2.在run()方法中调用以上同步方法
方案三:使用lock锁(接口)
步骤:
1.创建锁对象
Lock l=new ReentrantLock();
2.需要同步的代码块前 获取锁
l.lock();
3.需要同步的代码块后 归还锁
l.unlock();

死锁:

一般情况是拿到了对方的锁 因为同步代码块嵌套造成的
这种代码块嵌套 需要避免
使用线程等待wait()进入到WAITING状态(无限等待状态)可以在其他线程中通过notify()唤醒(应使用等待线程的对象)notifyAll()唤醒所有的线程

synchronized(obj) {
//设置等待被唤醒
try {
    obj.wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }

synchronized(obj) {
    System.out.println("包子做好了");
    obj.notify();
}

注意:同一个线程 等待和唤醒只能有一个在执行 需要使用同步锁
这种线程与线程的交互称为线程通信
线程对象.wait();
线程对象.notify();
notifyAll();
线程中断:
线程对象.isInterrupted();判断是否中断
线程对象.interrupted(); 中断某个线程

线程强制加入执行:
线程对象.join();
线程礼让:
线程对象.yield();
//让出CPU给其他线程用
线程优先级
线程对象.setPriority(Thread.MAX_PRIORITY);调制最高级 10
Thread.MIN_PRIORITY; 1
Thread.NORM_PRIORITY;5
优雅地关闭线程:
resum();
stop();
suspend();
以上都不推荐使用

 while(标记){}
 标记=false
 public static boolean flag=true;
  while(flag){

 }
Thead.sleep(1000);主线程休眠
//标记设置在主线程中 当标记变化时 线程停止从而控制线程执行时长
flag=false;

守护线程
和普通线程没什么区别
将普通线程通过简单的设置 称为守护线程 其他线程执行完毕 守护线程无论自己的任务是否完成
都会结束

拓展列题:
三个人 都到齐后 拍集体照 谁吃完了谁先走
同步屏障 具有等待功能,需要线程都执行以后才会继续执行
步骤

CyclicBarrier ob=new CyclicBarrier(3,new Runnable() {
public void run() {
   System.out.println("人员齐了 开始拍照");
   System.out.println("人员齐了 开始用餐");
ExecutorService es=Executors.newCachedThreadPool();
for(int i=0;i<3;i++) {
    int user=i+1;
    Runnable ra=new Runnable() {
        @Override
        public void run() {
            try {
                System.out.println("第"+user+"个人到达");
                ob.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
            //同步屏障的对象.await();
            System.out.println(user+"用餐完毕 回家");
            }
        };
        es.execute(ra);//每添加一个Runnable对象,就会生成一个线程
    }
    es.shutdown();
    }
});

拓展:
20个人 通过两个窗口买票
XX进入了窗口 XX买票成功 XX离开了窗口

信号量控制线程阻塞
//定义信号量数量(允许同时操作的线程数量)
Semaphore s = new Semaphore(2);

run()方法中添加信号量阻塞 及 释放信号量(类似于上锁和归还锁)
public void run() {
// TODO Auto-generated method stub
    try {
        //判断信号量(线程数量) 如果达到设定值 则发生阻塞
        s.acquire();
        System.out.println("第" + user + "个人进入窗口");
        Thread.sleep((long) (Math.random() * 10000));
        System.out.println("第"+ user +"个人买票成功");
        Thread.sleep((long) (Math.random() * 10000));
        System.out.println("第"+ user +"个人离开窗口");
        //线程离开 释放信号量
        s.release();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } 
}

线程状态:
创建线程->start()->可运行(RUNNABLE)->运行(RUNNING)->阻塞(BLOCKED)->死亡(DEAD)

六、IO流

File文件类

文件和目录路径地址的抽象表现形式
创建文件、文件夹 删除文件、文件夹 获取文件、文件夹 判断是否存在
获取文件大小

三个比较重要的单词:file文件 directory目录文件夹 path路径
为了保证代码中编写的路径地址信息能在不同的平台上正确编译 可以采用以下File类提供的静态量来标识\ ;

//构造方法创建File对象
构造方法字符串中以文件结尾 也可以以文件夹结尾
路径地址可以真实存在 也可以不存在
可以放相对路径 也可以放绝对路径
相对路径:选择参照物定位当前文件所在位置
绝对路径:是从根目录开始找到文件所在位置
路径信息不区分大小写(无论文件夹还是文件)
注意点:
一:
在window系统使用的是\反斜杠 反斜杠同时是转译符的标记 蓑衣要加两根反斜杠才是标识路径层级信息
二:
根据参照物不同定义路径形式
文件对象.getName();
文件对象.length();
不存在文件对象或者没有任何内容 返回0;
文件对象.exists();判断文件是否存在
文件对象.createNewFile(); 新建文件
文件对象.mkdir(); 创建文件夹
文件对象.mkdirs(); 创建嵌套关系的文件夹
文件对象.isDirectory();判断是否是文件夹
文件对象.isFile();判断是否是文件
文件对象.getPath();获取文件地址
文件对象.getAbsolutePath();获取文件绝对地址
文件对象.delete(); 删除文件对象
File[] 文件对象.listFiles();查看文件列表

如果需要遍历文件对象下所有的文件夹及内部文件 就需要迭代器

字节流        字符流

写出 OutputStream Writer (输出流)
读入 InputStream Reader (输入流)

内存-> 写出->硬盘
硬盘-> 读入->内存
void close();关闭此输出流并释放系统资源
void flush();刷新输出流强制缓冲的输出字节被写出
void write(int b);将制定的字节输出
void write(byte[] b);将字节数组中的字节使用输出流
void write(byte[] b,int off,int len);字节数组中从off开始截取len长度进行写出操作

FileOutputStream extends OutputStream
两种创建方式
FileOutputStream(Files file)
FileOutputStream(String str)

构造方法三点功能:
1.创建了一个FileOutputStream对象
2.根据构造方法中传递的文件、文件路径创建一个空的文件
3.会将此写出操作的输出流指向这个创建好的文件

字节流写出的步骤
//先创建字节流对象
FileOutputStream fos=new FileOutputStream(“E:\software\t.txt”,true);
加true可保留前面覆盖的内容
2.使用write()执行写出操作
fos.write(bytes);
fos.write(97);
3.关闭字节流
fos.close();

字节流读入操作
int read(); 读取数据的下一个字节 具备向下一个字节移动的能力
可以从字节流中获取一些字节存入准备好的缓冲区中int read(byte[] b)
void close();关闭字节流释放相关系统资源

缓冲区:存储每次读取到字节信息 对于大文件的字节流方式读取
一般定义为1024(1kb)或者1024整数倍
目标,就是从系统硬盘中获取数据信息 以字节流的形式读入到内存中,当缓冲区大小足够一次读完数据

不会循环读取,当缓冲区大小不足时,会循环读取数据,而且上一次存进缓冲区的数据会被覆盖,因此有
可能最后一次读取时,并没有完全覆盖之前一次的数据 导致展示出了上一次一六的数据信息

FileInputStream(Files file)
FileInputStream(String str)
1.创建一个FileInputStream对象
2.读入操作

3.添加缓冲区
byte[] b=new byte[1024];
while((l=fis.read(b))!=-1) {
    System.out.println(new String(b));
}
4.关闭字节流
fis.close();

先关写出操作

字符流:

针对于字符流是先把数据写到了内存中然后通过flush() 或者是close()才能将内存中的数据写出到内存中
fiush()只是刷新了缓冲区,并没有关闭流的对象 close()一边刷新缓冲区一边关闭流的对象

JDK7的新特性
在try关键字的后面添加一个()括号中可以去定义流的对象
在执行完try模块中的代码后会自动释放流的对象 所以也不需要写finally close();flush();

语法:
try(流对象的声明){
操作对象
}catch(异常对象){
异常展示
。}
缓冲流
在四个基本的流基础上进行的增强
字节读入 FileInputStream 写出FileOutputStream
BufferedInputStream BufferedOutputStream
使用方法:
BufferedInputStream bis=new BufferedInputStream(new FileInputStream(“E:\software\t.txt”));
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(“E:\software\tt.txt”,true));

字符读入 FileReader 写出FileWriter
BufferedReader BufferedWriter
使用方法与字节流一样

原理:在创建流对象的时候 同时创建一个内置的默认大小的缓冲区数组 通过缓冲区来读写数据信息从而降低了IO的次数,
达到提高读写速度的目的

序列化流

在序列化和反序列化的过程中会抛出异常 实体类并没有序列化,实体类需要通过实现java.io.Serializable接口功能;启用
实体类序列化的能力这种接口称为标记型接口
注意点
实现序列化标记的类中 成员变量不能为静态修饰 静态量会优于对象进入内存 因此static修饰的变量不能被序列化
transient关键字
用此关键词修饰成员变量则不可被序列化
java提供的一种对于对象序列化的机制 用一个字节序列可以表示一个对象,这个字节序列写出到文本中就相当于一个
对象被持久保存到文档当中

ObjectOutputStream 对象的序列化写出流
ObjectInputStream 对象的反序列化读入流

七、IDEA快捷键

1、Ctrl+F或者Ctrl+Shift+R 按照文本的内容查找
2、Ctrl+Shift+N按文件名搜索文件
3、Ctrl+H 查看类的继承关系
4、Alt+F7查找类或方法在哪被使用
5、Shift+Shift搜索任何东西