* 常见异常
* 数组越界异常
* 空指针异常
*
*
* 特点: 当程序出现异常的时候, 程序会打印异常信息并中断程序
* 所以当同时出现多个异常的时候只能执行第一个, 后边的用不到
*
* 单异常
* 对异常的处理 ->> 检测异常,捕获异常, 处理异常, finally(回收资源之类的收尾工作)
* try{
* 可能出异常的代码
* }catch(Exception e) { e是要捕获的异常
* 对异常的代码进行处理
* }finally{
* 不论怎样都会执行的代码(除非程序结束)(被System.exit()之类的代码 GANK)
* }
*
*
* 多异常
* try{
* 可能出异常的代码
* }catch(第一型异常 e1) { e1
* ...
* }catch(第二型异常 e2) { e2
* ...
* }catch(Exception e3) { default 处理
* ...
* }finally{
* 不论怎样都会执行的代码(被System.exit()之类的代码 GANK)
* }
* 如果try代码块的语句发生异常, 会立即catch 并终止try代码块的执行, 如果try代码块没有异常, try代码块会全部执行
* 由于异常的先后捕获顺序不同, 如果前边的 第一型异常 是 第二型异常 的父类 那么 发生第二型异常时其不会被 e2 捕获 其会被 e1捕获;
* 所以捕获顺序必须先进行上层捕获!!!最后可以加上个Exception e3 来捕获任意类型的异常
* finally 中的功能 例如: 资源释放 ->> (线程锁, 流, 数据库连接) 等的关闭
*
* 子类的同名方法中声明的异常可以与父类的不一致也可以不声明异常, 但是此时子类方法不能再抛出异常
* 如果子类同名方法声明了异常父类必须声明异常
*
*
* try finally 结构, 不进行catch
* 自定义异常 由于内部有异常的基本功能 所以一般都继承自Exception
*
* 自定义异常的原因: 系统没有我们需要的异常(我们需要的比较特殊), 比如订单异常 用户信息异常之类的 (订单里你总不能给我负数的钱吧~)
*
* 异常分类
* 编译异常: 在编译阶段抛出, 处理异常 除RuntimeException以外的所有异常
* 所有的工作都要程序员自己完成
* 运行时异常: 在运行阶段抛出, 处理的异常 对应RunException
* 所有的异常我们都可以不管
* 异常处理的方式:
* 异常的声明
* trycatch语句
*
* throw : 抛出异常
* throws : 声明异常-->>告诉调用者此方法可能出异常
*
* 异常声明后交给调用者处理, 调用者不处理那么交给jvm虚拟机处理
* trycatch 是真的对异常的处理
*/
实例:
try {
div(5, -2);
}catch (FushuException e) {
System.out.println("处理异常");
} finally {
System.out.println("收尾");
}
-------------------------------------------------------
public static int div(int x, int y) throws FushuException{
if(y<=0){
FushuException f = new FushuException();
throw f; //手动生成除数为负数的FushuException异常
// catch(f) {
// System.out.println("处理异常");
// }
}
return x/y;
}
--------------------------------------------------------
class FushuException extends Exception{
private static final long serialVersionUID = 1L;
public FushuException(){}
public FushuException(String message){super(message);} //加上super() 才能抛给jvm一份异常
}
//在重写的方法中使用异常的注意点:
///*
// * 1.子类的同名方法中声明的异常等级要=<父类的.
// * 2.子类的同名方法中声明的异常可以与父类的不一致,也可以不声明异常.但是此时子类方法不能再抛出异常
// * 3.如果子类同名方法声明了异常,父类必须声明异常.
包装类 Integer Character String StringBuffer StringBuilder 等
/*
* 包装类, 专门将简单数据类型进行封装 byte Byte short Short int Integer long Long float
* Float double Double boolean Boolean char Character
*
* 1.方便实现简单数据类型和字符串之间的转化 2.便于在集合中存储 3.可以更加方便对简单数据类型进行操作
*/
/*
* 对于Integer来说, 数字范围在在一个字节范围内
* 后边再定义它,直接使用前边的
* 超过一个字节其会新建对象
*/
// 包装类
// * 基本类型转成字符串类型
// static String Integer.toString(int i)
// static String Double.toString(double d)
// 字符串类型转基本类型
// 只能转字符串类型的
// int Integer.parseInt("23")
// double Double.parseDouble("3.45")
//
// 把十进制转成其它进制
// Integer.toHexString()
// Integer.toOctalString()
// Integer.toBinaryString()
//
// 把其它进制转十进制
// Integer.parseInt(数据,进制)
模板设计模式
* 模板设计模式: 实现一个功能的时候, 分成两部分(确定和不确定部分), 将确定的部分有当前类实现, 不确定的部分教育子类实现
* 子类实现的结果又会反过来影响确定的部分
*
* 实例: 求一个程序运行的时间
*
* 分析:
* 开始时间, 运行过程, 结束时间
*/
public class Demo5 {
public static void main(String[] args) {
Fu f = new Zi();
System.out.println(f.getTime());
}
}
abstract class Fu{
//开始时间, 运行过程, 结束时间
/*
* 此处为固定部分 运行过程是不确定部分交给子类
*/
public double getTime(){
long startTime = System.nanoTime();
// this.show();
for(short i =90;i<100;i++)
System.out.println(i);
long endTime = System.nanoTime();
return endTime - startTime;
}
public abstract void show();
}
class Zi extends Fu{
public void show() {
for(int i =0;i<100;i++)
System.out.println(i);
}
}
* 对于String的比较, 按照ascii码(中文好像按照拼音顺序) 比较
*
* 从左边第一个开始比较, 码数比较大的为较大的字符串
* compareTo 返回值为 前边的字符-后边的字符的值, 结束符号为 /u0000
String[] strs = str1.split(""); //->>1 2 3 a
"1,2,3".split(","); //->> 1 2 3 ','被忽略
System.out.println(Arrays.toString(strs));
// String:
//1.判断:
//判断是否包含一个子字符串
//boolean contains(CharSequence s)
//判断两个字符串的内容是否相同
//boolean equals(Object anObject)
//忽略大小写判断两个字符串的内容是否相同
//boolean equalsIgnoreCase(String anotherString)
//判断是否以某字符串开头
//boolean startsWith(String prefix)
//判断是否以某字符串结尾
//boolean endsWith(String suffix)
//2.转换:将字符数组转换成字符串
//1:使用构造方法
//String(char[] value)
//String(char[] value, int offset, int count)
//2:使用静态方法
//static String copyValueOf(char[] data)
//static String copyValueOf(char[] data, int offset, int count)
//将字符串转成字符数组
//char[] toCharArray()
//将字节数组转成字符串
//String(byte[] bytes)
//String(byte[] bytes, int offset, int length)
//String(byte[] bytes, String charsetName)//使用指定的编码将字节数组转换成字符成
//将字符串转成字节数组
//byte[] getBytes()
//将基本数据类型转换成字符串
//String.valueOf()
//3.替换:
//String replace(char oldChar, char newChar)
//子串:
//String substring(int beginIndex)
//String substring(int beginIndex, int endIndex) //包含起始位置,不包含结束位置,到结束位置的前一位
//转换,去除空格,比较:
//大小写转换
//String toLowerCase()
//String toUpperCase()
//将字符串两端的空格去掉
//String trim()
//按字典顺序比较两个字符串
//int compareTo(String anotherString)
//4.切割: String[] split(String)
* 可变字符串: 字符串缓冲区 StringBuffer jdk1.0 :: 线程安全的要考虑线程安全问题 StringBuilder jdk1.5
* ::线程不安全的不需要考虑线程安全问题
*
* 区分: 在不考虑线程安全的情况下尽量使用StringBuilder效率高速度快
StringBuffer stf = new StringBuffer(); // 事实上先
/*
* public StringBuffer() { super(16); }
* AbstractStringBuilder(int capacity) { value = new char[capacity]; }
*/
//验证是不是一个对象(其没有修改内存) !!!!!!!!!!!!!!!!!!!!!!!!! 敲黑板哦,
System.out.println(stf.append("1") == stf.append("2")); //还是在比较地址
// 1.存储:
// StringBuffer append(boolean b) 从最后插入
// StringBuffer insert(int offset, boolean b) 从指定位置插入
// 2.删除:
// StringBuffer delete(int start, int end)
// StringBuffer deleteCharAt(int index)
// 3.修改:
// StringBuffer replace(int start, int end, String str) 替换指定的子字符串
// void setCharAt(int index, char ch) 修改一个字符
// 4.获取:
// char charAt(int index)
// int indexOf(String str)
// int indexOf(String str, int fromIndex)
// int lastIndexOf(String str)
// 返回指定子字符串(从右边开始计数)在此字符串第一次出现时的索引
// int lastIndexOf(String str, int fromIndex)
// 返回指定子字符串(从右边开始计数,范围:当前指定的位置-0)在此字符串第一次出现时的索引
// int length()
// 返回长度(字符数)。
// 5.反转:
// StringBuffer reverse()
Date
//1,系统默认提供的格式 有限的四种格式, 分别是short long full, default
//第一个参数是设计日期的格式, 第二个格式是这只时间的格式
DateFormat df = DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.SHORT );
Date d = new Date();
String s= df.format(d);
System.out.println(s);
//2,自定义的格式
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd hh:mm:sss");
s = simpleDateFormat.format(new Date());
System.out.println(s);
Math
System.out.println(Math.abs(-1));
System.out.println(Math.floor(4.4999)); //floor 向下取整
System.out.println(Math.ceil(4.4)); //ceil 向上取整
System.out.println((long)(Math.random()*10));
* 容器: 分为 Collection 和Map
*
* 区分容器和数组, 数组>>> 数组可以存储不同类型的多个数据, 数据类型 可以是简单数据类型也可以是引用数据类型 缺点: 创建的是一个定制,
* 只能存储固定长度的数据, 一旦存满了, 就不能再继续
*
* 容器>>> 可以存储不同类型的多个数据, 只能存储引用数据类型 缺点: 只能存储引用数据类型 优点: 存储空间会随着存储数据的增大而增大,
* 所以可以更加合理的利用内存空间, 方法较多, 方便实现功能
*
* 数据存储的分类>>> 短期存储: 一旦计算机关闭, 存储的数据会被立刻释放,-变量, 对象, 数组, 容器 长期存储: 直接存储到磁盘上,
* 数据不会随着计算机的关闭丢失
*
*
* Collection : >List >> ArrayList >> Vector >>LinkedList >Set >> HashSet
* >>TreeSet Map: >>HashMap >> TreeMap >> Hashtable
Collection c = new ArrayList();
Collection b = new LinkedList();
Collection a = new LinkedList();
// Collection中定义是整个集合体系最共性的方法:
// 1.添加:
// boolean add(Object o)
// boolean addAll(Collection extends E> c)
c.add("123");//arrlist中add是直接存进去引用, addall是复制一份内存加进去 linkedlist 也这样...
c.add("asd");
System.out.println(c);
b.add("dtryfhggjh");
c.addAll(b);
c.addAll(a);
System.out.println(c);
/*
* 当集合中存在不同类型的数据时, 需要进行容错处理
* 迭代器模式:就是提供一种方法对一个容器对象中的各个元素进行访问,而又不暴露该对象容器的内部细节。
*/
Iterator i = c.iterator();//迭代器刚刚创建出来时是指向一个类似于Head的东西的对象的地址的
System.out.println(i);
while(i.hasNext())//hasNext() 判断当前迭代器下一个位置是否有元素
System.out.println(i.next());//next() 将下一个位置的元素取出,并且位置向后移动1步
while(i.hasNext())//这里再进行遍历时会失败,因为当前的位置已经在集合的最后-_-|
System.out.println(i.next()); //想要再次遍历, 重新获取迭代器 Iterator
//foreach 事实上对集合的遍历也是通过迭代器实现的;
// 2.删除:
// boolean remove(Object o)
// boolean removeAll(Collection> c)
// void clear()
// 3.判断:
// boolean contains(Object o)
// boolean containsAll(Collection> c)
// boolean isEmpty() //判断集合是否为空
// boolean equals(Object o)
// 4.获取:
// Iterator
// int size() //获取集合中对象的个数
// 5.集合变数组:
// Object[] toArray()
/*
* ConcurrentModificationException: 当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。
*
* 例如,某个线程在 Collection 上进行迭代时,通常不允许另一个线性修改该
* Collection。通常在这些情况下,迭代的结果是不确定的。如果检测到这种行为,一些迭代器实现(包括 JRE 提供的所有通用
* collection 实现)可能选择抛出此异常。执行该操作的迭代器称为快速失败
* 迭代器,因为迭代器很快就完全失败,而不会冒着在将来某个时间任意发生不确定行为的风险。
*
* 注意,此异常不会始终指出对象已经由不同
* 线程并发修改。如果单线程发出违反对象协定的方法调用序列,则该对象可能抛出此异常。例如,如果线程使用快速失败迭代器在 collection
* 上迭代时直接修改该 collection,则迭代器将抛出此异常。
*
* 注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败操作会尽最大努力抛出
* ConcurrentModificationException。因此,为提高此类操作的正确性而编写一个依赖于此异常的程序是错误的做法,
* 正确做法是:ConcurrentModificationException 应该仅用于检测 bug。
*/
/*
* Collection List : 存储有先后顺序 可重复 ArrayList:数据结构是数组, 线程不安全, 查找效率高, 添加删除速度慢
* Vector : 数据结构是数组, 线程安全, 查找效率高, 添加删除速度慢,使用枚举器 LinkedList : 数据结构是链表, 线程不安全,使用迭代器;
* 查找效率低, 添加删除速度快 Set : 存储没有先后顺序 不可重复
*/
ListIterator i = list.listIterator(10);
while (i.hasNext()) {
System.out.println(i.next());
// if(true) i.remove();
}
while(i.hasPrevious()){
System.out.println(i.previous());
}
// * List:特有方法,可以操作下标
// 1.增:
// void add(int index, E element)
// boolean addAll(int index, Collection extends E> c)
// 2.删
// E remove(int index)
// 3.改
// E set(int index, E element)
// 4.查
// ListIterator
// 返回此列表元素的列表迭代器(按适当顺序)。
// ListIterator
// List
// E get(int index)
// 5.删除全部对象
//void clear()
// https://www.jianshu.com/p/724f763fd242
//使用ListIterator 期间不要用list带的 增加或删除操作 要使用 ListTerator自带的增删
* contains 使用indexOf return indexOf(o) >= 0;
/*Set
* 无序的
* HashSet 数据结构是Hash表
* TreeSet 数据结构是二叉树
* HashSet 去重先对比元素的HashCode, 然后如果HashCode相同使用元素的equals对比是否相同
* 所以想要使用HashSet 必须先 重写HashCode 然后重写equals()
* 由于HashSet是按照的HashCode添加元素和比较元素, 因此HashSet不能进行排序
*
* TreeSet 是使用了红黑树的数据结构 使用TreeSet时, 其在添加时会根据compareTo()[来自Compareable接口]方法添加, 输出时按前序输出,所以实现了排序
* 实现Compareable接口才能让对象实现比较大小的功能
* 所以想要使用TreeSet必须实现Compareable 接口 实现 compareTo 方法
*
* 对TreeSet排序有两种方式
* 1: 元素实现Compareable接口 的compareTo(),
* 2: 创建实现接口Compareator接口的对象(其中)
*/