1、Finally块中代码在什么时候执行?
package testfinally;
public class Test {
public static int test(){
try{
return 1;
}catch(Exception e){
return 0;
}finally{
System.out.println("execute finally");
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int result = test();
System.out.println(result);
}
}
结果输出:1
package testfinally;
public class Test {
public static int test(){
try{
throw new Exception();
}catch(Exception e){
return 2;
}finally{
System.out.println("execute finally");
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int result = test();
System.out.println(result);
}
}
结果输出:2
结果分析:finally块中代码在相应的try..catch块中执行return语句前执行。
2、finally里return语句覆盖try..catch中的return?
package testfinally;
public class Test {
public static int test(){
try{
return 1;
}catch(Exception e){
return 2;
}finally{
System.out.println("execute finally");
return 3;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int result = test();
System.out.println(result);
}
}
结果输出:3
package testfinally;
public class Test {
public static int test(){
try{
throw new Exception();
}catch(Exception e){
return 2;
}finally{
System.out.println("execute finally");
return 3;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int result = test();
System.out.println(result);
}
}
结果输出:3
结果分析:finally里return语句覆盖try..catch中的return,直接在finally返回。
3、finally里的返回基本类型和引用型对象的问题
package testfinally;
public class Test {
public static int test(){
int result = 0;
try{
result = 1;
return result;
}catch(Exception e){
result = 2;
return result;
}finally{
result = 3;
System.out.println("execute finally");
}
}
public static String test2(){
String result;
try{
result = new String("aaa");
return result;
}catch(Exception e){
result = new String("bbb");
return result;
}finally{
result = new String("ccc");
System.out.println("execute2 finally");
}
}
public static StringBuffer test3(){
StringBuffer result = new StringBuffer("hello");
try{
return result;
}catch(Exception e){
return null;
}finally{
result.append(" world");
System.out.println("execute3 finally");
}
}
public static Person test4(){
Person p1 = new Person(11,"张三");
try{
return p1;
}catch(Exception e){
return null;
}finally{
p1.setAge(12);
p1.setName("李四");
System.out.println("execute4 finally");
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int result = test();
System.out.println(result);
String result2 = test2();
System.out.println(result2);
StringBuffer result3 = test3();
System.out.println(result3.toString());
Person result4 = test4();
System.out.println(result4.toString());
}
}
结果输出:
1
execute2 finally
aaa
execute3 finally
hello world
execute4 finally
name: 李四;age: 12
分析结果:由于在一个方法内部定义的变量都存储在栈中,当这个函数结束后,其对应的栈就会被回收,此时在其方法体中定义的变量将不存在,因此return返回时不是直接返回变量的值,而是先产生一个副本暂存,最后返回该副本。因此对于基本类型的数据,在finally块中改变return的值对返回的副本值没有任何影响。而对于引用型变量,当产生一个副本时,对于引用对象型数据并没有重新复制一份,而是指向了原来的数据,所以改变引用型中的对象数据,也就改变了副本中的引用型对象数据。对于test2的返回结果和test1一样是因为,引用型变量又指向了重新的定义的对象,而并为对其指向的对象型数据进行改变,所以没有引起副本中的对象型数据发生改变。
4、副本是在什么情况下产生的呢?
package testfinally;
public class Test {
public static int test(){
int result = 0;
try{
result = 1;
//return result;
}catch(Exception e){
result = 2;
//return result;
}finally{
result = 3;
System.out.println("execute finally");
}
return result;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int result = test();
System.out.println(result);
}
}
输出结果:3
package testfinally;
public class Test {
public static int test(){
int result = 0;
try{
result = 1;
return result;
}catch(Exception e){
result = 2;
//return result;
}finally{
result = 3;
System.out.println("execute finally");
}
return result;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int result = test();
System.out.println(result);
}
}
输出结果:1
结果分析:
所以我认为在有return语句的try或者catch语句块里创建副本