Java中的.close()舉例詳解
當(dāng)你遇到以下三種情況時(shí),一定要記得使用 .close():
1.操作文件
2.訪問網(wǎng)絡(luò)
3.連接數(shù)據(jù)庫
用法
.close()是一種方法,所以一般是 對(duì)象.close()來調(diào)用的
作用
.close() 的作用就是釋放程序占用的外部資源(如文件、網(wǎng)絡(luò)連接),把它們“還給”操作系統(tǒng),以避免資源浪費(fèi)和程序崩潰。
個(gè)人理解:.close() 的本質(zhì)是“有借有還”。當(dāng)你向操作系統(tǒng)“借用”了一個(gè)外部資源(比如打開一個(gè)文件),你就有責(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);
}
}這是一個(gè)簡(jiǎn)單的實(shí)現(xiàn)輸入功能的代碼,就以這個(gè)代碼舉例(之前發(fā)過一個(gè)“Java如何實(shí)現(xiàn)輸出”里面有詳細(xì)講解)
如何判斷代碼中的 input 對(duì)象要不要用到 .close()?
我們可以遵循一個(gè)簡(jiǎn)單的兩步判斷流程:
第一步:查看對(duì)象的類定義(是否聲明有implements AutoCloseable或 implements Closeable)
示例代碼中對(duì)象為‘input’,因?yàn)檫@個(gè)對(duì)象是根據(jù)“Scanner”這個(gè)類創(chuàng)造出來的,所以它的類是“Scanner”,長(zhǎng)按“Ctr”鼠標(biāo)放在“Scanner"上面,查看它的聲明中有沒有有沒有 implements AutoCloseable 或者 implements Closeable?

?? 如果【沒有】:
結(jié)論: 流程結(jié)束。絕對(duì)不需要 .close()。
例子: ArrayList, String, HashMap 等。它們不管理外部資源,所以沒有這個(gè)“資格”。
?? 如果【有】:
結(jié)論: 這個(gè)對(duì)象有資格被關(guān)閉。它是一個(gè)需要被嚴(yán)肅對(duì)待的資源對(duì)象。請(qǐng)繼續(xù)第二步判斷。
例子: Scanner, FileInputStream, Socket, Connection 等。
第二步:“關(guān)閉”是我的責(zé)任嗎?
只有通過了第一步的對(duì)象,才需要進(jìn)行這一步的審查。
操作: 看你是如何創(chuàng)建這個(gè)對(duì)象的。
提問: 創(chuàng)建這個(gè)對(duì)象時(shí),它所管理的核心資源是不是 System.in、System.out 或 System.err 這三個(gè)“全局共享”資源?
?? 如果【是】:
結(jié)論: 流程結(jié)束。絕對(duì)不要 .close()!
解釋: 你正在操作一個(gè)“預(yù)設(shè)資源”,用專業(yè)術(shù)語來講就是“標(biāo)準(zhǔn)I/O流”,它是在你程序運(yùn)行前,就由環(huán)境預(yù)先設(shè)置好的,不是由你自己寫代碼動(dòng)態(tài)創(chuàng)建的”。所以關(guān)閉的責(zé)任屬于Java虛擬機(jī)(JVM),不屬于你。關(guān)閉它會(huì)引發(fā)嚴(yán)重問題。
- 小知識(shí):什么是“標(biāo)準(zhǔn)I/O流”?
“標(biāo)準(zhǔn)I/O流”(Standard I/O Streams)是計(jì)算機(jī)領(lǐng)域的一個(gè)基礎(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)錯(cuò)誤 (Standard Error):程序默認(rèn)的錯(cuò)誤信息專用出口通道。在Java里,它就是 System.err,也通常連接到屏幕。
?? 如果【不是】:
結(jié)論: 流程結(jié)束。你必須 .close() 它!
解釋: 這個(gè)資源是由你的代碼主動(dòng)“借用”的,
如何識(shí)別“主動(dòng)借用”的資源?
所謂主動(dòng)“借用”,就是指你的代碼從無到有地創(chuàng)建了一個(gè)通往外部特定目標(biāo)的連接。
你可以通過以下兩個(gè)非常明顯的代碼特征來識(shí)別這個(gè)動(dòng)作:
看得見的行為:通常使用 new 關(guān)鍵字。
當(dāng)你寫下 new FileInputStream(...) 或 new Socket(...) 時(shí),這個(gè) new 的動(dòng)作本身就是在告訴操作系統(tǒng):“請(qǐng)為我創(chuàng)建一個(gè)全新的、到外部資源的連接。” 這與直接使用已經(jīng)存在的 System.in 完全不同。明確的目標(biāo):需要你提供一個(gè)具體的“地址”。
在創(chuàng)建時(shí),你必須指定一個(gè)目標(biāo),比如一個(gè)文件名 ("data.txt")、一個(gè)網(wǎng)址 ("example.com") 或一個(gè)數(shù)據(jù)庫地址。這個(gè)“地址”參數(shù)就是一個(gè)強(qiáng)烈的信號(hào),表明你正在操作一個(gè)程序外部的、需要“借用”才能訪問的資源。所以當(dāng)你用 new 創(chuàng)建一個(gè)需要“地址”的資源對(duì)象時(shí),你就是在“借用”它,關(guān)閉的責(zé)任也自然落在了你的身上
最佳實(shí)踐: 立即使用 try-with-resources 語法來確保它被自動(dòng)、安全地關(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é)束時(shí),fileScanner 會(huì)被自動(dòng)、安全地關(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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
舉例說明JAVA調(diào)用第三方接口的GET/POST/PUT請(qǐng)求方式
在日常工作和學(xué)習(xí)中,有很多地方都需要發(fā)送請(qǐng)求,這篇文章主要給大家介紹了關(guān)于JAVA調(diào)用第三方接口的GET/POST/PUT請(qǐng)求方式的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-01-01
MybatisPlus調(diào)用原生SQL的三種方法實(shí)例詳解
這篇文章主要介紹了MybatisPlus調(diào)用原生SQL的三種方法,在有些情況下需要用到MybatisPlus查詢?cè)鶶QL,MybatisPlus其實(shí)帶有運(yùn)行原生SQL的方法,我這里列舉三種,需要的朋友可以參考下2022-09-09
Java字符串格式化,{}占位符根據(jù)名字替換實(shí)例
這篇文章主要介紹了Java字符串格式化,{}占位符根據(jù)名字替換實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-10-10
線程局部變量的實(shí)現(xiàn)?ThreadLocal使用及場(chǎng)景介紹
這篇文章主要為大家介紹了線程局部變量的實(shí)現(xiàn)?ThreadLocal使用及場(chǎng)景詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
Spring Cloud使用Feign實(shí)現(xiàn)Form表單提交的示例
本篇文章主要介紹了Spring Cloud使用Feign實(shí)現(xiàn)Form表單提交的示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-03-03
Java實(shí)現(xiàn)基于JDBC操作mysql數(shù)據(jù)庫的方法
這篇文章主要介紹了Java實(shí)現(xiàn)基于JDBC操作mysql數(shù)據(jù)庫的方法,結(jié)合實(shí)例形式分析了java使用JDBC實(shí)現(xiàn)針對(duì)mysql數(shù)據(jù)庫的連接、查詢、輸出等相關(guān)操作技巧,需要的朋友可以參考下2017-12-12
Java基于Socket實(shí)現(xiàn)簡(jiǎn)單的多線程回顯服務(wù)器功能示例
這篇文章主要介紹了Java基于Socket實(shí)現(xiàn)簡(jiǎn)單的多線程回顯服務(wù)器功能,結(jié)合實(shí)例形式分析了java使用socket進(jìn)行多線程數(shù)據(jù)傳輸?shù)南嚓P(guān)操作技巧,需要的朋友可以參考下2017-08-08
JAVA實(shí)現(xiàn)redis分布式雙重加鎖的示例代碼
在高并發(fā)環(huán)境下,通過Redis分布式鎖實(shí)現(xiàn)數(shù)據(jù)唯一性校驗(yàn)非常關(guān)鍵,為避免用戶數(shù)據(jù)重復(fù),可使用Redis鎖或集合數(shù)據(jù)結(jié)構(gòu)進(jìn)行前置檢查,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-10-10
MyBatis代理Dao方式的增刪改查的實(shí)現(xiàn)小結(jié)
本文主要介紹了MyBatis代理Dao方式的增刪改查的實(shí)現(xiàn)小結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-11-11

