Object类
String toString()返回该对象的字符串表示
直接打印对象地址没意义,重写toString方法,没重写打印地址值
打印对象,默认调用toString
equals()方法
boolean equals(Object obj)只是其他某个对象是否于此对象相等
基本数据类型:比较值
引用数据类型:比较两个对象的地址值
没重写默认比较地址值
String重写了equals
用赋值符号创建的字符串可以用==(在常量池里面) 也可以用equals比较,new字符串,只能用equals
Objects
传两个参数,解决空指针异常的比较
null不能调方法
date:表示日期和时间的类
毫秒:把日期转换为毫秒计算
date空参构造
Data()获取当前系统日期时间
带参构造
Date(Long date):传递毫秒值,转换为Date日期
成员方法
Long getTime 把日期转换为毫秒
DateFormat使用方法
1.创建SimleDateFormat对象
2.调用对象中的方法format
DateFormat类对日期格式化
成员方法:String format(Date date)按照指定的模式把日期转换为符合模式的格式
Calendar类:日历类
抽象类,里面提供了操作日历字符串的方法
无法创建对象使用,静态方法getInstance,返回Calendar子类对象
常用成员方法:
get()返回给定日历字段的值
set() 将给定字段设置为给定值
add() 根据日历的规则,为给定的日历字段添加或减去指定的时间量
getTime()返回时间值的date对象
西方月份0-11 东方1-12
System类
常用方法
currentTimeMillis():返回一毫秒为单位的当前时间
arraycopy():将数组中的制定的数据拷贝到另一个数组当中
StringBuiler类
字符串缓冲区,可以提高字符串的操作效率(看成长度可以变化的字符串),底层也是一个数组,没有final修饰
在内存中始终是一个数组,占用空间少,如果超出,自动扩容
构造方法:
空参:
常用成员方法:
append:添加任意字符串形式,并返回当前自身对象,参数可以是任意数据类型
链式编程:方法的返回值是一个对象,可以根据对象继续调用方法
对于经常拼接的字符串使用
toString和StringBuilder可以相互转换
包装类
装箱与拆箱
装箱:把基本类型的数据,包装到包装类中
拆箱:在包装类中取出基本类型的数据
自动装箱、拆箱其实就是省略了转换的步骤,直接把int类型变成Integer
基本类型转换为String,
基本类型转换字符串:
1.基本类型数据值+“”,最简单方法
2.使用包装类中的静态方法
3.使用String类中静态方法
字符串转基本数据类型
使用包装类的静态方法parse(“”字符串)
比较-128~127之间的数字 可以使用==比较,应为地址相同(存在常量池中)否则用equals
主要内容
Collection
迭代器
增强for
泛型
学集合目标
1.会使用集合存储数据
2.会便利集合,把数据在取出来
3.掌握每种集合的特性
数组长度固定,集合可变
数组存同一类型元素,可以存基本类型值,可以存对象,集合存对象
集合提供各种方法,比数组功能更强大
集合框架的学习方式
1.学习顶层:学习顶层(接口/抽象类)中共性的方法,所有的子类都可以使用
2.使用底层:顶层不是实现抽象类,无法创建对象和i用,需要使用底层的子类创建对象使用
Collection集合框架
定义的是所有单列集合中共性的方法
所有的单列集合都可以使用(不包含带索引的方法)
List集合
1.有序的集合(存取顺序一致)
2.允许存储重复元素
3.有索引,包含一些带索引的方法
set接口
1.不允许重复元素
2.没有索引,不包含带索引的方法
Collection集合常用功能
1.public boolean add(E e) : 把给定的对象添加到当前集合中 。
返回值是boolean值,一般返回true,不用接收
2.public void clear() :清空集合中所有的元素。
不会把集合删除,集合还可以继续使用
3.public boolean remove(E e) : 把给定的对象在当前集合中删除。
返回值是boolean值
集合中存在元素,删除元素,返回true
集合中不存在元素,删除失败,返回false
集合中有相同元素,只会删除第一个
4.public boolean contains(E e) : 判断当前集合中是否包含给定的对象。
包含返回true
不包含返回false
5.public boolean isEmpty() : 判断当前集合是否为空。
集合为空返回true
不为空返回false
6.public int size() : 返回集合中元素的个数。
7.public Object[] toArray() : 把集合中的元素,存储到数组中。
迭代器
迭代:集合元素的通用获取方式,先判断在取元素
Iterator<E>接口:迭代器
两个常用方法
1.boolean hasNext()判断是否到达集合末尾,是返回false,否返回true
2.E next()取出集合中元素
迭代器使用步骤
1.使用集合中的方法iterator(),获取迭代器的实现类对象,使用Iterator接口接受实现类(多态)
2.使用hasNext判断是覅u到达集合末尾
3.使用next取出集合元素
注意:迭代器有泛型,泛型跟着集合走
迭代器并发修改异常
在使用迭代器的过程中,修改了集合的长度(添加删除元素),就会抛出并发修改异常,
并发:两件事情同时发生(1.迭代2.修改集合长度)
解决方法
1.在迭代的过程中,不对集合的长度进行修改
2.Iterator接口有一个子接口List Iterator接口(只有List接口下边的集合可以使使用)
List Iterator接口中定义了add方法和remove方法,可以对集合添加或删除元素,使用List Iterator自身的添加或删除
在创建集合的时候,会创建一个修改值,默认是0修改值会在每次改变集合长度的时候+1
创建迭代器对象的时候,会将集合的修改值复制一份是迭代器对象,每次调用nex()获取元素的时候和,都会去对比迭代器中的复制的那份期望修改值和集合中的修改值是否一致,如果不一致,就会抛出并发修改异常
添加或删除操作应写在迭代器new之前
泛型:是一种位置的数据类型,当我们不知道使用什么数据的时候,可以使用泛型
泛型也可以看出事一个变量,用来接收数据类型
创建集合对象的时候,就会确定泛型的数据类型
<E>未知数据类型,把数据类型作为参数传递赋值给E
创建集合对象,不适用泛型泛型
好处:集合不使用泛型,默认的数据类型就是Object类型,可以存储任意数据类型的数据
弊端:不安全会引发异常
创建集合对象使用泛型
好处:1.避免的类型转换的麻烦,存储数据是什么类型,取出数据就是什么类型
2.把运行期异常(代码运行后回抛出异常),提升到了编译期(写代码时报错)
弊端:泛型是什么类型,只能存储什么类型的数据
定义和使用含有泛型的类 模拟ArrayList集合
格式 :
修饰符 class 类名称<E>{}
定义含有泛型的方法:
格式:修饰符<泛型> 返回值类型 方法名(参数列表(使用泛型))
泛型的通配符:
?:代表任意数据类型
使用方法:
不能穿件对象使用
只能作为方法的参数使用
泛型的限定:
上限限定:? extends E 代表使用的泛型只能是E类型的子类/本身
下线限定:? super E 代表使用的泛型只能是E类型的父类
数据结构 栈
先进后出,入口和出口在同一侧
数据结构 队列
先进先出,入口出口在两侧
数据结构 数组
查询快:数组的地址是连续的,可以通过数组的首地址可以找到数组,通过数组的索引可以快速查找某一个元素
增删慢:数组的长度是固定的,我们想要增加/删除一个元素,必须创建一个新数组,把源数组的数据复制过来
在堆内存中,频繁的创建新数组,源数组被垃圾回收
数据结构 链表
查询慢:地址不连续,每次查询,都必须从头开始
增删快:链表结构,增加/删除一个元素,对链表的整体结构没有影响
链表的每一个元素也称之为一个节点,一个节点包含了一个数据源(存储数组),两个指针域(存储地址)
单项项链表:只有一条链子,不能保证元素的顺序(存储元素和取出元素的顺序有可能不一样)
双向链表:链表中有两条链子,有一条链子专门记录元素的顺序,是一个有序集合
数据结构 红黑树
二叉树:分支不能超过两个
排序树/查找树:在二叉树的基础上,元素是有大小顺序的
左小右大
平衡树:左右数量相等
不平衡树:左右不一样
红黑树:
特点:趋近于平衡树,查询的速度快,查询叶子节点最大次数和最小次数不能超过2倍
约束:
1:节点可以是红色或者黑色
2.根节点黑色
3.叶子节点(空节点)是黑色
4.每个红色的节点到其每一个叶子节点
的所有路径上黑色节点数相同
List集合
1.有序集合,存储去除元素顺序一致
2.有索引,包含一些带索引的方法
3.允许存储重复元素
List集合带索引的方法(特有)
注意:防止越界异常
ArrayList集合
Linked List集合
特点:1.底层是链表结构。查询慢,增删快
2.里面包含了大量操作首尾元素的方法
注意:使用Linked List集合特有的方法,不能使用多态
3.Vector
1.可以实现可增长的对象数组
HashSet集合
set接口特点:
1.不能存储重复元素
2.没有带索引的方法,不能使用普通for循环遍历
Hash Set特点:
1.不能存储重复元素
2.没有带索引的方法,不能使用普通for循环遍历
3.无序集合,存储元素和取出元素的顺序有可能不一致
4.底层是一个哈希表结构(查询速度非常快)
HashSet集合存储数据的结构(哈希表)
Set集合不允许存储重复元素的原理
在调用add方法的时侯,add方法会调用元素的hashCode方法和equals方法,判断是否重复
hashCode()获取哈希值去集合中判断有没有相同哈希值,有:执行equals方法判断该元素内容是否相同,如果内容也相同就不会添加到集合
Hashset存储自定义元素
重写hashCode和equals方法
LinkedHashSet集合
特点:底层是哈希表(数组+链表/红黑树)+链表(记录元素的存储顺序),保证元素有序,不允许重复
可变参数:
使用前提:
当方法的参数列表数据类型已经确定,但是参数的个数不确定,就可以使用可变参数,
使用格式:
修饰符 返回值类型 方法名(数据类型 变量名){}
原理:
底层是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些参数
残敌的参数个数,可以使0个,1,2多个
注意事项:
1.一个方法的参数列表,只能有一个可变参数
2.如果方法的参数有多个,那么可变参数必须写在参数列表的末尾
特殊写法(终极)写法
public static viod Object(Object...obj){}
Collections集合根据类的方法
add All:往集合中添加一些元素
shuffle:打乱集合中元素顺序
sort(List):将集合中元素按默认规则排序(默认升序)
注意事项:使用前提
被排序的集合里边储存的元素,必须实现comparable接口,重写compareTo定义的排序规则
字节(this)-参数 升序
Comparator和Comparable的区别
Comparable:自己(this)和别人(参数)比较,自己需要实现Comparable接口,重写比较的规则compare To方法
Comparator:相当于找一个第三方裁判
# Map集合
特点:
1.Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)
2.Map集合中的元素,key和value的数据类型可以相同,可以不同
3.key是唯一的,value可以重复,可以不重复
4.key和value是一一对应的
## Map类常用子类
### HashMap:
特点:
1.底层哈希表,查询速度特别快
JDk1.8之前:数组+单项链表
JDk1.8之后:数组+单项链表/红黑树:提升查询速度
2.是一个无序集合,存储元素和取出元素的顺序有可能不一致
### LinkedHashMap特点
1.集合底层是哈希表+链表
2、是一个有序集合,村粗元素和去除元素的顺序是一致的
## Map借口中常用方法
put(K key,V value ):吧指定的键与指定的值添加到Map集合中。
返回值:V
存储键值对的时候,key不重复,返回值v是null
key重复,会使用新的value替换map中重复的value,返回被替代的value
remove:把指定的键所对应的键值对元素在Map集合中删除,返回被删除元素值
key存在返回被删除值
key不存在,返回null
get:根据指定的键,在Map集合中获取对应的值
key存在,返回对应值
不存在,返回null
containsKey :根据指定键,判断集合中是否包含指定键
包含返回true,不包含返回false
## Map集合遍历
1.通过键找值得方式:keySet();
实现步骤:
1.使用Map集合中的方法keySet(),吧Map集合所有的key取出来,存储到一个Set集合中
2.遍历set集合,获取Map集合中的每一个key
3.通过Map集合keySet(),通过key找value
## Map内部接口Entry接口
作用:当Map集合已创建,那么就会在Map集合中创建对象,用来记录键与值(键值对对象,键与值得映射关系)就是一个键值对
#### 使用Entry对象遍历Map集合
步骤:1.使用Map集合中的方法entrySet(),把Map集合多个Entry对象取出来,存储到一个Set集合中
2.遍历Set集合,获取每一个Entry对象
3.使用Entry对象中的方法getKey()和getValue()获取键与值
## HashMap存储自定义数据类型键值
Map集合保证key是唯一的:
重写hashCode方法和equals方法
## LInkedHashMap集合
底层原理:哈希表+链表(记录元素的顺序)
### of方法
使用前提:当集合中存储的元素个数已经确定,不在改变时使用
注意:
1.of方法只适合用于list接口,set接口,map接口,不适用与接口的实现类
2.返回时是一个不能改变的集合,集合不能再使用add,put方法添加元素
3.Set接口和Map接口在调用Of时,不能有重复元素
# 异常
概念:就是不正常的意思,java处理异常方式是终断处理,并不是语法错误
#### 异常体系
Throwable体系:
Error:非常严重的错误
Exception:
#### 异常分类
Throwable类是Java语言中所有错误或者异常的超类
Exception:编译期异常,进行编译Java程序出现额问题
RuntimeException:运行期异常,Java程序运行过程中出现的问题
Error:错误
必须修改代码,程序才能继续运行
处理异常:1.往上抛,最终抛给虚拟机处理(打印异常信息,终断程序,后边如果有代码也不会执行)
2.try{}catch{}处理异常,处理完之后程序继续执行,不会停止
#### 异常产生过程:(怎么产生,如何处理)
访问数组索引越界异常,JVM就会检测出程序出现异常
1.JVM会根据异常产生的原因创建一个异常对象,这个异常对象包含了异常产生的内容、原因、位置
2.在getElement方法中,没有异常的处理逻辑(try...catch),那么JVM就会把异常对象抛出给方法的调用者,main方法来处理这个异常
3.main接受异常对象,没有处理逻辑,抛给JVM
4,JVM接收到异常对象,打印异常对象到控制台,终止当前正在执行的Java程序
#### throw关键字
作用:可以使用throw关键字在指定的方法中抛出指定异常
使用格式:throw new xxxException(“异常产生原因”);
注意:
1.throw必须卸载方法内部
2.throw关键字后边new的对象必须是Exception或者Exception的子对象
3.Throw关键字跑出指定异常对象,我们就必须处理这个异常对象
throw关键之后边创建的RuntimeException或者是RuntimeException的子对象,可以不处理,默认交给JVM处理
throw关键字后边创建的是编译异常(写代码时候报错),我们就必须处理这个异常
以后工作中我们首先必须对方法传递过来的参数进行合法性校验
如果参数不合法,那么我们就必须使用跑出异常的方式,告知方法的调用者,传递的参数有问题
throw:写在方法内部,我们自己抛出异常,可以之定义异常的信息,后面代码不执行
throws:写在方法上,JVM帮我们抛出异常,使用默认异常信息
#### Objects非空判断
静态方法:requireNonNull
#### throws关键字,异常处理的第一种方法,交给别人处理
作用:当方法内部抛出异常对象的时候,那么我们就处理这个异常对象,可以使用throws关键字处理异常对象,会把异常对象声明抛出给方法的调用者(自己不处理,给别人处理)
使用格式:再发声明时使用
修饰符 返回值类型 方法名(参数列表)throws AAAException,BBBException...
注意:
1.throws关键字必须写在方法声明出
2.throws关键字后面声明的异常必须是Exception或者是Exception的子类
3.方法内部如果抛出了多个异常,那么throws后面必须声明多个异常
如果抛出的多个异常对象有子父类关系,那么直接声明父类异常即可
4,。调用了一个声明抛出异常的方法,那么我们就必须的处理声明的异常
要么继续使用throws声明抛出,交给方法的调用者处理,最终交给JVM,要么try...catch自己处理异常
#### try...catch异常处理的第二种方法,自己处理异常
格式:try{
可能产生异常的代码
}catch(定义一个异常的变量,用来接收try中抛出的异常对象){
异常的处理逻辑,产生异常对象之后,怎么处理异常对象,一般在工作中,会把异常的信息记录到一个日志中
}....
catch(){}
注意
1.try中可能会抛出多个异常对象,那么就可以对个catch来出处理这些异常
2.如果try中产生了异常,那么就会执行catch中的异常处理逻辑,执行完毕catch中的处理逻辑,继续执行try...catch之后的代码
如果try中没有产生异常,那么就不会执行catch中异常的处理逻辑,执行完try中的代码,继续执行try...catch之后的代码
#### finally代码块
加在try...catch后面
注意事项:1.finally不能单独使用,必须和try一起使用
2.finally一般用于资源释放(资源回收),无论程序是否出现异常,最后都要执行
#### 多异常捕获处理
1.多个异常分别处理
2.多个异常一次捕获,多次处理
3.多个异常一次捕获,一次处理
一个try多个catch注意事项:
catch里面定义的异常边玲,如果有子父类关系,那么子类的异常边玲必须写在上边,否则就会报错
#### finally中有return语句
永远返回finally中的结果,尽量避免
#### 异常注意事项,子父类异常
如果父类抛出了多个异常,子类重写父类方法时,抛出和弗雷相同的异常或者是父类异常的子类或者不抛出异常
父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时自己诶产生该异常,只能捕获处理,不能声明抛出
注意事项:父类异常是什么样,子类异常就是什么样
#### 自定义异常
格式:public class XXXException extend Exception/RuntimeException{
添加一个空参数的构造方法
添加一个异常信息的构造方法
}
注意:
1.自定义异常类一般都是以Exception结尾,说明该类是一个异常类
2.自定义异常类,必须的继承Exception或者RuntimeException
继承Exception:那么自定义异常类就是一个编译器异常,如果方法抛出了编译期异常,就必须处理这个异常,要么throws,要么try...catch
继承RuntimeException:那么自定义异常类就是运行期异常,无需处理,交给虚拟机处理(中断处理)
# 线程
#### 并发与并行
并发:指两个或多个事件在同一个时间段内发生
并行:指两个或多个事件在同一时刻发生(同事发生)
#### 进程
一个内存中运行的应用程序
#### 线程
是进程中的一个执行单元,一个程序运行后至少有一个进程,一个进程中可以包含多个线程
线程属于进程,是进程中的一个执行单元,负责程序的执行
多线程好处:1.效率高2.多个线程之间互不影响
#### 线程调度
分时调度:线程分时使用
抢占式调度:优先让优先级高的线程使用CPU
#### 主线程:
执行主方法(main)方法的线程
单线程程序:Java程序中只有一个线程
执行从main方法开始,从上到下依次执行
#### 创建线程类
第一种方法:将类声明为Thread的子类
Thread是描述线程的类,我们想要实现多线程程序,就必须继承Thread类
实现步骤:
1.创建一个Thread类的子类
2.在Thread类的子类中重写Thread类中的润方法,设置线程任务(开启线程要做什么?)
3.创建Thread类的子类对象
4.调用Thread类中的方法start方法,开启新的线程,执行run方法
void start()使用该线程开始执行;Java虚拟机调用该线程的run方法
结果是两个线程并发的运行;当前线程(main)和另一个线程(创建新的线程,执行run方法)
多次启动一个线程是非法的,特别是当前线程已经结束后,不能再重新启动
Java程序属于抢占式调度,哪个线程的优先级高,那个线程先优先执行,同一个优先级,随机选一个执行
# 线程
#### 多线程原理
多个线程,竞争关系,互不影响
#### Thread类的常用方法
获取线程名称:
1.使用Thread类中方法getname()
String getName()返回该线程的名称
2.可以先获取当前正在执行的线程,使用线程中的方法getName()获取线程的名称
start Thread currentThread()返回当前正在执行的线程对象
线程名称:
主线程:main
新线程:Thread-0,Thread-1....
设置线程名称:
1.使用Thread类中的方法setName(名字)
void setName(String name)改变线程名称,使之与参数name相同
2.创建带参的构造方法,参数传递线程名称;调用父类的带参构造方法,
sleep方法:是当前正在执行的线程以指定的毫秒数暂停,毫秒执行之后继续执行
#### 创建线程第二种方式
实现Ruunnable接口
Runnable接口应该由那些打算通过们以线程执行其实列的类来实现。类必须定义一个称为run的无参数方法
实现步骤
1.创建一个Runnable接口的实现类
2.在实现类中重写run方法,设置线程任务
3.创建一个Runnable接口的实现类对象
4.创建Thread类对象,构造方法中传递Runnable接口的实现类对象
5.调用Thread类中的start方法,开始新的线程执行run方法
实现Runnable接口创建多线程程序的好处:
1.避免了单继承的局限性
一类只能继承一个类,类继承了Thread类就不能继承其他的类
2.增强了程序的扩展性,降低了程序的耦合性(解耦)
实现Runnable接口的方式,把设置线程任务和开启新线程进行了分离
实现类中,重写了run方法:用来设置线程任务
创建Thread类对象,调用start方法:用来开启新的线程
#### 线程安全问题
#### 线程安全问题产生原理
开启3个线程,头t0,t1,t2,3个线程一起抢夺cpu的执行权,谁抢到谁执行
注意:线程安全问题是不能产生的,我们可以让线程在访问
#### 线程同步
1.同步代码块:
synchronized(锁对象){
可能出现线程安全问题的代码(访问了共享数据的代码)
}
注意:
1.通过代码块中的锁对象,可以使用任意的对象
2.但是必须保证多个线程使用的锁对象是同一个
3.锁对象的作用:
把同步代码块锁住,只让一个线程在同步代码块中执行
#### 同步技术原理
使用了一个锁对象,这个锁对象叫同步锁,也叫对象监视器
总结:同步中的线程没有执行完毕不会释放锁,同步外的线程没有锁进不去同步
同步保证了只能有一个线程咋同步执行共享数据
同步每次判断,效率降低
#### 同步方法
使用synchronized修饰的方法,就是同步方法
使用步骤:1.把访问了共享数据的代码抽取出来,放到一个方法中
2.在方法上添加synchronized修饰符
同步方法也会把符内部的代码锁住,只让一个线程执行,同步方法的锁对象就是实现类 对象也就是this
#### 静态同步方法:
锁对象不能是this,this是创建对象之后产生,今天方法优先于对象
静态方法的锁对象是本类的class属性-->class文件反射
#### Lock锁
Lock实现提供了比使用synchronized方法和语句可获得的更广泛的锁定操作
Lock接口中的方法:
Lock()获取锁
unLock()释放锁
使用步骤:1.在成员位置创建一个ReetrantLock对象
2.在可能会出现安全问题代码前调用Lock接口中的方法lock获取锁
3.在可能出现安全问题代码后调用Lock家口中方法unLock来释放锁
## 线程状态概述
wait,在其他线程调用此对象的notify方法或notifyAll方法前,导致当前线程等待
notify唤醒在此对象监视器上等待的单个线程
会继续执行wait方法之后的代码
进图到TimeWaiting(计时等待)
1.使用sleep(long m)方法,在毫秒值结束之后,线程醒来进入到Runnable/Blocked状态
2.使用wait(long m)方法,wait方法如果在毫秒值结束之后,还没有被notify唤醒,就会自动醒来,
3.notify只能换一个线程
4.notifyAll唤醒所有等待线程 |
|