文章目錄
- JAVA編程基礎
- 如何理解面向物件編程?
- JDK 和 JRE 有什么區別?
- 如何理解Java中封裝,繼承、多型特性?
- 如何理解Java中的位元組碼物件?
- 你是如何理解Java中的泛型的?
- 說說泛型應用在什么場景呢?
- 如何理解Java中的泛型通配符?
- 說說什么是泛型型別擦除?
- Java 虛擬機分析
- 你是如何理解JVM的?
- 我們為什么要學習JVM?
- 市場上有哪些主流的JVM呢?
- JVM的體系結構是怎樣的?
- 你知道JVM有哪些運行模式嗎?
JAVA編程基礎
如何理解面向物件編程?
面向物件編程強調的是一種編程的思想,它是將客觀存在的一切事物都理解為計算機中的物件,當我們通過撰寫程式的方式去解決一些業務問題時,應該首先想到的是用什么物件去解決這個問題,其次是才是解決這個問題的步驟,例如將大象放冰箱,不能先想到的是打開門,放大象,關門這個步驟,這只是一種面向程序編程而已,而面向物件編程,強調的是你要放的是一個什么樣的大象,你是否有可以放下這個大象的冰箱,然后由誰將大象放到冰箱,也就是說面向物件的重點是物件,再比如說我要去上海,首先想到的應該是交通工具,然后才是先到哪里,再到哪里,總而言之,面向物件編程編程更符合人們看待事務的基本規律,這種思想也非常適合解決一些大型的業務問題,例如讓你做一航母,你應該想到的是這個航母的構成,而不是構建這個航母的基本步驟,讓你去做一個電商專案,你應該想到的是這個專案中系統服務物件的構成,例如商品服務,推薦服務,訂單服務,庫存服務,配送服務,優惠券服務,知識問答服務等等,這就是面向物件編程,
JDK 和 JRE 有什么區別?
JDK: Java Development Kit 的簡稱,Java開發工具包,提供了Java的開發環境和運行環境,
JRE: Java Runtime Environment的簡稱,Java運行環境,為Java的運行提供了所需環境,
實際上我們在安裝JDK時,它會包含一個Jre,同時還包含了編譯Java原始碼和運行Java 類檔案的一個開發、除錯和分析的工具,簡單點說,假如你需要運行Java程式,只需要安裝Jre就可以了,如何你需要撰寫,除錯Java程式,需要安裝JDK,
如何理解Java中封裝,繼承、多型特性?
封裝特性:
個人認為封裝特性應該是面向物件編程中最難的一個特性,大到一個系統的構成,比方說這個系統應該有多少個服務,每個服務應該有哪些模塊,每個模塊應該有哪些物件,這里其實強調的是一個系統邊界劃分的問題,當然也是封裝問題,還有,小到一個物件應該有哪些屬性,哪些方法,這些物件,屬性和方法分別使用什么樣的訪問修飾符進行定義,它們的可見范圍是怎樣的,這都是封裝特性,生活中大到國家有多個省份,每個省份有多少個地市,每個地市有多少個區縣,小到一個公司有多少個事業部,每個事業部有哪些成員,每個成員都有什么特征(個頭高,帥氣,漂亮),什么行為(做事,說話,跳舞,唱歌),這也都是封裝,在Java編程程序中,我們知道MyBatis實作了對JDBC操作資料庫這個程序的封裝,Spring封裝了物件的創建,依賴注入的程序,SpringBoot封裝了很多的基礎配置,實作了開箱即用的特性,Spring Cloud 封裝了一種服務治理的思想,例如如何實作服務注冊,發現,呼叫,配置等,當然程式中的每個物件也都有自己的特性和行為,例如執行緒物件封裝了執行任務的的特性和方法,IO物件封裝了讀寫記憶體,磁盤,網路資料方式等等,這些都是封裝特性,
繼承特性:
Java中的繼承特性是程式中實作代碼的復用的一種方式,也是它最大的優勢,實際編程中我們通常將共性寫到父類中,特性寫到子類中,當然子類也可以進行自己的擴展,這種繼承關系可以看成是一種is a的關系,例如class Circle extends Shape{}表示圓形(Circle)是一個圖形(Shape),class Dog extends Animal{}表示狗(Dog)是一個動物(Animal),在Java中類的繼承可以是多層,但不能是多重,即一個子類不能有多個直接的父類,子類可以繼承父類所有屬性和方法,但私有屬性和方法不能直接訪問,子類可以基于業務重寫父類可見方法,以實作功能拓展,我們也可以在子類構造方法內部通過super(引數串列)呼叫父類構造方法和super.xxx的方式呼叫父類的成員,在實際應用中繼承關系是一種強耦合關系,繼承關系層次最好不要多于三層,否則可能難于維護,
多型特性
多型是對物件行為的一種描述,在java中基于封裝和繼承特性,定義了編譯時多型和運行時多型,編譯時的多型就是方法的多載(方法名相同,引數串列不同),運行時的多型是基于繼承特性實作的一種重寫,本質上就是把做什么和具體怎么做分開了,例如我們定義了要做什么,但具體怎么做完全取決于具體的物件,例如睡覺是一種行為,但是有的人睡覺時磨牙,有的人說夢話,有的人打呼嚕,有的人夢游,同樣,吃飯也是一種行為,有的人吃飯細嚼慢咽,有的人狼吞虎咽,在程式中我們通常將多型特性應用在方法的回傳值和引數型別上,方法的回傳值和引數型別能用抽象則用抽象,便于后于進行多型拓展,
如何理解Java中的位元組碼物件?
每個類在加載(將類讀到記憶體)時都會創建一個位元組碼物件,其型別為Class型別,且這個物件在一個JVM記憶體中是唯一的.此物件中存盤的是類的結構資訊(元資料資訊),節碼物件的獲取方式常用的有如下三種:
a) 類名.class
b) Class.forName(“包名.類名”)
c) 類的實體物件.getClass();
代碼演示:
package com.java.oop;
//呈現類加載程序(通過配置JVM引數實作)
//-XX:+TraceClassLoading
public class TestClassObject01 {
static public void main(String[] args)throws Exception {
Class<Object> c1=Object.class;
Class<?> c2=Class.forName("java.lang.Object");
System.out.println(c1==c2);
Class<?> c3=new Object().getClass();
System.out.println(c2==c3);
}
}
你是如何理解Java中的泛型的?
泛型是JDK1.5推出的一種引數化的型別,我們可以將定義型別時使用的泛型,理解為形參,例如,List、Map<K,V>介面中的E,K,V都可以看成是泛型,也就是一種特殊的形參,當我們應用這些集合時傳入的具體型別可以看成是實際引數,例如List這里的String可以看成是實際引數,泛型也是是編譯時的一種型別,此型別僅僅在編譯階段有效,運行時無效.例如List在運行時String會被擦除,最終系統會認為都是Object型別,
說說泛型應用在什么場景呢?
泛型是實作通用編程的一種手段,通常應用在類,介面,方法的定義上,例如:
1.泛型類: class 類名<泛型,…>{}
2.泛型介面: interface 介面名<泛型,…>{}
3.泛型方法: 訪問修飾符 <泛型> 方法回傳值型別 方法名(形參){}
代碼演示:
泛型介面的定義,例如:
interface Container<T>{//泛型介面
void add(T t);
T get(int i);
int size();
}
interface Task<Param,Result>{//思考map中的泛型Map<K,V>
/**
* 此方法用于執行任務
* @param arg 其型別由泛型引數Param決定
* @return 其型別由泛型引數result決定
*/
Result execute(Param arg1);
}
泛型類的定義,例如:
interface Result<T>{//泛型類
T data;
}
泛型方法定義,例如:
class ObjectFactory{
//泛型方法
public <T>T newInstance(Class<T> cls)
throws Exception{
return cls.newInstance();
}
}
class ContainerUtils{
//泛型方法
//1)靜態方法假如有泛型肯定是泛型方法
//2)泛型類和泛型介面不作用于靜態方法
//3)泛型方法一定是靜態方法嗎?不是
public static <T>void sort(List<T> list) {}
}
總結:
- 泛型類和泛型介面用于約束類或介面中實體方法引數型別,回傳值型別,
- 泛型類或泛型介面中實際泛型型別可以在定義子類或構建其物件時傳入,
- 泛型方法用于約束本方法(實體方法或靜態方法)的引數型別或回傳值型別,
- 泛型類上的泛型不能約束類中靜態方法的泛型型別,
如何理解Java中的泛型通配符?
Java中的泛型通配符一般可以理解為一種通用的型別,也可認為不確定性型別,從應用上,它可分為三種型別:
1)無屆通配符:<?>
2)上屆通配符:<? extends 型別>
3)下屆通配符:<型別 extends ?>
代碼演示:
//無屆通配符
Class<?> c2=Class.forName("java.lang.Object");
//上界通配符
static void doPrint(List<? extends CharSequence> list){
System.out.println(list);
}
//下界通配符
static void doPrint(Set<? super Integer> set){//下屆
System.out.println(list);
}
說說什么是泛型型別擦除?
泛型是編譯時的一種型別,在運行時無效,運行時候都會變成Object型別,
例如基于反射向List list=new ArrayList() 集合中添加整數,關鍵代碼如下:
List<String> list=new ArrayList<>();
list.add("A");
list.add("B");
//list.add(100);
//在運行時將100寫入到list集合
//1.獲取list物件的位元組碼物件
Class<?> cls=list.getClass();
//2.獲取list位元組碼物件中的add方法物件
Method method=
//cls.getDeclaredMethod("add",Object.class);
cls.getDeclaredMethod("add",int.class,Object.class);
//3.通過反射執行方法物件將100寫入集合,
//執行list物件的method方法
//method.invoke(list, 100);
method.invoke(list, 0,100);
System.out.println(list);
Java 虛擬機分析
你是如何理解JVM的?
JVM(Java Virtual Machine)是JAVA平臺的一部分,是一種能夠運行Java bytecode的虛擬機,如圖所示:

JVM是硬體計算機的抽象(虛構)實作,可以解釋執行JAVA位元組碼,也是實作JAVA跨平臺運行的基石,如圖所示:

我們為什么要學習JVM?
深入理解JVM可以幫助我們從平臺角度提高解決問題的能力,例如:
- 有效防止記憶體泄漏(Memory leak),
- 優化執行緒鎖的使用 (Thread Lock),
- 科學進行垃圾回收 (Garbage collection),
- 提高系統吞吐量 (throughput),
- 降低延遲(Delay),提高其性能(performance),
市場上有哪些主流的JVM呢?
JVM是一種規范基于這種規范,不同公司就對此規范做了具體實作,例如市場上的一些主流JVM如下:
- JRockit VM (BEA公司研發,后在2008年由Oracle公司收購),
- HotSpot VM (Sun公司研發,后在2010年由Oracle公司收購),
- J9 VM (IBM 內部使用),
說明:HotSpot目前是甲骨文公司最主要的一款JVM虛擬機,也是我們現在最常用的一種,
JVM的體系結構是怎樣的?
JVM (Java Hotspot Architecture:主要分為三大部分,如圖-6所示:
- 類加載系統 (ClassLoader System) :負責加載類到記憶體,
- 運行時資料區 (Runtime Data Area):負責存盤資料資訊,
- 執行引擎 (Execution Engine):負責呼叫物件執行業務,

其中:
- ClassLoader作用是什么?(負責將類從磁盤或網路加載記憶體)
- ClassLoader 可以自己定義嗎?(可以,參考Tomcat,MyBatis,Spring等,他們都有自定義類加載器)
- JVM 中的方法區(Method Area) 如何理解?(邏輯上的一種定義,不同JVM有不同實作,比方說有JVM中稱元資料區,有的稱持久代)
- HotSpot JDK8虛擬機在創建物件時,所有的物件都會分配在堆中嗎?(不一定,小物件未逃逸,可以直接分配在堆疊上)
- 如何知道類的加載順序?(可通過配置JVM 引數-XX:+TraceClassLoading 檢查類的加載程序)
JDK8中的Hotspot簡易記憶體體系結構如下:

你知道JVM有哪些運行模式嗎?
JVM有兩種運行模式Server與Client,兩種模式的區別在于,Client模式啟動速度較快,Server模式啟動較慢;但是啟動進入穩定期之后Server模式的程式運行速度比Client要快很多,這是因為Server模式啟動的JVM采用的是重量級的虛擬機,對程式采用了更多的優化;而Client模式啟動的JVM采用的是輕量級的虛擬機,所以Server啟動慢,但穩定后速度比Client遠遠要快,
現在64位的jdk中默認都是server模式(可通過 java -version進行查看),當虛擬機運行在-client模式的時候,使用的是一個代號為C1的輕量級編譯器, 而server模式啟動的虛擬機采用相對重量級,代號為C2的編譯器.c1、c2都是JIT編譯器, C2比C1編譯器編譯的相對徹底,服務起來之后,性能更高,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/385474.html
標籤:其他
