第十二章
这一章节就讲解了JAVA中的整个异常体系
一.异常
异常指的就是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。
java.lang.Throwable类是java语言中所有错误或者异常的超类。在这个类下面就有一个Error(错误)还有一个Exception(异常)。
异常下面又分为几种不同异常。其中最主要的就是RuntimeException(运行期异常)。
二.throw关键字
作用:可以使用throw在指定方法中抛出指定的异常。
格式:throw new ....Exception(“异常的原因”)
throws语句用在方法定义时声明该方法要抛出的异常类型,如果抛出的是Exception异常类型,则该方法被声明为抛出所有的异常。多个异常可使用逗号分割。抛出几个异常就必须在方法定义后面写明抛出几个异常。
methodname throws Exception1,Exception2,..,ExceptionN { }
再看throw和throws具体怎么用: throws是在方法定义后面使用,而throw是在方法内部使用
package org.axc.com.Action;
import java.lang.Exception;
public class TestException {
public static void count(int x) throws MyException{
if(x>0) {
throw new MyException("发生了自定义的异常");
}
}
public static void main(String[] args) {
// 自己定义的异常如下
try {
count(3);
} catch (MyException e) {
e.printStackTrace();
}
// 通过try-catch正常触发的异常
try {
int num=1/0;
}catch(Exception e) {
System.out.println(e);
}
}
}
throw(非throws)注意事项:
1.throw关键字必须写在方法内部 2.throws关键字后边new的对象必须是Exception或者Exception的子类对象
3.throw关键字抛出的指定的异常对象,我们就必须处理,要么throws掉,要么try catch
所以当我们在方法内部使用throw抛出异常之后,我们就必须处理这个异常了。
三.两种处理异常的方式
1.throws抛出
将这个异常往上一级抛出,也就是方法的调用者处理(最终交给JVM处理,JVM会进行中断处理)
格式就像下面的代码,这里是抛出一个,如果有多个就抛出多个
public static void count(int x) throws MyException{}
注意:1.throws关键字要写在方法定义之后,也就是方法申明处
2.throws关键字后边声明的异常必须是Exception或者是Exception的子类
3.方法内部如果抛出了多个异常对象,那么throws后边必须也声明多个异常。如果抛出的多个异常对象有子父类关系,那么直接声明父类异常即可。
4.调用了一个声明抛出异常的方法,我们就必须处理这个异常。要么继续抛出,要么try catch
2.try catch(自己处理异常)
格式:
public static void main(String[] args) {
// 自己定义的异常如下
try {
count(3);
} catch (MyException e) {
e.printStackTrace();
}
// 通过try-catch正常触发的异常
try {
int num=1/0;
}catch(Exception e) {
System.out.println(e);
}
}
注意:1.可以使用多个catch来处理多个异常的情况
2.如果try中出现了异常,那么就会执行catch中的异常处理逻辑。执行完毕后,不会再执行try后面的代码,就直接执行try catch之后的代码。所以这里就要有finally(区分final,这不要搞混了)
四.finally关键字
当抛出异常的时候,剩余的代码就会终止执行,这时候一些资源就需要主动回收。Java 的解决方案就是 finally
子句——不管异常有没有被捕获,finally
子句里的代码都会执行。在下面的示例当中,输入流将会被关闭,以释放资源。
public static void main(String[] args) {
InputStream is = null;
try {
is = new FileInputStream("沉默王二.txt");
int b;
while ((b = is.read()) != -1) {}
} catch (IOException e) {
e.printStackTrace();
} finally {
is.close();
}
}
所以,finally关键字就是在这个代码块里的代码一定会被执行,不管出没出现异常,所以一般情况下,这finally里都是用来清理资源,释放资源的。
五.Throwable类中3个异常处理的方法
1.String getMessage():返回此throwable的简短描述
2.String toString():返回次throwable的详细消息字符串
3.void printStackTrace() JVM打印异常对象,默认此方法打印的异常信息是最全面的。
第十三章
一.string 不可变 它为什么不可变?
在面试中经常遇到这样的问题:1、什么是不可变对象。不可变对象有什么好处。在什么情景下使用它,或者更具体一点,java的String类为什么要设置成不可变类型?
首先我们必须知道String类是不可变得,String类中每一个看似在修改它内容的方法,都是先创建一个副本在副本上进行操作,根本没有对原始进行修改。再来说String对象为什么不可变,因为不可变是最有效率和最安全的。
相比于可变对象,不可变对象有很多优势:
(1)不可变对象可以提高String Pool(字符串常量池)的效率和安全性。如果你知道一个对象是不可变动 ,那么需要拷贝的对象的内容时就不用复制它本身二只是复制它的地址,复制地址(通常一个指针的大小)需要很小的内存,效率也很好。
(2)不可变对象对于多线程是安全的,因为在多线程同事进行的情况下,一个可变对象的值很可能被其他线程改变这样会造成不可预期的结果么人,使用不可变对象就可以避免这种情况出现。
二.String 类怎么做到不可变得
首先需要补充一个容易混淆的知识点:当使用final修饰基本类型变量时,不能对基本类型变量重新赋值,因此基本类型变量不能被改变。但对于引用类型变量而言,它保存的仅仅是一个引用,final只保证这个引用变量所引用的地址不会改变,即一直引用同一个对象,但这个对象完全可以发生改变。例如某个指向数组的final引用,它必须从此至终指向初始化时指向的数组,但是这个数组的内容完全可以改变。
我们来看一下String类的两个主要成员变量,其中value指向的是一个字符串数组,字符串中的字符就是用这个value变量存储起来的,并且用final修饰,也就是说value一旦赋予初始值之后,value指向的地址就不能再改变了。虽然value指向的数组是可以改变的,但是String也没有提供相应的方法让我们去修改value指向的数组的元素。然而在StringBuilder中是提供了相应的方法让我们去修改value指向的数组的元素,这也是StringBuilder的字符串序列可变的原因。
三. String类的操作
四.+ 和stringbuilder的关系
“+”可以连接两个字符串,如下面代码
String s = "abc"+"ddfa";
这样也完成了添加的效果,同样Stringbuilder类也有append()方法来添加。
使用“+”的时候,编译期会自动引入Stringbuilder类,但是每一个String字符串,都会创建一个Stringbuilder类对象,所以效率低下,浪费空间。所以一般添加字符串要用Stringbuilder类。
五.stringBuilder和stringBuffer
StringBuilder类提供多种方法:append toString insert replace substring reverse delete 等各种方法,效率高,但线程不安全。
StringBuffer和StringBuilder基本差不多,效率低,但是线程安全。
第十四章
1.instanceof 和 isInstance区别
功能上没有区别,两者判定结果是完全一致的。只是在用法的格式上有区别
instanceof 是一个操作符,它的用法 :
if (Obj a instanceof Class b) {
//logic
}
isInstance是一个方法,它的用法:
if(B.Class.isInstance(Obj a)){
}
2.反射 为什么要用反射
https://www.jianshu.com/p/9be58ee20dee
这篇博客已经总结非常详细了