java 快速入门
- Public class Main 表示一个公开的类
- Public static void main (String[] args) 表示程序的入口
- Main { } 表示类的开始与结束
- Main{} 方法的开始与结束
- 输出一条语句
java 开发细节
- Java 源文件以. Java 为扩展名。源文件的基本组成部分是类,如本类中的 Main 类
- Java 应用程序的执行入口是 main ()方法。他有固定的书写格式
- Java 语言严格区分大小写
- 大括号都是成对出现的,缺一不可。
- 一个源文件最只能有一个 public 类。其他类的个数不限。
- 如果源文件包含一个 public 类,则源文件名必需与该类类名一致
- 一个源文件中最多只能有一个 public 类。其他类的个数不限,每个类都可以有自己的 main 方法。
转义字符
- 制表符
- 换行
- 一个
- 一个单引号
- 一个双引号
- 回车
相对路径和绝对路径
- 相对路径:从当前目录开始定位,形成的一个路径
- 绝对路径:从顶层目录开始定位,形成的一个路径
变量
- 变量是程序的基本组成单位
- 变量三要素 ^f56ef2
- 类型
- 名称
- 值
- 注意事项
- 变量表示内存中的一个存储区域(不同变量占字节数不同)
- 该区域有自己的名称和类型
- 变量必须先声明在使用
- 该区域的数据在同一类型范围内不断变化
- 变量在同一个作用于内不能重名
- 变量= 类型+名称+值
- +号的使用
- 当左右两边都是数值时,做加法运算
- 左右两边有一边为字符串时,做拼接
- 运算顺序是从左到右
- 数据类型
- 基本数据类型
- 数值型
- 整数型
- 使用细节
- 声明 类型需要在数字后加 l 或 L
- 使用细节
- 浮点型
- 使用细节
- 声明 float 需要在小数后加 f 或 F
- 有两种表示形式:十进制和科学计数法
- 注意精度问题
- 8.1/3 并不等于 2.7
- 使用细节
- 整数型
- 字符型
- 存放一个字符
- 使用细节
- Char 的值是单引号括起来的单·个字符
- 本质是一个整数,对照 unicode 码表
- 可以直接赋值为一个整数范围在(0~255)
- 可以直接进行运算
- 布尔型
- 存放 true 和 false
- 使用细节
- 只能存放 true 和 false,无 null
- 数值型
- 引用数据类型
- 类(class)
- 数组(Array)
- 接口(interface)
- 枚举(enum)
- 记录
- String
- 数据类型转换
- 基本数据类型转换
- 自动类型转换
- 细节
- 当有多种数据类型同时进行运算时,会将所有数据类型全部转为最大的数据类型进行计算
- 当精度大的数据类型转为精度小的数据类型时会报错,反之为自动类型转换
- (byte 和 short)与 char 之间不会进行自动数据类型转换
- 三者之间可以计算,在计算时自动转为 int 类型
- Boolean 类型不参与转换
- 自动提升原则:表达式结果的类型自动提升为表达式中最高的类型
- 细节
- 强制类型转换
- 将大容量的数据类型转为小容量的数据类型时需要加上强制类型转换符 ,但可能会造成精度丢失
- 细节
- 强转符号只针对于最近的操作数有效
- 类型只能保存 的常量值不能保存 int 的变量,需要强转
- 基本数据类型与 string 类型相互转换
- 基本数据类型转为 string 直接+“”
- String 转为基本数据类型可以调用对应数据类型的包装类的方法
- 例如
- 字符串转为字符
- 可以通过 方法提取相应位置的字符
- 注意事项
- 将 string 转为基本数据类型时要确保 string 类型可以转成有效的数据比如"123"可以转为 123 但是“hello”无法转为数值
- 自动类型转换
- 基本数据类型转换
- 基本数据类型
运算符
算术运算符
- 细节说明
- 对于/,整数除和小数除是有区别的,整数除是取整,直接舍去小数部分,只保留整数部分
- 当对一个数取模时,可以等价于 。
- 当自增做一个独立语言使用时,不管是前置加还是后置加都是本身自增一。
- 当自增作为一个表达式使用时
- 当自增作为一个表达式使用时
- 注意
关系运算符
- 细节说明
- 值都为 boolean 型
- == 不能误写为=
逻辑运算符
- 用于连接多个关系表达式,结果为布尔值
- 与 (仅左右语句都为真时为真)包括:逻辑与& 和短路与&&
- 或 (左右语句有一则或超过一则为真时为真)包括:逻辑或| 和短路或||
- 非 (取反,假时为真,真时为假)包括:逻辑非!
- 异或 (左右相异时为真,左右相同时为假)包括:逻辑异或^
赋值运算符
- 特点
- 顺序为从右往左
- 赋值运算符的左边只能是变量,右边可以是变量也可以是表达式,常量值。
- 复合赋值运算符会进行类型转换。
三元运算符
- 条件表达式 ? 表达式 1:表达式 2;
- 规则
- 条件表达式为 true 返回表达式 1 反之返回表达式 2
运算符优先级
标识符
- 规范
- 由字母、数字、下划线、$组成
- 数字不能开头
- 不能使用关键字和保留字
- 严格区分大小写
- 不能包含空格
进制
位运算符
流程控制
If else
Switch
- Switch 判断的类型必须为
循环控制
- For
- While
- Do while
数组
一维数组
- 数值型数组和字符型数组默认值为 0,boolean 默认值为 false String 型默认值为 null
二维数组
数组使用注意事项
- 数组是多个相同类型数据的组合,实现对这些数据的统一管理
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型,但是不能混用
- 数组索引是从零开始
- 数组下表需要再指定范围内使用
- 数组属于引用类型,数组型数据是对象
java基础入门目录
面向对象基础
类与对象
- 类是抽象的,概念的,代表一类事物
- 对象是实体,具体的,代表一个具体的事物
- 类是对象的模板,对象是类的具体表现形式
对象在内存中的形式
属性/成员/字段
- 概念上这三者相同。
- 属性是类的组成,一般是基本数据类型,也可以是引用数据类型。
注意事项
- 属性的定义语法同变量,与变量不同的是属性有四种权限修饰符
- 属性可以定义为任意类型
- 属性如果不赋值有默认值,规则和数组一致
类和对象的内存分配机制
- 栈:一般存放基本数据类型
- 堆:存放对象(数组)等
- 方法区:常量池,类加载信息
方法的调用机制原理
成员方法的传参机制
基本数据类型的传参机制
- 传递的是值,形参的任何变化都不会影响实参
引用数据类型的传参机制
- 传的是地址值,形参的变化会引起实参的变化
形参置为 null 时不会影响到实参,只是将形参保存的值消去。
递归的规则
- 执行一个方法时,就创建一个新的受保护的独立空间。
- 方法的局部变量是独立的,不会相互影响。
- 如果方法中使用的是引用类型变量,会共享该引用类型的数据
- 递归必须向退出递归的条件逼近,否则就是无线递归
- 当一个方法执行完毕,或者遇到 return,就会返回
方法重载
- 方法名:必须相同
- 形参列表:必须不同(形参类型或者个数或者顺序,至少有一样不同,参数名无要求)
- 返回类型:无要求
可变参数
- 基本语法
- 注意事项
- 可变参数的实参可以为 0 个或任意多个
- 可变参数的实参可以为数组
- 可变参数的本质就是数组
- 可变参数可以喝普通类型的参数一起放在形参列表,但必须保证可变参数在最后
- 一个形参列表中只能出现一个可变参数
作用域
- 属性和局部变量可以重名
- 在同一个作用域中,变量不能重名
- 属性生命周期较长,与对象相关。局部变量生命周期较短,与代码块相关
- 范围不同,全局变量可以在本类或者其他类中使用,局部变量只能在本类中使用
- 全局变量可以加修饰符,局部变量无法加修饰符
构造器
- 构造器的修饰符可以是默认,也可以是
- 构造器没有返回值
- 名字和类名一致
- 参数列表和成员方法一样
- 构造器的调用由系统完成
注意事项
- 构造器也可以重载
- 构造器只完成对象初始化并不是创建对象
- 创建对象时系统自动调用构造方法
- 如果系统没有定义构造器,系统会自动给类生成一个默认的无参构造器
- 一旦定义了机子的构造器,默认的构造器就覆盖了,就不能在使用默认的无参构造器,除非显示定义
对象创建流程
This 关键字
- 代表当前类的对象
- This 关键字可以用来访问本类属性、方法、构造器
- This 用于区分当前类的属性和局部变量
- 访问成员方法,可以直接
- 访问构造器 ==只能在构造函数中访问另一个构造函数
- This 只在当前类中,代表本类
面向对象中级
包
包的三大作用
- 区分相同名字的类
- 当类很多时可以很好的管理
- 控制访问范围
包的基本语法
- 表示包
- 表示包名
包的本质分析
包的命名
- 只能包含数字、字母、下划线、小圆点,但不能用数字开头,不能是保留字或关键字
常用的包
- 基本包,默认引入
- 系统提供的工具包
- 网络包
- java 界面开发 GUI
包的注意事项
- 需要放在类的最上面
访问修饰符
基本介绍
- 对外公开
- 对本包下以及本类的子类公开
- 默认,对本包公开
- 对本类公开
访问范围
注意事项
- 修饰符可以用来修饰类中的属性,成员方法以及类
- 只有默认的和 public 才能修饰类
- 成员方法的访问规则和属性完全一样
面向对象的三大特征
封装
- 把抽象出的数据和对数据才做的方法封装在一起,数据被保护在内部,程序的其他部分只有通过特定的端口,才能对数据进行操作
封装的理解和好处
- 隐藏实现细节
- 可以对数据进行验证,保证安全合理
封装步骤
继承
集成作用
- 提高代码复用
继承示意图
基本语法
注意事项
- 子类继承了所有的属性和方法,但不包括私有的,在子类中访问父类私有的属性和方法也需要通过父类提供的端口
- 子类必须调用父类的构造器,完成父类的初始化
- 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化,否则编译失败
- Super 可以显示指定调用父类的哪个构造器super 只能在构造器中使用
- Super 在使用时必须放在子类构造器第一行
- Super 和 this 都只能放在构造器的第一行,因此这两个方法不能共存于同一个构造器
- Java 所有类都是 Object 的子类,object 是所有类的基类
- 父类构造器的调用不限于直接父类!将一直追溯到 object 类
- 子类做多只能继承一个父类单继承
继承的本质
super 关键字
基本介绍
- 代表父类的引用,用于访问父类的属性、方法、构造器
基本语法
- 访问父类属性,但不能访问父类的私有属性
- 访问父类方法,不能访问父类的私有方法
- 访问父类的构造器
Super 和 this 比较
方法重写
- 子类的一个方法与父类方法相同(名称、返回类型、参数相同)
注意事项
- 子类不能缩小父类的访问权限
多态
基本介绍
- 方法或对象具有多种状态,多态是建立在封装和继承的基础上的
- 一个对象的编译类型和运行类型可以不一致
- 编译类型在定义对象时就确定了,不能改变
- 运行类型是可以变化的
- 编译类型看=左边运行类型看=右边
注意事项
- 多态的前提是两个对象存在继承关系
向上转型
- 本质:父类引用只想子类对象
- 语法
- 特点:编译类型看左边,运行类型看右边,可以调用父类中所有成员,不能调用子类中私有成员,最终运行效果看子类的具体实现
向下转型
- 语法:子类类型引用名=(子类类型)父类引用
- 只能强转父类的引用,不能强转父类的对象
- 要求父类的引用必须指向的是当前目标类型的对象
- 当向下转型后,可以调用子类类型中所有成员
动态绑定
- 当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定
- 当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用
Object 类
Equals
== 与 equals 对比
- == :既可以判断基本类型,又可以判断引用类型
- == :如果判断基本类型,判断的是值是否相等
- == :如果判断引用类型,判断的是地址是否相等,及判定是不是同一个对象
- Equals 是 object 类中的方法,只能判断引用类型,
- 默认判断的是地址是否相等,子类一般会重写该方法,用于判断内容是否相等。
零钱通项目案例
房屋出租项目代码
- 修改功能未写(懒)
面向对象高级
类变量
类变量定义
- 类变量也叫静态变量,是属于类的,所有对象实例共有的属性。
类变量定义方式
变量的内存布局
类变量访问方式
类变量使用细节
- 类变量与实例变量区别
- 类变量是该类的所有对象共享的,而实例变量是每个对象独享的。
- 加上 static 称为类变量或静态变量,否则称为实例变量/普通变量/非静态变量
- 类变量可以通过类名调用或者对象名调用,推荐使用类名调用
- 实例变量不能通过类名调用
- 类变量是在类加载时初始化,也就是说,即使你没有创建对象,只要类加载了,就可以使用类变量
- 类变量的声明周期是随类的加载开始,随类消亡而销毁。
类方法
类方法的基本介绍
- 类方法也叫静态方法,可以通过类名嗲用
类方法的定义
使用场景
- 一般将一些通用的方法定义为静态的,方便使用
类方法注意事项
- 类方法和普通方法都是随着类的加载而加载,将结构信息存储在方法区,类方法中不能使用 this,普通方法中可以使用 this
- 类方法可以通过类名调用
- 普通方法只能通过对象名调用
- 类方法不允许使用 this 与 supe
- 类方法只能访问静态变量或静态方法
- 普通成员方法,既可以访问非静态成员也可以访问静态成员
Main 方法
Main 方法的形式
- main 方法时虚拟机调用所以该方法的权限是公开的
- Java 虚拟机在执行 main 的时候不会创建对象所以是 static
- 该方法接受 string 类型数组,该数组中保存执行 java 命令时传递给所运行的类的参数
代码块
基本介绍
- 代码块又称为初始化块,属于类中的成员,类似于方法,讲逻辑语句封装在方法体中,通过{}包围起来。
- 但和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不同通过对象或类显示调用,而是加载类时,或创建对象时隐式调用。
定义方式
- 修饰符是可选的,只能写 static
- 代码块分为静态代码块和普通代码块
- 逻辑语句可以为任何逻辑语句
- 分号可以写也可以省略
代码块作用
- 可以将多个构造器中重复的操作写在代码块中,提高复用性
注意事项
- 静态代码块随着类的加载而执行,并且只会执行一次,如果是普通代码块,每创建一个对象就会执行一次。
- 类什么时候加载
- 创建队形实例时
- 创建子类对象实例,父类也会加载
- 使用类的静态成员时
创建对象时类的调用顺序
- 调用静态代码块和静态属性初始化(如果有多个按定义的顺序调用)
- 普通代码块和普通属性的初始化(如果有多个按定义的顺序加载)
- 调用构造方法
创建子类对象时调用顺序
- 父类的静态代码块和静态属性初始化(按定义顺序)
- 子类的静态代码块和静态属性(按定义顺序)
- 父类的普通代码块和普通属性初始化
- 父类的构造方法
- 子类的普通代码块和普通属性初始化
- 子类的构造方法
- 静态代码块只能调用静态成员
单例设计模式
基本介绍
- 采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法
- 单例模式有两种
- 饿汉式
- 懒汉式
饿汉式
懒汉式
饿汉式与懒汉式对比
- 创建时机不同
- 饿汉式不存在线程安全问题,懒汉式存在线程安全问题。(完善方式写在线程那部分)
- 饿汉式存在浪费资源的可能。因为如果程序员一个对象实例都没有使用,那饿汉式创建的对象就浪费了,懒汉式是使用时创建,不存在这个问题。
Final 关键字
基本介绍
- Final 可以修饰类,属性,方法和局部变量
- Final 修饰的类不被继承,修饰的方法不被重写,修饰的属性和局部变量值不变
注意事项
- Final 修饰的属性又叫常量
- Final 的属性在定义时必须复制,并且以后不能再修改,赋值可以在如下位置之一
- 在定义时
- 在构造器中
- 在代码块中
- 如果 final 修饰的属性是静态的,则初始化位置只能在
- 定义时
- 静态代码块中
- Final 类不能被继承但是可以实例化对象
- Final 修饰的方法不能被重写但是可以被继承
- Final 不能修饰构造器
- Final 一般和 static 搭配使用,不会导致类加载,底层做了优化
抽象类
基本介绍
- 用 abstract 关键字修饰一个类时,这个类就称为抽象类
- 定义形式
- 用 abstract 修饰方法时,该方法为抽象方法,特点没有方法体
注意事项
- 抽象类不能实例化
- 抽象类不一定包含抽象方法
- 一个类如果包含抽象方法,则必须声明为抽象类
- Abstract 只能等修饰类和方法
- 抽象类可以有任何成员(本质就是类)
- 抽象方法不能有方法体
- 如果一个类继承了抽象类则必须实现所有抽象方法,除非这个类也声明为抽象类
- 抽象方法不能使用 修饰
模板设计模式
接口
基本介绍
- 接口是更加抽象的抽象类,抽象类里的方法可以有方法体,接口里只有静态方法、默认方法才可以有方法体
注意事项
- 接口不能被实例化
- 接口所有方法都是 public 方法接口中抽象方法,可以不同 abstract 修饰
- 一个普通类实现接口,就必须将该接口的所有方法都实现
- 抽象类实现接口,可以不用实现接口的方法
- 一个类可以实现多个接口
- 接口中的属性只能是 final 的,而且是 修饰。
- 接口中属性的访问形式
- 接口不能继承其他类,但是可以继承多个别的接口
- 接口的修饰符只能是 public 和默认。
接口与继承对比
- 继承的价值在于解决代码的复用性和可维护性
- 接口的价值在于设计规范
- 接口在一定程度上实现代码解耦
接口的多态性
- 多态参数
- 多态数组
- 多态传递
内部类
基本介绍
- 如果类定义在方法或代码块中
- 局部内部类
- 匿名内部类
- 定义在成员位置
- 成员内部类
- 静态内部类
- 一个类被定义在另一个类中称为内部类
基本语法
局部内部类的使用
- 可以直接访问外部类的所有成员
- 不能添加访问修饰符,但是可以使用 final 修饰
- 作用域:仅仅在定义它的方法或代码块中
- 外部类访问局部内部类需要创建对象
- 本质仍然是一个类
- 外部其他类不能访问局部内部类
- 如果外部类和局部类成员重名,默认尊许就近原则,访问外部类成员可以用
匿名内部类
- 没有类名并且是一个对象
- 其他同上
成员内部类
- 可以添加访问修饰符
- 作用域为整个类
- 其他同上
静态内部类
- 只能访问静态成员
- 可以添加访问年休师傅
- 作用域为整个类
- 其他同上
枚举和注解
枚举
- 默认继承 类,而且是一个 final 类
- 如果使用无参构造器创建枚举对象,则实参列表和小括号都可以省略
- 当有多个枚举对象时,使用,间隔,最后有一个分号结尾
- 枚举对象必须放在枚举类的行首
- 枚举类可以实现接口
注解
异常
异常结构图
异常处理
常用类
包装类
包装类的分类
基本数据类型包装类intIntegercharCharacterbyteByteshortShortlongLongfloatFloatdoubleDoublebooleanBoolean
包装类和基本数据类型转换
包装类与 String 类型相互转换
Integer 与 Character 常用方法
注意事项
- 如果创建的 Integer 值在-128 到 127 之间直接返回这个值而不会在堆中创建对象
- Integer 与基本数据类型比较判断的是值
String 类
基本介绍
- String 保存字符串底层使用不可变的字符数组保存
- 不区分字母和汉字一个字符占两个字节
- string 实现了这俩接口代表可以在网络上传输和比较
创建 string 的两种方式
- 方式 1 先查看常量池中是否已经存在该值,如果有直接指向,如果没有在常量池中创建然后再指向
- 方式 2 先在堆中创建一个空间,然后使用 value 属性指向常量池中该值的地址
- 返回的是常量池中的地址
字符串的特性
- 字符串是一个 final 类,代表不可变序列,一旦分配内存空间,其内容不可变,修改变量的值会重新在常量池中创建一个对象
- 两个字符串相加只会创建一个对象
- 两个字符串变量相加会使用 StringBuider 拼接后转为 String 最后对象是存在堆空间中
String 类常见方法
StringBuffer 类
- Stringbuffer 是一个可变序列,一部分方法与 string 相同,可以对字符串内容进行增删
- Stringbuffer 在每次修改时不会更换地址,只是更换值
string 与 stringbuffer 相互转换
Stringbuffer 常见方法
注意
- Stringbuffer 可以追加一个 null 但是不可以使用构造器创建 stringbuffer 对象时传入一个 null
Stringbuilder
- Stringbuilder 与 stringbuffer 类似,只不过 stringbuilder 不是线程安全的,在单线程情况下要比 stringbuffer 快
Math
Arrays
System
BigInteger 和 BigDecimal 类
- BigInteger 保存较大的整数
- BigDecimal 保存较大的浮点数
- 二者都提供了加减乘除方法
日期类
第一代日期类 Date
- 精确到毫秒,代表特定的瞬间
- SimpleDateFormat 格式化日期
第二代日期类 calendar
分析
- 第一代日期类,随着第二代的引入,大多数方法已经弃用了
- 第二代日期类
- 可变性:像日期和时间这样的类应该是不可变的
- 偏移性:Date 中的年份是从 1900 年开始的,而月份从 0 开始
- 格式化:格式化只对 Date 有用,Calendar
- 第一代日期与第二代日期都不是线程安全的,不能处理润秒(每隔两天,多出一秒)
第三代日期
- LocalDate:只包含日期
- LocalTime: 只包含时间
- LocalDateTime:包含日期和时间
DateTimeFormatter
类似于 SimpleDateFormat
时间戳
第三代日期方法
集合
Collection 特点
- 实现子类可以存放多个元素,每个元素可以是 Object
- 有些 Collection 的实现类,可以存放重复的元素,有些不可以
- 有些 Collection 的实现类,有些是有序的 list,有些不是有序 set
- Collection 接口没有直接的实现子类,是通过它的子接口 set 和 list 来实现的
Collection 常用方法
迭代器
增强 for
- 底层使用的是迭代器
List 接口
- 有序,可重复
- 支持索引
常用方法
三种遍历方式
- 迭代器
- 增强 for
- For 循环
ArrayList
注意事项
- 可以加入 null
- 有数组实现存储
- 基本等同于 Vector,
- 线程不安全
- 改查快
底层源码分析
- ArrayList 中维护了一个 object 数组 transient 表示该数组不会被序列化
- 当创建 arraylist 对象时,如果使用的是无参构造器,则初始 elementData 容量为 0,第一次扩容 elementData 值为 10,再次扩容为 elementData 1.5 倍
- 当使用的是制定大小的构造器,则初始 elementData 为指定大小,如果需要扩容,则直接扩容 elementData 1.5 倍
Vector
- 与 arraylist 基本一致,线程安全
- 默认扩容两倍可以指定扩容大小
- 默认初始化 10
LinkedList
- 底层实现了双向链表和双端队列特点
- 可以添加任意元素,包括 null
- 线程不安全
- 增删块
操作机制
- 底层维护了一个双向链表
- Linkedlist 维护了两个属性 first 和 last 分别指向首尾节点
- 每个节点,又维护了 preve、next、item 属性,preve 指向前一个节点,next 指向后一个节点
Set 接口
基本介绍
- 无序,无索引
- 不可重复
遍历方式
- 迭代器
- 增强 for
Hashset 说明
- 底层使用的是 hashmap
- 可以存放 null
- 不能保证顺序,因为索引是由 hash 确定的
- 不能有重复元素
案例说明
Hashset
- 底层是红黑树加链表加数组
- 现获取元素的哈希值
- 对哈希值进行运算,得出一个索引值即为要存在哈希表中的位置号
- 如果该位置上没有其他元素则直接存放,如果该位置已经有其他元素,则需要进行 equals 判断,如果相等,则不添加,如果不相等则以链表形式添加
- 在 java 8 中如果一条链表长度达到 8 ,并且 table 大小达到 64 时,会进行树化,否则仍然采用数组扩容机制
分析扩容机制
- Hashset 底层是 hashmap,第一次添加时 table 扩容到 16,临界值是 16*加载因子 0.75=12
- 如果 table 数组使用到了临界值(添加次数达到 12),就会扩容到 16_2=32,新的临界值就是 32_0.75=24,以此类推
linkedHashset
- hashset 的一个子类
- 底层维护了一个数组+双向链表
- linkedhashset根据元素的hashcode值来决定元素的存储位置,同时使用链表维护元素的次序(图),使元素看起来向是以插入顺序保存的
- linkedhashset不允许添加重复元素
map接口和常用方法
接口实现类特点
- map与collection并列存在。用于保存具有映射关系的数据
- map中的key不允许重复
- map中的value可以重复
- map的key可以为null,注意key为null,只能有一个,value为null可以为多个
- 常用的string类作为map的key
- key和value之间存在单向一对一对应关系,即通过指定的key总能找到对应的value
常用方法
map遍历方式
- containKey:查找键是否存在
- keySet:获取所有键
- entrySet:获取所有关系k-v
- values:获取所有的值
hashMap
- hashmap是map接口使用频率最高的实现类
- hashmap是以键值对方式来存储数据
- key不能重复,但是值可以重复,允许使用null键和null值
- 如果添加相同的key,则会覆盖原来的key-val,等同于修改。
- 与hashset一样,不保证映射的顺序,因为底层是以hash表的方式来存储的
- hashmap没有实现同步,因此线程不安全,方法没有做同步互斥的操作,没有
hashmap底层机制
hashtable
基本介绍
- 存放的是键值对
- hashtable的键和值都不能为null,否则会抛出空指针异常
- hashtable使用方法基本和hashmap一样
- hashtable是线程安全的hashmap是线程不安全的
properties
基本介绍
- 继承自hashtable并实现了map接口,也是键值对形式的数据
- 特点与hashtable类似
- properties还可以用于从配置文件中加载数据到properties对象中
如何选择集合
- 先判断存储类型
- 一组对象(单例):collection接口
- 允许重复:list
- 增删多:linkedlist(底层是一个双向链表)
- 改查多:arraylist(底层是一个object数组)
- 不允许重复 set
- 无序:hashset(底层是hashmap,维护了一个哈希表(数组+链表+红黑树))
- 排序:treeset
- 插入和取出顺序一致:linkedhashset,(维护数组+双向链表)
- 允许重复:list
- 一组键值对
- 键无序:hashmap(底层是哈希表)
- 键排序:treemap
- 键插入和取出顺序一致:linkedhashmap
- 读取文件properties
- 一组对象(单例):collection接口
collections工具类
看api
泛型
基本介绍
- 泛型又称参数化类型,用来解决数据类型的安全性问题
- 在类声明或实例化时只要制定好需要的具体的类型即可
- java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生类型转换异常
- 可以在类声明时通过一个标识标识类中某个属性的类型,或者是某个方法的返回值类型,或者参数类型
泛型声明
注意事项和细节
自定义泛型类
基本语法
细节
- 普通成员可以使用泛型
- 使用泛型数组,不能初始化
- 静态方法中不能使用类的泛型
- 泛型的类型,实在创建对象时确定的(因为创建对象时,需要指定确定类型)
- 如果在创建对象时没有指定类型,默认为object
自定义泛型接口
基本语法
细节
- 接口中,静态成员也不能使用泛型
- 泛型接口的类型,在继承接口或者实现接口时确定
- 没有指定类型默认为obejct
自定义泛型方法
基本语法
注意细节
- 泛型方法,可以定义在普通类中,也可以定义在泛型类中
- 当泛型方法被调用时,需确定类型
泛型的继承和通配符
基本说明
多线程
相关概念
程序
就是我们写的代码
进程
- 进程是指运行中的程序,比如我们使用就启动一个进程,操作系统就会为该进程分配内存空间。当我们使用迅雷,又启动了一个进程,操作系统将为迅雷分配新的内存空间
- 进程是程序的一次执行过程,或是正在运行的一个程序。是动态过程:有自身的产生、存在和消亡的过程。
线程
- 线程由进程创建的,是进程的一个实体
- 一个进程可以拥有多个线程
其他相关概念
单线程
同一个时刻,只允许执行一个线程
多线程
同一个时刻,可以执行多个线程,比如:一个进程,可以同时打开多个聊天窗口。
并发
同一个时刻,多个任务交替执行,造成一种貌似同时的错觉,(单核cpu实现多任务就是并发)
并行
同一个时刻,多个任务同时执行。(多核cpu可以实现并行)
线程的基本使用
继承Thread类
实现Runnable
使用案例
- 编写两个线程,其中一个输出helloword,输出100次结束,另一个输出hi输出50次结束.
继承与实现方式的区别
- 从java设计角度看,通过继承或者实现接口来创建线程本质没有区别。
- 实现接口方式更加适合多个线程共享一个资源的情况,并且避免了单继承的限制,建议使用runnable
售票系统模拟,并分析问题
- 存在超卖以及重复买票问题
线程终止
基本说明
- 当线程完成任务后,自动退出
- 还可以通过控制变量来控制run方法退出的方式停止线程,即通知方式
控制变量方式案例
线程常用方法
常用方法第一组
注意事项和细节
- start底层会创建新的线程,调用run,run就是一个简单的方法调用,不会启动新线程
- 线程优先级范围
- interrupt,中断线程,但并没有真正的结束线程。所以一般用于中断正在休眠线程
- sleep 线程的静态方法,使当前线程休眠
常用方法第二组
- yield线程的礼让。让出cpu,让其他线程执行,但礼让时间不确定
- join:线程插队,线程的插队一旦插队成功,则肯定先执行完插入的线程所有的任务,由需要插队的线程调用
用户线程和守护线程
- 用户线程:也叫工作线程,当线程的任务执行完或通知方式结束
- 守护线程:一般是为工作线程服务的,当所有的用户线程结束,守护线程自动结束
- 常见的守护线程:垃圾回收机制
线程的声明周期
线程状态转换图
线程的同步
线程同步机制
- 在多线程编程一些敏感数据不允许被多个线程同时访问,此时使用同步访问技术,保证数据在任何同一时刻,最多有一个线程访问,以保证数据的完整性
- 线程同步,即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作,其他线程才能对该内存地址进行操作
同步具体方法
互斥锁
基本介绍
- java引入了对象互斥锁,来保证共享数据操作的完整性
- 每个对象都对应于一个可称为互斥锁的标记,这个标记用来保证在任意时刻只有一个线程访问该对象
- 关键字synchronized来与对象的互斥锁联系,当某个对象用synchronized修饰时,表明该对象在任一时刻只能由一个线程访问
- 同步的局限性:导致程序的执行效率要降低
- 同步方法(非静态)的锁可以是this,也可以是其他对象(要求是同一个对象)
- 同步方法(静态)的锁为当前类本省对象
解决卖票问题
线程的死锁
基本介绍
- 多个线程都占用了对方的锁资源,但不肯相让,导致了死锁,在编程是一定要避免死锁的发生
模拟线程死锁
释放锁
释放锁情况
- 当前线程的同步方法、同步代码块执行结束
- 当前线程在同步代码块、同步方法中遇到break、return
- 当前线程在同步代码块、同步方法中出现了未处理的error或exception,导致异常结束
- 当前线程在同步代码块、同步方法中执行了线程对象的wait方法、当前线程暂停,并释放锁
不会释放锁情况
- 调用sleep、yield方法
- 其他线程使用了该线程的suspend方法将该项成挂起不会释放锁
IO流
文件
常用的文件操作
获取文件相关信息
目录的操作和文件删除
IO流的分类
- 按操作数据单位不同:
- 字节流(8 bit)二进制文件,字符流(按字符)文本文件
- 按数据流的流向不同分为:输入流,输出流
- 按流的角色的不同分为:节点流,处理流/包装流
抽象基类字节流字符流输入流InputStreamReader输出流OutputStreamWriter
- java的io总共设计40多个类,都从上表四个抽象基类派生出来的
- 由这四个派生出来的子类名称都是以其父类名作为子类名后缀
IO流常用类
IO体系图
FileInputStream
FileOutputStream
FileReader和FileWriter
fileReader相关方法
fileWriter相关方法
- 覆盖模式
- 写入字符
- == FileWrite 使用后必须关闭或刷新,否则写入不到指定的文件
节点流和处理流
基本介绍
- 节点流可以从一个特定的数据源读写数据
- 处理流是连接在已存在的流智商,为程序提供更为强大的读写功能。
节点流和处理流的区别和联系
- 节点流是底层流,直接跟数据源相接
- 处理流包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出
- 处理流对接点流进行包装,使用了修饰器设计模式,不会直接与数据源相连
处理流的功能体现
- 性能:主要以增加缓冲的方式提高输入输出效率
- 操作:处理流提供了一系列便捷方法来一次输入输出大批量的数据,使用更加灵活方便
BufferedReader 和 BufferedWriter
不能操作二进制文件会造成损坏
BufferedInputStream 和 BufferedOutputStream
ObjectInputStream 和 ObjectOutputStream
- 对数据类型和对象进行序列化
序列化和反序列化
- 序列化就是在保存数据时,保存数据的值和数据类型
- 反序列化就是在恢复数据时,恢复数据的值和数据类型
- 序列化条件
- 实现接口或者实现接口
注意事项
- 读写顺序要一致
- 序列化的类中创建SerialversionUID可以提高版本兼容性
- 序列化对象时,默认将里面所有属性都序列化,除了static或transient修饰的成员
- 序列化对象时要求里面属性的类型实现了序列化接口
- 序列化具备可继承性
标准输入输出流
InputStreamReader 和 OutputStreamWriter
- :的子类,可以将(字节流)包装成(字符流)
- :的子类,实现将(字节流)包装成(字符流)
- 可以解决中文问题,提升效率
- 可以在使用时指定编码格式
PrintStream 和 PrintWriter
Properties 类
- 用来读取配置文件
- 键值对不需要有空格,值不需要用引号引起来。默认值是字符串
- load:加载配置文件
- list:输出数据
- getProperty(key)
- setProperty(key,value)
- store:对象中的键值对存储在配置文件中,如果含有中文idea会显示unicode码,可以再设置中修改为显示中文
网络编程
TCP和UDP
TCP
- 使用tcp协议前,需要先建立连接,形成传输数据通道
- 传输前,采用三次握手方式,是可靠的
- tcp协议进行通信的两个应用进程:客户端、服务端
- 在连接中可进行大数据量的传输
- 传输完毕,需释放已建立的连接,效率低
UDP
- 将数据、源、目的封装成数据包,不需要建立连接
- 每个数据包大小限制在64K内,不适合传输大量数据
- 因无序连接,所以不可靠
- 发送数据结束时无序释放资源(因为不是面向连接的)速度快
InetAddress
相关方法
运行结果
Socket
- 套接字(socket)开发网络应用程序被广泛采用,以至于称为事实上的标准
- 通信的两端都要有socket,是两台机器通信的断电
- 网络通信其实就是socket间的通信
- socket允许程序把网络连接当成一个流,数据在两个socket间通过IO传输
- 一般主动发起通信的应用程序属客户端,等待通信请求的为服务端
示意图
基于socket的tcp编程实例
字节流案例
字符流案例
传输图片案例
netstat指令
- netstat -an 可以查看当前主机网络情况,包括端口监听情况和网络连接情况
- netstat -an|more 可以分页显示
- 要求在dos控制台下执行
- listening 表示某个端口在监听
- 如果有一个外部程序(客户端)连接到该端口,就会显示一条连接信息
tcp注意事项
客户端与服务器通信也是通过一个端口进行的,这个端口是随机的
udp编程
反射
Reflection
- 反射机制允许程序在执行期间借助于 reflection api 取得任何类的内部信息,并能操作对象属性及方法。反射在设计模式和框架底层都会用到
- 加载完类之后,在堆中就产生了一个 class 类型的对象(一个类只有一个 class 对象),这个对象包含了类的完整结构信息。通过这个对象得到类的结构。这个 class 对象就像一面镜子,透过这个镜子看到类的结构,所以,形象的称之为:反射
反射原理示意图
反射优缺点
- 优点:可以动态的创建和使用对象(也是框架底层核心),使用灵活,没有反射机制,框架技术就失去底层支撑。
- 缺点:使用反射基本是解释执行,对执行速度有影响。
Class 类
- Class 也是类,因此也继承 object 类
- Class 类对象不是 new 出来的,而是系统创建的
- 类的 class 对象在内存中只有一个,因为类只加载一次
- 每个类的实力都会记得自己是由哪个 class 实力所生成的
- 通过 class 对象可以得到一个类的完整结构
- Class 对象是存在堆中
- 类的字节码二进制数据,是放在方法区的,有的地方称为类的元数据(包括方法代码,变量名,方法名,访问权限)
Class 类的常用方法
获取 class 类对象
- 前提:已知一个类的全类名,且该类在类路径下,可通过 class 类的静态方法 获取,可能抛出
- 若已知具体类可以通过类. Class 获取
- 已知某个类实例可以通过 方法实现
- 其他方式通过类加载器获取 class 对象
- 基本数据通过. 得到
- 基本类型对应的包装类通过 得到
哪些类有 class 对象
- 外部类,成员内部类,静态内部类,局部内部类,匿名内部类
- Interface:接口
- 数组
- Enum:枚举
- Annotation;注解
- 基本数据类型
- Void
类加载
基本说明
- 静态加载:编译时加载相关的类,如果没有则报错,依赖性太强
- 动态加载:运行时加载需要的类,如果运行时不用该类,及时不存在该类,则不报错,降低了依赖性
类加载时机
- 静态加载
- 当创建对象时(new)
- 当子类被加载时,父类也加载
- 调用类中静态成员时
- 动态加载
- 通过反射
类加载过程图
类加载各阶段任务
加载阶段
Jvm 在该阶段的主要目的是将字节码从不同的数据源(可能是 class 文件、也可能是 jar 包,甚至网络)转化为二进制字节流加载到内存中,并生成一个代表该类的 class 对象
连接阶段-验证
- 目的是为了确保 class 文件的字节流中包含的信息符合虚拟机的要求,并且不会危害虚拟机的自身安全
- 文件格式验证、元数据验证、字节码验证、和符号引用验证
- 可以考虑使用 参数来关闭大部分的类验证措施,缩短虚拟机类加载的时间。
连接阶段-准备
- Jvm 会在该阶段对静态变量,分配内存并默认初始化(对应数据类型的默认初始值)。这些变量所使用的内存都将在方法区中进行分配
连接阶段-解析
虚拟机将常量池的符号引用替换为直接的引用的过程
初始化
- 到初始化阶段,才真正开始执行类中定义的 java 程序代码,此阶段是执行client()方法的过程
- client()方法是由编译器按语句在源文件中出现的顺序,依次自动收集类中所有静态变量的赋值动作和静态代码块的语句,并进行合并。
- 虚拟机会保证一个类的client()方法在多线程环境中被正确地枷锁,同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的client()方法,其他线程都需要阻塞等待,直到活动线程执行client()方法完毕
通过反射获取类结构信息
Class 类
Filed
Method
Constructor
通过反射创建对象
通过反射获取类中的成员
- 如果是静态属性和静态方法参数对象可以换成 null
正则表达式
正则表达式底层实现
正则表达式语法
基本介绍
- 限定符
- 选择匹配符
- 分组组合和反向引用符
- 特殊字符
- 字符匹配符
- 定位符
元字符-转义号
符号说明:在我们使用正则表达式去检索某些特殊字符时,需要用转义字符,否则检索不到结果,甚至报错
字符匹配符
符号介绍示例解释[]可接受的字符列表[efgh]efgh 中的任意一个字符[^]不接受的字符列表[^abc]除 abc 以外的其他字符包括数字和特殊符号-连字符A-Z任意单个大写字母.匹配 以外的任何字符a…b以 a 开头,b 结尾,中间包括两个任意字符长度为 4 的字符串\d匹配单个数字\d{3}(\d)?包括 3 个或 4 个数字的字符串\D匹配单个非数字字符\D (\d)*一单个非数字开头后接任意个数字字符串\w匹配单个数字、大小写字母\d{3}\w{4}以三个数字开头长度为 7 的数字字母字符串\W匹配单个非数字、大小写字母\W+\d{2}以至少 1 个非数字字母字符开头,2 个数字字符结尾的字符串\s匹配任何空白字符\S匹配任何非空白字符//.匹配除 之外的所有字符,如果要匹配. 则使用\.
选择匹配符
相当于或
限定符
符号含义示例说明*指定字符重复 0 或 n 次(abc)*包含任意个 abc 的字符串, 等效于\w*+指定字符重复 1 次或 n 次m+(abc)*以至少一个 m 开头,后接任意个 abc 的字符串?指定字符重复 0 次或 1 次m+abc?以至少 1 个 m 开头,后接 ab 或 abc 的字符{n}只能输入 n 个字符[abcd]{3}由 abcd 中字母组成的任意长度为 3 的字符串{n,}指定至少 n 个[abcd]{3,}由 abcd 字母组成的任意长度不小于 3 的字符串{n, m}指定至少 n 个但不多于 m 个[abcd]{3,5}由 abcd 字母组成长度不少于 3 个,不大于 5 的字符串
定位符
符号含义示例说明^指定起始字符$指定结束字符\b匹配目标字符串的边界这里的边界指的是目标子串间有空格或者结束位置\B匹配目标字符串的非边界匹配的是开始位置, 包括空格之后的起始
分组
常用分组构造形式说明pattern非命名捕获。捕获匹配的子字符串。编号为 0 的第一个捕获是由整个正则表达式模式匹配的文本,其他捕获结果则根据左括号的顺序从 1 开始自动编号(?pattern)命名捕获。将匹配的子字符串捕获到一个组名称或编号名称中。用于 name 的字符串不能包括任何标点符号,并且不能以数字开头。可以使用单引号替代接括号 (?‘name’)(?:pattern)匹配 pattern 但不捕获该匹配的子表达式,即他是一个非捕获匹配,不存储供以后使用的匹配。例如 industr(?: y|ies) 比 industry|industries 更经济的表达式(?=pattern)他是一个非匹配捕获例如 windows (?=95|98|NT|2000)匹配 windows 2000 中的 windows, 但不匹配 windows 3.1 中的 windows(?!Pattern)
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.bianchenghao6.com/h6javajc/3434.html