static,可以修飾屬性、方法、代碼塊。
每個(gè)對(duì)象稱為類的實(shí)例,對(duì)象之間的存儲(chǔ)區(qū)互不干涉。
static int data;是類變量(共享),為類開辟一個(gè)空間。共享存儲(chǔ)區(qū)域。
訪問類變量,通過類名訪問。一個(gè)對(duì)象引用也可以使用靜態(tài)成員,與它的編譯時(shí)類型的類訪問,一致。
MyClass m = new MyClass();
m.data 《= 》MyClass.data;
靜態(tài)方法-〉沒有當(dāng)前對(duì)象概念-〉也就不允許訪問的類中的非靜態(tài)成員(實(shí)例變量)
主方法之所以是靜態(tài)的,它是程序入口,JVM最初沒有對(duì)象,必須通過使用類名調(diào)用方法,主方法必須為靜態(tài)的。
靜態(tài)方法不能被覆蓋。
靜態(tài)代碼塊只執(zhí)行一次。
static 用于單例模式Singleton模式















final 修飾 類、屬性、方法
修飾類,無子類,保證用戶使用的一致性。典型范例String類。
修飾屬性或者變量一旦賦值,不得更改。
對(duì)于對(duì)象變量來說,是不能再指向其他對(duì)象,而現(xiàn)有的對(duì)象內(nèi)部屬性可以改變。
會(huì)配合static一起使用,只分配一個(gè)存儲(chǔ)空間,只需要維護(hù)一個(gè)空間。
public static final,是一個(gè)常量。大寫。
class SuperClass{
final int AGE;
public SuperClass(){
AGE=10;
}
}
初始值0不算,需要顯示賦一次值。
初始設(shè)定在兩個(gè)地方,1定義時(shí)直接賦值,2構(gòu)造器
靜態(tài)常量也在兩個(gè)地方設(shè)定,1初始設(shè)定,2靜態(tài)代碼塊
final方法不能覆蓋,由于多態(tài),一個(gè)編譯時(shí)類型對(duì)應(yīng)多個(gè)運(yùn)行時(shí)類型,final保證某方法的穩(wěn)定性。
private
左邊的修飾符有其中一個(gè),系統(tǒng)都默認(rèn)添加了final修飾符。
static
所以之前的靜態(tài)方法不能覆蓋。
=====================
方法繼承是決定于在子類中是否可見。能見到就是繼承。
final不決定繼承。
實(shí)際上如果實(shí)例化一個(gè)子類對(duì)象,它的父類對(duì)象的所有屬性(包括private成員都創(chuàng)建了,就是訪問不了,所以不能成為繼承的一部分,也就是不能繼承咯)
=====================
abstract 修飾 類 方法
修飾類 -> 這個(gè)類必須被繼承使用->不能生成對(duì)象
用處,把子類最大的共性提取出來放入其中,面向?qū)ο笠话阍瓌t。
雖然不能生成對(duì)象(不能作為運(yùn)行時(shí)類型),但可以聲明為類型(可作為編譯時(shí)類型)。
抽象方法,沒有實(shí)現(xiàn),留給子類覆蓋。
final永遠(yuǎn)不可能和abstract在一起,那么private和static也不能和abstract聯(lián)合修飾。
final表示必須不能被繼承,不能覆蓋;abstract表示必須繼承,方法沒有實(shí)現(xiàn),必須覆蓋使用。所以矛盾。
abstract class SuperClass{
abstract void print(); //print(){},這是空實(shí)現(xiàn),也是實(shí)現(xiàn),所以不能帶大括號(hào)。
}
如果類中有抽象方法的話,那么類只能是抽象類。(一個(gè)半成品)
如果子類沒有實(shí)現(xiàn)父類的抽象方法,就會(huì)編譯出錯(cuò),因?yàn)樽宇惱^承了抽象方法,需要聲明為抽象類。
SuperClass sc = new SubClass();
sc.print();動(dòng)態(tài)類型判定,運(yùn)行時(shí)類型不會(huì)改變,肯定是一個(gè)實(shí)現(xiàn)抽象方法的類對(duì)象。
接口:是同類,同一個(gè)層次的數(shù)據(jù)結(jié)構(gòu)。
interface IA{
void print();
int A = 1;
}
修飾符省略
一個(gè)Java文件,只能定義一個(gè)公開接口
一個(gè)接口等同于一個(gè)抽象類
一個(gè)特殊的抽象類:
所有方法都是公開抽象的:public abstract
所有屬性都是公開靜態(tài)常量:public static final
interface IA{
void print();
int A = 1;
}
等價(jià)于
abstract class IA{
public static final int A=1;
public abstract void print();
}
這時(shí)可要注意,類實(shí)現(xiàn)接口時(shí),覆蓋方法的訪問控制符一定要寫上public,接口是省略為public,類不寫可是default,根據(jù)Overriding規(guī)則,覆蓋方法的訪問控制等于或者大于父類方法的訪問控制。
class IAImpl extends java.util.ArrayList implements IA{}
1一個(gè)類除了繼承類,還可以實(shí)現(xiàn)接口(多個(gè))。
2盡管一個(gè)類只能繼承一個(gè)類,一個(gè)類可以實(shí)現(xiàn)多個(gè)接口
3接口與接口之間可以繼承并可以多繼承,實(shí)現(xiàn)多重繼承,但復(fù)雜度不增加。
interface IC extends IA,IB{}
IC有著IA,IB所有方法的定義
IA,IB可以作為編譯時(shí)類型。
========================
接口,被用來定義可以***的東西。
存儲(chǔ)設(shè)備 輸入設(shè)備
----|----------------|----- ----------|-----------
硬盤 U盤 鼠標(biāo)
----|----
移動(dòng)硬盤
使用接口來剝離出一部分抽象。
移動(dòng)硬盤、U盤、鼠標(biāo)除了間接父類是統(tǒng)一的設(shè)備父類外。
他們都是USB設(shè)備,這部分抽象就需要用接口定義。
那么機(jī)器上的連接器是一個(gè)方法,connect(USB接口),不管你什么具體設(shè)備,你都必須實(shí)現(xiàn)USB規(guī)范,才能往上插。
那么用接口來定義一個(gè)規(guī)范。
例子2,JDBC,使用Java來訪問數(shù)據(jù)庫。
首先,如果由Sun公司自己提供各種數(shù)據(jù)庫的驅(qū)動(dòng),那么各個(gè)DB廠商需要把數(shù)據(jù)庫核心代碼提供給Sun,這是不可能的,核心商業(yè)機(jī)密。
而由各個(gè)DB廠商自己寫的話,會(huì)出現(xiàn)方法名的不同,導(dǎo)致如果數(shù)據(jù)庫遷移,代碼需要改動(dòng)。(例如Oracle提供的方法為ConnectOracle()而ms提供的方法為ConnectSQL)。那么無法真正實(shí)現(xiàn)Write Once,Run Anywhere,Sun不同意。
怎么辦?使用接口。
由Sun和DB聯(lián)合制定一些一系列接口。
interface Driver()
{
void connect();
...
}
OracleDriver implements Driver
SQLDriver implements Driver
實(shí)現(xiàn)不同的connect()邏輯。
用戶Driver d = getDriver();
d.connect();
接口是實(shí)現(xiàn)Java一次編譯,到處運(yùn)行的重要技術(shù)。
保證了Sun制定規(guī)范,數(shù)據(jù)庫廠商實(shí)現(xiàn),用戶使用。保證架構(gòu)穩(wěn)定性(將三方分開)
對(duì)于用戶來說,接口最大化屏蔽差異。
1.實(shí)現(xiàn)不同層次,不同體系的對(duì)象的抽象。
2.保證架構(gòu)穩(wěn)定性。對(duì)用戶透明。
==============================
Object 類,所有類的父類(直接,間接父類)
finalize(),當(dāng)一個(gè)對(duì)象被垃圾回收的時(shí)候,會(huì)調(diào)用一下。不適合放入釋放資源的方法。
toString(),對(duì)象的字符串表現(xiàn)形式。
System.out.println(obj);->obj.toString()
自定義類,覆蓋該方法,返回一些有意義的信息。
== 判斷字面值是否相等,
String a = new String("hello");
String b = new String("hello");
b==a false
String final類,并且它的值也是immutable的。
String a = "A"
a = a + "B"
這兩步操作一共產(chǎn)生了3個(gè)對(duì)象。
JVM內(nèi)部有一個(gè)字符串池,一個(gè)獨(dú)立存儲(chǔ)區(qū)域,保存已創(chuàng)建的字符串,如果再有相同的,會(huì)將引用指向字符串池中的已有對(duì)象,不再創(chuàng)建新的,如果沒有再創(chuàng)建。
String a = "abc";
String b = "abc";
所以上面的例子是采用new String("abc")方式創(chuàng)建String對(duì)象,不會(huì)再去池中找,直接在堆中創(chuàng)建新對(duì)象。
String a = new String("hello");
String b = "hello";
a為堆地址,b為串池地址,a==b,false。
這種方式,是一種用時(shí)間換空間的做法,比如如果程序中有100個(gè)"hello",難道程序要去維護(hù)100個(gè)對(duì)象嘛。
Object.equals 判斷對(duì)象值是否相等。



















































自定義類如果要進(jìn)行對(duì)象值的比較,覆蓋Object的equals方法,自行判斷,如果不覆蓋,直接調(diào)用Object.equals是判斷地址。
equals方法覆蓋標(biāo)準(zhǔn)流程:





















