final finally finalize的理论与部分实践

本文深入探讨了Java中的final、finally关键字及finalize方法在异常处理中的应用,通过实例展示了它们如何在方法中进行异常捕获、清除操作以及对象状态的管理。详细解析了finally块在不同情况下的执行顺序和作用,包括返回值的改变和对象属性的更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

尴尬经常问到的3个东西 

 

经常会问到的基础问题,final和finally可能比较熟悉,finalize就不行了

一:final—修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载。

[例外情况是:final修饰引用类型的方法参数时,只能要求引用对象的地址不能变,但是引用对象的属性值是可以修改的。]

 
二:finally—再异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。

从下面测试只能说,finally会跟在它前面的return之后执行,如果前面没有return,则依次执行。

并且对于有返回值的方法,

1,如果前面有return,并且返回值是基本类型,如test1(),那么finally可以改变返回值但不作为返回结果。返回结果追溯到最后一次return前。

       如果前面没有return,并且返回值是基本类型,如test2(),按照顺序执行,finally在最终的return之前执行,所以可以改变返回值并作为返回结果。

2,如果前面有return,并且返回值是引用类型,如testHasReturn(),那么finally可以改变返回值并且可作为返回结果返回。

       如果前面没有return,并且返回值是引用类型,如testNoReturn(),按照顺序执行,finally在最终的return之前执行,所以可以改变返回值并作为返回结果返回,但是该值在最后一次return之前依然可以被改变。

 

	public static void main(String[] args) throws InterruptedException{
		System.out.println("****************************");
		int i=test1();
		System.out.println("after test!"+i);
		System.out.println("----------------------------");
		i=test2();
		System.out.println("after test2!"+i);
		System.out.println("****************************");
		Car car=testHasReturn();
		System.out.println(car.getBrand());
		System.out.println("----------------------------");
		Car car2=testNoReturn();
		System.out.println(car2.getBrand());
	}

	public static int test1() throws InterruptedException {
		int j=0;
		try {
			int i=9/0;
			//throw new NullPointerException();
		} catch (Exception e) {
			j=j+1;
			System.out.println("Exception:"+j);
			return j;
		} finally {
			j=j+1;
			System.out.println("finally:"+j);
		}
		return j;
	}
	
	public static int test2() throws InterruptedException {
		int j=0;
		try {
			int i=9/0;
			//throw new NullPointerException();
		} catch (Exception e) {
			j=j+1;
			System.out.println("Exception:"+j);
			//return j;
		} finally {
			j=j+1;
			System.out.println("finally:"+j);
		}
		return j;
	}

	public static Car testHasReturn() throws InterruptedException {
		Car car=new Car();
		try {
			int i=9/0;
			//throw new NullPointerException();
		} catch (Exception e) {
			System.out.println("before e "+car.getBrand());
			car.setBrand("BenChi");
			System.out.println("after e "+car.getBrand());
			return car;
		} finally {
			System.out.println("before f "+car.getBrand());
			car.setBrand("BaoMa");
			System.out.println("after f "+car.getBrand());
		}
		return car;
	}
	
	public static Car testNoReturn() throws InterruptedException {
		Car car=new Car();
		try {
			int i=9/0;
			//throw new NullPointerException();
		} catch (Exception e) {
			System.out.println("before e "+car.getBrand());
			car.setBrand("BenChi");
			System.out.println("after e "+car.getBrand());
			//return car;
		} finally {
			System.out.println("before f "+car.getBrand());
			car.setBrand("BaoMa");
			System.out.println("after f "+car.getBrand());
		}
		car.setBrand("BaoMa2");
		return car;
	}

	输出内容如下:
	****************************
	Exception:1
	finally:2
	after test!1
	----------------------------
	Exception:1
	finally:2
	after test2!2
	****************************
	before e null
	after e BenChi
	before f BenChi
	after f BaoMa
	BaoMa
	----------------------------
	before e null
	after e BenChi
	before f BenChi
	after f BaoMa
	BaoMa2

可能测试还不够全面。。。再看吧。。。


三:finalize—方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。

<think>我们正在讨论Java中的finalfinallyfinalize的区别。根据引用内容,这三个概念分别属于不同的领域: - final:关键字,用于修饰类、方法、变量,表示不可变 - finally:异常处理机制的一部分,确保代码块一定执行 - finalize:Object类的方法,在垃圾回收前被调用(已弃用) 下面我将详细解释每个概念,并比较它们的区别。</think>### Java 中 finalfinallyfinalize 的区别详解 #### 1. **final(不可变性修饰符)** - **核心作用**:声明不可变实体 - **应用场景**: - **修饰类**:类不可被继承(如 `String` 类) ```java final class ImmutableClass { } // 禁止继承[^1][^2] ``` - **修饰方法**:方法不可被子类重写 ```java class Parent { final void secureMethod() { } // 子类不能覆盖此方法 } ``` - **修饰变量**:变量值不可修改(常量) ```java final double PI = 3.14159; // 值初始化后不可变[^5] ``` - **内存特性**: - 基本类型常量:值直接存储(栈/方法区) - 引用类型常量:引用地址不可变,对象内容可能可变[^4] #### 2. **finally(异常处理保障)** - **核心作用**:确保关键代码**必定执行** - **使用场景**: ```java FileInputStream fis = null; try { fis = new FileInputStream("file.txt"); // 文件操作... } catch (IOException e) { e.printStackTrace(); } finally { if (fis != null) { fis.close(); // 确保资源释放[^3] } } ``` - **关键特性**: - 无论是否发生异常都会执行 - 即使 `try/catch` 中有 `return` 语句仍会执行 - 需单独处理 `finally` 中的异常[^4] #### 3. **finalize(对象回收钩子)** - **核心作用**:对象被垃圾回收前执行清理(**已弃用**) - **工作机制**: ```java public class ResourceHolder { @Override protected void finalize() throws Throwable { try { cleanup(); // 清理非内存资源 } finally { super.finalize(); } } } ``` - **严重缺陷**: - 执行时机不确定(依赖GC) - 可能引发资源泄漏 - JDK 9+ 标记为 `@Deprecated`[^1][^5] #### 三者的核心区别总结 | **特性** | final | finally | finalize | |----------------|--------------------------------|-----------------------------|------------------------------| | **类型** | 关键字 | 异常处理代码块 | Object 类的方法 | | **作用** | 强制不可变性 | 确保代码执行 | 垃圾回收前清理资源 | | **执行时机** | 编译期约束 | 异常处理后必定执行 | GC 运行时不确定 | | **现状** | 广泛使用 | 关键资源处理必备 | JDK 9+ 已弃用 | | **典型场景** | 常量声明、安全类设计 | 资源释放(文件/数据库连接) | 历史遗留资源清理(不推荐) | #### ⚠️ 重要注意事项 1. **资源释放优先选择 finally** 而非 `finalize`,因后者执行不可靠[^3] 2. **final 的常量优化** 编译器可能将 `final` 常量直接内联到代码中 3. **finally 中的 return 陷阱** 若 `finally` 和 `try` 同时存在 `return`,`finally` 的返回值会覆盖 `try` 的返回值 4. **替代 finalize 的方案** 使用 `AutoCloseable` 接口配合 `try-with-resources`: ```java try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) { // 自动资源管理 } // 无需显式调用 close()[^4] ``` --- ### 📚 总结决策图 ```mermaid graph TD A[需要什么特性?] A --> B[需要不可变性?] -->|类/方法/变量| FINAL A --> C[需要确保代码执行?] -->|资源清理| FINALLY A --> D[对象回收前操作?] -->|已弃用| FINALIZE ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值