1. try {}里有一个 return 语句,那么紧跟在这个 try 后的 finally{}里的 code 会不会被执行,什么时候被执行,在 return 前还是后?
咱们晓得 finally{}中的语句是肯定会执行的,那么这个可能失常脱口而出就是 return 之前,return 之后可能就出了这个办法了,鬼晓得跑哪里去了,但更精确的应该是在 return 两头执行,请看上面程序代码的运行后果:
public classTest {public static void main(String[]args) {System.out.println(newTest().test());;
}
static int test()
{
intx = 1;
try
{return x;}
finally
{++x;}
}
}
执行后果如下:
1
运行后果是 1,为什么呢?主函数调用子函数并失去后果的过程,好比主函数筹备一个空罐子,当子函数要返回后果时,先把后果放在罐子里,而后再将程序逻辑返回到主函数。所谓返回,就是子函数说,我不运行了,你主函数持续运行吧,这没什么后果可言,后果是在说这话之前放进罐子里的。
22. 运行时异样与个别异样有何异同?
异样示意程序运行过程中可能呈现的非正常状态,运行时异样示意虚拟机的通常操作中可能遇到的异样,是一种常见运行谬误。java 编译器要求办法必须申明抛出可能产生的非运行时异样,然而并不要求必须申明抛出未被捕捉的运行时异样。
24W 字 Java 面试手册下载地址:https://shimo.im/docs/Wyj8QRp…
24W 字 Java 面试手册下载地址:https://shimo.im/docs/Wyj8QRp…
24W 字 Java 面试手册下载地址:https://shimo.im/docs/Wyj8QRp…
23. error 和 exception 有什么区别?
error 示意复原不是不可能但很艰难的状况下的一种重大问题。比如说内存溢出。不可能指望程序能解决这样的状况。exception 示意一种设计或实现问题。也就是说,它示意如果程序运行失常,从不会产生的状况。
24. 简略说说 Java 中的异样解决机制的简略原理和利用。
异样是指 java 程序运行时(非编译)所产生的非正常状况或谬误,与现实生活中的事件很类似,现实生活中的事件能够蕴含事件产生的工夫、地点、人物、情节等信息,能够用一个对象来示意,Java 应用面向对象的形式来解决异样,它把程序中产生的每个异样也都别离封装到一个对象来示意的,该对象中蕴含有异样的信息。
Java 对异样进行了分类,不同类型的异样别离用不同的 Java 类示意,所有异样的根类为 java.lang.Throwable。
Throwable 上面又派生了两个子类:
- Error 和 Exception,Error 示意应用程序自身无奈克服和复原的一种重大问题,程序只有奔溃了,例如,说内存溢出和线程死锁等零碎问题。
- Exception 示意程序还可能克服和复原的问题,其中又分为零碎异样和一般异样:
零碎异样是软件自身缺点所导致的问题,也就是软件开发人员考虑不周所导致的问题,软件使用者无奈克服和复原这种问题,但在这种问题下还能够让软件系统持续运行或者让软件挂掉,例如,数组脚本越界(ArrayIndexOutOfBoundsException),空指针异样(NullPointerException)、类转换异样(ClassCastException);
一般异样是运行环境的变动或异样所导致的问题,是用户可能克服的问题,例如,网络断线,硬盘空间不够,产生这样的异样后,程序不应该死掉。
java 为零碎异样和一般异样提供了不同的解决方案,编译器强制一般异样必须 try..catch 解决或用 throws 申明持续抛给下层调用办法解决,所以一般异样也称为 checked 异样,而零碎异样能够解决也能够不解决,所以,编译器不强制用 try..catch 解决或用 throws 申明,所以零碎异样也称为 unchecked 异样。
25. == 和 equals 的区别是什么?
“==”
对于根本类型和援用类型 == 的作用成果是不同的,如下所示:
- 根本类型:比拟的是值是否雷同;
- 援用类型:比拟的是援用是否雷同;
String x = "string";
String y = "string";
String z = new String("string");
System.out.println(x==y); // true
System.out.println(x==z); // false
System.out.println(x.equals(y)); // true
System.out.println(x.equals(z)); // true
因为 x 和 y 指向的是同一个援用,所以 == 也是 true,而 new String()办法则重写开拓了内存空间,所以 == 后果为 false,而 equals 比拟的始终是值,所以后果都为 true。
equals
equals 实质上就是 ==,只不过 String 和 Integer 等重写了 equals 办法,把它变成了值比拟。看上面的代码就明确了。
首先来看默认状况下 equals 比拟一个有雷同值的对象,代码如下:
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 比拟的是值是否相等。
26. Hashcode 的作用
java 的汇合有两类,一类是 List,还有一类是 Set。前者有序可反复,后者无序不反复。当咱们在 set 中插入的时候怎么判断是否曾经存在该元素呢,能够通过 equals 办法。然而如果元素太多,用这样的办法就会比拟满。
于是有人创造了哈希算法来进步汇合中查找元素的效率。这种形式将汇合分成若干个存储区域,每个对象能够计算出一个哈希码,能够将哈希码分组,每组别离对应某个存储区域,依据一个对象的哈希码就能够确定该对象应该存储的那个区域。
hashCode 办法能够这样了解:它返回的就是依据对象的内存地址换算出的一个值。这样一来,当汇合要增加新的元素时,先调用这个元素的 hashCode 办法,就一下子能定位到它应该搁置的物理地位上。如果这个地位上没有元素,它就能够间接存储在这个地位上,不必再进行任何比拟了;如果这个地位上曾经有元素了,就调用它的 equals 办法与新元素进行比拟,雷同的话就不存了,不雷同就散列其它的地址。这样一来理论调用 equals 办法的次数就大大降低了,简直只须要一两次。
24W 字 Java 面试手册下载地址:https://shimo.im/docs/Wyj8QRp…
24W 字 Java 面试手册下载地址:https://shimo.im/docs/Wyj8QRp…
24W 字 Java 面试手册下载地址:https://shimo.im/docs/Wyj8QRp…
27. 两个对象的 hashCode() 雷同,那么 equals() 也肯定为 true 吗?
不对,两个对象的 hashCode() 雷同,equals() 不肯定 true。
代码示例:
String str1 = "keep";
String str2 = "brother";
System. out. println(String. format("str1:%d | str2:%d", str1. hashCode(),str2. hashCode()));
System. out. println(str1. equals(str2));
执行后果:
str1:1179395 | str2:1179395
false
代码解读:很显然“keep”和“brother”的 hashCode() 雷同,然而 equals() 则为 false,因为在散列表中,hashCode() 相等即两个键值对的哈希值相等,然而哈希值相等,并不一定能得出键值对相等。
28. 泛型罕用特点
泛型是 Java SE 1.5 之后的个性,《Java 核心技术》中对泛型的定义是:
“泛型”意味着编写的代码能够被不同类型的对象所重用。
“泛型”,顾名思义,“泛指的类型”。咱们提供了泛指的概念,但具体执行的时候却能够有具体的规定来束缚,比方咱们用的十分多的 ArrayList 就是个泛型类,ArrayList 作为汇合能够寄存各种元素,如 Integer, String,自定义的各种类型等,但在咱们应用的时候通过具体的规定来束缚,如咱们能够束缚汇合中只寄存 Integer 类型的元素,如
List<Integer> iniData = new ArrayList<>()
应用泛型的益处?
以汇合来举例,应用泛型的益处是咱们不用因为增加元素类型的不同而定义不同类型的汇合,如整型汇合类,浮点型汇合类,字符串汇合类,咱们能够定义一个汇合来寄存整型、浮点型,字符串型数据,而这并不是最重要的,因为咱们只有把底层存储设置了 Object 即可,增加的数据全副都可向上转型为 Object。更重要的是咱们能够通过规定依照本人的想法管制存储的数据类型。
29. 面向对象的特色
面向对象的编程语言有封装、继承、形象、多态等 4 个次要的特色。
- 封装:把形容一个对象的属性和行为的代码封装在一个模块中,也就是一个类中,属性用变量定义,行为用办法进行定义,办法能够间接拜访同一个对象中的属性。
- 形象:把现实生活中的对象形象为类。分为过程形象和数据抽象
- 数据抽象 –> 鸟有翅膀, 羽毛等(类的属性)
- 过程形象 –> 鸟会飞, 会叫(类的办法)
- 继承:子类继承父类的特色和行为。子类能够有父类的办法,属性(非 private)。子类也能够对父类进行扩大,也能够重写父类的办法。毛病就是进步代码之间的耦合性。
- 多态:多态是指程序中定义的援用变量所指向的具体类型和通过该援用变量收回的办法调用在编程时并不确定,而是在程序运行期间才确定(比方:向上转型,只有运行能力确定其对象属性)。办法笼罩和重载体现了多态性。
30. Java 多态的了解
- 多态是继封装、继承之后,面向对象的第三大个性。
- 多态现实意义了解:
- 事实事物常常会体现出多种状态,如学生,学生是人的一种,则一个具体的同学张三既是学生也是人,即呈现两种状态。
- Java 作为面向对象的语言,同样能够形容一个事物的多种状态。如 Student 类继承了 Person 类,一个 Student 的对象便既是 Student,又是 Person。
- 多态体现为父类援用变量能够指向子类对象。
- 前提条件:必须有子父类关系。
留神:在应用多态后的父类援用变量调用办法时,会调用子类重写后的办法。
- 多态的定义与应用格局
定义格局:父类类型 变量名 =new 子类类型();
31. 重载和重写的区别
重写(Override)
从字面上看,重写就是 从新写一遍的意思。其实就是在子类中把父类自身有的办法从新写一遍。子类继承了父类原有的办法,但有时子类并不想一成不变的继承父类中的某个办法,所以在办法名,参数列表,返回类型 (除过子类中办法的返回值是父类中办法返回值的子类时) 都雷同的状况下,对办法体进行批改或重写,这就是重写。但要留神子类函数的拜访润饰权限不能少于父类的。
public class Father {public static void main(String[] args) {
// TODO Auto-generated method stub
Son s = new Son();
s.sayHello();}
public void sayHello() {System.out.println("Hello");
}
}
class Son extends Father{
@Override
public void sayHello() {
// TODO Auto-generated method stub
System.out.println("hello by");
}
}
重写 总结:
1. 产生在父类与子类之间
2. 办法名,参数列表,返回类型(除过子类中办法的返回类型是父类中返回类型的子类)必须雷同
3. 拜访修饰符的限度肯定要大于被重写办法的拜访修饰符(public>protected>default>private)
4. 重写办法肯定不能抛出新的查看异样或者比被重写办法申明更加宽泛的查看型异样
重载(Overload)
在一个类中,同名的办法如果有不同的参数列表(参数类型不同、参数个数不同甚至是参数程序不同 )则视为重载。同时,重载对返回类型没有要求,能够雷同也能够不同,但 不能通过返回类型是否雷同来判断重载。
public class Father {public static void main(String[] args) {
// TODO Auto-generated method stub
Father s = new Father();
s.sayHello();
s.sayHello("wintershii");
}
public void sayHello() {System.out.println("Hello");
}
public void sayHello(String name) {System.out.println("Hello" + " " + name);
}
}
重载 总结:
1. 重载 Overload 是一个类中多态性的一种体现
2. 重载要求同名办法的参数列表不同(参数类型,参数个数甚至是参数程序)
3. 重载的时候,返回值类型能够雷同也能够不雷同。无奈以返回型别作为重载函数的辨别规范
24W 字 Java 面试手册下载地址:https://shimo.im/docs/Wyj8QRp…
24W 字 Java 面试手册下载地址:https://shimo.im/docs/Wyj8QRp…
24W 字 Java 面试手册下载地址:https://shimo.im/docs/Wyj8QRp…
33. Java 创建对象有几种形式?
java 中提供了以下四种创建对象的形式:
- new 创立新对象
- 通过反射机制
- 采纳 clone 机制
- 通过序列化机制
34. ConcurrentModificationException 异样呈现的起因
public class Test {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<Integer>();
list.add(2);
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()){Integer integer = iterator.next();
if(integer==2)
list.remove(integer);
}
}
}
执行上段代码是有问题的,会抛出 ConcurrentModificationException
异样。
起因 :调用list.remove()
办法导致 modCount
和expectedModCount
的值不统一。
final void checkForComodification() {if (modCount != expectedModCount)
throw new ConcurrentModificationException();}
解决办法 :在迭代器中如果要删除元素的话,须要调用Iterator
类的 remove
办法。
public class Test {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<Integer>();
list.add(2);
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()){Integer integer = iterator.next();
if(integer==2)
iterator.remove(); // 留神这个中央}
}
}
35. HashMap 和 HashTable、ConcurrentHashMap 区别?
相同点:
- HashMap 和 Hashtable 都实现了 Map 接口
- 都能够存储 key-value 数据
不同点:
- HashMap 能够把 null 作为 key 或 value,HashTable 不能够
- HashMap 线程不平安,效率高。HashTable 线程平安,效率低。
- HashMap 的迭代器 (Iterator) 是 fail-fast 迭代器,而 Hashtable 的 enumerator 迭代器不是 fail-fast 的。
什么是 fail-fast?
就是最快的工夫能把谬误抛出而不是让程序执行。
36. 如何保障线程平安又效率高?
Java 5 提供了 ConcurrentHashMap,它是 HashTable 的代替,比 HashTable 的扩展性更好。
ConcurrentHashMap 将整个 Map 分为 N 个 segment(相似 HashTable),能够提供雷同的线程平安,然而效率晋升 N 倍,默认 N 为 16。
37. 咱们是否让 HashMap 同步?
HashMap 能够通过上面的语句进行同步:
Map m = Collections.synchronizeMap(hashMap);
38. Java 中 IO 流分为几种?
按性能来分:输出流(input)、输入流(output)。
按类型来分:字节流和字符流。
字节流和字符流的区别是:字节流按 8 位传输以字节为单位输入输出数据,字符流按 16 位传输以字符为单位输入输出数据。
39. BIO、NIO、AIO 有什么区别?
- BIO:Block IO 同步阻塞式 IO,就是咱们平时应用的传统 IO,它的特点是模式简略使用方便,并发解决能力低。
- NIO:Non IO 同步非阻塞 IO,是传统 IO 的降级,客户端和服务器端通过 Channel(通道)通信,实现了多路复用。
- AIO:Asynchronous IO 是 NIO 的降级,也叫 NIO2,实现了异步非梗塞 IO,异步 IO 的操作基于事件和回调机制。
40. Files 的罕用办法都有哪些?
- Files. exists():检测文件门路是否存在。
- Files. createFile():创立文件。
- Files. createDirectory():创立文件夹。
- Files. delete():删除一个文件或目录。
- Files. copy():复制文件。
- Files. move():挪动文件。
- Files. size():查看文件个数。
- Files. read():读取文件。
- Files. write():写入文件。
41. Java 反射的作用于原理
1、定义:
反射机制是在运行时,对于任意一个类,都可能晓得这个类的所有属性和办法;对于任意个对象,都可能调用它的任意一个办法。在 java 中,只有给定类的名字,就能够通过反射机制来取得类的所有信息。
这种动静获取的信息以及动静调用对象的办法的性能称为 Java 语言的反射机制。
2、哪里会用到反射机制?
jdbc 就是典型的反射
Class.forName('com.mysql.jdbc.Driver.class');// 加载 MySQL 的驱动类
这就是反射。如 hibernate,struts 等框架应用反射实现的。
24W 字 Java 面试手册下载地址:https://shimo.im/docs/Wyj8QRp…
24W 字 Java 面试手册下载地址:https://shimo.im/docs/Wyj8QRp…
24W 字 Java 面试手册下载地址:https://shimo.im/docs/Wyj8QRp…
42. 反射的实现形式
第一步:获取 Class 对象,有 4 种办法:1)Class.forName(“类的门路”);2)类名.class 3)对象名.getClass() 4)根本类型的包装类,能够调用包装类的 Type 属性来取得该包装类的 Class 对象
43. 实现 Java 反射的类:
1)Class:示意正在运行的 Java 应用程序中的类和接口 留神:所有获取对象的信息都须要 Class 类来实现。2)Field:提供无关类和接口的属性信息,以及对它的动静拜访权限。3)Constructor:提供对于类的单个构造方法的信息以及它的拜访权限 4)Method:提供类或接口中某个办法的信息
44. 反射机制的优缺点:
长处:
1、可能运行时动静获取类的实例,进步灵活性;
2、与动静编译联合
毛病:
1、应用反射性能较低,须要解析字节码,将内存中的对象进行解析。
解决方案:
1、通过 setAccessible(true)敞开 JDK 的安全检查来晋升反射速度;
2、屡次创立一个类的实例时,有缓存会快很多
3、ReflectASM 工具类,通过字节码生成的形式放慢反射速度
2、绝对不平安,毁坏了封装性(因为通过反射能够取得公有办法和属性)
45. Java 中 IO 流分为几种?
- 依照流的流向分,能够分为输出流和输入流;
- 依照操作单元划分,能够划分为字节流和字符流;
- 依照流的角色划分为节点流和解决流。
Java Io 流共波及 40 多个类,这些类看上去很芜杂,但实际上很有规定,而且彼此之间存在十分严密的分割,Java I0 流的 40 多个类都是从如下 4 个抽象类基类中派生进去的。
- InputStream/Reader: 所有的输出流的基类,前者是字节输出流,后者是字符输出流。
- OutputStream/Writer: 所有输入流的基类,前者是字节输入流,后者是字符输入流。
按操作形式分类结构图: