關(guān)鍵字

Advanced Language Features

知識(shí)點(diǎn):一. static修飾符

static修飾符可以用來修飾類的成員變量鬼譬、成員方法和代碼塊诀蓉。

. 用static修飾的成員變量表示靜態(tài)變量什湘,可以直接通過類名來訪問骑祟;

. 用static修飾的成員方法表示靜態(tài)方法,可以直接通過類名來訪問态贤;

. 用static修飾的程序代碼表示靜態(tài)代碼塊舱呻,當(dāng)Java虛似機(jī)加載類時(shí),就會(huì)執(zhí)行該代碼塊抵卫;

被static所修飾的成員變量和成員方法表明歸某個(gè)類所有狮荔,它不依賴于類的特定實(shí)例胎撇,被類的所有實(shí)例共享介粘。

1. static 變量

成員變量:定義在類里面殖氏、方法外面的變量, 分兩種:

a. 實(shí)例變量;

b. 靜態(tài)變量;形式和實(shí)例變量類似姻采,在實(shí)例變量前面加static關(guān)鍵字雅采;

static變量和實(shí)例變量的區(qū)別:

. static變量對(duì)于每個(gè)類而言在內(nèi)存中只有一個(gè),能被類的所有實(shí)例所共享慨亲;實(shí)例變量對(duì)于每個(gè)類的每個(gè)實(shí)例都有一份婚瓜,它們之間互不影響;

. Java虛擬機(jī)在加載類的過程中為static變量分配內(nèi)存刑棵,實(shí)例變量在加載完類后創(chuàng)建對(duì)象時(shí)分配內(nèi)存巴刻;

. static變量可以直接通過類名訪問,實(shí)例變量通過引用類型變量訪問蛉签;

舉例: public class Counter {

public int count1 = 0;

public static int count2 = 0;

public static void main(String[] args) {

Counter counterA = new Counter();

Counter counterB = new Counter();

counterA.count1++;

counterA.count2++;

counterB.count1++;

counterB.count2++;

}

}

練習(xí):統(tǒng)計(jì)一個(gè)類創(chuàng)建實(shí)例的個(gè)數(shù)胡陪;

2. static 方法

成員方法分為靜態(tài)方法和實(shí)例方法。用static修飾的方法叫靜態(tài)方法碍舍,或類方法柠座。靜態(tài)方法也和靜態(tài)變量一樣,不需要?jiǎng)?chuàng)建類的實(shí)例片橡,可以直接通過類名來訪問妈经。

public class Sample1 {

public static int add(int x, int y) {

return x+y;

}

}

public class Sample2 {

public void method() {

int result = Sample1.add(1,2);

System.out.println("result= " + result);

}

}

a. static方法可以直接訪問所屬類的實(shí)例變量和實(shí)例方法,直接訪問所屬類的靜態(tài)變量和靜態(tài)方法捧书;

注:1) 不能使用this關(guān)鍵字吹泡;

2) 不能使用super關(guān)鍵字,super關(guān)鍵字用來訪問當(dāng)前實(shí)例從父類中繼承的方法和屬性。super關(guān)鍵字與類的特定實(shí)例相關(guān)经瓷;

3) 靜態(tài)方法必須被實(shí)現(xiàn)爆哑。靜態(tài)方法用來表示某個(gè)類所特有的功能,這種功能的實(shí)現(xiàn)不依賴于類的具體實(shí)例了嚎,也不依賴于它的子類泪漂。既然如此,當(dāng)前類必須為靜態(tài)方法提供實(shí)現(xiàn)歪泳。

b. 父類的靜態(tài)方法不能被子類覆為非靜態(tài)方法萝勤。以下代碼編譯出錯(cuò)。

public class Base {

public static void method() {}

}

public class Sub extends Base {

public void method() {}//編譯出錯(cuò)

}

c. 父類的非靜態(tài)方法不能被子類覆蓋為靜態(tài)方法呐伞;

3. static 代碼塊

類中可以包含靜態(tài)代碼塊敌卓,它不存于任何方法中。在Java虛擬機(jī)中加載類時(shí)會(huì)執(zhí)行這些靜態(tài)代碼塊伶氢。如果類中包含多個(gè)靜態(tài)代碼塊趟径,那么Java虛擬機(jī)將按照它們?cè)陬愔谐霈F(xiàn)的順序依次執(zhí)行它們瘪吏,每個(gè)靜態(tài)代碼塊只會(huì)被執(zhí)行一次。(思考:什么時(shí)候JVM對(duì)一個(gè)類進(jìn)行類加載)

public class Sample {

static int i = 5;

static {//第一個(gè)靜態(tài)代碼塊

System.out.println("First Static code i="+i++);

}

static {//第二個(gè)靜態(tài)代碼塊

System.out.println("Second Static code i="+i++);

}

public static void main(String[] args) {

Sample s1 = new Sample();

Sample s2 = new Sample();

System.out.println("At last, i= "+i);

}

}

類的構(gòu)造方法用于初始化類的實(shí)例蜗巧,而類的靜態(tài)代碼塊則可用于初始化類掌眠,給類的靜態(tài)變量賦初始值。

靜態(tài)代碼塊與靜態(tài)方法一樣幕屹,也不能直接訪問類的實(shí)例變量和實(shí)例方法蓝丙,而必須通過實(shí)例的引用來訪問它們。

//Student s = new Student();

new一個(gè)對(duì)象的時(shí)候JVM都做了那些事情:

1.之前沒有進(jìn)行類加載

1.類加載,同時(shí)初始化類中靜態(tài)的屬性(賦默認(rèn)值)

2.執(zhí)行靜態(tài)代碼塊

3.分配內(nèi)存空間,同時(shí)初始化非靜態(tài)的屬性(賦默認(rèn)值)

4.調(diào)用父類構(gòu)造器

5.父類構(gòu)造器執(zhí)行完后,如果自己聲明屬性的同時(shí)有顯示的賦值,那么進(jìn)行顯示賦值把默認(rèn)值覆蓋

6.執(zhí)行匿名代碼塊

7.執(zhí)行構(gòu)造器

8.返回內(nèi)存地址

例子:

package com.briup.ch06;

public class Test {

public static void main(String[] args) {

A a = new B();

}

}

class A{

protected String name = "lisi";

public A() {

System.out.println("父類構(gòu)造器A");

System.out.println("父類構(gòu)造器A中調(diào)用test方法開始,由于子類重寫過test方法所以這里執(zhí)行子類的test方法");

test();

System.out.println("父類構(gòu)造器A中調(diào)用test方法結(jié)束");

}

public void test(){

}

}

class B extends A{

private String name = "tom";

{

System.out.println("子類匿名代碼塊中:"+name);

}

public B() {

System.out.println("子類構(gòu)造器B");

}

public void test(){

System.out.println("test方法中:this.name="+this.name);

System.out.println("test方法中:super.name="+super.name);

}

}

打印結(jié)果:

父類構(gòu)造器A? ? ? ? ? ? ? ? ? ? ? ? ? ? //子類構(gòu)造器調(diào)用父類構(gòu)造器

父類構(gòu)造器A中調(diào)用test方法開始,由于子類重寫過test方法所以這里執(zhí)行子類的test方法

test方法中:this.name=null? ? //這個(gè)時(shí)候父類構(gòu)造器還沒有執(zhí)行完 所以子類中的屬性不會(huì)顯示賦值 所以只有初始的默認(rèn)值null

test方法中:super.name=lisi? //這個(gè)時(shí)候父類構(gòu)造器開始調(diào)用 了 所以父類中的屬性已經(jīng)有了顯示賦的值了

父類構(gòu)造器A中調(diào)用test方法結(jié)束

子類匿名代碼塊中:tom? ? ? ? ? //這個(gè)時(shí)候父類構(gòu)造器已經(jīng)調(diào)用結(jié)束 所以子類中的屬性已經(jīng)有了顯示賦的值了

子類構(gòu)造器B

結(jié)論:? 子類中的屬性的顯示賦值的時(shí)機(jī) 是在 父類構(gòu)造器執(zhí)行完之后和子類的匿名代碼塊執(zhí)行之前的某個(gè)時(shí)候

2.之前已經(jīng)進(jìn)行了類加載

1.分配內(nèi)存空間,同時(shí)初始化非靜態(tài)的屬性(賦默認(rèn)值)

2.調(diào)用父類構(gòu)造器

3.父類構(gòu)造器執(zhí)行完后,如果自己聲明屬性的同時(shí)有顯示的賦值,那么進(jìn)行顯示賦值把默認(rèn)值覆蓋

4.執(zhí)行匿名代碼塊

5.執(zhí)行構(gòu)造器

6.返回內(nèi)存地址

練習(xí)例子:StaticTest.java? StaticTest2.java

4. 靜態(tài)導(dǎo)入

靜態(tài)導(dǎo)入也是JDK5.0引入的新特性望拖。

要使用靜態(tài)成員(方法和變量)我們必須給出提供這個(gè)靜態(tài)成員的類渺尘。使用靜態(tài)導(dǎo)入可以使被導(dǎo)入類的靜態(tài)變量和靜態(tài)方法在當(dāng)前類中可以直接使用,使用這些靜態(tài)成員無(wú)需再在前面寫上他們所屬的類名说敏。

//例如:

import static java.lang.Math.random;

import static java.lang.Math.PI;;

public class Test {

public static void main(String[] args) {

//之前是需要Math.random()調(diào)用的

System.out.println(random());

System.out.println(PI);

}

}

二. final修改符

final具有"不可改變的"含義鸥跟,它可以修飾非抽象類、非抽象成員方法和變量盔沫。

. 用final修飾的類不能被繼承医咨,沒有子類;

. 用final修飾的方法不能被子類的方法覆蓋迅诬;

. 用final修飾的變量表示常量腋逆,只能被賦一次值;

final不能用來修飾構(gòu)造方法侈贷,因?yàn)?方法覆蓋"這一概念僅適用于類的成員方法惩歉,而不適用于類的構(gòu)造方法,父類的構(gòu)造方法和子類的構(gòu)造方法之間不存在覆蓋關(guān)系. 因此用final修飾構(gòu)造方法是無(wú)意義的俏蛮。父類中用private修飾的方法不能被子類的方法覆蓋撑蚌,因此private類型的方法默認(rèn)是final類型的。

1. final類

繼承關(guān)系的弱點(diǎn)是打破封裝搏屑,子類能夠訪問父類的方法争涌,而且能以方法覆蓋的方式修改實(shí)現(xiàn)細(xì)節(jié)。在以下情況下,

可以考慮把類定義為final類型辣恋,使得這個(gè)類不能被繼承亮垫。

. 子類有可能會(huì)錯(cuò)誤地修改父類的實(shí)現(xiàn)細(xì)節(jié);

. 出于安全伟骨,類的實(shí)現(xiàn)細(xì)節(jié)不允許有任何改動(dòng)饮潦;

. 在創(chuàng)建對(duì)象模型時(shí),確信這個(gè)類不會(huì)再被擴(kuò)展携狭;

例如JDK中java.lang.String類被定義為final類型继蜡;

2. final方法;

某些情況下,出于安全原因稀并,父類不允許子類覆蓋某個(gè)方法仅颇, 此時(shí)可以把這個(gè)方法聲明為final類型。例如在

java.lang.Object類中碘举,getClass()方法為final類型忘瓦。

3. final變量:

final修飾的屬性(成員變量)賦值的位置:

非靜態(tài)的成員變量

1.聲明的同時(shí)

2.匿名代碼塊

3.構(gòu)造器(類中出現(xiàn)的所有構(gòu)造器)

靜態(tài)的成員變量

1.聲明的同時(shí)

2.static代碼塊

a. final可以修飾靜態(tài)變量、實(shí)例變量殴俱、局部變量政冻;

b. final變量都必須顯示初始化枚抵,否則會(huì)導(dǎo)致編譯錯(cuò)誤线欲;

1) 靜態(tài)變量,定義變量時(shí)進(jìn)行初始化或者static代碼塊中賦值汽摹;

2) 實(shí)例變量李丰,可以在定義變量時(shí),或者在構(gòu)造方法中進(jìn)行初始化逼泣;

c. final變量只能賦一次值趴泌。

public class Sample {

private final int var1 = 1;

public Sample() {

var1 = 2;? ? ? ? ? ? ? ? //編譯出錯(cuò),不允許改變var1實(shí)例變量的值拉庶;

}

public void method(final int param) {

final int var2 = 1;

var2++;? ? ? ? ? ? ? ? ? //編譯出錯(cuò)嗜憔,不允許改變var2局部常量的值

param++;? ? ? ? ? ? ? ? //編譯出錯(cuò),不允許改變final類型參數(shù)的值氏仗;

}

}

public class Sample {

final int var1;? ? ? ? ? ? ? //定義var1實(shí)例常量

final int var2 = 0;? ? ? ? ? //定義并初始化var2實(shí)例常量

Sample() {

var1 = 1;? ? ? ? ? ? ? //初始化var1實(shí)例常量

}

Sample(int x) {

var1 = x;? ? ? ? ? ? ? ? //初始化var1實(shí)例常量

}

}

練習(xí) FinalTest.java

三. abstract修飾符

可用來修飾類和成員方法吉捶。

. 用abstract修飾的類表示抽象類,抽象類不能實(shí)例化皆尔,即不允許創(chuàng)建抽象類本身的實(shí)例呐舔。沒有用abstract修飾的類稱為具體類,具體類可以被實(shí)例化慷蠕。

. 用abstract修飾的方法表示抽象方法珊拼,抽象方法沒有方法體。抽象方法用來描述系統(tǒng)具有什么功能流炕,但不提供具體的實(shí)現(xiàn)澎现。

沒有abstract修飾的方法稱為具體方法,具體方法具有方法體每辟。

語(yǔ)法規(guī)則剑辫;

1) 抽象類中可以沒有抽象方法,但包含了抽象方法的類必須被定義為抽象類影兽;

2) 沒有抽象構(gòu)造方法揭斧,也沒有抽象靜態(tài)方法;

3) 抽象類中可以有非抽象的構(gòu)造方法;

4) 抽象類及抽象方法不能被final修飾符修飾讹开。

抽象類不允許實(shí)例化:思考原因?

練習(xí) AbstractTest.java

四. 接口

接口使用的目的:解決多重繼承問題盅视;例如Fish類繼承Animal類,表明Fish是一種動(dòng)物旦万,但魚同樣也是一種食物闹击,如何表示這種關(guān)系呢? 由于Java語(yǔ)言不支持一個(gè)類有多個(gè)直接的父類成艘,因此無(wú)法用繼承關(guān)系來描述魚既是一種食物赏半,又是一種動(dòng)物,為了解決這一問題淆两,Java語(yǔ)言引入接口類型断箫,簡(jiǎn)稱接口。一個(gè)類只能有一個(gè)直接的父類秋冰,但是可以實(shí)現(xiàn)多個(gè)接口仲义。 采用這種方式,Java語(yǔ)言對(duì)多繼承提供了有力的支持剑勾。

1. 接口是抽象類的另外一種形式

抽象類抽象到極致就是接口埃撵,抽象類可存在有方法體的方法,接口中的方法全部為抽象方法虽另;

2. 接口中的所有方法均是抽象方法暂刘, 默認(rèn)都是public、abstract類型的捂刺;

public interface A {

void method1();? ? ? ? ? ? ? ? //合法谣拣,默認(rèn)為public、abstract類型

public abstract void method2();//合法叠萍,顯示聲明為public芝发、abstract類型

3. 接口中的成員變量默認(rèn)都是public, static, final類型,必須被顯式初始化苛谷;

public interface A {

int CONST = 1;? ? ? ? ? ? ? ? //合法辅鲸,CONST默認(rèn)為public, static, final類型

public static final int OPAQUE = 1;? //合法,顯示聲明為public static final 類型

}

4. 接口中只能包含public, static, final類型成員變量和public腹殿、abstract類型的成員方法独悴;

5. 接口中沒有構(gòu)造方法,不能被實(shí)例化锣尉。

6. 一個(gè)類只能繼承一個(gè)直接的父類刻炒,但能實(shí)現(xiàn)多個(gè)接口。

抽象類和接口比較:

1. 相同點(diǎn):

a. 都不能被實(shí)例化自沧;

b. 都能包含抽象方法坟奥;

2. 不同點(diǎn)树瞭;

a. 抽象類中可以為部分方法提供默認(rèn)的實(shí)現(xiàn),從而避免子類中重復(fù)實(shí)現(xiàn)它們爱谁,提高代碼的可重用性晒喷,而接口中只能包含抽象方法;

b. 一個(gè)類只能繼承一個(gè)直接的父類访敌,這個(gè)父類有可能是抽象類凉敲;但一個(gè)類可以實(shí)現(xiàn)多個(gè)接口,這是接口的優(yōu)勢(shì)所在寺旺。

練習(xí):InterfaceTest.java InterfaceTest2.java

五. 訪問控制

面向?qū)ο蟮幕舅枷胫皇欠庋b實(shí)現(xiàn)細(xì)節(jié)并且公開方法爷抓。Java語(yǔ)言采用訪問控制修飾符來控制類及類的方法和變量的訪問

權(quán)限,從而只向使用者暴露方法阻塑,但隱藏實(shí)現(xiàn)細(xì)節(jié)蓝撇。訪問控制分4種級(jí)別。

訪問級(jí)別? ? ? 訪問控制修飾符? ? ? ? 同類? ? ? 同包? ? ? 子類? ? ? 不同的包

公開級(jí)別:? ? ? public? ? ? ? ? ? ? ? y? ? ? ? y? ? ? ? ? y? ? ? ? ? y

受保護(hù)? ? ? ? ? protected? ? ? ? ? ? y? ? ? ? ? y? ? ? ? ? y

默認(rèn)? ? ? ? ? 沒有訪問控制符? ? ? ? ? y? ? ? ? ? y

私有? ? ? ? ? ? private? ? ? ? ? ? ? ? y

成員變量叮姑、成員方法和構(gòu)造方法可以處于4個(gè)訪問級(jí)別中的一個(gè)唉地;

頂層類只可以處于公開或默認(rèn)訪問級(jí)別;

注意:protected和default都有包訪問權(quán)限(同包下可以訪問)

六. 內(nèi)部類

在一個(gè)類的內(nèi)部定義的類稱為內(nèi)部類传透。

內(nèi)部類分為:

成員內(nèi)部類 靜態(tài)內(nèi)部類 局部?jī)?nèi)部類 匿名內(nèi)部類

頂層類(正常類)只能處于public和默認(rèn)訪問級(jí)別,而成員內(nèi)部類可以處于public, protected, private和默認(rèn)這4種訪問級(jí)別极颓;

1.? 靜態(tài)內(nèi)部類朱盐;

例子:StaticOutterClass.java

是成員內(nèi)部類的一種,用static修飾菠隆。靜態(tài)內(nèi)部類具有以下特點(diǎn):

1)? 靜態(tài)內(nèi)部類:(相對(duì)應(yīng)類中的一個(gè)靜態(tài)變量)

靜態(tài)內(nèi)部類中訪問不到外部類的非靜態(tài)屬性或者方法

靜態(tài)內(nèi)部類的對(duì)象不需要依賴于外部類的對(duì)象

內(nèi)部類 變量名字 = new 內(nèi)部類();

public class A {

public static class B{

private int v;

public void say(){

System.out.println("hello");

}

}

public static void main(String[] args){

B b = new B();

}

}

2) 靜態(tài)內(nèi)部類可以直接訪問外部類的靜態(tài)成員兵琳,如果訪問外部類的實(shí)例成員,就必須通過外部類的實(shí)例去訪問骇径。

class A {

private int a1;? ? ? ? ? ? ? //實(shí)例變量a1

private static int a2;? ? ? //靜態(tài)變量a2

public static class B {

int b1 = a1;? ? ? ? ? //編譯錯(cuò)誤躯肌,不能直接訪問外部類A的實(shí)例變量a1

int b2 = a2;? ? ? ? ? //合法,可以直接訪問外部類A的靜態(tài)變量a2

int b3 = A.this.a1;? //不合法 靜態(tài)內(nèi)部類中不能訪問外部對(duì)象的this

}

}

3) 在靜態(tài)內(nèi)部類中可以定義靜態(tài)成員和實(shí)例成員破衔。

class A {

public static class B {

int v1;? ? ? ? ? ? ? ? ? ? ? //實(shí)例變量

static int v2;? ? ? ? ? ? ? ? //靜態(tài)變量

public static class C {

static int v3;? ? ? ? //靜態(tài)內(nèi)部類

}

}

}

4) 可以通過完整的類名直接訪問靜態(tài)內(nèi)部類的靜態(tài)成員清女。

class A {

public static class B {

int v1;? ? ? ? ? ? ? ? ? ? ? //實(shí)例變量

static int v2;? ? ? ? ? ? ? ? //靜態(tài)變量

public static class C {

static int v3;? ? ? ? //靜態(tài)內(nèi)部類

int v4;

}

}

}

public class Tester {

public void test() {

A.B b = new A.B();

A.B.C c = new A.B.C();

b.v1 = 1;

v.v2 = 1;

A.B.v1 = 1;? ? ? ? ? ? //編譯錯(cuò)誤

A.B.v2 = 1;? ? ? ? ? ? //合法

A.B.C.v3 = 1;? ? ? ? ? //合法

}

}

2.? 成員內(nèi)部類:(相當(dāng)于類中的一個(gè)成員變量)

成員內(nèi)部類中不能有static的聲明屬性或者方法

成員內(nèi)部類可以由public protected default private修飾

成員內(nèi)部類是依賴于外部類的對(duì)象而存在的

外部類.內(nèi)部類 var = new 外部類().內(nèi)部類();

例子:InstanceOutterClass.java

1) 在創(chuàng)建實(shí)例內(nèi)部類的實(shí)例時(shí),外部類的實(shí)例必須已經(jīng)存在晰筛。

Outer.InnerTool tool = new Outer().new InnerTool();

等價(jià)于:

Outer outer = new Outer();

Outer.InnerTool tool = outer.new InnerTool();

以下代碼會(huì)導(dǎo)致編譯錯(cuò)誤:

Outer.InnerTool tool = new Outer.InnerTool();

2) 實(shí)例內(nèi)部類的實(shí)例自動(dòng)持有外部類的實(shí)例的引用嫡丙。在內(nèi)部類中, 可以直接訪問外部類的所有成員读第,包括

成員變量和成員方法曙博。

public class A {

private int a1;

public int a1;

static int a1;

public A(int a1, int a2) {

this.a1 = a1;

this.a2 = a2;

}

protected int methodA() {

return a1*a2;

}

class B {

int b1 = a1;? ? ? ? ? ? ? //直接訪問private的a1

int b2 = a2;? ? ? ? ? ? ? //直接訪問public的a2

int b3 = a3;? ? ? ? ? ? ? //直接訪問static的a3

int b4 = A.this.a1;? ? //訪問類A的當(dāng)前實(shí)例中的a1

int b5 = methodA();? ? ? ? //訪問methodA()方法

}

public static void main(String args[]) {

A.B b = new A(1,2).new B();

System.out.println("b.b1="+b.b1);? ? //打印b.b1=1;

System.out.println("b.b2="+b.b2);? ? //打印b.b2=2;

System.out.println("b.b3="+b.b3);? ? //打印b.b3=0;

System.out.println("b.b4="+b.b4);? ? //打印b.b4=3;

System.out.println("b.b5="+b.b5);? ? //打印b.b5=2;

}

}

3) 外部類實(shí)例與內(nèi)部類實(shí)例之間是一對(duì)多的關(guān)系,一個(gè)內(nèi)部類實(shí)例只會(huì)引用一個(gè)外部類實(shí)例怜瞒,而一個(gè)外部類實(shí)例對(duì)應(yīng)零個(gè)或多個(gè)內(nèi)部類實(shí)例父泳。在外部類中不能直接訪問內(nèi)部類的成員,必須通過內(nèi)部類的實(shí)例去訪問。

class A {

class B {

private int b1 = 1;

public int b2 = 2;

class C{}

}

public void test() {

int v1 = b1;? ? ? ? ? ? ? ? ? ? ? ? ? //invalid

int v2 = b2;? ? ? ? ? ? ? ? ? ? ? ? ? //invalid

B.C c1 = new C();? ? ? ? ? ? ? ? ? ? //invalid

B b = new B(); //valid

int v3 = b.b1;? ? ? ? ? ? ? ? ? ? ? ? ? //valid

int v4 = b.b2;? ? ? ? ? ? ? ? ? ? ? ? ? //valid

B.C c2 = b.new C();? ? ? ? ? ? ? ? ? ? //valid

B.C c3 = new B().new C();? ? ? ? ? ? ? //valid

}

}

4) 實(shí)例內(nèi)部類中不能定義靜態(tài)成員惠窄,而只能定義實(shí)例成員逝她。

5) 如果實(shí)例內(nèi)部類B與外部類A包含同名的成員,那么在類B中睬捶, this.v表示類B的成員黔宛, A.this.v表示類A的成員。

3.? 局部?jī)?nèi)部類:(相當(dāng)于一個(gè)方法中的局部變量)

局部?jī)?nèi)部類不能用public private等修飾符修飾

寫在方法當(dāng)中,而且只能在方法當(dāng)中使用

可以訪問外層類的普通成員變量和靜態(tài)成員變量以及普通方法和靜態(tài)方法,也可以訪問該內(nèi)部類所在方法當(dāng)中的局部變量,但是這個(gè)局部變量必須是final修飾擒贸;

例子:LocalOutterClass.java

1) 局部?jī)?nèi)部類只能在當(dāng)前方法中使用臀晃。

class A {

B b = new B();? ? ? ? ? ? ? ? //編譯錯(cuò)誤;

public void method() {

class B{

int v1;

int v2;

class C {

int v3;

}

}

B b = new B();? ? ? ? ? ? ? ? //合法

B.C c = b.new C();? ? ? ? ? ? //合法

}

}

2) 局部?jī)?nèi)部類和實(shí)例內(nèi)部類一樣介劫,不能包含靜態(tài)成員徽惋。

class A {

public void method() {

class B{

static int v1;? ? ? ? ? //編譯錯(cuò)誤

int v2;? ? ? ? ? ? ? ? ? //合法

static class C {? ? ? ? //編譯錯(cuò)誤

int v3;

}

}

}

}

3) 在局部?jī)?nèi)部類中定義的內(nèi)部類也不能被public、protected和private這些訪問控制修飾符修飾座韵;

4) 局部?jī)?nèi)部類和實(shí)例內(nèi)部類一樣险绘,可以訪問外部類的所有成員,此外誉碴,局部?jī)?nèi)部類還可以訪問所在方法中的final類型

的參數(shù)和變量宦棺。

4.匿名內(nèi)部類:(和局部?jī)?nèi)部類很相似)

匿名內(nèi)部類也是用的最多的內(nèi)部類

可以寫成成員變量的形式,也可以寫在方法當(dāng)中,一般寫在方法當(dāng)中較多

匿名內(nèi)部類里可以訪問外部類的普通屬性和方法,已經(jīng)靜態(tài)屬性和方法,如果要訪問這個(gè)內(nèi)部類所在方法中的局部變量,那么要求這個(gè)局部變量必須是final修飾的

匿名內(nèi)部類里面沒有構(gòu)造函數(shù),因?yàn)檫@個(gè)類沒有名字,所以在其他地方不能用

例子:AnonymousOutterClass.java

public class Hello{

public void test(){

//假如A是同包下的一個(gè)接口,有一個(gè)抽象方法go

A a = new A(){

public void go(){

System.out.println("gogogo");

}

};

}

}

幾種內(nèi)部類的區(qū)別:

1. 創(chuàng)建

a. 聲明的位置:

靜態(tài)內(nèi)部類:類的內(nèi)部黔帕,方法的外部代咸,用static關(guān)鍵字修飾;

實(shí)例內(nèi)部類:類的內(nèi)部成黄,方法的外部呐芥,不用static關(guān)鍵字修飾;

局部?jī)?nèi)部類:方法的內(nèi)部奋岁;

匿名內(nèi)部類:既可以在類的內(nèi)部思瘟,方法的外部,也可以在方法的內(nèi)部闻伶;

b. 實(shí)例化方式:

靜態(tài)內(nèi)部類:new Outer.Inner();? ? ? ? ? //在外部類外創(chuàng)建滨攻;

new Inner();? ? ? ? ? ? ? ? //在外部類內(nèi)內(nèi)部類外創(chuàng)建

實(shí)例內(nèi)部類:new Outer().new Inner();? ? ? //在外部類外創(chuàng)建;

this.new Inner();? ? ? ? ? ? //在外部類內(nèi)內(nèi)部類外創(chuàng)建

局部?jī)?nèi)部類:new Inner();? ? ? ? ? ? ? ? ? //只能在方法內(nèi)部創(chuàng)建虾攻;

匿名內(nèi)部類:new 類名() {};

2. 訪問

a. 外部類訪問內(nèi)部類:

靜態(tài)內(nèi)部類:通過完整的類名直接訪問靜態(tài)內(nèi)部類的靜態(tài)成員;

實(shí)例內(nèi)部類:通過內(nèi)部類的實(shí)例去訪問內(nèi)部類的成員;

局部?jī)?nèi)部類:不能訪問铡买;

匿名內(nèi)部類:不能訪問;

b. 內(nèi)部類訪問外部類:

靜態(tài)內(nèi)部類:直接訪問外部類的靜態(tài)成員霎箍;

實(shí)例內(nèi)部類:可以直接訪問外部類的所有成員;

如果實(shí)例內(nèi)部類B與外部類A包含同名的成員奇钞,那么在類B中, this.v表示類B的成員漂坏,

A.this.v表示類A的成員景埃。

局部?jī)?nèi)部類:可以直接訪問外部類的所有成員, 訪問所在方法中的final類型的參數(shù)和變量媒至;

匿名內(nèi)部類:可以直接訪問外部類的所有成員, 訪問所在方法中的final類型的參數(shù)和變量;

七. ==? 和 equals() 的區(qū)別

== :比較的是,值是不是相等

基本數(shù)據(jù)類型比較的是值,引用類型比較的是地址值

equals(Object o): Object類中的方法,所以,在每一個(gè)java類中,都會(huì)有這個(gè)方法,因?yàn)槊恳粋€(gè)java類都是直接或者間接的Object類的子類,會(huì)繼承到這個(gè)方法

如果自己所寫的類中已經(jīng)重寫了equals方法,那么就安裝用戶自定義的方式來比較倆個(gè)對(duì)象是否相等,如果沒有重寫過equal方法,那么會(huì)調(diào)用父類(Object)中的equals方法進(jìn)行比較,也就是比較地址值

注意:equals(Object o)方法只能是一個(gè)對(duì)象來調(diào)用,然后參數(shù)也是要傳一個(gè)對(duì)象的

所以下面是錯(cuò)誤的寫法:

int a = 1;

a.equals(1);

因?yàn)榛緮?shù)據(jù)類型不是算是對(duì)象,不能調(diào)用方法

如果是基本數(shù)據(jù)類型那么就用==比較

如果是引用類型的話,想按照自己的方式去比較,就要重寫這個(gè)類中的equals方法, 如果沒有重寫,那么equals和==比較的效果是一樣的,都是比較引用的地址值

如果是比較字符串,那么直接用equals就可以了,因?yàn)镾tring類里面已經(jīng)重寫了equals方法,比較的時(shí)候字符串的內(nèi)容,而不是引用的地址值了

toString(): Object類中的方法,所以,在每一個(gè)java類中,都會(huì)有這個(gè)方法,因?yàn)槊恳粋€(gè)java類都是直接或者間接的Object類的子類,會(huì)繼承到這個(gè)方法

當(dāng)前用一個(gè)引用指向一個(gè)對(duì)象的時(shí)候,比如:Student s = new Student(),然后如果直接打印這個(gè)引用s,其實(shí)是調(diào)用了s.toString()方法,然后就會(huì)把這個(gè)引用里面的存放的堆區(qū)對(duì)象的地址值顯示出來

所以我們會(huì)常常在類中重寫這個(gè)toString()方法,然后讓這個(gè)類的引用按照我們要求來返回內(nèi)容谷徙。

getClass():Object類中的方法,所以,在每一個(gè)java類中拒啰,都會(huì)有這個(gè)方法,并且這個(gè)方式final修飾的,不能被子類重寫,這個(gè)方法可以返回某一個(gè)引用在運(yùn)行的時(shí)候指向?qū)ο蟮念愋?/p>

例如:Person p = new Student()

//會(huì)輸出:class com.briup.chap06.Student

//說明這個(gè)引用p在運(yùn)行時(shí)指向的是Student這個(gè)類的對(duì)象

//注意這個(gè)引用p的類型是Person的(多態(tài))

System.out.println(p.getClass());

八. 基本數(shù)據(jù)類型對(duì)應(yīng)的包裝類型

boolean Boolean

byte Byte

short Short

char Character

int Integer

long Long

float Float

double Double

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市完慧,隨后出現(xiàn)的幾起案子谋旦,更是在濱河造成了極大的恐慌,老刑警劉巖屈尼,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件册着,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡脾歧,警方通過查閱死者的電腦和手機(jī)甲捏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鞭执,“玉大人司顿,你說我怎么就攤上這事⌒址模” “怎么了大溜?”我有些...
    開封第一講書人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)囤热。 經(jīng)常有香客問我猎提,道長(zhǎng),這世上最難降的妖魔是什么旁蔼? 我笑而不...
    開封第一講書人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮疙教,結(jié)果婚禮上棺聊,老公的妹妹穿的比我還像新娘。我一直安慰自己贞谓,他們只是感情好限佩,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著裸弦,像睡著了一般祟同。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上理疙,一...
    開封第一講書人閱讀 52,246評(píng)論 1 308
  • 那天晕城,我揣著相機(jī)與錄音,去河邊找鬼窖贤。 笑死砖顷,一個(gè)胖子當(dāng)著我的面吹牛贰锁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播滤蝠,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼豌熄,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了物咳?” 一聲冷哼從身側(cè)響起锣险,我...
    開封第一講書人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎览闰,沒想到半個(gè)月后芯肤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡焕济,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年纷妆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晴弃。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡掩幢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出上鞠,到底是詐尸還是另有隱情际邻,我是刑警寧澤,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布芍阎,位于F島的核電站世曾,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏谴咸。R本人自食惡果不足惜轮听,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望岭佳。 院中可真熱鬧血巍,春花似錦、人聲如沸珊随。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)叶洞。三九已至鲫凶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間衩辟,已是汗流浹背螟炫。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留惭婿,地道東北人不恭。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓叶雹,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親换吧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子折晦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法沾瓦,內(nèi)部類的語(yǔ)法满着,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法贯莺,線程的語(yǔ)...
    子非魚_t_閱讀 31,662評(píng)論 18 399
  • C++關(guān)鍵字的思考 本章內(nèi)容:1 關(guān)鍵字的相關(guān)理解1.1 const關(guān)鍵字1.2 static關(guān)鍵字1.3 非局部...
    Haley_2013閱讀 778評(píng)論 0 50
  • 文章大綱:1.為什么static會(huì)有這樣的效果风喇?2.static的使用3.static誤區(qū)4.static面試題 ...
    檸檬烏冬面閱讀 5,869評(píng)論 3 43
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)缕探,斷路器魂莫,智...
    卡卡羅2017閱讀 134,696評(píng)論 18 139
  • 我們經(jīng)常碰到一些情況: 搬家換城市等,或以前固定的理發(fā)師搬走等爹耗,需要更換理發(fā)師耙考。然而,每次換理發(fā)師就像買彩票一樣潭兽,...
    寶貝安心睡閱讀 726評(píng)論 0 0