21.try catch finally,try中存在return,finally还执行嘛?
执行,并且finally的执行早于try里面的return
关于try...catch...finally的结论
- 不管有没有出现异常,finally块中的代码都会执行。
- 当try和catch语句块中出现return的时候,finally仍会执行。
- finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是finally执行前确定的;
- finally中最好不要写return,否则程序会提前退出,返回值不是try或catch中保存的返回值。
22. Exception与Error包结构
Java可抛出(Throwable)的结构分为三种类型:被检查的异常(CheckedException),运行时异常(RuntimeException),错误(Error)
1. 运行时异常
运行时异常的定义:
运行时异常指的就是:RuntimeException及其子类都被称为运行时异常。
运行时异常的特点:
Java编译器不会检查它。也就是说,当程序中可能出现这类异常时,倘若既"没有通过throws声明抛出它",也"没有用try-catch语句捕获它",还是会编译通过。例如,除数为零时产生的ArithmeticException异常,数组越界时产生的IndexOutOfBoundsException异常,fail-fast机制产生的ConcurrentModifificationException异常(java.util包下面的所有的集合类都是快速失败的,“快速失败”也就是fail-fast,它是Java集合的一种错误检测机制。当多个线程对集合进行结构上的改变的操作时,有可能会产生fail-fast机制。记住是有可能,而不是一定。例如:假设存在两个线程(线程1、线程2),线程1通过Iterator在遍历集合A中的元素,在某个时候线程2修改了集合A的结构(是结构上面的修改,而不是简单的修改集合元素的内容),那么这个时候程序就会抛出ConcurrentModifificationException 异常,从而产生fail-fast机制,这个错叫并发修改异常。Failsafe,java.util.concurrent包下面的所有的类都是安全失败的,在遍历过程中,如果已经遍历的数组上的内容变化了,迭代器不会抛出ConcurrentModifificationException异常。如果未遍历的数组上的内容发生了变化,则有可能反映到迭代过程中。这就是ConcurrentHashMap迭代器弱一致的表现。ConcurrentHashMap的弱一致性主要是为了提升效率,是一致性与效率之间的一种权衡。要成为强一致性,就得到处使用锁,甚至是全局锁,这就与Hashtable和同步的HashMap一样了)等,都属于运行时异常。
2. 被检查时异常
被检查时异常的定义:
被检查异常指的就是:Exception类本身,以及Exception的子类中除了"运行时异常"之外的其它子类都属于被检查异常。
被检查时异常的特点:
Java编译器会检查它。 此类异常,要么通过throws进行声明抛出,要么通过try-catch进行捕获处理,否则不能通过编译。例如,CloneNotSupportedException就属于被检查异常。当通过clone()接口去克隆一个对象,而该对象对应的类没有实现Cloneable接口,就会抛出CloneNotSupportedException异常。被检查异常通常都是可以恢复的。
以下都是被检查时抛出的异常:
IOException // 输出输出异常 FileNotFoundException // 文件找不到异常 SQLException // SQL语句异常 复制代码
被检查的异常适用于那些不是因程序引起的错误情况,比如:读取文件时文件不存在引发的FileNotFoundException 。然而,不被检查的异常通常都是由于糟糕的编程引起的,比如:在对象引用时没有确保对象非空而引起的 NullPointerException 。
3. 错误:
错误的定义:
错误就是指:Error类及其子类
错误的特点:
当资源不足、约束失败、或是其它程序无法继续运行的条件发生时,就产生错误。程序本身无法修复这些错误的。例如,VirtualMachineError就属于错误。出现这种错误会导致程序终止运行。OutOfMemoryError、ThreadDeath。
Java虚拟机规范规定JVM的内存分为了好几块,比如堆,栈,程序计数器,方法区等
23. OOM遇到的情况以及SOF遇到的情况
关于OOM的异常,OOM叫做堆溢出异常
- OutOfMemoryError异常
除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError(OOM)异常的可能。
Java Heap 溢出:
一般的异常信息:java.lang.OutOfMemoryError:Java heap spacess。
java堆用于存储对象实例,我们只要不断的创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,就会在对象数量达到最大堆容量限制后产生内存溢出异常。
- 虚拟机栈和本地方法栈溢出
如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflflowError异常。如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常这里需要注意当栈的大小越大可分配的线程数就越少。
- 运行时常量池溢出
异常信息:java.lang.OutOfMemoryError:PermGenspace
如果要向运行时常量池中添加内容,最简单的做法就是使用String.intern()这个Native方法。该方法的作用是:如果池中已经包含一个等于此String的字符串,则返回代表池中这个字符串的String对象;否则,将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用。由于常量池分配在方法区内,我们可以通过-XX:PermSize和-XX:MaxPermSize限制方法区的大小,从而间接限制其中常量池的容量。
- 方法区溢出
方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。也有可能是方法区中保存的class对象没有被及时回收掉或者class信息占用的内存超过了我们配置。异常信息:java.lang.OutOfMemoryError:PermGenspace
方法区溢出也是一种常见的内存溢出异常,一个类如果要被垃圾收集器回收,判定条件是很苛刻的。在经常动态生成大量Class的应用中,要特别注意这点。
关于SOF异常(堆栈溢出异常)
StackOverflflowError 的定义:当应用程序递归太深而发生堆栈溢出时,抛出该错误。因为栈一般默认为1-2m,一旦出现死循环或者是大量的递归调用,在不断的压栈过程中,造成栈容量超过1m而导致溢出。
栈溢出的原因:递归调用,大量循环或死循环,全局变量是否过多,数组、List、map数据过大。
24. 简述线程、程序、进行的基本概念。以及他们之间的关系
24.1 程序
程序是含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,也就是说程序是静态的代码。
24.2 进程
进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。简单来说,一个进程就是一个执行中的程序,它在计算机中一个指令接着一个指令地执行着,同时,每个进程还占有某些系统资源如 CPU 时间,内存空间,文件,输入输出设备的使用权等等。换句话说,当程序在执行时,将会被操作系统载入内存中。 线程是进程划分成的更小的运行单位。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。从另一角度来说,进程属于操作系统的范畴,主要是同一段时间内,可以同时执行一个以上的程序,而线程则是在同一程序内几乎同时执行一个以上的程序段。
24.3 线程
线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。
25. Java序列化中如果有些字段不想序列化怎么办
对于不想进行序列化的变量,使用 transient 关键字修饰。
transient 关键字的作用是:阻止实例中那些用此关键字修饰的的变量序列化;当对象被反序列化时,被 transient 修饰的变量值不会被持久化和恢复。transient 只能修饰变量,不能修饰类和方法。
26. Object有哪些方法?大致说一下每个方法的含义
- clone方法
保护方法,实现对象的浅复制,只有实现了 Cloneable 接口才可以调用该方法,否则抛出CloneNotSupportedException 异常,深拷贝也需要实现 Cloneable,同时其成员变量为引用类型的也需要实现 Cloneable,然后重写 clone 方法。
- finalize方法
该方法和垃圾收集器有关系,判断一个对象是否可以被回收的最后一步就是判断是否重写了此方法。
- equals方法
该方法用于哈希查找,重写了 equals 方法一般都要重写 hashCode 方法,这个方法在一些具有哈希功能的 Collection 中用到。
一般必须满足 obj1.equals(obj2)==true 。可以推出 obj1.hashCode()==obj2.hashCode() ,但是hashCode 相等不一定就满足 equals。不过为了提高效率,应该尽量使上面两个条件接近等价。
- JDK1.6、JDK1.7默认是返回随机数。
- JDK1.8默认是通过和当前线程有关的一个随机数+三个确定值,运用Marsaglia's xorshiftscheme随机数算法得到的一个随机数。
- wait方法
配合 synchronized 使用,wait 方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait() 方法一直等待,直到获得锁或者被中断。wait(long timeout)设定一个超时间隔,如果在规定时间内没有获得锁就返回。
调用该方法后当前线程进入睡眠状态,直到以下事件发生。
- 其他线程调用了该对象的notify方法。
- 其他线程调用了该对象的notifyAll方法
- 其他线程调用了interrupt中断该线程。
此时该线程就可以被调度了,如果是被中断的话就抛出一个InterruptedException异常。
- notify方法
配合 synchronized 使用,该方法唤醒在该对象上等待队列中的某个线程(同步队列中的线程是给抢占 CPU 的线程,等待队列中的线程指的是等待唤醒的线程)。
- notifyAll方法
配合 synchronized 使用,该方法唤醒在该对象上等待队列中的所有线程。
总结
只要把上面几个方法熟悉就可以了,toString 和 getClass 方法可以不用去讨论它们。该题目考察的是对 Object 的熟悉程度,平时用的很多方法并没看其定义但是也在用,比如说:wait() 方法,equals() 方法等。
Class Object is the root of the class hierarchy.Every class has Object as a superclass. All objects, including arrays, implement the methods of this class. 复制代码
大致意思:Object 是所有类的根,是所有类的父类,所有对象包括数组都实现了 Object 的方法。
27. 获取一个类Class对象的方式有那些?
一定要搞清楚类对象和实例对象,但都是对象
第一种:通过类对象的getClass()方法获取,细心点的都知道,这个getClass是Object类里面的方法。
User user=new User(); //clazz就是一个User的类对象 Class<?> clazz=user.getClass(); 复制代码
第二种:通过类的静态成员表示,每个类都有隐含的静态成员class
//clazz就是一个User的类对象 Class<?> clazz=User.class; 复制代码
第三种:通过Class类的静方法forName()方法获取
Class<?> clazz = Class.forName("com.tian.User"); 复制代码
28. 接口和抽象类的区别
29. 说说你平时是怎么处理Java异常的
try-catch-finally
- try块负责监控可能出现异常的代码。
- catch块负责捕获可能出现的异常,并进行处理。
- finally块负责清理各种资源,不管是否出现异常都会执行。
- 其中try块是必须的,catch和finally至少存在一个标准的异常处理。
在开发过程中会使用到自定义异常,在通常情况下,程序很少会自己抛出异常,因为异常的类名通常也包含了该异常的有用信息,所以在选择抛出异常的时候,应该选择合适的异常类,从而可以明确地描述该异常情况,所以这时候往往都是自定义异常。
自定义异常通常是通过继承 java.lang.Exception 类,如果想自定义 Runtime 异常的话,可以继承java.lang.RuntimeException 类,实现一个无参构造和一个带字符串参数的有参构造方法。
在业务代码里,可以针对性的使用自定义异常。比如说:该用户不具备某某权限、余额不足等。
30. 说说final、finalize和finally
三者没有任何相关性
- final是一个修饰符,用于修饰变量、方法和类,如果final修饰变量,意味着该变量的值在初始化后不能被改变。
- finalize()方法是在对象被回收之前调用的方法,给对象自己最后一个复活的机会,但是该方法由Finalizer线程调用,并且调用时机无法保证。
- finally是一个关键字,与try和catch一起用于异常的处理,finally{}一定会执行,不论try和catch是否发生异常。
31. Java中基本数据类型占用的字节数