Java中的.close()舉例詳解
當(dāng)你遇到以下三種情況時,一定要記得使用 .close():
1.操作文件
2.訪問網(wǎng)絡(luò)
3.連接數(shù)據(jù)庫
用法
.close()是一種方法,所以一般是 對象.close()來調(diào)用的
作用
.close() 的作用就是釋放程序占用的外部資源(如文件、網(wǎng)絡(luò)連接),把它們“還給”操作系統(tǒng),以避免資源浪費和程序崩潰。
個人理解:.close() 的本質(zhì)是“有借有還”。當(dāng)你向操作系統(tǒng)“借用”了一個外部資源(比如打開一個文件),你就有責(zé)任在用完后通過 .close() 歸還它。
舉例
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
String i = input.nextLine();
int a = Integer.parseInt(i);
System.out.println(a);
}
}這是一個簡單的實現(xiàn)輸入功能的代碼,就以這個代碼舉例(之前發(fā)過一個“Java如何實現(xiàn)輸出”里面有詳細(xì)講解)
如何判斷代碼中的 input 對象要不要用到 .close()?
我們可以遵循一個簡單的兩步判斷流程:
第一步:查看對象的類定義(是否聲明有implements AutoCloseable或 implements Closeable)
示例代碼中對象為‘input’,因為這個對象是根據(jù)“Scanner”這個類創(chuàng)造出來的,所以它的類是“Scanner”,長按“Ctr”鼠標(biāo)放在“Scanner"上面,查看它的聲明中有沒有有沒有 implements AutoCloseable 或者 implements Closeable?

?? 如果【沒有】:
結(jié)論: 流程結(jié)束。絕對不需要 .close()。
例子: ArrayList, String, HashMap 等。它們不管理外部資源,所以沒有這個“資格”。
?? 如果【有】:
結(jié)論: 這個對象有資格被關(guān)閉。它是一個需要被嚴(yán)肅對待的資源對象。請繼續(xù)第二步判斷。
例子: Scanner, FileInputStream, Socket, Connection 等。
第二步:“關(guān)閉”是我的責(zé)任嗎?
只有通過了第一步的對象,才需要進(jìn)行這一步的審查。
操作: 看你是如何創(chuàng)建這個對象的。
提問: 創(chuàng)建這個對象時,它所管理的核心資源是不是 System.in、System.out 或 System.err 這三個“全局共享”資源?
?? 如果【是】:
結(jié)論: 流程結(jié)束。絕對不要 .close()!
解釋: 你正在操作一個“預(yù)設(shè)資源”,用專業(yè)術(shù)語來講就是“標(biāo)準(zhǔn)I/O流”,它是在你程序運行前,就由環(huán)境預(yù)先設(shè)置好的,不是由你自己寫代碼動態(tài)創(chuàng)建的”。所以關(guān)閉的責(zé)任屬于Java虛擬機(JVM),不屬于你。關(guān)閉它會引發(fā)嚴(yán)重問題。
- 小知識:什么是“標(biāo)準(zhǔn)I/O流”?
“標(biāo)準(zhǔn)I/O流”(Standard I/O Streams)是計算機領(lǐng)域的一個基礎(chǔ)概念,你可以把它理解為程序與外界溝通的三條默認(rèn)通道:
標(biāo)準(zhǔn)輸入 (Standard Input):程序默認(rèn)的數(shù)據(jù)來源通道。在Java里,它就是 System.in,通常連接到鍵盤。
標(biāo)準(zhǔn)輸出 (Standard Output):程序默認(rèn)的正常信息出口通道。在Java里,它就是 System.out,通常連接到屏幕。
標(biāo)準(zhǔn)錯誤 (Standard Error):程序默認(rèn)的錯誤信息專用出口通道。在Java里,它就是 System.err,也通常連接到屏幕。
?? 如果【不是】:
結(jié)論: 流程結(jié)束。你必須 .close() 它!
解釋: 這個資源是由你的代碼主動“借用”的,
如何識別“主動借用”的資源?
所謂主動“借用”,就是指你的代碼從無到有地創(chuàng)建了一個通往外部特定目標(biāo)的連接。
你可以通過以下兩個非常明顯的代碼特征來識別這個動作:
看得見的行為:通常使用 new 關(guān)鍵字。
當(dāng)你寫下 new FileInputStream(...) 或 new Socket(...) 時,這個 new 的動作本身就是在告訴操作系統(tǒng):“請為我創(chuàng)建一個全新的、到外部資源的連接。” 這與直接使用已經(jīng)存在的 System.in 完全不同。明確的目標(biāo):需要你提供一個具體的“地址”。
在創(chuàng)建時,你必須指定一個目標(biāo),比如一個文件名 ("data.txt")、一個網(wǎng)址 ("example.com") 或一個數(shù)據(jù)庫地址。這個“地址”參數(shù)就是一個強烈的信號,表明你正在操作一個程序外部的、需要“借用”才能訪問的資源。所以當(dāng)你用 new 創(chuàng)建一個需要“地址”的資源對象時,你就是在“借用”它,關(guān)閉的責(zé)任也自然落在了你的身上
最佳實踐: 立即使用 try-with-resources 語法來確保它被自動、安全地關(guān)閉。
import java.io.File;
import java.util.Scanner;
// 從文件讀取,就必須關(guān)閉
try (Scanner fileScanner = new Scanner(new File("data.txt"))) {
while (fileScanner.hasNextLine()) {
System.out.println(fileScanner.nextLine());
}
} catch (FileNotFoundException e) {
System.err.println("文件未找到!");
}
// 當(dāng) try 塊結(jié)束時,fileScanner 會被自動、安全地關(guān)閉例如:
new FileInputStream("文件名")
new Socket("網(wǎng)址", 端口)
dataSource.getConnection()
new Scanner(new File("文件名"))
總結(jié)
到此這篇關(guān)于Java中的.close()的文章就介紹到這了,更多相關(guān)Java中.close()內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Spring框架注解掃描開啟之配置細(xì)節(jié)
本篇文章主要介紹了詳解Spring框架注解掃描開啟之配置細(xì)節(jié),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-08-08
Java中main函數(shù)的String[]?args用法舉例詳解
這篇文章主要給大家介紹了關(guān)于Java中main函數(shù)的String[]?args用法的相關(guān)資料,JAVA類中main函數(shù)的參數(shù)String[]?args指的是運行時給main函數(shù)傳遞的參數(shù),文中通過圖文以及代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12
SpringBoot整合MybatisPlus的基本應(yīng)用詳解
MyBatis-Plus (簡稱 MP)是一個 MyBatis的增強工具,在 MyBatis 的基礎(chǔ)上只做增強不做改變,為 簡化開發(fā)、提高效率而生,本文將給大家介紹一下SpringBoot整合MybatisPlus的基本應(yīng)用,需要的朋友可以參考下2024-05-05
一文解決pom.xml報錯Dependency "xxx" not f
我們在使用maven進(jìn)行jar包管理時有時會遇到pom.xml中報錯Dependency “XXX” not found,所以在本文中將給大家介紹一下pom.xml報錯Dependency "xxx" not found的解決方案,需要的朋友可以參考下2024-01-01
SpringBoot注入靜態(tài)屬性或靜態(tài)對象的方法
我們在使用SpringBoot為一些靜態(tài)屬性或者靜態(tài)對象注入時會發(fā)現(xiàn)注入不成功,我們可以以下這幾種方式把需要注入的值注入到靜態(tài)屬性中,感興趣的朋友一起看下2024-12-12

