java基础知识中有一些细节问题其实还是挺重要的,如果平时不注意可能就会犯错(面试中也有可能会问到),针对平时遇到的一些java基础知识中的一些细节做一些总结,以后遇到更多,再继续添加。
目录
1.异常机制中的finally
finally代码可以跟在try之后或者catch之后,finally内的代码不管有无异常发生,都会执行:具体来说:
如果没有异常发生,在try代码块内的代码执行结束后执行。
如果发生异常且被catch捕获,在catch内的代码执行结束后执行。
如果异常发生但是没有被捕获,则在异常被抛给上层之前执行。
由于finally的这个特点,它一般被用来释放资源,比如数据库连接,文件IO流等;
try...catch...finally语法中,catch不是必须的,可以只有try...finally,不捕获异常,异常自动向上传递,但finally中的代码在异常发生后也执行。
finally语句的执行细节:
如果在try或者catch代码块语句中有return语句,则return语句在finally语句执行结束后才执行,但是finally并不能改变返回值。看一个例子:
package com.xiaomifeng1010.rbacboot.common.util;
/**
* @author xiaomifeng1010
* @version 1.0
* @date: 2020/5/20 23:46
*/
public class JavaDetailTest {
public static void main(String[] args) {
System.out.println("执行finallyTest1方法后返回值:"+finallyTest1());
System.out.println("执行finallyTest2方法后返回值:"+finallyTest2());
}
public static int finallyTest1(){
int inv=0;
try {
return inv;
}finally {
inv=2;
}
}
public static int finallyTest2(){
int nv=0;
try {
int iv=5/0;
return nv;
}finally{
return 2;
}
}
}
运行后:
执行结果,第一种情况,方法的返回值是0,而不是2,实际执行过程是:在执行到try内的return inv;语句前,会先将返回值inv保存在一个临时变量中,然后才执行finally语句,最后try再返回那个临时变量,finally对inv的修改不会被返回,相当于try语句中的return延迟返回了,等finally语句执行完才返回的。
第二种情况比较好理解,第二种情况返回的是2,也就是直接返回了finally语句中的返回值。如果在finally中也有return语句,则try和catch内的return会丢失,实际会返回finally中的返回值。finally中有return不仅会覆盖try和catch中的返回值,还会掩盖try和catch内的异常,就像异常没有发生一样。代码中的5/0会触发ArithmeticException,但是finally中有return语句,这个方法会返回2,而不再向上传递异常了。finally中如果抛出了异常,则原异常也会被掩盖
改造一下第二个方法:
public static int finallyTest2(){
int nv=0;
try {
int iv=5/0;
return nv;
}finally{
throw new RuntimeException("啊哈出错了!");
}
}
2,一些数学运算引起的异常的差别
例如代码中出现1.0/0(注意除数是0,被除数是1.0浮点数)会不会抛出异常?
如果是1/0,又会抛出怎样的异常提示?
如果是0.0/0.0呢?
现在在ide工具中演示一下
public class ArithmeticOPerationTest {
public static void main(String[] args) {
System.out.println("1.0/0之后的结果:"+1.0/0);
System.out.println("1/0之后的结果:"+1/0);
System.out.println("0.0/0.0之后的结果:"+0.0/0.0);
}
}
执行之后:
第一个输出语句:输出的是Infinity,无限大的意思(数学中的无穷大∞)
第二个输出语句直接抛出了异常,算数异常 /by zero,原因是分母不能为0,因为分子是整形的
因为第二个语句抛出了异常,所以第三句没有执行,现在注释掉第二句,再执行一下:
第三句输出为NaN,是不是在JavaScript中有点熟悉 not a number,不是数字
(控制台中打印了jvm连接和断开信息,是因为idea中安装了jvisualvm的插件,并且配置了路径,刚才启动main方法时点成jvisualvm插件方式启动了,所以就有那两条语句。
3.数组和集合框架中需要注意的细节:
3.1 foreach可以循环遍历数组和集合,但是仅限于遍历集合用于查询,如果要对集合元素进行修改,例如插入和删除,则需要使用原生的迭代器模式来操作。
package com.xiaomifeng1010.rbacboot.common.util;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* @author xiaomifeng1010
* @version 1.0
* @date: 2020/5/21 0:37
*/
public class CollectionDetailTest {
public static void main(String[] args) {
List<String> list= new ArrayList<>();
list.add("xiaomifeng1010");
list.add("好好学习");
// 做查找(循环遍历时可以用foreach)
for (String str : list) {
System.out.println(str);
}
// 现在再添加一个元素,会报错(这里会抛出ConcurrentModificationException并发修改异常)
for (String modify :
list) {
if ("好好学习".equals(modify)){
list.add("才能找到好工作");
}
}
// 使用迭代器(这里也会抛出ConcurrentModificationException并发修改异常)
Iterator<String> it=list.iterator();
while (it.hasNext()){
if ("好好学习".equals(it.next())){
list.add("才能找到好工作!");
}
}
System.out.println(list.toString());
}
}
运行之后:
将foreach修改list注释掉,使用迭代器修改,第一种迭代器修改也会抛出异常
如果想在遍历的过程中添加元素,可以用ListIterator中的add方法
所以修改一下迭代器
package com.xiaomifeng1010.rbacboot.common.util;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
/**
* @author xiaomifeng1010
* @version 1.0
* @date: 2020/5/21 0:37
*/
public class CollectionDetailTest {
public static void main(String[] args) {
List<String> list= new ArrayList<>();
list.add("xiaomifeng1010");
list.add("好好学习");
// 做查找(循环遍历时可以用foreach)
// for (String str : list) {
// System.out.println(str);
// }
// 现在再添加一个元素,会报错(这里会抛出ConcurrentModificationException并发修改异常)
// for (String modify :
// list) {
// if ("好好学习".equals(modify)){
// list.add("才能找到好工作");
// }
// }
// 使用迭代器(这里也会抛出ConcurrentModificationException并发修改异常)
// Iterator<String> it=list.iterator();
// while (it.hasNext()){
// String str=it.next();
// if ("好好学习".equals(str)){
// list.add("才能找到好工作!");
// }
// }
// 使用ListIterator
ListIterator<String> listIterator = list.listIterator();
while (listIterator.hasNext()){
String str=listIterator.next();
if ("好好学习".equals(str)){
// 使用ListIterator中的add方法添加元素
listIterator.add("才能找到好工作");
}
}
System.out.println(list.toString());
}
}
3.2 注意Arrays这个工具类中的asList()方法,会返回一个List类型,但是注意,这个返回的List和集合框架中的各种List实现类是不同的,不能对返回的list做add等修改操作:
会抛出异常:不支持的操作
为什么会抛出异常呢?:asList的返回对象是一个Arrays内部类,并没有实现集合的修改方法。Arrays.asList体现的是适配器模式,只是转换接口,后台的数据仍是数组。
修改一下:
可以看到数组元素修改后,list元素也修改了;
再看一下源码:
返回的是一个ArrayList,但是这个ArrayList是Arrays类的内部类,并不是Collection接口下的那个实现类ArrayList
在看一下这个内部类ArrayList相关源码
是没有相关的修改操作的。今天挺晚了,先总结到这里,以后再添加内容吧!