天天看點

Java基礎中的基礎

基礎中的基礎

jdk 是 java development kit 縮寫,它是功能齊全的 java sdk。它擁有 jre 所擁有的一切,還有編譯器(javac)和工具(如 javadoc 和 jdb)。它能夠建立和編譯程式。

jre是java運作時環境,它是運作已編譯 java 程式所需的所有内容的集合,包括 java 虛拟機(jvm),java 類庫,java 指令和其他的一些基礎構件。但是,它不能用于建立新程式。

sdk是software development kit 一般指軟體開發包,可以包括函數庫、編譯程式等。

openjdk與oraclejdk的差別是,openjdk是開源的,但是他是不穩定的,釋出頻率相對比較高,oraclejdk可以了解為定制版的openjdk,更加穩定,但是不是完全免費的,因為其中加入了商業的部分。在響應性和 jvm 性能方面,oracle jdk 提供了更好的性能;

這裡就用java的好處來介紹了

java簡單易學,java沒有提供指針操作記憶體,進而保證了記憶體的安全;

兩者都支援封裝、繼承、多态;

java有自己的垃圾回收機制,程式員不需要自己通過程式設計進行記憶體回收;

java隻支援單繼承(接口支援多實作),c++支援多繼承;

java和javax都隻是一個名字,沒有差別,都是javaapi的組成部分,隻是先來後到的關系;

== 比較的是基本類型的時候,會比較其值,如果比較的是引用類型的時候會比較其位址值(對于java中隻有值傳遞這個說法來看,== 比較的都是值,隻是說引用變量的值為位址值);

equals( )方法的情況就是比較複雜的了。

類沒有覆寫 equals()方法 :通過equals()比較該類的兩個對象時,等價于通過“==”比較這兩個對象,使用的預設是 object類equals()方法。

類覆寫了 equals()方法 :一般我們都覆寫 equals()方法來比較兩個對象中的屬性是否相等;若它們的屬性相等,則傳回 true(即,認為這兩個對象相等)。

<code>hashcode( )</code>的作用是擷取哈希碼,也稱為散列碼;它實際上是傳回一個 int 整數。這個哈希碼的作用是确定該對象在哈希表中的索引位置。<code>hashcode()</code>定義在 jdk 的 <code>object</code> 類中,這就意味着 java 中的任何類都包含有 <code>hashcode( )</code> 函數。另外需要注意的是:<code>object</code> 的 <code>hashcode</code>方法是本地方法,也就是用 c 語言或 c++ 實作的,該方法通常用來将對象的 記憶體位址 轉換為整數之後傳回。(散清單存儲的是鍵值對(key-value),它的特點是:能根據“鍵”快速的檢索出對應的“值”。這其中就利用到了散列碼!

equals( )就是另一個方法了,我在上邊也詳細的描述了equals( )的用法及其作用,這裡不作贅述;

當我們向hashset中存放一個值得時候,他就會首先會計算一下他的哈希值,進而确定它将被存到的位置。如果這個哈希值對應的位置上是有對象存在的,那麼<code>equals( )</code>就會被調用出來比較兩個對象的位址值,如果<code>equals( )</code>傳回的值為<code>false</code>,則成功讓其加入<code>hashset</code>; 如果equals( )傳回為<code>true</code>,那麼就不允許加入<code>hashset</code>(hashset不允許存放重複的對象);

包裝類的自動封裝、拆箱;

裝箱:将基本類型轉換為包裝類

拆箱:将包裝類轉換為基本類型

包裝類中,大部分都實作了常量池技術,byte、short、integer、long等四種包裝類,都有預設數值對象存在于常量池中【-128127】;character則是存在有【0127】範圍内的緩存資料。在這種常量池存在的背景下,我們隻要是直接指派的,那麼就會首先去常量池檢視有沒有,如果沒有才會建立對象,如果有的話就會直接取出來指派。如果是通過new出來的包裝類型,那麼就不會從常量池檢視,而是直接建立對象。

靜态方法、靜态變量會在類加載的時候就進行配置設定記憶體,随着類的加載而加載;而普通方法會在建立對象的時候才進行初始化,是以這就是為什麼靜态方法不能夠調用非靜态變量以及非靜态方法的原因。

有繼承關系的加載順序

首先會加載父類的靜态字段或者靜态代碼塊

子類的靜态字段或者靜态代碼塊

父類的普通變量、普通代碼塊

父類的構造方法

子類的普通變量、普通代碼塊

子類的構造方法

沒有繼承關系的類加載順序

加載類的靜态變量、靜态代碼塊

類的構造器

string是一個非常常見且特殊的類。string是一個資料類型,代表字元串;其底層是通過 final修飾的字元數組來儲存字元串的,是以string是不可變的,指派被改變時,隻會建立一個新的引用!

在java9之後,string、stringbuilder、stringbuffer等的底層實作都是位元組數組byte[] value;

直接通過字面量指派;這種方式是java中唯一一個不需要new就産生的對象,在java中他被叫做直接量;

通過new建立對象的方式;

兩個方法創造的對象,終将指向常量池中的同一個方法區裡的常量池中的資料的位址;形式指派産生的直接量在建立的時候,會在常量池中先檢視是否存在内容相同的字元串,有的話會直接将他指向常量池存在的已有的相同字元串,如果常量池沒有的話,就會建立一個字元串放入常量池;

intern():在調用”ab”.intern()方法的時候會傳回”ab”,但是這個方法會首先檢查字元串池中是否有”ab”這個字元串,如果存在則傳回這個字元串的引用,否則就将這個字元串添加到字元串池中,然會傳回這個字元串的引用。

string:底層final的,不可變的字元序列

stringbuffer:底層非final的,可變的字元序列,線程安全,但是效率偏低

stringbuilder:底層非final的,可變的字元序列,效率高,但是線程不安全

上述三者的共同點是:java8之前包括8,他們的底層實作都是的字元數組 <code>char [ ]</code>,在java9以及之後的版本中改為了 位元組數組;

stringbuilder 與 stringbuffer 都繼承自 abstractstringbuilder 類

三者的效率:stringbuilder &gt; stringbuilder &gt; string

操作少量的資料: 适用 string

單線程操作字元串緩沖區下操作大量資料: 适用 stringbuilder

多線程操作字元串緩沖區下操作大量資料: 适用 stringbuffer

object是祖宗類!

當object沒有實作cloneable接口時,沒有實作clone( )方法并且進行調用的時候,就會抛出異常clonenotsupportexception;

對于任何對象的表達式<code>a.clone( ) != a</code>為true,且<code>a.clone().getclass() == a.getclass()</code>為ture

注意:sleep方法沒有釋放鎖,而wait方法釋放了鎖 ,timeout是等待時間。

通過反射可以獲得、調用一個類的所有屬性和方法;他可以幫助我們獲得在運作時分析類、執行類中方法的能力;

優缺點:

優點:寫代碼時更加靈活,為各種架構提供了開箱即用的便捷;

缺點:具有安全問題,比如可以無視泛型的安全檢查,其次反射也會影響性能,但是在架構中是可以忽略不計的;

其中動态代理就用到了反射原理!(待梳理動态代理)

spring中的bean的注解注冊,也是得益于反射原理!

Java基礎中的基礎

異常的祖宗類是<code>java,lang</code>包下的<code>throwable</code>類。theowable類有兩個重要的子類,我們從圖中就可以得知是error和exception,他們又各自擁有很多子類;error是虛拟機無法處理的(隻能盡量避免),而exception可以認為的處理或者交給虛拟機進行處理。

其中有編譯檢查異常和編譯不檢查異常(運作時異常)

按照流向可以分為輸入流和輸出流;按照操作單元來分的話,可以分為位元組流和字元流;按照流的角色來劃分的話,可以劃分為節點流和處理流;

inputstream(輸入)/reader(讀入): 所有的輸入流的基類,前者是位元組輸入流,後者是字元輸入流。

outputstream(輸出)/writer(寫出): 所有輸出流的基類,前者是位元組輸出流,後者是字元輸出流。

節點流:直接從資料源或者目的地讀寫資料;

Java基礎中的基礎

處理流:不能直接連接配接到資料源或目的地,而是“連接配接”在已存在的流(節點流或處理流)之上,通過對資料的處理為程式提供更為強大的讀寫功能;

Java基礎中的基礎

inputstream 和reader 是所有輸入流的基類。

inputstream的經典實作是fileinputstream,存在的方法有 int read( )、等