關(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)成員無需再在前面寫上他們所屬的類名。

//例如:

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)造方法是無意義的。父類中用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è)直接的父類,因此無法用繼承關(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)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚_t_閱讀 31,764評(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閱讀 785評(píng)論 0 50
  • 文章大綱:1.為什么static會(huì)有這樣的效果?2.static的使用3.static誤區(qū)4.static面試題 ...
    檸檬烏冬面閱讀 5,888評(píng)論 3 43
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,908評(píng)論 18 139
  • 我們經(jīng)常碰到一些情況: 搬家換城市等,或以前固定的理發(fā)師搬走等,需要更換理發(fā)師。然而,每次換理發(fā)師就像買彩票一樣,...
    寶貝安心睡閱讀 732評(píng)論 0 0