异常学习笔记
知识点1:异常
1.异常的分类
1.按照程度来分
1.Error严重错误
2.Exception一般问题
2.按照处理方式来分
1) 受检异常(checked) 在程序中必须接受检查和处理的异常. 如果不处理编译错误,也称为编译时异常
Exception及其子类(RuntimeException及其子类除外)
2) 非受检异常(unchecked) 在程序中不是必须接受检查和处理的异常, 如果不处理不生编译错误, 但是运行时仍会出问题, 也称为运行时异常
Error及其子类.
RuntimeException及其子类.
2.异常处理:适用与所有异常,包括Error
1.捕获
try {
可能抛出异常的语句;
} catch (可能的异常类型1 引用) {
对异常处理.
} catch (可能的异常类型2 引用) {
对异常处理.
} .....
catch (Exception e) {
确保万无一失
} finally { // final 修饰符, 修饰类, 方法, 变量
释放不在GC区中资源, 而是由OS管理的资源. 比如文件,网络等硬件资源.
}
try catch
try catch finally
try finally
2.抛出:使用throws体现异常的抛出
在方法声明中的throws 异常类型列表, 作用是警告调用者, 此方法有风险.
在方法体中使用throw语句, 在方法中真的抛出异常对象.
可以只有throws而没有throw
只要有throw必须要有throws
throws 是警告
throw 是玩真的.
方法覆盖条件中对于异常的描述 :
要求如下 :
1) 方法签名一致, 子类方法的返回值的对象类型可以小于等于父类方法返回的对象类型.
2) 子类方法的访问控制修饰符的范围要大于等于父类的.
3) 被覆盖方法不可以被private, static, final.
4) 子类方法抛出的受检异常范围要小于等于父类方法抛出的受检异常.
3.先捕获再抛出
先
try {
可能抛出异常的语句;
} catch(任意异常类型 引用) {
throw new 自定义异常(引用);
}
处理方式的选择 :
1) 入口方法尽量捕获.
2) 功能方法尽量抛出.
3.自定义异常
自定义异常 : 1) 继承Exception 表明它是一个异常,
2) 提供2个构造器一个String,一个是Throwable 创建自定义异常对象方便
4.举例
class DividedByZeroException extends Exception { // 这是受检异常, 必须要处理
public DividedByZeroException(String message) {
super(message); // 间接调用到父类构造, 完成私有的detailMessage的初始化.
}
public DividedByZeroException(Throwable cause) { // 对象关联专用
super(cause);
}
}
public class ExceptionTest {
public static int divide(int x, int y) throws DividedByZeroException {
try {
return x / y;
} catch (ArithmeticException e) {
throw new DividedByZeroException(e); // 包装 : 自定义异常对象内部包含一个其他异常对象.
}
}
public static void main(String[] args) {
try {
try {
System.out.println(divide(10, 2));
System.out.println(divide(10, 0));
} catch (DividedByZeroException e) {
System.out.println(e.getMessage());
}
System.out.println(divide(20, 5));
} catch (DividedByZeroException e) {
e.printStackTrace();
} finally {
System.out.println("finally");
}
}
}
class ExceptionTest3 {
// throws的作用是警告调用者, 调用此方法有风险!!!
public static int divide(int x, int y) throws DividedByZeroException { // throws和throw最好要一致, 显得诚实
if (y == 0) {
// 真的抛出一个异常对象, 当前方法就会提前弹栈返回结束, 并给调用者产生破坏.
throw new DividedByZeroException("除数不可以为0错误!!!!");
}
return x / y;
}
//public static void main(String[] args) throws DividedByZeroException { main方法虽然可以抛出异常, 但是不要抛.
public static void main(String[] args) {
try {
System.out.println(divide(10, 2));
System.out.println(divide(10, 0));
} catch (DividedByZeroException e) {
System.out.println(e.getMessage());
}
System.out.println("end");
}
}
class ExceptionTest2 {
public static int divide(int x, int y) {
if (y == 0) {
RuntimeException re = new RuntimeException("除数不可以为0"); // throw和return效果一样, 都是让方法返回的
throw re;
// return 是和平返回, throw 带有破坏性的返回.
}
return x / y;
}
public static void main(String[] args) {
try {
System.out.println(divide(10, 2));
System.out.println(divide(10, 0));
} catch (RuntimeException e) {
System.out.println(e.getMessage());
}
System.out.println("end...");
}
}
class ExceptionTest1 {
public static void main(String[] args) {
System.out.println("main begin");
boolean b = true;
if (b) {
//return;
}
try {
int n = Integer.parseInt(args[0]);
System.out.println(n);
return;
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(e);
} catch (NumberFormatException e) {
System.out.println(e.getMessage());
} catch (Exception e) {
System.out.println("其他可能的异常 : " + e);
} finally {
// 无论前面try catch中发生什么, 我都要执行....
System.out.println("finally");
}
System.out.println("main end");
}
}
String类
1.概念
String 类的实例表示一个字符串,String 是一种不可变字符串,一对字符串进行改变操作,则创建一个全新的对象,然后把引用指向这个新的对象。
2.String的相关方法
* public int length(). string.length() => 35 获取字符串长度(字符数)
* public char charAt(int index) 获取指定下标位置处的字符 string.charAt(12) => '欢', string.charAt(18) => '我';
* public char[] toCharArray() 获取内部的char[]
* char result[] = new char[value.length]; // 创建一个新数组, 容量和内部的value一样大.
*
* for (int i = 0; i < value.length; i++) {
* result[i] = value[i];
* }
*
* System.arraycopy(value, 0, result, 0, value.length);
* // 第一个参数是源数组对象, 第二个参数是源数组的开始下标, 第三个参数是目标数组对象, 第四个参数是目标数组的开始下标
* // 第五个参数是要复制的元素个数.
举例
public class StringTest {
// 练习 : 把字符串反转一下
@Test
public void exer13() {
String string = " abcAQQY 我喜欢你,你喜欢我吗?我不喜欢你 zzz123 ";
char[] arr = string.toCharArray();
for (int i = 0; i < arr.length / 2; i++) {
// 首尾交换, i和length - 1 - i
char tmp = arr[i];
arr[i] = arr[arr.length - 1 - i];
arr[arr.length - 1 - i] = tmp;
}
String string2 = new String(arr);
System.out.println(string2);
}
@Test
public void exer12() {
String string = " abcAQQY 我喜欢你,你喜欢我吗?我不喜欢你 zzz123 ";
String string2 = "";
for (int i = 0; i < string.length(); i++) {
char ch = string.charAt(i);
string2 = ch + string2;
}
System.out.println(string2);
}
@Test
public void exer1() {
String string = " abcAQQY 我喜欢你,你喜欢我吗?我不喜欢你 zzz123 ";
String string2 = "";
for (int i = string.length() - 1; i >= 0 ; i--) {
char ch = string.charAt(i);
string2 += ch;
}
System.out.println(string2);
}
@Test
public void test5() {
String string = " abcAQQY 我喜欢你,你喜欢我吗?我不喜欢你 zzz123 ";
System.out.println(string.length());
System.out.println(string.charAt(13));
System.out.println(string.charAt(0));
System.out.println(string.charAt(32));
//System.out.println(string.charAt(500));
System.out.println("**************************");
for (int i = 0; i < string.length(); i++) {
char ch = string.charAt(i);
System.out.println(ch);
}
System.out.println("***************************");
char[] chars = string.toCharArray();
for (int i = 0; i < chars.length; i++) {
System.out.println(chars[i]);
}
}
@Test
public void test4() {
char[] arr = {'a', '1', 'q', '我', '3', '好', 'o'};
String s1 = new String(arr); // 制作一个副本
arr[1] = '大';
System.out.println(s1);
String s2 = new String(arr, 2, 3);// 第2个参数是开始下标, 第3个参数是长度
System.out.println(s2);
String s3 = new String(arr, 0, arr.length);
System.out.println(s3);
}
@Test
public void test3() {
String s1 = "hello";
String s2 = "java";
String s4 = "java";
String s3 = new String("java");
System.out.println(s2 == s3);
System.out.println(s2 == s4);
System.out.println(s2.equals(s3));
String s5 = "love";
// 字符串拼接时, 如果有变量参与, 结果一定是新字符串对象, 并且在堆.
String s6 = (s1 + s2).intern(); // intern() 作用是把字符串塞入常量区中, 如果常量区中已经有此对象了,则返回常量对象的地址.
System.out.println(s5 == s6); // true
System.out.println(s5.equals(s6));
}
@Test
public void test2() {
String s1 = new String();
String s2 = "";
String s3 = null;
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
String s4 = new String("qqq");
}
@Test
public void test1() {
String s1 = "abc";
s1 += "yyy";
System.out.println(s1);
}
}