1,JDK和JRE有什么區別?
JRE:Java Runtime Environment( java 運行時環境),即java程式的運行時環境,包含了 java 虛擬機,java基礎類別庫,
JDK:Java Development Kit( java 開發工具包),即java語言撰寫的程式所需的開發工具包,JDK 包含了 JRE,同時還包括 java 原始碼的編譯器 javac、監控工具 jconsole、分析工具 jvisualvm等,
2,==和equals的區別是什么?
== 是關系運算子,equals() 是方法,結果都回傳布林值
Object 的 == 和 equals() 比較的都是地址,作用相同
== 作用:
基本型別,比較值是否相等
參考型別,比較記憶體地址值是否相等
不能比較沒有父子關系的兩個物件
equals()方法的作用:
JDK 中的類一般已經重寫了 equals(),比較的是內容
自定義類如果沒有重寫 equals(),將呼叫父類(默認 Object 類)的 equals() 方法,Object 的 equals() 比較使用了 this == obj
可以按照需求邏輯,重寫物件的 equals() 方法(重寫 equals 方法,一般須重寫 hashCode 方法)
3,==和equals的區別是什么?
不屬于,
Java 中 8 種基礎的資料型別:byte、short、char、int、long、float、double、boolean
但是 String 型別卻是最常用到的參考型別,
4,普通類和抽象類有哪些區別?
抽象類不能被實體化
抽象類可以有抽象方法,抽象方法只需申明,無需實作
含有抽象方法的類必須申明為抽象類
抽象類的子類必須實作抽象類中所有抽象方法,否則這個子類也是抽象類
抽象方法不能被宣告為靜態
抽象方法不能用 private 修飾
抽象方法不能用 final 修飾
5,JDK、JRE、JVM之間的關系是什么樣的?
JDK 是 JAVA 程式開發時用的開發工具包,包含 Java 運行環境 JRE
JDk、JRE 內部都包含 JAVA虛擬機 JVM
JVM 包含 Java 應用程式的類的解釋器和類加載器等
6,講講面向物件三大特征
封裝
封裝:就是隱藏物件的屬性和實作細節,僅對外提供公共訪問方式,讓使用者知道的才暴露出來,不需要讓使用者知道的全部隱藏起來
封裝的好處:避免使用者直接操作屬性值,隱藏類的實作細節;讓使用者只能通程序式員規定的方法來訪問資料;可以方便的加入存取控制陳述句,限制不合理操作,提高程式安全性,
繼承
繼承是類與類之間的關系,與現實世界中的繼承(例如孩子繼承父母基因)類似,
繼承可以理解為一個類從另一個類獲取方法和屬性的程序,
例如:類B繼承于類A,那么B就擁有A的部分方法和屬性(private修飾或不在同一個包default修飾的無法訪問),
3.多型
多型是同一個行為具有多個不同表現形式或形態的能力,
多型分類和實作
編譯時多型(靜態多型):方法多載實作的多型
運行時多型(動態多型):類繼承/介面實作 + 重寫 + 向上轉型實作的多型
基于繼承/介面來實作的多型:面向介面的方式編程為的就是可以使用多型的特性讓編程變得更加靈活,
多型的優點:消除型別之間的耦合關系(可替換性,可擴充性,介面性,靈活性,簡化性)
7,什么是泛型?為什么要使用泛型?
泛型:
"引數化型別",將型別由具體的型別引數化,把型別也定義成引數形式(稱之為型別形參),然后在使用/呼叫時傳入具體的型別(型別實參),
是 JDK 5 中引入的一個新特性,提供了編譯時型別安全監測機制,該機制允許程式員在編譯時監測非法的型別,
泛型的本質是把引數的型別引數化,也就是所操作的資料型別被指定為一個引數,這種引數型別可以用在類、介面和方法中,
為什么要用泛型?
使用泛型撰寫的程式代碼,要比使用 Object 變數再進行強制型別轉換的代碼,具有更好的安全性和可讀性,
多種資料型別執行相同的代碼使用泛型可以復用代碼,
比如集合類使用泛型,取出和操作元素時無需進行型別轉換,避免出現 java.lang.ClassCastException 例外
8,String、StringBuilder、StringBuffer的區別?
相同點:
都可以儲存和操作字串
都使用 final 修飾,不能被繼承
提供的 API 相似
區別:
String 是只讀字串,String 物件內容是不能被改變的
StringBuffer 和 StringBuilder 的字串物件可以對字串內容進行修改,在修改后的記憶體地址不會發生改變
StringBuilder 執行緒不安全;StringBuffer 執行緒安全
方法體內沒有對字串的并發操作,且存在大量字串拼接操作,建議使用 StringBuilder,效率較高,
9,&和&&的作用和區別
&
邏輯與,& 兩邊的運算式都會進行運算
整數的位運算子
&&
短路與,&& 左邊的運算式結果為 false 時,&& 右邊的運算式不參與計算
10,說一說你的對面向程序和面向物件的理解
軟體開發思想,先有面向程序,后有面向物件
在大型軟體系統中,面向程序的做法不足,從而推出了面向物件
都是解決實際問題的思維方式
兩者相輔相成,宏觀上面向物件把握復雜事物的關系;微觀上面向程序去處理
面向程序以實作功能的函式開發為主;面向物件要首先抽象出類、屬性及其方法,然后通過實體化類、執行方法來完成功能
面向程序是封裝的是功能;面向物件封裝的是資料和功能
面向物件具有繼承性和多型性;面向程序則沒有
11,說一說你的對面向程序和面向物件的理解
垃圾回識訓制,簡稱 GC
Java 語言不需要程式員直接控制記憶體回收,由 JVM 在后臺自動回收不再使用的記憶體
提高編程效率
保護程式的完整性
JVM 需要跟蹤程式中有用的物件,確定哪些是無用的,影響性能
特點
回收 JVM 堆記憶體里的物件空間,不負責回收堆疊記憶體資料
無法處理一些作業系統資源的釋放,如資料庫連接、輸入流輸出流、Socket 連接
垃圾回收發生具有不可預知性,程式無法精確控制垃圾回識訓制執行
可以將物件的參考變數設定為 null,垃圾回識訓制可以在下次執行時回收該物件,
JVM 有多種垃圾回收 實作演算法,表現各異
垃圾回識訓制回收任何物件之前,會先呼叫物件的 finalize() 方法
可以通過 System.gc() 或 Runtime.getRuntime().gc() 通知系統進行垃圾回收,會有一些效果,但系統是否進行垃圾回收依然不確定
不要主動呼叫物件的 finalize() 方法,應該交給垃圾回識訓制呼叫
12,說一說你的對面向程序和面向物件的理解
記憶體溢位(out of memory):指程式在申請記憶體時,沒有足夠的記憶體空間供其使用,出現 out of memory,
記憶體泄露(memory leak):指程式在申請記憶體后,無法釋放已申請的記憶體空間,記憶體泄露堆積會導致記憶體被占光,
memory leak 最侄訓導致 out of memory,
13,說一說你的對面向程序和面向物件的理解
final 表示最終的、不可改變的,用于修飾類、方法和變數,final 修飾的類不能被繼承;final 方法也同樣只能使用,不能重寫,但能夠多載;final 修飾的成員變數必須在宣告時給定初值或者在構造方法內設定初始值,只能讀取,不可修改;final 修飾的區域變數必須在宣告時給定初值;final 修飾的變數是非基本型別,物件的參考地址不能變,但物件的屬性值可以改變
finally 例外處理的一部分,它只能用在 try/catch 陳述句中,表示希望 finally 陳述句塊中的代碼最后一定被執行(存在一些情況導致 finally 陳述句塊不會被執行,如 jvm 結束)
finalize() 是在 java.lang.Object 里定義的,Object 的 finalize() 方法什么都不做,物件被回收時 finalize() 方法會被呼叫,Java 技術允許使用 finalize() 方法在垃圾收集器將物件從記憶體中清除出去之前做必要清理作業,在垃圾收集器洗掉物件之前被呼叫的,一般情況下,此方法由JVM呼叫,特殊情況下,可重寫 finalize() 方法,當物件被回收的時候釋放一些資源,須呼叫 super.finalize() ,
14,return與finally的執行順序對回傳值的影響
對于 try 和 finally 至少一個陳述句塊包含 return 陳述句的情況:
finally 陳述句塊會執行
finally 沒有 return,finally 對 return 變數的重新賦值修改無效
try 和 finally 都包含 return,return 值會以 finally 陳述句塊 return 值為準
如下面的例子
如下面的例子
public static void main(String[] args) {
System.out.println(getString());
}
public static String getString() {
String str = "A";
try {
str = "B";
return str;
} finally {
System.out.println("finally change return string to C");
str = "C";
}
}
列印
finally change return string to C
B
finally 陳述句塊中新增 return 陳述句
public static void main(String[] args) {
System.out.println(getString());
}
public static String getString() {
String str = "A";
try {
str = "B";
return str;
} finally {
System.out.println("finally change return string to C");
str = "C";
return str;
}
}
列印結果
finally change return string to C
C
15,Math.round(-1.5) 等于多少?
運行結果: -1
JDK 中的 java.lang.Math 類
ceil() :向上取整,回傳小數所在兩整數間的較大值,回傳型別是 double,如 -1.5 回傳 -1.0
floor() :向下取整,回傳小數所在兩整數間的較小值,回傳型別是 double,如 -1.5 回傳 -2.0
round() :朝正無窮大方向回傳引數最接近的整數,可以換算為 引數 + 0.5 向下取整,回傳值是 int 或 long,如 -1.5 回傳 -1
16,抽象類能使用final修飾嗎?
不能,抽象類是被用于繼承的,final修飾代表不可修改、不可繼承的,
17,抽象類能使用final修飾嗎?
throw:
表示方法內拋出某種例外物件(只能是一個)
用于程式員自行產生并拋出例外
位于方法體內部,可以作為單獨陳述句使用
如果例外物件是非 RuntimeException 則需要在方法申明時加上該例外的拋出,即需要加上 throws 陳述句 或者 在方法體內 try catch 處理該例外,否則編譯報錯
執行到 throw 陳述句則后面的陳述句塊不再執行
throws:
方法的定義上使用 throws 表示這個方法可能拋出某些例外(可以有多個)
用于宣告在該方法內拋出了例外
必須跟在方法引數串列的后面,不能單獨使用
需要由方法的呼叫者進行例外處理
18,動態代理是什么?應用場景?
動態代理:在運行時,創建目標類,可以呼叫和擴展目標類的方法,
Java 中實作動態的方式:
JDK 中的動態代理
Java類別庫 CGLib
應用場景:
統計每個 api 的請求耗時
統一的日志輸出
校驗被呼叫的 api 是否已經登錄和權限鑒定
Spring的 AOP 功能模塊就是采用動態代理的機制來實作切面編程
19,動態代理是什么?應用場景?
final 語意是不可改變的,
被 final 修飾的類,不能夠被繼承
被 final 修飾的成員變數必須要初始化,賦初值后不能再重新賦值(可以呼叫物件方法修改屬性值),對基本型別來說是其值不可變;對參考變數來說其參考不可變,即不能再指向其他的物件
被 final 修飾的方法不能重寫
20,finally陳述句塊一定執行嗎?
答案是不一定,存在很多特殊情況導致 finally 陳述句塊不執行,如:
直接回傳未執行到 try-finally 陳述句塊
拋出例外未執行到 try-finally 陳述句塊
系統退出未執行到 finally 陳述句塊
21,String屬于基礎的資料型別嗎?
不屬于,
Java 中 8 種基礎的資料型別:byte、short、char、int、long、float、double、boolean
但是 String 型別卻是最常用到的參考型別,
22,面向物件和面向程序的區別?
面向程序:
優點:性能比面向物件高,因為類呼叫時需要實體化,開銷比較大,比較消耗資源;比如單片機、嵌入式開發、Linux/Unix等一般采用面向程序開發,性能是最重要的因素,
缺點:沒有面向物件易維護、易復用、易擴展,
面向物件:
優點:易維護、易復用、易擴展,由于面向物件有封裝、繼承、多型性的特性,可以設計出低耦合的系統,使系統更加靈活、更加易于維護,
缺點:性能比面向程序低,
23,面向物件和面向程序的區別?
方法的多載和重寫都是實作多型的方式,區別在于前者實作的是編譯時的多型性,而后者實作的是運行時的多型性,
重寫發生在子類與父類之間, 重寫方法回傳值和形參都不能改變,與方法回傳值和訪問修飾符無關,即多載的方法不能根據回傳型別進行區分,即外殼不變,核心重寫!
多載(overloading) 是在一個類里面,方法名字相同,而引數不同,回傳型別可以相同也可以不同,每個多載的方法(或者建構式)都必須有一個獨一無二的引數型別串列,最常用的地方就是構造器的多載,
24,抽象類和介面的區別是什么?
語法層面上的區別:
抽象類可以提供成員方法的實作細節,而介面中只能存在public abstract 方法;
抽象類中的成員變數可以是各種型別的,而介面中的成員變數只能是public static final型別的;
介面中不能含有靜態代碼塊以及靜態方法,而抽象類可以有靜態代碼塊和靜態方法;
一個類只能繼承一個抽象類,而一個類卻可以實作多個介面,
設計層面上的區別:
抽象類是對一種事物的抽象,即對類抽象,而介面是對行為的抽象,抽象類是對整個類整體進行抽象,包括屬性、行為,但是介面卻是對類區域(行為)進行抽象,
設計層面不同,抽象類作為很多子類的父類,它是一種模板式設計,而介面是一種行為規范,它是一種輻射式設計,
25,java 創建物件有哪幾種方式?
java中提供了以下四種創建物件的方式:
new創建新物件
通過反射機制
采用clone機制
通過序列化機制
前兩者都需要顯式地呼叫構造方法,對于clone機制,需要注意淺拷貝和深拷貝的區別,對于序列化機制需要明確其實作原理,在java中序列化可以通過實作Externalizable或者Serializable來實作,
26,為什么重寫 equals 方法必須重寫 hashcode 方法 ??
判斷的時候先根據hashcode進行的判斷,相同的情況下再根據equals()方法進行判斷,如果只重寫了equals方法,而不重寫hashcode的方法,會造成hashcode的值不同,而equals()方法判斷出來的結果為true,
在Java中的一些容器中,不允許有兩個完全相同的物件,插入的時候,如果判斷相同則會進行覆寫,這時候如果只重寫了equals()的方法,而不重寫hashcode的方法,Object中hashcode是根據物件的存盤地址轉換而形成的一個哈希值,這時候就有可能因為沒有重寫hashcode方法,造成相同的物件散列到不同的位置而造成物件的不能覆寫的問題,
27,包裝型別是什么?基本型別和包裝型別有什么區別?
Java 為每一個基本資料型別都引入了對應的包裝型別(wrapper class),int 的包裝類就是 Integer,從 Java 5 開始引入了自動裝箱/拆箱機制,把基本型別轉換成包裝型別的程序叫做裝箱(boxing);反之,把包裝型別轉換成基本型別的程序叫做拆箱(unboxing),使得二者可以相互轉換,
Java 為每個原始型別提供了包裝型別:
原始型別: boolean,char,byte,short,int,long,float,double
包裝型別:Boolean,Character,Byte,Short,Integer,Long,Float,Double
基本型別和包裝型別的區別主要有以下 幾點:
包裝型別可以為 null,而基本型別不可以,它使得包裝型別可以應用于 POJO 中,而基本型別則不行,那為什么 POJO 的屬性必須要用包裝型別呢?《阿里巴巴 Java 開發手冊》上有詳細的說明, 資料庫的查詢結果可能是 null,如果使用基本型別的話,因為要自動拆箱(將包裝型別轉為基本型別,比如說把 Integer 物件轉換成 int 值),就會拋出 NullPointerException 的例外,
包裝型別可用于泛型,而基本型別不可以,泛型不能使用基本型別,因為使用基本型別時會編譯出錯,
List<int> list = new ArrayList<>(); // 提示 Syntax error, insert "Dimensions" to complete ReferenceType
List<Integer> list = new ArrayList<>();
因為泛型在編譯時會進行型別擦除,最后只保留原始型別,而原始型別只能是 Object 類及其子類——基本型別是個特例,
基本型別比包裝型別更高效,基本型別在堆疊中直接存盤的具體數值,而包裝型別則存盤的是堆中的參考, 很顯然,相比較于基本型別而言,包裝型別需要占用更多的記憶體空間,
28,int 和 Integer 有什么區別?
Integer是int的包裝類;int是基本資料型別;
Integer變數必須實體化后才能使用;int變數不需要;
Integer實際是物件的參考,指向此new的Integer物件;int是直接存盤資料值 ;
Integer的默認值是null;int的默認值是0,
29,什么是反射?反射機制的優缺點有哪些?
反射是在運行狀態中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個物件,都能夠呼叫它的任意一個方法和屬性;這種動態獲取的資訊以及動態呼叫物件的方法的功能稱為 Java 語言的反射機制,
優點:能夠運行時動態獲取類的實體,提高靈活性;可與動態編譯結合Class.forName('com.mysql.jdbc.Driver.class');,加載MySQL的驅動類,
缺點:使用反射性能較低,需要決議位元組碼,將記憶體中的物件進行決議,其解決方案是:通過setAccessible(true)關閉JDK的安全檢查來提升反射速度;多次創建一個類的實體時,有快取會快很多;ReflflectASM工具類,通過位元組碼生成的方式加快反射速度,
30,Java反射API有幾類?
反射 API 用來生成 JVM 中的類、介面或則物件的資訊,
Class 類:反射的核心類,可以獲取類的屬性,方法等資訊,
Field 類:Java.lang.reflec 包中的類,表示類的成員變數,可以用來獲取和設定類之中的屬性值,
Method 類:Java.lang.reflec 包中的類,表示類的方法,它可以用來獲取類中的方法資訊或者執行方法,
Constructor 類:Java.lang.reflec 包中的類,表示類的構造方法,
31,Java序列化與反序列化是什么?
Java序列化是指把Java物件轉換為位元組序列的程序,而Java反序列化是指把位元組序列恢復為Java物件的程序:
序列化:序列化是把物件轉換成有序位元組流,以便在網路上傳輸或者保存在本地檔案中,核心作用是物件狀態的保存與重建,我們都知道,Java物件是保存在JVM的堆記憶體中的,也就是說,如果JVM堆不存在了,那么物件也就跟著消失了,
而序列化提供了一種方案,可以讓你在即使JVM停機的情況下也能把物件保存下來的方案,就像我們平時用的U盤一樣,把Java物件序列化成可存盤或傳輸的形式(如二進制流),比如保存在檔案中,這樣,當再次需要這個物件的時候,從檔案中讀取出二進制流,再從二進制流中反序列化出物件,
反序列化:客戶端從檔案中或網路上獲得序列化后的物件位元組流,根據位元組流中所保存的物件狀態及描述資訊,通過反序列化重建物件,
32,為什么需要序列化與反序列化?
簡要描述:對記憶體中的物件進行持久化或網路傳輸, 這個時候都需要序列化和反序列化
深入描述:
物件序列化可以實作分布式物件,
主要應用例如:RMI(即遠程呼叫Remote Method Invocation)要利用物件序列化運行遠程主機上的服務,就像在本地機上運行物件時一樣,
java物件序列化不僅保留一個物件的資料,而且遞回保存物件參考的每個物件的資料,
可以將整個物件層次寫入位元組流中,可以保存在檔案中或在網路連接上傳遞,利用物件序列化可以進行物件的"深復制",即復制物件本身及參考的物件本身,序列化一個物件可能得到整個物件序列,
序列化可以將記憶體中的類寫入檔案或資料庫中,
比如:將某個類序列化后存為檔案,下次讀取時只需將檔案中的資料反序列化就可以將原先的類還原到記憶體中,也可以將類序列化為流資料進行傳輸,
總的來說就是將一個已經實體化的類轉成檔案存盤,下次需要實體化的時候只要反序列化即可將類實體化到記憶體中并保留序列化時類中的所有變數和狀態,
物件、檔案、資料,有許多不同的格式,很難統一傳輸和保存,
序列化以后就都是位元組流了,無論原來是什么東西,都能變成一樣的東西,就可以進行通用的格式傳輸或保存,傳輸結束以后,要再次使用,就進行反序列化還原,這樣物件還是物件,檔案還是檔案,
33,為什么需要序列化與反序列化?
java.lang.IllegalAccessError:違法訪問錯誤,當一個應用試圖訪問、修改某個類的域(Field)或者呼叫其方法,但是又違反域或方法的可見性宣告,則拋出該例外,
java.lang.InstantiationError:實體化錯誤,當一個應用試圖通過Java的new運算子構造一個抽象類或者介面時拋出該例外.
java.lang.OutOfMemoryError:記憶體不足錯誤,當可用記憶體不足以讓Java虛擬機分配給一個物件時拋出該錯誤,
java.lang.StackOverflowError:堆疊溢位錯誤,當一個應用遞回呼叫的層次太深而導致堆疊溢位或者陷入死回圈時拋出該錯誤,
java.lang.ClassCastException:類造型例外,假設有類A和B(A不是B的父類或子類),O是A的實體,那么當強制將O構造為類B的實體時拋出該例外,該例外經常被稱為強制型別轉換例外,
java.lang.ClassNotFoundException:找不到類例外,當應用試圖根據字串形式的類名構造類,而在遍歷CLASSPAH之后找不到對應名稱的class檔案時,拋出該例外,
java.lang.ArithmeticException:算術條件例外,譬如:整數除零等,
java.lang.ArrayIndexOutOfBoundsException:陣列索引越界例外,當對陣列的索引值為負數或大于等于陣列大小時拋出,
java.lang.IndexOutOfBoundsException:索引越界例外,當訪問某個序列的索引值小于0或大于等于序列大小時,拋出該例外,
java.lang.InstantiationException:實體化例外,當試圖通過newInstance()方法創建某個類的實體,而該類是一個抽象類或介面時,拋出該例外,
java.lang.NoSuchFieldException:屬性不存在例外,當訪問某個類的不存在的屬性時拋出該例外,
java.lang.NoSuchMethodException:方法不存在例外,當訪問某個類的不存在的方法時拋出該例外,
java.lang.NullPointerException:空指標例外,當應用試圖在要求使用物件的地方使用了null時,拋出該例外,譬如:呼叫null物件的實體方法、訪問null物件的屬性、計算null物件的長度、使用throw陳述句拋出null等等,
java.lang.NumberFormatException:數字格式例外,當試圖將一個String轉換為指定的數字型別,而該字串確不滿足數字型別要求的格式時,拋出該例外,
java.lang.StringIndexOutOfBoundsException:字串索引越界例外,當使用索引值訪問某個字串中的字符,而該索引值小于0或大于等于序列大小時,拋出該例外,
34,try-catch-finally 中哪個部分可以省略?
catch 可以省略,更為嚴格的說法其實是:try只適合處理運行時例外,try+catch適合處理運行時例外+普通例外,也就是說,如果你只用try去處理普通例外卻不加以catch處理,編譯是通不過的,因為編譯器硬性規定,普通例外如果選擇捕獲,則必須用catch顯示宣告以便進一步處理,而運行時例外在編譯時沒有如此規定,所以catch可以省略,你加上catch編譯器也覺得無可厚非,
理論上,編譯器看任何代碼都不順眼,都覺得可能有潛在的問題,所以你即使對所有代碼加上try,代碼在運行期時也只不過是在正常運行的基礎上加一層皮,但是你一旦對一段代碼加上try,就等于顯示地承諾編譯器,對這段代碼可能拋出的例外進行捕獲而非向上拋出處理,如果是普通例外,編譯器要求必須用catch捕獲以便進一步處理;如果運行時例外,捕獲然后丟棄并且+finally掃尾處理,或者加上catch捕獲以便進一步處理,
至于加上finally,則是在不管有沒捕獲例外,都要進行的“掃尾”處理,
35,JVM 是如何處理例外的?
在一個方法中如果發生例外,這個方法會創建一個例外物件,并轉交給 JVM,該例外物件包含例外名稱,例外描述以及例外發生時應用程式的狀態,創建例外物件并轉交給 JVM 的程序稱為拋出例外,可能有一系列的方法呼叫,最終才進入拋出例外的方法,這一系列方法呼叫的有序串列叫做呼叫堆疊,
JVM 會順著呼叫堆疊去查找看是否有可以處理例外的代碼,如果有,則呼叫例外處理代碼,當 JVM 發現可以處理例外的代碼時,會把發生的例外傳遞給它,如果 JVM 沒有找到可以處理該例外的代碼塊,JVM 就會將該例外轉交給默認的例外處理器(默認處理器為 JVM 的一部分),默認例外處理器列印出例外資訊并終止應用程式,
36,Java的IO 流分為幾種?
按照流的方向:輸入流(inputStream)和輸出流(outputStream);
按照實作功能分:節點流(可以從或向一個特定的地方讀寫資料,如 FileReader)和處理流(是對一個已存在的流的連接和封裝,通過所封裝的流的功能呼叫實作資料讀寫, BufferedReader);
按照處理資料的單位: 位元組流和字符流,分別由四個抽象類來表示(每種流包括輸入和輸出兩種所以一共四個):InputStream,OutputStream,Reader,Writer,Java中其他多種多樣變化的流均是由它們派生出來的,
37,位元組流如何轉為字符流?
位元組輸入流轉字符輸入流通過 InputStreamReader 實作,該類的建構式可以傳入 InputStream 物件,
位元組輸出流轉字符輸出流通過 OutputStreamWriter 實作,該類的建構式可以傳入 OutputStream 物件,
38,字符流與位元組流的區別?
讀寫的時候位元組流是按位元組讀寫,字符流按字符讀寫,
位元組流適合所有型別檔案的資料傳輸,因為計算機位元組(Byte)是電腦中表示資訊含義的最小單位,字符流只能夠處理純文本資料,其他型別資料不行,但是字符流處理文本要比位元組流處理文本要方便,
在讀寫檔案需要對內容按行處理,比如比較特定字符,處理某一行資料的時候一般會選擇字符流,
只是讀寫檔案,和檔案內容無關時,一般選擇位元組流,
39,BIO、NIO、AIO的區別?
BIO:同步并阻塞,在服務器中實作的模式為一個連接一個執行緒,也就是說,客戶端有連接請求的時候,服務器就需要啟動一個執行緒進行處理,如果這個連接不做任何事情會造成不必要的執行緒開銷,當然這也可以通過執行緒池機制改善,BIO一般適用于連接數目小且固定的架構,這種方式對于服務器資源要求比較高,而且并發局限于應用中,是JDK1.4之前的唯一選擇,但好在程序直觀簡單,易理解,
NIO:同步并非阻塞,在服務器中實作的模式為一個請求一個執行緒,也就是說,客戶端發送的連接請求都會注冊到多路復用器上,多路復用器輪詢到有連接IO請求時才會啟動一個執行緒進行處理,NIO一般適用于連接數目多且連接比較短(輕操作)的架構,并發局限于應用中,編程比較復雜,從JDK1.4開始支持,
AIO:異步并非阻塞,在服務器中實作的模式為一個有效請求一個執行緒,也就是說,客戶端的IO請求都是通過作業系統先完成之后,再通知服務器應用去啟動執行緒進行處理,AIO一般適用于連接數目多且連接比較長(重操作)的架構,充分呼叫作業系統參與并發操作,編程比較復雜,從JDK1.7開始支持,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/524910.html
標籤:其他
上一篇:Google Guava 工具類(一)—— EventBus(觀察者模式的實作)
下一篇:java Stream流練習
