——》個人平時筆記,看到的同學歡迎指正錯誤,文中多處摘錄于各大博主精華、書籍
解釋型語言:雖然Java代碼是要先編譯再運行的,但是Java代碼編譯之后生成的并不是計算機可識別的二進制文件,而是一種特殊的class文件,這種class文件只有Java虛擬機(Android中叫ART,一種移動優(yōu)化版的虛擬機)才能識別,而這個Java虛擬機擔當?shù)钠鋵嵕褪墙忉屍鞯慕巧?,它會在程序運行時將編譯后的class文件解釋成計算機可識別的二進制數(shù)據(jù)后再執(zhí)行,因此,準確來講,Java屬于解釋型語言而非編譯型語言。
1、android:exported屬性:主要作用是:是否支持其它應用調(diào)用當前組件。默認值:如果包含有intent-filter 默認值為true; 沒有intent-filter則默認值為false。雖然說加了這個屬性,可以使該組件不被其他的程序調(diào)用。但是,需要注意的是,如果兩個程序的userid是一樣的話,exported=”false”會失效。
2、 java反射:JAVA反射機制是在運行狀態(tài)中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調(diào)用它的任意一個方法和屬性;這種動態(tài)獲取的信息以及動態(tài)調(diào)用對象的方法的功能稱為java語言的反射機制。即:java在運行狀態(tài)中反射知道一個類里面的所有方法和屬性;通過反射獲得對象后,能夠調(diào)用對象的任意屬性和方法。
java內(nèi)?。簝?nèi)省基于反射實現(xiàn),主要用于操作JavaBean,通過內(nèi)省 可以獲取bean的getter/setter,只要看到有g(shù)etter或者setter就認為這個類有那么一個字段,比如看到getName() 內(nèi)省就會認為這個類中有name字段,但事實上并不一定會有name。

3、泛型,即“參數(shù)化類型”。一提到參數(shù),最熟悉的就是定義方法時有形參,然后調(diào)用此方法時傳遞實參。參數(shù)化類型就是將類型由原來的具體的類型參數(shù)化,類似于方法中的變量參數(shù),此時類型也定義成參數(shù)形式(可以稱之為類型形參),然后在使用/調(diào)用時傳入具體的類型(類型實參),由傳入的實參類型決定的參數(shù)類型。在方法中使用通配符“?”作為形參,實則它的使用是一種類型實參,此時“?”可以理解為說有類型實例的父類,就是一種真實的類型。
java 泛型詳解-絕對是對泛型方法講解最詳細的,沒有之一
public void showKeyValue1(Generic<?> obj){
Log.d("泛型測試","key value is " + obj.getKey());
}

4、 泛型通配符“?”(泛型詳解):
“ ? ”是通配符,泛指所有類型:一般用于定義一個引用變量,這么做的好處是,如下所示,定義一個sup的引用變量,就可以指向多個對象。
SuperClass<?> sup = new SuperClass<String>("lisi");
sup = new SuperClass<People>(new People());
sup = new SuperClass<Animal>(new Animal());
若不用?,用固定的類型的話,則:
>
> SuperClass<String> sup1 = new SuperClass<String>("lisi");
>
> SuperClass<People> sup2 = new SuperClass<People>("lisi");
>
> SuperClass<Animal> sup3 = new SuperClass<Animal>("lisi");
這就是?通配符的好處。
? extends T, ?是指T類型或T的子類型
? super T ,?是指T類型或T的父類型
這個兩個一般也是和?一樣用在定義引用變量中,但是傳值范圍不一樣
T和?運用的地方有點不同,?是定義在引用變量上,T是類上或方法上;如果有泛型方法和非泛型方法,都滿足條件,會執(zhí)行非泛型方法。
帶不同泛型的ArrayList在編譯后生成的Class是相同的!也就是說,泛型在編譯生成字節(jié)碼文件時會被”擦除”;不管ArrayList<E>帶什么泛型,在編譯后都是ArrayList所對應的字節(jié)碼文件。
eg:

強引用:直接的對象引用,實例化對象。在內(nèi)存不足的情況下,JVM寧愿拋出OutOfMemory錯誤也不會回收這種對象。中斷強引用和某個對象之間的關(guān)聯(lián),可以顯示地將引用賦值為null,這樣一來的話,JVM在合適的時間就會回收該對象。在方法內(nèi)部有一個強引用,這個引用保存在 java棧 中,而真正的引用內(nèi)容 (Object)保存在 java 堆中。當這個方法運行完成后,就會退出方法棧,則引用對象的引用數(shù)為 0 ,這個對象會被回收。
軟引用:有用但并不是必需的對象,在Java中用java.lang.ref.SoftReference類來表示。當一個對象只有軟引用存在時,系統(tǒng)內(nèi)存不足時此對象會被JVM回收。一般用于服務端。
弱引用:弱引用也是用來描述非必需對象的,當JVM進行垃圾回收時,無論內(nèi)存是否充足,都會回收被弱引用關(guān)聯(lián)的對象。在java中,用java.lang.ref.WeakReference類來表示。只要JVM進行垃圾回收,被弱引用關(guān)聯(lián)的對象必定會被回收掉。移動端內(nèi)存緊缺推薦使用弱引用。
虛引用:虛引用和前面的軟引用、弱引用不同,它并不影響對象的生命周期。在java中用java.lang.ref.PhantomReference類表示。如果一個對象與虛引用關(guān)聯(lián),則跟沒有引用與之關(guān)聯(lián)一樣,在任何時候都可能被垃圾回收器回收。
在使用軟引用和弱引用的時候,我們可以顯示地通過System.gc()來通知JVM進行垃圾回收,但是要注意的是,雖然發(fā)出了通知,JVM不一定會立刻執(zhí)行,也就是說這句是無法確保此時JVM一定會進行垃圾回收的。
6、try catch是直接處理,處理完成之后程序繼續(xù)往下執(zhí)行;throw則是將異常拋給它的上一級處理(是明確的一定會拋出異常),程序便不往下執(zhí)行了。
throws并不是拋出一個實際的Exception而是一個異常聲明,它聲明這個方法可能會拋出一個異常,注意是可能,所以在沒有異常的情況下也是可以用throws的,而throws本身的作用也是用來提高程序的健壯性,反過來,如果這個方法的的確確的有一個異常,那么編譯器會強制讓你加上throws這個異常聲明。
try這個程序塊名字很易懂,就是嘗試,嘗試能不能正常的走完整個作用域,所以我們在try塊里經(jīng)常放上可能會拋出異常的程序段。而catch恰好就是處理try里拋出來的異常,其中catch的參數(shù)列表接收的是一個異常的引用,是throw拋出來的異常的引用,這樣我們就可以得到這個異常的對象,倒不如說我們是得到了這個異常對象的引用,因為在java里,通常我們也只能通過引用來操縱對象。
7、一個類只能初始化一次,卻可以多次實例化。(java虛擬機類加載機制)
類的初始化的執(zhí)行順序
》沒有父類的情況:
類的靜態(tài)屬性
類的靜態(tài)代碼塊
類的非靜態(tài)屬性
類的非靜態(tài)代碼塊
構(gòu)造方法
》有父類的情況:
父類的靜態(tài)屬性
父類的靜態(tài)代碼塊
子類的靜態(tài)屬性
子類的靜態(tài)代碼塊
父類的非靜態(tài)屬性
父類的非靜態(tài)代碼塊
父類構(gòu)造方法
子類非靜態(tài)屬性
子類非靜態(tài)代碼塊
子類構(gòu)造方法
部分特殊不引起類初始化,先記錄下吧。
通過子類引用父類的靜態(tài)字段,不會導致子類初始化,對于靜態(tài)字段,只有直接定義這個字段的類才會被初始化
通過數(shù)組定義來引用類,不會觸發(fā)此類的初始化
常量在編譯階段會存入調(diào)用類的常量池中,本質(zhì)上并沒有直接引用到定義常量的類,因此不會觸發(fā)定義常量的類初始化
public static final int x =6/3; 能夠在編譯時期確定的,叫做編譯常量,不會引起類的初始化!!!
public static final int x =new Random().nextInt(100); 運行時才能確定下來的,叫做運行時常量,運行時常量會引起類的初始化!!!,類的初始化只會有一次
在虛擬機規(guī)范中使用了一個很強烈的限定語:“有且僅有”,這5種場景中的行為稱為對類進行主動引用。除此之外,所有引用類的方式都不會觸發(fā)初始化,稱為被動引用。
類變量(靜態(tài)變量)與成員變量的區(qū)別
靜態(tài)static修飾的成員,不僅可以被對象所使用,還能被類直接使用;類其實也是對象,JVM啟動時就會加載類路徑目錄下的類,當內(nèi)存中加載的類太多太多,JVM的GC會根據(jù)某種算法對加載的某些類進行清理,釋放空間。當JVM關(guān)閉時,類消失,靜態(tài)變量屬性也煙消云散。
靜態(tài)的優(yōu)點:
實現(xiàn)共享數(shù)據(jù)在內(nèi)存中的唯一存儲,節(jié)約了內(nèi)存空間;
每個對象都不用在堆內(nèi)存中為其單獨開辟空間保存,直接使用共享的數(shù)據(jù)即可。靜態(tài)的缺點:
常駐內(nèi)存,內(nèi)存釋放周期長,只隨著類的消失而消失。
類什么時候消失?類變量不是類的成員變量
存儲位置不一樣
成員變量,在堆內(nèi)存中,每個對象都有自己的一份不同的成員變量存儲區(qū);隨著對象的創(chuàng)建而存在,隨著對象的回收而釋放
靜態(tài)變量,在方法區(qū)中,只有唯一的一份,是類變量,每個對象都共享使用這個變量;隨著類的加載而存在,隨著類的消失而釋放生命周期不一樣
成員變量,隨著對象的創(chuàng)建而存在,隨著對象的回收而釋放
靜態(tài)變量,隨著類的加載而存在,隨著類的消失而釋放調(diào)用方式不同
成員變量,只能由對象調(diào)用
靜態(tài)變量,一般直接使用類名進行調(diào)用
成員變量,實例變量,對象的特有屬性
靜態(tài)變量,類變量,該類中的對象都具有相同的一個屬性
8、字符串在Java生產(chǎn)開發(fā)中的使用頻率是非常高的,字符串對于我們而言非常關(guān)鍵。在C中是沒有String類型的,那么C語言要想實現(xiàn)字符串就必須使用char數(shù)組,通過一個個的字符來組拼成字符串。而在Java中String源碼分析可知,String也是char數(shù)組拼接而成的。字符串一定會被保存到常量池中,且Java虛擬機如果發(fā)現(xiàn)常量池中已經(jīng)存在需要創(chuàng)建的字符串中,它就不會重復創(chuàng)建,而是指向那個字符串即可,(深入Java源碼剖析之字符串常量)這就類似于如下操作。
Student aa=new Student(123,"小花");//保存在堆內(nèi)存中,而非常量池
Student bb=aa;
Student cc=aa;
9、Java中的 數(shù)據(jù)類型分兩種:基本數(shù)據(jù)類型和引用數(shù)據(jù)類型
基本數(shù)據(jù)類型:Java中的簡單類型(基本數(shù)據(jù)類型)從概念上分為四種:實數(shù)、整數(shù)、字符、布爾值。八種基本數(shù)據(jù)類型如下:
實數(shù):double、float
整數(shù):byte、short、int、long
字符:char
布爾值:boolean
復雜類型(引用數(shù)據(jù)類型):String、類對象、數(shù)組。
引用數(shù)據(jù)類型和基本數(shù)據(jù)類型的內(nèi)存模型本質(zhì)上是不一樣的。
基本數(shù)據(jù)類型的存儲原理是這樣的:所有的基本數(shù)據(jù)類型不存在“引用”的概念,基本數(shù)據(jù)類型都是直接存儲在棧內(nèi)存中的,??臻g里存儲的地址就是數(shù)據(jù)本身的值。而Java語言里面只有這八種基本數(shù)據(jù)類型是這種存儲模型;
而其他的只要是繼承于Object類的引用數(shù)據(jù)類型,都是按照Java里面存儲對象的內(nèi)存模型來進行數(shù)據(jù)存儲的。引用數(shù)據(jù)類型使用Java內(nèi)存堆和內(nèi)存棧來進行這種類型的數(shù)據(jù)存儲;堆內(nèi)存存儲值,棧中存儲對象在堆內(nèi)存的首地址(引用地址),而這個棧引用就叫引用變量。
簡單地講,基本數(shù)據(jù)類型是存儲在有序的棧內(nèi)存中的,而引用數(shù)據(jù)類型本身的值存儲在堆內(nèi)存中的。
基本數(shù)據(jù)類型由于長度固定,且需要空間比較少,所以直接存儲在棧中;而對象比較大,所以棧中只存儲一個4btye大小的引用地址,堆內(nèi)存中存值。
10、java中聲明了一個變量,便會給這個變量分配內(nèi)存空間,且被聲明的變量會對應有一個內(nèi)存地址生成。在類型轉(zhuǎn)換中,低比特數(shù)(bit)的數(shù)據(jù)類型向高比特數(shù)的類型轉(zhuǎn)換可以自動轉(zhuǎn)換,高比特數(shù)的數(shù)據(jù)類型向低比特數(shù)的類型轉(zhuǎn)換就需要使用強制類型轉(zhuǎn)換了。
比特數(shù)由低到高 byte->short->char->int->long->float->double
1.bit就是位,也叫比特位, 也是b ,是計算機表示數(shù)據(jù)最小的單位
2.byte就是字節(jié),也是B
3.1byte=8bit
4.1byte就是1B
5.一個字符=2字節(jié)
6.1KB=1024B
7.轉(zhuǎn)換關(guān)系如下:
(1)1KB=1024B
(2) 1B= 8b
11、棧內(nèi)存、堆內(nèi)存、常量池區(qū)別:
Java內(nèi)存分配主要包括以下幾個區(qū)域:
- 寄存器:最快的存儲區(qū), 由編譯器根據(jù)需求進行分配,我們在程序中無法控制
- 棧:存放基本數(shù)據(jù)類型的數(shù)據(jù)和對象的引用(引用變量),但對象本身不存放在棧中,而是存放在堆中
- 堆:存放用new產(chǎn)生的數(shù)據(jù)或者說對象
- 靜態(tài)域:存放在對象中用static定義的靜態(tài)成員
- 常量池:存放常量。字符串常量(例如:String a="123")和final修飾的基本數(shù)據(jù)類型常量。
- 非RAM(隨機存取存儲器)存儲:硬盤等永久存儲空間
?由上圖可以看出,使用雙引號直接定義的String對象會指向常量池中的同一個對象,通過new產(chǎn)生一個字符串(假設為“china”)時,會先去常量池中查找是否已經(jīng)有了“china”對象,如果沒有則在常量池中創(chuàng)建一個此字符串對象,然后堆中再創(chuàng)建一個常量池中此”china”對象的拷貝對象。
----》好文參考推薦:Java內(nèi)存分配之堆、棧和常量池

12、靜態(tài)變量、靜態(tài)方法是不屬于某個實例對象,而是屬于類的,所以也稱為類變量,只要程序加載了類的字節(jié)碼,不用創(chuàng)建任何實例對象,靜態(tài)變量就會被分配空間,靜態(tài)變量就可以被使用了。總之,實例變量必須創(chuàng)建對象后才可以通過這個對象來使用,靜態(tài)變量則可以直接使用類名來引用。每個靜態(tài)變量內(nèi)存地址是唯一的,UserBean類中有一個name靜態(tài)變量,不管new UserBean()多少個實例,name變量所指向的內(nèi)存地址是唯一的(也就是說m1.name、m2.name和UserBean.name指向同一個變量),只要有一個地方對靜態(tài)變量做更改,所有使用引用的地方都會改變,eg:m1.name=“小紅”,則m2.name、UserBean.name都是改為了“小紅”。
靜態(tài)初始化器:靜態(tài)初始化器是類中由static修飾的一對“{ }”包裹的,不同于構(gòu)造方法,它并不是方法,因為它并沒有返回值和方法名。它是屬于類的,在初始化器加載類的時候初始化一次,其它時候不執(zhí)行不加載。多個靜態(tài)初始化器是按編碼秩序依次執(zhí)行。
注意:
靜態(tài)內(nèi)部類不會持有外部類的實例引用,因此不會導致外部類實例無法釋放,不會引起內(nèi)存泄露。
非靜態(tài)內(nèi)部類持有外部類實例的引用,如果非靜態(tài)內(nèi)部類實例的生命周期超出了外部類實例的生命周期,可能會導致內(nèi)存泄露。
是否可以從一個static方法內(nèi)部發(fā)出對非static方法的調(diào)用?
不可以。因為非static方法要與對象關(guān)聯(lián)在一起,必須創(chuàng)建一個對象后,才可以在該對象上進行方法的調(diào)用,而static方法調(diào)用時不需要創(chuàng)建對象,可以直接調(diào)用。也就是說,一個static方法被調(diào)用時,可能還沒有創(chuàng)建任何實例對象,所以,一個static方法內(nèi)部不可以發(fā)出對非static方法的調(diào)用。
13、Java中是值傳遞,而不是引用傳遞,不管是是基本數(shù)據(jù)類型還是引用數(shù)據(jù)類型都是值傳遞。
java參數(shù)傳遞(到底是值傳遞還是引用傳遞?)
java是值傳遞還是引用傳遞?
14、List 接口實現(xiàn)了 Collection 接口,它主要有兩個實現(xiàn)類:ArrayList 類和 LinkedList 類。
- LinkedList是鏈接列表實現(xiàn)的,同樣也是屬于線程不安全,每一個值都會有兩個引用,一個引用指向列表前一個值,另一個引用指向后一個值,所以它占用的內(nèi)存更多。但是它對數(shù)據(jù)的添加、插入、刪除是最快的。
- ArrayList底層是基于動態(tài)數(shù)組實現(xiàn)的,屬于線程不安全的,每一次值的增刪都要要移動數(shù)組重新排列和計算數(shù)組的容量,造成速度很慢,ArrayList 中不斷添加元素,其容量也自動增長。它的查找速度是最快的。
- Vector和ArrayList基本相似,利用數(shù)組及擴容實現(xiàn)List,但Vector是一種線程安全的List結(jié)構(gòu),它的讀寫效率不如ArrayList,其原因是在該實現(xiàn)類內(nèi)在方法上加上了同步關(guān)鍵字synchronized
- Stack繼承于Vector,基本特性與Vector一致,線程安全,但效率低,實際就是利用Vector抽象成棧,使之擁有后進先出的特性。
List:有序集合
Set:不重復集合,LinkedHashSet按照插入排序,SortedSet可排序,HashSet無序
Map:鍵值對集合
- List和Set是存儲單列數(shù)據(jù)的集合,Map是存儲鍵值對這樣的雙列數(shù)據(jù)的集合;
- List中存儲的數(shù)據(jù)是有順序的,并且值允許重復;Map中存儲的數(shù)據(jù)是無序的,它的鍵是不允許重復的,但是值是允許重復的;Set中存儲的數(shù)據(jù)是無順序的,并且不允許重復,但元素在集合中的位置是由元素的hashcode決定,即位置是固定的(Set集合是根據(jù)hashcode來進行數(shù)據(jù)存儲的,所以位置是固定的,但是這個位置不是用戶可以控制的,所以對于用戶來說set中的元素還是無序的)。
三大集合:List、Map、Set的區(qū)別與聯(lián)系
15、Map的幾種類型
- HashMap是基于哈希表實現(xiàn)的,是無序的。每一個元素是一個key-value對,其內(nèi)部通過單鏈表解決沖突問題,HasnMap內(nèi)部有自己的擴容機制,容量不足(超過了閥值)時,同樣會自動增長。HashMap是非線程安全的,只是用于單線程環(huán)境下,多線程環(huán)境下可以采用concurrent并發(fā)包下的ConcurrentHashMap。HashMap 實現(xiàn)了Serializable接口,因此它支持序列化,實現(xiàn)了Cloneable接口,能被克隆。HashMap中key和value都允許為null。key為null的鍵值對永遠都放在以table[0]為頭結(jié)點的鏈表中。
HashMap可以使用可變對象作為key,但是對象實體類需要重寫equals(Object obj)、hashCode()兩方法
- HashTable同HashMap一樣是基于哈希表實現(xiàn)的,是無序的。同樣每個元素也是一個key-value對,其內(nèi)部也是通過單鏈表解決沖突問題,容量不足(超過了閥值)時,同樣會自動增長。HashTable也是JDK1.0引入的類,但是是線程安全的,適合用于多線程環(huán)境中。HashTable同樣實現(xiàn)了Serializable接口,它支持序列化,實現(xiàn)了Cloneable接口,能被克隆。 HashTable繼承自Dictionary類,而HashMap繼承自AbstractMap類。但二者都實現(xiàn)了Map接口?,F(xiàn)在已經(jīng)過時了。
- LinkedHashMap是HashMap的子類,是有序的集合。LinkedHashMap可以認為是HashMap+LinkedList,即它既使用HashMap操作數(shù)據(jù)結(jié)構(gòu),又使用LinkedList維護插入元素的先后順序。LinkedHashMap雖然增加了時間和空間上的開銷,但是通過維護一個運行于所有條目的雙向鏈表,LinkedHashMap保證了元素迭代的順序。該迭代順序可以是插入順序或者是訪問順序,即插入的順序和取出的順序相同。
- TreeMap 是一個有序的key-value集合,它是通過紅黑樹實現(xiàn)的。默認是按key升值排序。
- TreeMap和LinkedHashMap是有序的,HashMap、ConcurrentHashMap、HashTable是無序的,且只有ConcurrentHashMap和HashTable是線程安全的。
HashTable和HashMap的區(qū)別詳解

16、String,StringBuffer與StringBuilder的區(qū)別
- String的值是不可變的,這就導致每次對String的操作都會生成新的String對象,這樣不僅效率低下,而且大量浪費有限的內(nèi)存空間。
- 和 String 類不同的是,StringBuffer 和 StringBuilder 類的對象能夠被多次的修改,并且不產(chǎn)生新的未使用對象。
- StringBuilder 類在 Java 5 中被提出,它和 StringBuffer 之間的最大不同在于 StringBuilder 的方法不是線程安全的(不能同步訪問),StringBuffer的append、insert等操作方法都是加synchronized鎖的。但是StringBuilder 相較于 StringBuffer 有速度優(yōu)勢。
17、Java中類、抽象類、接口:
- 類:在java中所有的類的都是直接或者間接的繼承Object這個類,也就是說所有的類都是Object的子類,而一般我們沒有特別extends繼承其他類,那我們創(chuàng)建的這個類的直接父類就是Object
- 抽象類:抽象類類似于一個給其他類的一個模板,抽象類里面定義多個抽象方法,用abstract聲明,供它的子類去實現(xiàn)這個方法(這里所謂實現(xiàn)就是指具體重寫),在子類方法里去實現(xiàn)想要的具體操作。抽象類只能被子類繼承去實現(xiàn)具體方法,而不能創(chuàng)建對象,即不能通過new來生成抽象類對象。子類繼承了抽象類就必須要實現(xiàn)它的所有抽象方法。
- 接口:接口可以說是特殊的抽象類,因為接口類里面只能只能含abstract聲明的抽象方法存在,一般abstract是默認存在不需要我們寫出來的。接口的屬性成員必須初始化。接口只能被子類implements實現(xiàn),而不能直接extends繼承,但是接口類A可以" A implements B , C "其中A、B、C都是接口,即接口具有多繼承性。
18、數(shù)據(jù)庫



