一、JDK 和 JRE 有什么区别
JDK:Java Development Kit 的简称,Java 开发工具包,提供了 Java 的开发环境和运行环境。
JRE:Java Runtime Environment 的简称,Java 运行环境,为 Java 的运行提供了所需环境。
具体来说 JDK 其实包含了 JRE,同时还包含了编译 Java 源码的编译器 Javac,还包含了很多 Java 程序调试和分析的工具。简单来说:如果你需要运行 Java 程序,只需安装 JRE 就可以了,如果你需要编写 Java 程序,需要安装 JDK。
二、String 属于基础的数据类型吗?
String 不属于基础类型。
基础类型有 8 种:byte、boolean、char、short、int、float、long、double,而 String 属于应用类型。
三、自动装箱与拆箱?
装箱:将基本类型用它们对应的引用类型包装起来;
拆箱:将包装类型转换为基本数据类型;
很简单,下面两句代码就可以看到装箱和拆箱过程
//自动装箱
Integer total = 99;
//自定拆箱
int totalprim = total;
下面我们来看看需要装箱拆箱的类型有哪些:
四、获取用键盘输入常用的的两种方法?
方法1:通过 Scanner
Scanner input = new Scanner(System.in);
String s = input.nextLine();
input.close();
方法2:通过 BufferedReader
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String s = input.readLine();
五、Java如何生成随机数?
java中产生随机数的方法主要有三种:
【1】第一种:new Random()
需要借助java.util.Random类来产生一个随机数发生器,也是最常用的一种,构造函数有两个,Random()和Random(long seed)。第一个就是以当前时间为默认种子,第二个是以指定的种子值进行。
public static void main(String[] args){
Random r = new Random(1);
for(int i=0 ; i<5 ; i++){
int ran1 = r.nextInt(100);
System.out.println(ran1);
}
}
【2】第二种:Math.random()
使用java.lang.Math的random()方法,该方法返回的数值是[0.0,1.0)的double型数值,由于double类数的精度很高,可以在一定程度下看做随机数,借助(int)来进行类型转换就可以得到整数随机数了。
public static void main(String[] args){
int max=100,min=1;
int ran2 = (int) (Math.random()*(max-min)+min);
System.out.println(ran2);
}
【3】第三种:currentTimeMillis()
该方法虽然不常用,但是也是一种思路。方法返回从1970年1月1日0时0分0秒(这与UNIX系统有关)到现在的一个long型的毫秒数,取模之后即可得到所需范围内的随机数。
public static void main(String[] args){
int max=100,min=1;
long randomNum = System.currentTimeMillis();
int ran3 = (int) (randomNum%(max-min)+min);
System.out.println(ran3);
}
六、Java.util包常用的类或者接口有哪些?
1、集合相关的接口与其实现类:
(1)java.util.Collection、java.util.Map、java.util.List 、java.util.set、java.util.Iterator等接口
(2)ArrayList、LinkedList、HashMap、Hashtable等实现类
2、java.util.Collections类,包含了处理集合的各种方法。
3、java.util.Arrays类,包含了处理数组的各种方法.
4、java.util.Objects,继承自Object,可以算作Object工具类,包含了静态的处理对象的方法,如equals,deepEquals等;
5、时间处理相关的
(1)java.util.Date类,时间处理;
(2)java.util.Calendar,这个类是与时间操作有关的类,获取时间,时间加减,时间比较等;日期处理;
(3)java.util.Formatter类,用于格式化输出;
6、java.util.Random类,用于生成随机数;
7、java.util.Scanner类,主要用途用于键盘输入;
8、java.util.UUID类,生成全局唯一id;
9、java.util.Timer类,定时器,实际上是个线程,一般和TimerTask一起处理定时任务;
10、java.util.concurrent包:JUC包,是并发工具包。在此包中增加了在并发编程中很常用的工具类,用于定义类似于线程的自定义子系统,包括线程池,异步 IO 和轻量级任务框架
七、== 与 equals 区别
【1】== : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象。
(基本数据类型 == 比较的是值,引用数据类型 == 比较的是内存地址)
【2】equals() : 它的作用也是判断两个对象是否相等。
(equals 本质上就是 == ,只不过 String 和 Integer 等重写了 equals 方法,把它变成了值比较。也允许自己重写equals所以就灵活。)
它一般有两种使用情况:
情况1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。即比较内存地址。
情况2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来两个对象的内容相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。
class Cat {
public Cat(String name) {
this.name = name;
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Cat c1 = new Cat("精彩猿笔记");
Cat c2 = new Cat("精彩猿笔记");
System.out.println(c1.equals(c2)); // false
》》输出结果出乎我们的意料,竟然是 false?这是怎么回事,看了 equals 源码就知道了,源码如下:
public boolean equals(Object obj) {
return (this == obj);
}
》》原来 equals 本质上就是 ==。
》》那问题来了,两个相同值的 String 对象,为什么返回的是 true?代码如下:
String s1 = new String("精彩猿笔记");
String s2 = new String("精彩猿笔记");
System.out.println(s1.equals(s2)); // true
同样的,当我们进入 String 的 equals 方法,找到了答案,代码如下:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
原来是 String 重写了 Object 的 equals 方法,把引用比较改成了值比较。
》》总结 :== 对于基本类型来说是值比较,对于引用类型来说是比较的是引用;
而 equals 默认情况下是引用比较,只是很多类重新了 equals 方法,
比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等。
public class Test {
public static void main(String[] args){
//【1】String 的比较
//==比较的是内存地址 equals比较的也是内存地址 但是很多常用的String Interger等对象重写了
// equals方法 所以比较的是内容 。可以看出来 是 =""的方式 == 就是true ,而= new String()的方式 ==就是false。
String a1 ="1";
String a2 ="1";
String b1 = new String("1");
String b2 = new String("1");
String c1 ="12587965";
String c2 ="12587965";
String d1 ="-12587965";
String d2 ="-12587965";
System.out.println(a1==a2);
System.out.println(a1.equals(a2));
System.out.println(b1==b2);
System.out.println(b1.equals(b2));
System.out.println(c1==c2);
System.out.println(d1==d2);
//【2】Interger比较
//Integer为对象判断是否相等还是使用equals最靠谱,int为基本类型,判断是否相等就是可以使用==。
//Integer用==时,在-128到127范围就相等,不在就不等
Integer i1 = 15678;
Integer i2 = 15678;
System.out.println(i1==i2);
}
}
八、两个对象的 hashCode() 相同,则 equals() 也一定为 true,对吗?
不对,两个对象的 hashCode() 相同,equals() 不一定 true。
代码示例:
String str1 = “精彩”;
String str2 = “笔记”;
System. out. println(String. format(“str1:%d | str2:%d”, str1. hashCode(),str2. hashCode()));
System. out. println(str1. equals(str2));
执行的结果:
str1:1179395 | str2:1179395
false
执行解读:很显然“精彩”和“笔记”的 hashCode() 相同,然而 equals() 则为 false,因为在散列表中,hashCode() 相等即两个键值对的哈希值相等,然而哈希值相等,并不一定能得出键值对相等。
源码:hashCode是继承自Object的方法,首先看hashCode方法的定义:
public native int hashCode();
可见hashCode方法是一个native方法【“A native method is a Java method whose implementation is provided by non-java code.”】,因为native方法是由非Java语言实现的,所以这个方法的定义中也没有具体的实现。根据jdk文档,该方法的实现一般是“通过将该对象的内部地址转换成一个整数来实现的”,这个返回值就作为该对象的哈希码值返回。
结论:两个对象equals相等,则它们的hashcode必须相等,反之则不一定。
九、final 在 Java 中有什么作用?
final关键字主要用在三个地方:变量、方法、类。
- 对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的 变量,则在对其初始化之后便不能再让其指向另一个对象。
- 使用final方法的原因有两个。
第一个原因是把方法锁定,以防任何继承类修改它的含义;
第二个原因是效率。
在早期的Java实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的 任何性能提升(现在的Java版本已经不需要使用final方法进行这些优化了)。类中所有的private方法都隐式地 指定为final。 - 当用final修饰一个类时,表明这个类不能被继承。final类中的所有成员方法都会被隐式地指定为final方法。
九、static 在 Java 中有什么作用?
static关键字主要用在三个地方:变量、方法、代码块、类。
1、对于static变量:相当于是类变量,全局共享,调用不需要实例化,类.变量名
2、对于static方法:相当于是类方法,不能访问类的⾮静态成员变量和⾮静态成员⽅法,调用不需要实例化,类.方法名即可
3、static代码块:
【1】加载类的时候,静态代码块会被执⾏⼀次,且只能执⾏⼀次
【2】静态内容优先于⾮静态内容,所以静态代码⽐构造⽅法先执⾏
【3】使⽤场景:⽤来⼀次性对静态成员变量进⾏赋值,或者类资源初始化等操作
4、static类:静态内部类
十、String 类的常用方法都有那些?
indexOf():返回指定字符的索引。
charAt():返回指定索引处的字符。
replace():字符串替换。
trim():去除字符串两端空白。
split():分割字符串,返回一个分割后的字符串数组。
getBytes():返回字符串的 byte 类型数组。
length():返回字符串长度。
toLowerCase():将字符串转成小写字母。
toUpperCase():将字符串转成大写字符。
substring():截取字符串。
equals():字符串比较。
十一、Java 中操作字符串都有哪些类?它们之间有什么区别?
操作字符串的类有:String、StringBuffer、StringBuilder。
三者区别:
【1】可变性:
简单的来说:String 类中使用 final 关键字字符数组保存字符串,private final char value[] ,所以 String对象是不可变的。而StringBuilder 与 StringBuffer 都继承自 AbstractStringBuilder 类,在 AbstractStringBuilder 中也是使用字符数组保存字符串, 存储数据的字符数组没有被final修饰,说明值可以改变,抽象类AbstractStringBuilder内部都提供了一个自动扩容机制,当发现长度不够的时候(初始默认长度是16),会自动进行扩容工作,扩展为原数组长度的2倍加2,创建一个新的数组,并将数组的数据复制到新数组,所以对于拼接字符串效率要比String要高。
【2】线程安全性
String 中的对象是不可变的,也就可以理解为常量,线程安全。
StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。
StringBuilder 并没有对 方法进行加同步锁,所以是非线程安全的。
【3】性能
每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象。
StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用 StirngBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。
使用总结:
- 操作少量的数据 = String
- 单线程操作字符串缓冲区下操作大量数据 = StringBuilder
- 多线程操作字符串缓冲区下操作大量数据 = StringBuffer
十二、如何将字符串反转?
使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。
示例代码:
// StringBuffer reverse
StringBuffer stringBuffer = new StringBuffer();
stringBuffer. append("abcdefg");
System. out. println(stringBuffer. reverse()); // gfedcba
// StringBuilder reverse
StringBuilder stringBuilder = new StringBuilder();
stringBuilder. append("abcdefg");
System. out. println(stringBuilder. reverse()); // gfedcba
十三、普通类和抽象类有哪些区别?
【1】普通类不能包含抽象方法,抽象类可以包含抽象方法。
【2】抽象类是不能被实例化的,就是不能用new调出构造方法创建对象,普通类可以直接实例化。
【3】如果一个类继承于抽象类,则该子类必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,则必须将子类也定义为abstract类。
十四、接口和抽象类的区别是什么
【1】 接口的方法默认是 public,所有方法在接口中不能有实现(Java 8 开始接口方法可以有默认实现),抽象类可以 有非抽象的方法
【2】接口中的实例变量默认是 final 类型的,而抽象类中则不一定
【3】 一个类可以实现多个接口,但最多只能实现一个抽象类
【4】一个类实现接口的话要实现接口的所有方法,而抽象类不一定
【5】 接口不能用 new 实例化,但可以声明,但是必须引用一个实现该接口的对象 从设计层面来说,抽象是对类的抽 象,是一种模板设计,接口是行为的抽象,是一种行为的规范。
》》备注:在JDK8中,接口也可以定义静态方法,可以直接用接口名调用。实现类和实现是不可以调用的。如果同时实现 两个接口,接口中定义了一样的默认方法,必须重写,不然会报错。
》》版本区别:
关于抽象类
JDK 1.8以前,抽象类的方法默认访问权限为protected
JDK 1.8时,抽象类的方法默认访问权限变为default
关于接口
JDK 1.8以前,接口中的方法必须是public的
JDK 1.8时,接口中的方法可以是public的,也可以是default的
JDK 1.9时,接口中的方法可以是private的
十五、抽象类能使用 final 修饰吗?
不能,定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能修饰抽象类。
十六、Object类的常见方法总结
public final native Class<?> getClass()
//native方法,用于返回当前运行时对象的Class对象,使用了 final关键字修饰,故不允许子类重写。
public native int hashCode()
//native方法,用于返回对象的哈希码,主要使用在哈希表中,比如JDK中的 HashMap。
public boolean equals(Object obj)
//用于比较2个对象的内存地址是否相等,String类对该方法进行了重写用 户比较字符串的值是否相等。
protected native Object clone() throws CloneNotSupportedException
//naitive方法,用于创建并返 回当前对象的一份拷贝。一般情况下,对于任何对象 x,表达式 x.clone() != x 为true,
x.clone().getClass() == x.getClass() 为true。Object本身没有实现Cloneable接口,所以不重写clone 方法并且进行调用的话会发生CloneNotSupportedException异常。
public String toString()
//返回类的名字@实例的哈希码的16进制的字符串。建议Object所有的子类都重写这个 方法。
public final native void notify()
//native方法,并且不能重写。唤醒一个在此对象监视器上等待的线程(监 视器相当于就是锁的概念)。如果有多个线程在等待只会任意唤醒一个。
public final native void notifyAll()
//native方法,并且不能重写。跟notify一样,唯一的区别就是会唤 醒在此对象监视器上等待的所有线程,而不是一个线程。
public final native void wait(long timeout) throws InterruptedException
//native方法,并且不 能重写。暂停线程的执行。注意:sleep方法没有释放锁,而wait方法释放了锁 。timeout是等待时间。
public final void wait(long timeout, int nanos) throws InterruptedException
//多了nanos参 数,这个参数表示额外时间(以毫微秒为单位,范围是 0-999999)。 所以超时的时间还需要加上nanos毫秒。
public final void wait() throws InterruptedException
//跟之前的2个wait方法一样,只不过该方法一直 等待,没有超时时间这个概念
protected void finalize() throws Throwable { }
//实例被垃圾回收器回收的时候触发的操作
十七、重载和重写的区别
【1】重载:
1)含义:重载(Overload)
重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
最常用的地方就是构造器的重载。
2)区别:发生在同一个类中,方法名必须相同,参数类型 或者 参数个数 或者 参数顺序不同,方法返回值和访问修饰符可以不同,发生在编译时。
【2】重写:
1)含义:重写(Override)
重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!
重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。
2)区别:发生在父子类中,方法名、参数列表(类型,个数,顺序)必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类, 访问修饰符范围大于等于父类;如果父类方法访问修饰符为 private 则子类就不能重写该方法。
十八、Java中this 与 super用法与含义
this: 是自身的一个对象,代表对象本身,用法大致分为以下3类:
1、普通直接引用当前对象本身
2、形参和成员名重名,用this来区分
3、引用构造方法 ,this(参数) ,应该为构造函数中的第一条语句,调用的事1本类中另外一种形式的构造方法。
super:可以理解为是指向自己超(父)类对象,这个超类指的是离自己最近的一个父类。也大致分为3中中用法
1、普通的直接引用,与this类似,只不过它是父类对象,可以通过它调用父类成员。
2、子类中的成员变量或方法与父类中的成员变量或方法同名,可以使用super区分。
3、引用构造方法,super(参数):调用父类中的某一个构造方法(应该为构造方法中的第一条语句)。
示例:
class Person {
public static void prt(String s) {
System.out.println(s);
}
//构造方法(1)
Person() {
prt("父类·无参数构造方法: "+"A Person");
}
//构造方法(2)
Person(String name) {
prt("父类·含一个参数的构造方法: "+"A person's name is " + name);
}
}
public class Chinese extends Person {
Chinese() {
super(); // 调用父类构造方法(1)
prt("子类·调用父类无参数构造方法" + "A chinese coder");
}
Chinese(String name) {
super(name);// 调用父类具有相同形参的构造方法(2)
prt("子类·调用父类”含一个参数的构造方法“: "+"his name is " + name);
}
Chinese(String name, int age) {
this(name);// 调用具有相同形参的构造方法(3)-->调用(2)
prt("子类:调用子类具有相同形参的构造方法:his age is " + age);
}
public static void main(String[] args) {
Chinese cn = new Chinese();
cn = new Chinese("people");
cn = new Chinese("people", 18);
}
}
总结:
1、super()和this()类似,区别是,super()从子类中调用父类的构造方法,this()在同一类内调用其它方法。
2、super()和this()均需放在构造方法内第一行。
3、尽管可以用this调用一个构造器,但却不能调用两个。
4、this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。
5、this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。
6、从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。
十九、Java 中 IO 流分为几种
【1】按功能来分:输入流(input)、输出流(output)。
【2】按类型来分:字节流和字符流。
字节流和字符流的区别是:字节流按 8 位传输以字节为单位输入输出数据,字符流按 16 位传输以字符为单位输入输出数据。
二十、BIO、NIO、AIO 有什么区别
【1】BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。
【2】NIO:New IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。
【3】AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。
二十一、Files的常用方法都有哪些?
Files. exists():检测文件路径是否存在。
Files. createFile():创建文件。
Files. createDirectory():创建文件夹。
Files. delete():删除一个文件或目录。
Files. copy():复制文件。
Files. move():移动文件。
Files. size():查看文件个数。
Files. read():读取文件。
Files. write():写入文件。
···
二十二、为什么要使用克隆?
克隆的对象可能包含一些已经修改过的属性,而 new 出来的对象的属性都还是初始化时候的值,所以当需要一个新的对象来保存当前对象的“状态”就靠克隆方法了。
二十三、如何实现对象克隆?
实现 Cloneable 接口并重写 Object 类中的 clone() 方法。
实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。
二十四、深拷贝和浅拷贝区别是什么?
【1】浅拷贝:当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。
【2】深拷贝:除了对象本身被复制外,对象所包含的所有成员变量也将复制。
二十五、Java 中的异常处理简介
1、要理解Java异常处理是如何工作的,你需要掌握以下三种类型的异常:
【1】 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
【2】运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
【3】错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
2、Java异常类层次结构图
在 Java 中,所有的异常都有一个共同的祖先java.lang包中的 Throwable类。
【1】Throwable: 有两个重要的子类:Exception(异常) 和 Error(错误) ,二者都是 Java 异常处理的重要子类,各自都包含大量子类。
【2】Error(错误):是程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。例如,Java虚拟机运行错误(Virtual MachineError),当JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。
这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,如Java虚拟机运行错误(Virtual MachineError)、类定义错误(NoClassDefFoundError)等。这些错误是不可查的,因为它们在应用程序的控制和处理能力之 外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。在 Java中,错误通过Error的子类描述。
【3】Exception(异常):是程序本身可以处理的异常。
【4】Exception 类有一个重要的子类 RuntimeException。
RuntimeException 异常由Java虚拟机抛出。NullPointerException(要访问的变量没有引用任何对象时,抛出该异常)、ArithmeticException(算术运算异常,一个整数除以0时,抛出该异常)和ArrayIndexOutOfBoundsException (下标越界异常)。
注意:异常和错误的区别:异常能被程序本身可以处理,错误是无法处理。
二十六、throw 和 throws 的区别?
【1】throw:是真实抛出一个异常。碰到异常:自己处理或者自己捕获但是不想处理 再throw 出去。
【2】throws:是声明可能会抛出一个或者多个异常。谁调用我谁再处理。必须跟在方法参数列表的后面,不能单独使用。
二十七、final、finally、finalize 有什么区别?
【1】final:是修饰符,如果修饰类,此类不能被继承;如果修饰方法和变量,则表示此方法和此变量不能在被改变,只能使用。
【2】finally:是 try{} catch{} finally{} 最后一部分,表示不论发生任何情况都会执行,finally 部分可以省略,但如果 finally 部分存在,则一定会执行 finally 里面的代码。
【3 】finalize: 是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法。
二十八、try-catch-finally 中哪个部分可以省略?
try-catch-finally 其中 catch 和 finally 都可以被省略,但是不能同时省略,也就是说有 try 的时候,必须后面跟一个 catch 或者 finally。
二十九、try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?
finally 一定会执行,即使是 catch 中 return 了,catch 中的 return 会等 finally 中的代码执行完之后,才会执行。
三十、常见的异常类有哪些?
NullPointerException 空指针异常
ClassNotFoundException 指定类不存在
NumberFormatException 字符串转换为数字异常
IndexOutOfBoundsException 数组下标越界异常
ClassCastException 数据类型转换异常
FileNotFoundException 文件未找到异常
NoSuchMethodException 方法不存在异常
IOException IO 异常
SocketException Socket 异常
···