java基础部分知识总结--21-50

21、描述一下JVM 加载class文件的原理机制?

答:JVM 中类的装载是由类加载器(ClassLoader) 和它的子类来实现的,Java中的类加载器是一个重要的Java 运 行时系统组件,它负责在运行时查找和装入类文件中的类。
补充:
1.由于Java的跨平台性,经过编译的Java源程序并不是一个可执行程序,而是一个或多个类文件。当Java程序需要
使用某个类时,JVM会确保这个类已经被加载、连接(验证、准备和解析)和初始化。类的加载是指把类的.class文件
中的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后产生与所加载类对应的Class对象。加载完
成后,Class对象还不完整,所以此时的类还不可用。当类被加载后就进入连接阶段,这一阶段包括验证、准备(为
静态变量分配内存并设置默认的初始值)和解析(将符号引用替换为直接引用)三个步骤。最后JVM对类进行初始化,
包括:1如果类存在直接的父类并且这个类还没有被初始化,那么就先初始化父类;2如果类中存在初始化语句,就
依次执行这些初始化语句。2.类的加载是由类加载器完成的,类加载器包括:根加载器(BootStrap)、扩展加载器(Extension)、系统加载
器(System)和用户自定义类加载器(java.lang.ClassLoader的子类)。从JDK 1.2开始,类加载过程采取了父亲
委托机制(PDM)。PDM更好的保证了Java平台的安全性,在该机制中,JVM自带的Bootstrap是根加载器,其他的
加载器都有且仅有一个父类加载器。类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器
自行加载。JVM不会向Java程序提供对Bootstrap的引用。下面是关于几个类加载器的说明:
a)Bootstrap:一般用本地代码实现,负责加载JVM基础核心类库(rt.jar);
b)Extension:从java.ext.dirs系统属性所指定的目录中加载类库,它的父加载器是Bootstrap;
c)System:又叫应用类加载器,其父类是Extension。它是应用最广泛的类加载器。它从环境变量classpath或者系
统属性java.class.path所指定的目录中记载类,是用户自定义加载器的默认父加载器。

22、char 型变量中能不能存贮一个中文汉字?为什么?

答:char类型可以存储一个中文汉字,因为Java中使用的编码是Unicode(不选择任何特定的编码,直接使用字符
在字符集中的编号,这是统一的唯一方法),一个char类型占2个字节(16bit),所以放一个中文是没问题的。
补充:使用Unicode意味着字符在JVM内部和外部有不同的表现形式,在JVM内部都是Unicode,当这个字符被从
JVM内部转移到外部时(例如存入文件系统中),需要进行编码转换。所以Java中有字节流和字符流,以及在字符
流和字节流之间进行转换的转换流,如InputStreamReader和OutputStreamReader,这两个类是字节流和字符流
之间的适配器类,承担了编码转换的任务;对于C程序员来说,要完成这样的编码转换恐怕要依赖于union(联合
体/共用体)共享内存的特征来实现了。

23、抽象类(abstract class)和接口(interface)有什么异同?

答:抽象类和接口都不能够实例化,但可以定义抽象类和接口类型的引用。一个类如果继承了某个抽象类或者实现
了某个接口都需要对其中的抽象方法全部进行实现,否则该类仍然需要被声明为抽象类。接口比抽象类更加抽象,
因为抽象类中可以定义构造器,可以有抽象方法和具体方法,而接口中不能定义构造器而且其中的方法全部都是抽
象方法。抽象类中的成员可以是private、默认、protected、public的,而接口中的成员全都是public的。抽象类
中可以定义成员变量,而接口中定义的成员变量实际上都是常量。有抽象方法的类必须被声明为抽象类,而抽象类
未必要有抽象方法。

24、静态嵌套类(Static Nested Class)和内部类(Inner Class)的不同?

答:Static Nested Class是被声明为静态(static)的内部类,它可以不依赖于外部类实例被实例化。而通常的内部
类需要在外部类实例化后才能实例化,其语法看起来挺诡异的,如下所示。
1 package com.lovo;
2
3 /**
4

  • 扑克类(一副扑克)
    5
    6 *
    7 /
    8 public class Poker { 9 private static String[] suites = {“黑桃”, “红桃”, “草花”, “方块”};
    10 private static int[] faces = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
    11
    12 private Card[] cards;
    13
    14 /
    *
    15 * 构造器
    16 *
    17 /
    18 public Poker() {
    19 cards = new Card[52];
    20 for(int i = 0; i < suites.length; i++) {
    21 for(int j = 0; j < faces.length; j++) {
    22 cards[i * 13 + j] = new Card(suites[i], faces[j]);
    23 }
    24 }
    25 }
    26
    27 /
    *
    28 * 洗牌 (随机乱序)
    29 *
    30 /
    31 public void shuffle() {
    32 for(int i = 0, len = cards.length; i < len; i++) {
    33 int index = (int) (Math.random() * len);
    34 Card temp = cards[index];
    35 cards[index] = cards[i];
    36 cards[i] = temp;
    37 }
    38 }
    39
    40 /
    *
    41 * 发牌
    42 * @param index 发牌的位置
    43 *
    44 /
    45 public Card deal(int index) {
    46 return cards[index];
    47 }
    48
    49 /
    *
    50 * 卡片类(一张扑克)
    51 * [内部类]
    52 * @author 骆昊
    53 *
    54 */
    55 public class Card {
    56 private String suite; // 花色
    57 private int face; // 点数
    58
    59 public Card(String suite, int face) {
    60 this.suite = suite;
    61 this.face = face; 62 }
    63
    64 @Override
    65 public String toString() {
    66 String faceStr = “”;
    67 switch(face) {
    68 case 1: faceStr = “A”; break;
    69 case 11: faceStr = “J”; break;
    70 case 12: faceStr = “Q”; break;
    71 case 13: faceStr = “K”; break;
    72 default: faceStr = String.valueOf(face);
    73 }
    74 return suite + faceStr;
    75 }
    76 }
    77 }
    测试类:
    package com.lovo;

class PokerTest {

public static void main(String[] args) {
Poker poker = new Poker();
poker.shuffle();
Poker.Card c1 = poker.deal(0);
// 对于非静态内部类Card
// 只有通过其外部类Poker对象才能创建Card对象
Poker.Card c2 = poker.new Card(“红心”, 1);
// 洗牌
// 发第一张牌
// 自己创建一张牌

  System.out.println(c1);     // 洗牌后的第一张  
  System.out.println(c2);     // 打印: 红心A  

}
}
//

25、Java 中会存在内存泄漏吗,请简单描述。

答:理论上Java因为有垃圾回收机制(GC)不会存在内存泄露问题(这也是Java被广泛使用于服务器端编程的一个
重要原因);然而在实际开发中,可能会存在无用但可达的对象,这些对象不能被GC回收也会发生内存泄露。一
个例子就是Hibernate的Session(一级缓存)中的对象属于持久态,垃圾回收器是不会回收这些对象的,然而这些
对象中可能存在无用的垃圾对象。下面的例子也展示了Java中发生内存泄露的情况:
1 package com.lovo; 2 //
3 import java.util.Arrays;
4 import java.util.EmptyStackException;
5
6 public class MyStack {
7 private T[] elements;
8 private int size = 0;
9
10 private static final int INIT_CAPACITY = 16;
11
12 public MyStack() {
13 elements = (T[]) new Object[INIT_CAPACITY];
14 }
15
16 public void push(T elem) {
17 ensureCapacity();
18 elements[size++] = elem;
19 }
20
21 public T pop() {
22 if(size == 0)
23 throw new EmptyStackException();
24 return elements[–size];
25 }
26
27 private void ensureCapacity() {
28 if(elements.length == size) {
29 elements = Arrays.copyOf(elements, 2 * size + 1);
30 }
31 }
32 }
上面的代码实现了一个栈(先进后出(FILO))结构,乍看之下似乎没有什么明显的问题,它甚至可以通过你编写
的各种单元测试。然而其中的pop方法却存在内存泄露的问题,当我们用pop方法弹出栈中的对象时,该对象不会
被当作垃圾回收,即使使用栈的程序不再引用这些对象,因为栈内部维护着对这些对象的过期引用(obsolete
reference)。在支持垃圾回收的语言中,内存泄露是很隐蔽的,这种内存泄露其实就是无意识的对象保持。如果
一个对象引用被无意识的保留起来了,那么垃圾回收器不会处理这个对象,也不会处理该对象引用的其他对象,即
使这样的对象只有少数几个,也可能会导致很多的对象被排除在垃圾回收之外,从而对性能造成重大影响,极端情
况下会引发Disk Paging(物理内存与硬盘的虚拟内存交换数据),甚至造成OutOfMemoryError。

26、抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰?

答:都不能。抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。本地方法是由本地代码
(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。synchronized和方法的实现细节有关,抽象方
法不涉及实现细节,因此也是相互矛盾的。

27、静态变量和实例变量的区别?

答:静态变量是被static修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,一个类不管创
建多少个对象,静态变量在内存中有且仅有一个拷贝;实例变量必须依存于某一实例,需要先创建对象然后通过对
象才能访问到它。静态变量可以实现让多个对象共享内存。在Java开发中,上下文类和工具类中通常会有大量的静
态成员。

28、是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?

答:不可以,静态方法只能访问静态成员,因为非静态方法的调用要先创建对象,因此在调用静态方法时可能对象
并没有被初始化。

29、如何实现对象克隆?

答:有两种方式:
1.实现Cloneable接口并重写Object类中的clone()方法;
2.实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆,代码如下。
1 package com.lovo;
2
3 import java.io.ByteArrayInputStream;
4 import java.io.ByteArrayOutputStream;
5 import java.io.ObjectInputStream;
6 import java.io.ObjectOutputStream;
7
8 public class MyUtil {
9
10 private MyUtil() {
11 throw new AssertionError();
12 }
13
14 public static T clone(T obj) throws Exception {
15 ByteArrayOutputStream bout = new ByteArrayOutputStream();
16 ObjectOutputStream oos = new ObjectOutputStream(bout);
17 oos.writeObject(obj);
18
19 ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
20 ObjectInputStream ois = new ObjectInputStream(bin);
21 return (T) ois.readObject();
22
23 // 说明:调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法没有任何意

24 // 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源
25 }
26 }
// 下面是测试代码:
1 package com.lovo;
2
3 import java.io.Serializable;
4
5 /**
6 * 人类
7 * @author 骆昊
8 *
9 /
10 class Person implements Serializable {
11 private static final long serialVersionUID = -9102017020286042305L;
12
13 private String name; // 姓名
14 private int age; // 年龄
15 private Car car; // 座驾
16
17 public Person(String name, int age, Car car) {
18 this.name = name;
19 this.age = age;
20 this.car = car;
21 }
22
23 public String getName() {
24 return name;
25 }
26
27 public void setName(String name) {
28 this.name = name;
29 }
30
31 public int getAge() {
32 return age;
33 }
34
35 public void setAge(int age) {
36 this.age = age;
37 }
38
39 public Car getCar() {
40 return car;
41 }
42
43 public void setCar(Car car) {
44 this.car = car;
45 }
46
47 @Override 48 public String toString() {
49 return “Person [name=” + name + “, age=” + age + “, car=” + car + “]”;
50 }
51
52 }
53
54 /
*
55 * 小汽车类
56 * @author 骆昊
57 *
58 */
59 class Car implements Serializable {
60 private static final long serialVersionUID = -5713945027627603702L;
61
62 private String brand; // 品牌
63 private int maxSpeed; // 最高时速
64
65 public Car(String brand, int maxSpeed) {
66 this.brand = brand;
67 this.maxSpeed = maxSpeed;
68 }
69
70 public String getBrand() {
71 return brand;
72 }
73
74 public void setBrand(String brand) {
75 this.brand = brand;
76 }
77
78 public int getMaxSpeed() {
79 return maxSpeed;
80 }
81
82 public void setMaxSpeed(int maxSpeed) {
83 this.maxSpeed = maxSpeed;
84 }
85
86 @Override
87 public String toString() {
88 return “Car [brand=” + brand + “, maxSpeed=” + maxSpeed + “]”;
89 }
90
91 }
92 //
93 class CloneTest {
94
95 public static void main(String[] args) {
96 try {
97 Person p1 = new Person(“Hao LUO”, 33, new Car(“Benz”, 300));
98 Person p2 = MyUtil.clone(p1); // 深度克隆
99 p2.getCar().setBrand(“BYD”);
100 // 修改克隆的Person对象p2关联的汽车对象的品牌属性 101 // 原来的Person对象p1关联的汽车不会受到任何影响
102 // 因为在克隆Person对象时其关联的汽车对象也被克隆了
103 System.out.println(p1);
104 } catch (Exception e) {
105 e.printStackTrace();
106 }
107 }
108 }
注意:基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象
是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常,这种是方案明显优于使用Object类的clone
方法克隆对象。

30、GC 是什么?为什么要有GC?

答:GC是垃圾收集的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系
统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语
言没有提供释放已分配内存的显示操作方法。Java程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要
请求垃圾收集,可以调用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,但JVM可以屏蔽掉显示的
垃圾回收调用。
垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低优先级的线
程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的
调用垃圾回收器对某个对象或所有对象进行垃圾回收。在Java诞生初期,垃圾回收是Java最大的亮点之一,因为服
务器端的编程需要有效的防止内存泄露问题,然而时过境迁,如今Java的垃圾回收机制已经成为被诟病的东西。
补充:垃圾回收机制有很多种,包括:分代复制垃圾回收、标记垃圾回收、增量垃圾回收等方式。标准的Java进程
既有栈又有堆。栈保存了原始型局部变量,堆保存了要创建的对象。Java平台对堆内存回收和再利用的基本算法被
称为标记和清除,但是Java对其进行了改进,采用“分代式垃圾收集”。这种方法会跟Java对象的生命周期将堆内存
划分为不同的区域,在垃圾收集过程中,可能会将对象移动到不同区域:
伊甸园(Eden):这是对象最初诞生的区域,并且对大多数对象来说,这里是它们唯一存在过的区域。
幸存者乐园(Survivor):从伊甸园幸存下来的对象会被挪到这里。
终身颐养园(Tenured):这是足够老的幸存对象的归宿。年轻代收集(Minor-GC)过程是不会触及这个地
方的。当年轻代收集不能把对象放进终身颐养园时,就会触发一次完全收集(Major-GC),这里可能还会牵
扯到压缩,以便为大对象腾出足够的空间。
与垃圾回收相关的JVM参数:
-Xms / -Xmx — 堆的初始大小 / 堆的最大大小
-Xmn — 堆中年轻代的大小
-XX:-DisableExplicitGC — 让System.gc()不产生任何作用
-XX:+PrintGCDetail — 打印GC的细节
-XX:+PrintGCDateStamps — 打印GC操作的时间戳

31、String s=new String(“xyz”);创建了几个字符串对象?

答:两个对象,一个是静态存储区的"xyz",一个是用new创建在堆上的对象。## ## 32、接口是否可继承(extends)接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承具体类(concreteclass)?
答:接口可以继承接口。抽象类可以实现(implements)接口,抽象类可继承具体类,但前提是具体类必须有明确的
构造函数。

`33、一个“.java”源文件中是否可以包含多个类(不是内部类)?

有什么限制?`
答:可以,但一个源文件中最多只能有一个公开类(public class)而且文件名必须和公开类的类名完全保持一
致。

35、内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制?

答:一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员。

36、Java 中的final关键字有哪些用法?

答:(1)修饰类:表示该类不能被继承;(2)修饰方法:表示方法不能被重写;(3)修饰变量:表示变量只能一次赋值
以后值不能被修改(常量)。

37、指出下面程序的运行结果:

1 class A{
2
3 static{
4 System.out.print(“1”);
5 }
6
7 public A(){
8 System.out.print(“2”);
9 }
10 }
11
12 class B extends A{
13
14 static{
15 System.out.print(“a”);
16 }
17
18 public B(){
19 System.out.print(“b”); 20 }
21 }
22 //
23 public class Hello{
24
25 public static void main(String[] args){
26 A ab = new B();
27 ab = new B();
28 }
29
30 }
答:执行结果:1a2b2b。创建对象时构造器的调用顺序是:先初始化静态成员,然后调用父类构造器,再初始化非静态成员,最后调用自身构造器。

38、数据类型之间的转换:

1)如何将字符串转换为基本数据类型?
2)如何将基本数据类型转换为字符串?
答:
1)调用基本数据类型对应的包装类中的方法parseXXX(String)或valueOf(String)即可返回相应基本类型;
2)一种方法是将基本数据类型与空字符串(””)连接(+)即可获得其所对应的字符串;另一种方法是调用String 类
中的valueOf(…)方法返回相应字符串

39、如何实现字符串的反转及替换?

答:方法很多,可以自己写实现也可以使用String或StringBuffer / StringBuilder中的方法。有一道很常见的面试
题是用递归实现字符串反转,代码如下所示:
public static String reverse(String originStr) {

if(originStr == null || originStr.length() <= 1)

}
return originStr;
return reverse(originStr.substring(1)) + originStr.charAt(0);
//

40、怎样将GB2312编码的字符串转换为ISO-8859-1编码的字符串?

答:代码如下所示:
String s1 = “你好”;
String s2 = new String(s1.getBytes(“GB2312”), “ISO-8859-1”);

41、日期和时间:1)如何取得年月日、小时分钟秒?

2)如何取得从1970年1月1日0时0分0秒到现在的毫秒数?
3)如何取得某月的最后一天?
4)如何格式化日期?
答:操作方法如下所示:
1)创建java.util.Calendar 实例,调用其get()方法传入不同的参数即可获得参数所对应的值
2)以下方法均可获得该毫秒数:
Calendar.getInstance().getTimeInMillis();
System.currentTimeMillis();
//
3)示例代码如下:
Calendar time = Calendar.getInstance();
time.getActualMaximum(Calendar.DAY_OF_MONTH);
//
4)利用java.text.DataFormat 的子类(如SimpleDateFormat类)中的format(Date)方法可将日期格式化。

42、打印昨天的当前时刻。

答:
public class YesterdayCurrent {

public static void main(String[] args){
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, -1);
System.out.println(cal.getTime());

}
}
//

44、什么时候用assert?

答:assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制。一般来说,assertion
用于保证程序最基本、关键的正确性。assertion检查通常在开发和测试时开启。为了提高性能,在软件发布后,
assertion检查通常是关闭的。在实现中,断言是一个包含布尔表达式的语句,在执行这个语句时假定该表达式为
true;如果表达式计算为false,那么系统会报告一个AssertionError。
断言用于调试目的:assert(a > 0); // throws an AssertionError if a <= 0
断言可以有两种形式:
assert Expression1;
assert Expression1 : Expression2 ;
Expression1 应该总是产生一个布尔值。
Expression2 可以是得出一个值的任意表达式;这个值用于生成显示更多调试信息的字符串消息。
断言在默认情况下是禁用的,要在编译时启用断言,需使用source 1.4 标记:
javac -source 1.4 Test.java
要在运行时启用断言,可使用-enableassertions 或者-ea 标记。
要在运行时选择禁用断言,可使用-da 或者-disableassertions 标记。
要在系统类中启用断言,可使用-esa 或者-dsa 标记。还可以在包的基础上启用或者禁用断言。可以在预计正常情
况下不会到达的任何位置上放置断言。断言可以用于验证传递给私有方法的参数。不过,断言不应该用于验证传递
给公有方法的参数,因为不管是否启用了断言,公有方法都必须检查其参数。不过,既可以在公有方法中,也可以
在非公有方法中利用断言测试后置条件。另外,断言不应该以任何方式改变程序的状态。

45、Error 和Exception 有什么区别?

答:Error 表示系统级的错误和程序不必处理的异常,是恢复不是不可能但很困难的情况下的一种严重问题;比如
内存溢出,不可能指望程序能处理这样的情况;
Exception 表示需要捕捉或者需要程序进行处理的异常,是一种设计或实现问题;也就是说,它表示如果程序运行正常,从不会发生的情况。
补充:2005年摩托罗拉的面试中曾经问过这么一个问题“If a process reports a stack overflow run-time error,
what’s the most possible cause?”,给了四个选项a. lack of memory; b. write on an invalid memory space; c.
recursive function calling; d. array index out of boundary. Java程序在运行时也可能会遭遇
StackOverflowError,这是一个错误无法恢复,只能重新修改代码了,这个面试题的答案是c。如果写了不能迅速
收敛的递归,则很有可能引发栈溢出的错误,如下所示:
package com.lovo;

public class StackOverflowErrorTest {

public static void main(String[] args) {

main(null);
}
} //
因此,用递归编写程序时一定要牢记两点:1. 递归公式;2. 收敛条件(什么时候就不再递归而是回溯了)。

46、try{}里有一个return语句,那么紧跟在这个try后的finally{}里的code会不会被执行,什么时候被执行,在return前还是后?

答:会执行,在方法返回调用者前执行。Java允许在finally中改变返回值的做法是不好的,因为如果存在finally代
码块,try中的return语句不会立马返回调用者,而是记录下返回值待finally代码块执行完毕之后再向调用者返回其
值,然后如果在finally中修改了返回值,这会对程序造成很大的困扰,C#中就从语法上规定不能做这样的事。

47、Java 语言如何进行异常处理,关键字:throws、throw、try、catch、finally分别如何使用?

答:Java 通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口。在Java 中,每
个异常都是一个对象,它是Throwable 类或其子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中
包含有异常信息,调用这个对象的方法可以捕获到这个异常并进行处理。Java 的异常处理是通过5 个关键词来实现
的:try、catch、throw、throws和finally。一般情况下是用try来执行一段程序,如果出现异常,系统会抛出
(throw)一个异常,这时候你可以通过它的类型来捕捉(catch)它,或最后(finally)由缺省处理器来处理;try
用来指定一块预防所有“异常”的程序;catch 子句紧跟在try块后面,用来指定你想要捕捉的“异常”的类型;throw
语句用来明确地抛出一个“异常”;throws用来标明一个成员函数可能抛出的各种“异常”;finally 为确保一段代码不
管发生什么“异常”都被执行一段代码;可以在一个成员函数调用的外面写一个try语句,在这个成员函数内部写另一
个try语句保护其他代码。每当遇到一个try 语句,“异常”的框架就放到栈上面,直到所有的try语句都完成。如果下
一级的try语句没有对某种“异常”进行处理,栈就会展开,直到遇到有处理这种“异常”的try 语句。

48、运行时异常与受检异常有何异同?

答:异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一
种常见运行错误,只要程序设计得没有问题通常就不会发生。受检异常跟程序运行的上下文环境有关,即使程序设
计无误,仍然可能因使用的问题而引发。Java编译器要求方法必须声明抛出可能发生的受检异常,但是并不要求必
须声明抛出未被捕获的运行时异常。异常和继承一样,是面向对象程序设计中经常被滥用的东西,神作《Effective
Java》中对异常的使用给出了以下指导原则:
不要将异常处理用于正常的控制流(设计良好的API不应该强迫它的调用者为了正常的控制流而使用异常)
对可以恢复的情况使用受检异常,对编程错误使用运行时异常
避免不必要的使用受检异常(可以通过一些状态检测手段来避免异常的发生)
优先使用标准的异常
每个方法抛出的异常都要有文档
保持异常的原子性
不要在catch中忽略掉捕获到的异常

49、列出一些你常见的运行时异常?

答:
ArithmeticException(算术异常)
ClassCastException (类转换异常)
IllegalArgumentException (非法参数异常)
IndexOutOfBoundsException (下表越界异常)NullPointerException (空指针异常)
SecurityException (安全异常)

50、final, finally, finalize 的区别?

答:
final:修饰符(关键字)有三种用法:
如果一个类被声明为final,意味着它不能再派生出新的子类,即不能被继承,因此它和abstract是反义词。将变量声明为final,可以保证它们在使用中不被改变,被声明为final 的变量必须在声明时给定初值,而在以后的引用中只能读取不可修改。被声明为final 的方法也同样只能使用,不能在子类中被重写
finally:通常放在try...catch的后面构造总是执行代码块,这就意味着程序无论正常执行还是发生异常,这里的代码只要JVM不关闭都能执行,可以将释放外部资源的代码写在finally块中
finalize:Object类中定义的方法,Java中允许使用finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。 这个方法是
由垃圾收集器在销毁对象时调用的,通过重写finalize() 方法可以整理系统资源或者执行其他清理工作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值