好,那么我就开始了 day_05
object类:
是类层次结构的根类(上帝),无论那个类最后都会继承到Object类
String toString() : 返回该对象的字符串表示
boolean equals(Object obj)
return getClass().getName()+"@"+Integer.toHexString(hashCode());
getClass():返回一个字节码对象
Integer.toHexString():返回指定参数的十六进制字符串形式
hashcode():返回该对象的哈希码值(内部地址)
生成toSting方法: shift+alt+s ---Source---Gengerate toString
获取字节码对象的方式:
方式1 通过Object类的getclass()方法获取
方式2 通过类名调用属性class来获取
方式3 通过class类的静态方法 forName()来获取
类名的获取:在类名上右键 --- copy什么什么name
Object的equals方法:
booleanequals(Object obj)
使用 == 比较两个对象是否相等,比较地制值是否相等
快捷键生成就可以了
System类:
java.lang 包下的类,可以直接用
system 类:包含一些有用的类和字段
常用静态方法
复制源数组中指定长度个元素到一个新数组中:
static void arraycopy (Object src, int srcPos, Object dest,int destPos, int length)
Object scr:源数组
int scrPos:指定从哪个索引开始复制
Object dest:目标数组
int destPos:制定目标数组接收元素位置的索引
int length:目标数组接收元素的个数
返回当前系统时间: static longcurrentTimeMillis();//从1970-01-01 00:00:00
终止虚拟机的运行: static voidexit(int status);//传入0是正常退出,非0是异常
Date类的概述和构造:
Date:表示特定的书剑,精确到毫秒,可以通过方法来设定自己所表示的时间,可以表示任何的时间
System.currentTimeMillis(): 返回的是当前系统时间,1970-1-1至今的毫秒数
构造方法:
Date():创建的是一个表示当前系统时间的Date对象
Date(long date):根据"指定时间"创建Date对象
Date的常用方法:
毫秒值 --- Date [设置] 返回值是void,参数是long
Date --- 毫秒值 [获取] 返回long,无参数 long getTime()
构造方法:
SimpleDateFormat():使用默认的模式进行对象的构建
SimpleDateFormat(Stringpattern):使用的指定的模式进行对象的构建
calender的概述和测试
日历类:提供了年月日时的方法
获取 get 返回给定日历字段的值
修改 set 把指定的字段改成指定的值
添加 add 在指定的字段上加上指定的值
包装类:
什么是包装类?
封装了基本数据类型的类,提供了更多的方法和变量
把基本数据类型的使用
正则表达式概述
什么是正则表达式?
· 是一种用于匹配字符串的规则
· 可用于判断字符串是否符合某种规则,比如是否是邮箱,是否是手机号等等
· 那么开始第六天: 集合(Collection, 迭代器, 增强for, 泛型, List子集)
集合的体系结构
Collection:
集合:
是一个统称, 包含很多集合的实现类. 根据不同数据结构, 提供了不同的集合类
数据结构:
数据的组织和存储方式
体系结构:
将不同的集合实现类的共性向上抽取出父类, 从而形成一种体系
如何学习一种体系结构:
从顶层开始学习共性
从底层使用具体实现
Collection接口中常用的功能
常用方法
增
boolean add:(E e)添加元素 .添加成功返回true,添加失败返回false,永远能够添加成功
删
boolean remove(object o ): 删除元素中的指定元素,成功返回true,失败返回flase
void clear(): 清空集合中的元素
判断
boolean contains(object o): 判断集合中是否包含指定元素 包含返回true, 否则false
boolean isEmpty :判断集合是否为空集合, 即没有元素. 没有元素返回true, 否则false
获取个数int size():获取集合中的元素的个数
转换
Object [] toArray(): 将集合转换成一个Object类型的数组
Iterator<E> iterator():获取集合的迭代器对象
ListIterator接口
boolean hasNext
迭代器的概述和测试
Iterator 接口:
Iterator接口:
迭代器
作用:
提供遍历集合的安全方式获取迭代器:
使用集合对象调用Interator<E>iterator()方法
成员方法
1 boolean hasNext(): 是否有下一个元素
2 E next(): 返回下一个元素
void remove(): 从迭代器指向的 collection 中移除迭代器返回的最后一个元素
集合的遍历方式:
toArray(), 可以把集合转换成数组,然后遍历数组即可
iterator(),可以返回一个迭代器对象,可以通过迭代器对象来迭代集合
Iterator:可以用于遍历集合
boolean nexthas():判断是否有写一个元素
E.next():返回迭代的下一个元素
并发修改异常:
ConcurrentModificationException
发生原因:
迭代器依赖于集合, 相当于集合的一个副本, 当迭代器在操作时, 如果发现迭代器的副本和集合不一样, 则抛出并发修改异常
如何避免:
方式1: 不使用迭代器
方式2: 在使用迭代器遍历时, 使用迭代器的方法修改
添加元素:
List接口中的ListIteratorlistIterator()获取用于List的迭代器, 然后调用ListIterator的add()方法
删除元素: remove()
List接口
列表, 是Collection的子接口
特点: 元素存取有序, 元素可以重复, 有索引
泛型的概述和体现
为什么出现泛型?
由于集合可以存储任意类型的对象, 所以可以按照Object类型存入, 如果我们向集合中存储不同类型的对象 后 再遍历出来元素, 都是Object类型, 若要使用该类型的方法, 必须进行类型转换, 有可能发生类型转换错误
作用: 运行时才发生的类型转换问题提前到了编译时期
由于集合可以存储任意类型的对象,当我们存储了不同类型的对象,就有可能在转换的时候出现类型转换异常
所以java为了解决这个问题,给我们提供了一种机制,叫做泛型
泛型:是一种广泛的类型,把明确数据类型的工作提前到了编译时期,借鉴了数组的特点
泛型好处: 避免了类型转换的问题
减少警告
可以简化我们代码的书写
什么时候可以使用泛型?
当我们看到<E>的时候
补充: 小问题
为什么泛型写为<E>?
只是在集合相关的泛型中会使用E, E是Element的缩写, 表示元素, 说明这个泛型的类型表示的是集合中元素的数据类型
在其他地方有可能还会出现<T>等其他字母, T是Type的缩写, 说明这个泛型表示的是数据类型
英文字母并不一定对应单词的缩写, 只是为了见名知义. 写成任意的<A>, <B>...都可以
foreach的概述
foreach:增强for循环,一般用于遍历集合或者数组
格式:
元素的类型变量集合或者数组对象可以直接使用变量
注意:
增强for循环中不能修改集合(改变集合长度), 会发生并发修改异常
原因: 因为增强for循环内部使用的是迭代器进行迭代
增强for的优缺点:
优点: 简单快捷的拿到每一个元素
缺点: 循环过程中不能修改集合
不能像普通for循环那样使用索引
常见数据结构: 数组
数组的特点:
长度一旦确定则不可改变
元素有整数索引
只能存储同一类型的元素
既可以存储基本数据类型, 也可存储引用数据类型
数组的增删改查:
增加/插入元素:
创建一个新数组, 长度为原数组长度+1
遍历原数组, 将原数组的元素复制到新数组的相同索引位置, 直到遇到要增加元素的索引位置
将要增加的元素值赋值到索引位置
继续复制剩余元素
删除元素:
创建一个新数组, 长度为原数组长度-1
遍历原数组, 将原数组的元素复制到新数组的相同索引位置, 直到遇到要删除元素的索引位置
跳过要删除的元素, 继续将剩余元素复制到后续索引位置
修改元素: arr[0] = 10;
获取元素: int i = arr[0];
通过以上增删改查的操作, 总结出数组的特点:
增删慢
查询快
常见数据结构: 链表
什么是链表: 链接列表, 好比通过链子链接起来的一些结点
什么是结点: 由本结点地址值, 值, 下一个结点的地址值这三部分组成
链表的增删改查
增加元素:
修改下一个结点的地址值
删除元素:
将要删除结点的前一个结点中保存的下一个结点地址值, 修改为要删除结点的下一个结点的地址值(也就是说, 直接跳过要删除的元素)
修改元素:
从第一个结点根据其下一个结点地址值不断去寻找, 然后修改值
获取元素:
从第一个结点根据其下一个结点地址值不断去寻找
从以上增删改查操作中总结出链接的特点
增删快
查询慢
扩展: 数组和链表在存储上的区别
数组中元素的内存地址值是连续的
在查找时只要找到索引0位置的元素的地址值, 后面按地址值往后找即可. 好比课桌上的学号, 我找到0号在哪, 再找5号往后数就行了, 因为座位肯定是挨着的
链表中元素的内存地址值可以不连续
常见数据结构: 栈, 队列
栈(stack)
特点:
先进后出(FILO, First In Last Out). 或后进先出(LIFO, Last InFirst Out)
队列(queue)
特点:
先进先出(FIFO, First In First Out).
List的特点和特有功能
List接口
继承自Collection接口. 在java.util包下
特点
元素有序(存入和取出的顺序一样)
有整数的索引
元素可以重复
特有功能 (都是按索引进行操作的)
void add(int index,E element): 添加元素
E remove(int index): 删除元素
E set(int index, Eelement): 修改元素
E get(int index): 获取元素
List的子类概述, LinkedList特有功能
List的子类
ArrayList: 底层数组结构. 查询快, 增删慢
常用方法之前学过
LinkedList: 底层链表结构. 查询慢, 增删快
特有方法 (用于处理开头和结尾的元素)
void addFirst(E e): 将元素添加到开头
void addLast(E e): 将元素添加到末尾
E getFirst(): 获取开头的元素
E getLast(): 获取结尾的元素
E removeFirst(): 删除第一个元素, 并返回删除的元素
E removeLast(): 删除最后一个元素, 并返回删除的元素
如何选择: 根据数据结构特点
查询多, 增删少, 用ArrayList
查询少, 增删多, 用LinkedList
不知道, 用ArrayList
今日扩展
如何自定义泛型
泛型出现的目的:
如果没有泛型, 我们想让一个方法能够传入不同类型的参数, 有以下几种方式:
定义不同参数类型的重载方法.
缺点: 定义方法太多
使用所有类的共同父类Object依靠多态接收.
缺点: 不能使用子类特有方法, 强转也有风险
有没有办法既能向方法传入任何类型的对象, 又能使用该类特有的方法?
JDK1.5引入的泛型, 就可以实现这一点
优点: 只需要定义一个方法, 我们指定泛型为String, 那么就可以使用String特有方法; 如果指定为Integer, 就能使用Integer特有的方法
泛型的类型擦除
泛型只是一种安全检测机制, 只在编译时期有效
当源代码编译为class字节码文件后, 代码中是不存在泛型的, 这称为泛型的类型擦除
所以, 集合本质能够存储Object类型是没有因为添加了泛型而发生改变的
泛型的定义位置
类: class Student<T>
接口: interface USB<T>
方法
成员方法: 成员方法既能使用自己定义的泛型, 也能使用该方法所在类上定义的泛型
使用方法自己的泛型:
public <C>void eat(C c) {}
public <C> Ceat(C c) {} // 返回泛型对象
使用类的泛型:
public void eat(Tt)
静态方法: 静态方法只能使用自己定义的泛型, 不能使用该方法所在类上定义的泛型
方法自己的泛型:
public <C>void eat(C c) {}
类的泛型: 不能用
泛型的边界
主要解决, 当传入参数为List<各种类型>的问题
如果参数要求为List<Object>, 那么传入List<Dog>是不对的, 因为Java认为Dog不是Object! 怎么办?
<?>: 通配符泛型
表示不知道是什么类型
如: List<?>, 注意这种情况编译器会给泛型随便起一个类型名字, 如capture#1, 我们没有任何类型可以匹配到, 所以这种集合只能存入null
这种集合没什么用途
<? extends T>: 上界通配符
传入对象可以使用E类型及其子类对象
如: List<? extends Animal>, 表示可以存入Animal及其子类对象
<? super T>: 下界通配符
传入的对象可以使用E类型及其父类对象
如: List<? super Dog>, 表示可以存入Dog及其父类对象
<?>和<T>的异同:
相同点:
都表示不确定的类型
不同点:
<T>
用于声明泛型
是自定义泛型
表示具体的某一种类型
可以作为类型使用: T t = itertator.next();
<?>
用于作为泛型使用
是通配符泛型
泛指所有类型
不可作为类型使用
不能使用与泛型相关的方法, 如add(E e)等. 因为?不知道是什么类型
使用LinkedList实现栈和队列
栈: 先进后出
进: 元素添加到末尾, addLast(E e)
出: 删除末尾的元素, removeLast(E e)
队列: 先进先出
进: 元素添加到末尾, addLast(E e)
出: 删除开头的元素, E removeFirst()
好了开始第七天
集合(HashSet,HashMap, Map集合嵌套)
Set体系的特点
Set接口:
继承自Collection接口
特点
元素无序(存入和取出的顺序不一致)
元素不能重复(元素唯一)
没有索引
注意:
无序: 指的是存入的顺序和取出的顺序不一样, 而不是说每次取出来是随机顺序, 存入后每次取出来的顺序都一样, 但和存入的顺序不一样
直接打印和获取元素都属于取出, 所以不要把打印当成是HashSet内部存储的样子
HashSet存储自定义对象并遍历
HashSet类: 是Set接口的实现类
成员方法 HashSet的add()方法, 首先将新添加的元素和当前集合中的已有元素进行hash值比较, 依靠对象的"hashCode()"
* 如果hash值不一样, 则认为不重复, 直接添加新元素
* 如果比较结果一样, 则认为重复, 不添加
* 如果hash值一样, 则继续与已有元素比较"地址值"或使用"equals()方法"进行比较
所以, 自定义对象的hashCode()和equals()方法决定了该对象能否被去重
* 如果和所有的已有元素比较都不一样, 则认为不重复, 添加元素
去重的2个判断方法
先调用元素的hashCode()方法判断哈希值是否相同
如果相同, 再调用元素的equals()方法判断
注意:
重写的是元素的类中的hashCode()和equals()方法, 因为比较的是元素
hashCode()方法和equals()方法的优化
优化hashCode()方法, 让该方法的返回值和成员属性相关联, 减少equals()的调用, 提高效率
方案:
让hashCode()方法返回所有成员变量之和.
基本数据类型直接相加
引用数据类型获取该成员变量的hashCode方法返回值后再相加(boolean不能参与运算)
优化equals方法
提高效率: this == objreturn true
提高向下转型的安全性:this.getClass() == obj.getClass() return false
Collections工具类
Collection和Collections有什么区别?
Collection是接口, 是单列集合的顶层, 包含一些共性方法
Collections是类, 提供操作Collection的一些工具方法, 类似的还有操作数组的Arrays工具类
Collections类
常用静态方法
static intbinarySearch(List list, T key): 使用二分查找来查找元素在指定列表的索引位置
二分查找的前提是集合已经排序, 查找原理类似猜数字
static voidcopy(List dest, List src): 将源列表中的数据复制到目标列表
注意: 目标列表的长度至少等于源列表的长度
static voidfill(List list, Object obj): 使用指定对象填充指定列表的所有元素
static voidreverse(List list): 反转集合中的元素
static voidshuffle(List list): 随机打乱集合中元素的顺序
static voidsort(List list): 将集合中的元素按照元素的自然顺序排序
自然顺序: 元素要具有比较性
A-Z, 0-9本身就具有自然顺序
自定义的对象, 如Student等, 需要自己定义如何进行比较
static voidswap(List list, int i, int j): 将指定列表中的两个索引进行位置互换
HashMap类
多态创建对象: (也可以不使用多态)
Map<K, V> map = new HashMap<>();
常用方法:
增和改
V put(K key, V value): 添加键值对.
注意: 如果key已经存在, 则会使用新的value覆盖原有value, 并将原有value返回
删
void clear(): 清空集合
V remove(Object key): 删除指定键的值(key和value都会删除)
查
V get(Object key): 通过指定键获取值
int size(): 获取集合长度
判断
boolean containsKey(Object key): 是否包含指定的键
boolean containsValue(Object value): 是否包含指定的值
boolean isEmpty(): 是否为空
遍历
Set<Map.Entry<K, V>> entrySet(): 获取键值对的Set集合
Set<K> keySet(): 获取所有键的Set集合
Collection<V> values(): 获取所有值得Collection集合
Map的第一种遍历方式: keySet()
遍历步骤
通过map.keySet()方法获取到key的Set集合
遍历key的set集合
通过get(K key)方法获取key对应的value
Map的第二种遍历方式: entrySet()
遍历步骤
通过map.entrySet()获取到Entry<K, V>的Set集合
遍历Set集合获取到每一个Entry<K,V>
使用Entry的getKey()获取key, 使用Entry的getValue()获取value
好了,开始第八天的
异常概述和体系:
我们在写代码的时候,经常会出现一些小问题,那么为了我们方便处理这些问题,JAVA为我们提供了异常机制
异常
不正常的情况,是代码编译或运行时发生的错误
异常包含了错误的类型,原因以及位置
异常体系结构
java.lang.Throwable(最高层)
Error(不应该试图捕获的严重问题,不能处理的异常)Exception(可以处理的异常) 编译时异常:编译时期就会发生的异常
RuntimeException 运行时异常:编译时正常,运行时才发生的异常
异常处理的方式
JVM默认处理方式
如果出现异常我们没有处理,JVM会帮我们处理,他会把异常的类型原因和位置显示在命令行,并且还终止了程序,异常后面的代码将不再执行
手动处理异常的2种放方式
捕获异常并处理: try...catch语句 try{ //有可能出现问题的代码 //可以有多行代码 }catch(异常类型 异常对象名){ //对异常进行处理的代码; } try...catch的执行顺序 首先执行try语句 如果发现异常,异常线面的代码不再执行,直接跳入catch语句中, catch语句结束后,整个try...catch结束 如果没有发现异常,try语句执行结束后,try..catch直接结束, 不再执行catch语句直接抛出异常:在方法声明上添加 thorws异常类型:
Throwable的常用方法:
String getMessage() : 原因
String toString () : 类型和原因
void printStackTrace() : 类型 原因和 位置
finally:
作用:
组合try...catch使用,用于释放资源等收尾工作,无论try...catch语句如何执行,finally一定执行
try{
可能出现问题的代码
}catch(异常对象){
处理异常;
}finally{
释放资源;
清理垃圾
}
异常的分类:
运行时期异常:RuntimeException的子类就是运行时期异常
处理方式:在编译时期可以自由选择处理或者不处理
编译时期异常:,是Exception的子类(除RuntimeException体系)
处理方式:编译时期必须处理(try...catch 或者throws)
thorws:
注意:如果抛出的是编译时期异常,必须在方法声明处抛出(throws)
如何自定义一个异常类?
写一个类去继承Exception或RuntimeException,然后实现多个构造即可
递归
递归的概念: 把大问题拆成很多小问题,然后把小问题拆成更多的小问题,
当我们把更多的小问题解决了,小问题也解决了
随着小问题的解决,大问题也随之解决
递归的注意事项: 递归一定要有出口,内存溢出
递归次数不宜过多,内存溢出