詳解Java中static關(guān)鍵字和內(nèi)部類(lèi)的使用
一. static 關(guān)鍵字
在Java中,被static修飾的成員,稱(chēng)之為靜態(tài)成員,也可以稱(chēng)為類(lèi)成員,其不屬于某個(gè)具體的對(duì)象,是所有對(duì)象所共享的。
1. static修飾成員變量
static修飾的成員變量,稱(chēng)為靜態(tài)成員變量
【靜態(tài)成員變量特性】:
- 不屬于某個(gè)具體的對(duì)象,是類(lèi)的屬性,所有對(duì)象共享的,不存儲(chǔ)在某個(gè)對(duì)象的空間中
- 既可以通過(guò)對(duì)象引用訪問(wèn)(不推薦使用),也可以通過(guò)類(lèi)名訪問(wèn),但一般更推薦使用類(lèi)名訪問(wèn)
- 類(lèi)變量存儲(chǔ)在方法區(qū)當(dāng)中
- 生命周期伴隨類(lèi)的一生(即:隨類(lèi)的加載而創(chuàng)建,隨類(lèi)的卸載而銷(xiāo)毀)
public class Student{ public String name; public String gender; public int age; public double score; public static String classRoom = "rj2104"; public Student(String name, String gender, int age, double score) { this.name = name; this.gender = gender; this.age = age; this.score = score; } // ... public static void main(String[] args) { // 靜態(tài)成員變量可以直接通過(guò)類(lèi)名訪問(wèn) System.out.println(Student.classRoom); Student s1 = new Student("Li leilei", "男", 18, 3.8); Student s2 = new Student("Han MeiMei", "女", 19, 4.0); Student s3 = new Student("Jim", "男", 18, 2.6); // 也可以通過(guò)對(duì)象訪問(wèn):但是classRoom是三個(gè)對(duì)象共享的 System.out.println(s1.classRoom); System.out.println(s2.classRoom); System.out.println(s3.classRoom); } }
2. static修飾成員方法
一般類(lèi)中的數(shù)據(jù)成員都設(shè)置為private,而成員方法設(shè)置為public,
Java中,被static修飾的成員方法稱(chēng)為靜態(tài)成員方法,是類(lèi)的方法,不是某個(gè)對(duì)象所特有的。
靜態(tài)成員一般是通過(guò)靜態(tài)方法來(lái)訪問(wèn)的。
public class Student2{ // ... private static String classRoom = "rj2104"; // ... public static String getClassRoom(){ return classRoom; } } class TestStudent { public static void main(String[] args) { System.out.println(Student2.getClassRoom()); } }
【靜態(tài)方法特性】:
- 不屬于某個(gè)具體的對(duì)象,是類(lèi)方法
- 可以通過(guò)對(duì)象調(diào)用,也可以通過(guò) 類(lèi)名.靜態(tài)方法名(…) 方式調(diào)用,更推薦使用后者
- 不能在靜態(tài)方法中訪問(wèn)任何非靜態(tài)成員變量和非靜態(tài)成員方法;因?yàn)榉庆o態(tài)方法中默認(rèn)有this參數(shù),但在靜態(tài)方法中調(diào)用時(shí)候無(wú)法傳遞this引用;除非在靜態(tài)方法中新new一個(gè)對(duì)象,再通過(guò)對(duì)象引用去訪問(wèn)此對(duì)象
- 靜態(tài)方法無(wú)法重寫(xiě),不能用來(lái)實(shí)現(xiàn)多態(tài)
3. static成員變量的初始化
靜態(tài)成員變量一般不會(huì)放在構(gòu)造方法中來(lái)初始化,構(gòu)造方法中初始化的是與對(duì)象相關(guān)的實(shí)例屬性
靜態(tài)成員變量的初始化分為兩種:就地初始化 和 靜態(tài)代碼塊初始化。
就地初始化:在定義時(shí)直接給出初始值
public class Student2{ // ... //就地初始化 private static String classRoom = "rj2104"; //... }
用靜態(tài)代碼塊完成初始化
public class Student2{ // ... private static String classRoom; //靜態(tài)代碼塊初始化 static { classRoom = "rj2104"; } // ... }
二. 內(nèi)部類(lèi)
在 Java 中,可以將一個(gè)類(lèi)定義在另一個(gè)類(lèi)或者一個(gè)方法的內(nèi)部, 前者稱(chēng)為內(nèi)部類(lèi),后者稱(chēng)為外部類(lèi)。內(nèi)部類(lèi)也是封裝的一種體現(xiàn)。
內(nèi)部類(lèi)和外部類(lèi)共用同一個(gè)java源文件,但是經(jīng)過(guò)編譯之后,內(nèi)部類(lèi)會(huì)形成單獨(dú)的字節(jié)碼文件, 一般形成的字節(jié)碼文件文件名為:外部類(lèi)名字$內(nèi)部類(lèi)名字.class
public class OutClass { class InnerClass{ } } // OutClass是外部類(lèi) // InnerClass是內(nèi)部類(lèi)
根據(jù)內(nèi)部類(lèi)定義的位置不同,一般可以分為以下幾種形式:
1.成員內(nèi)部類(lèi)(普通內(nèi)部類(lèi))
實(shí)例內(nèi)部類(lèi):未被static修飾的成員內(nèi)部類(lèi)
靜態(tài)內(nèi)部類(lèi):被static修飾的成員內(nèi)部類(lèi)
2.局部?jī)?nèi)部類(lèi)
3.匿名內(nèi)部類(lèi)
1. 實(shí)例內(nèi)部類(lèi)
即未被static修飾的成員內(nèi)部類(lèi)。
【注意事項(xiàng)】:
- 外部類(lèi)中的任何成員都可以在實(shí)例內(nèi)部類(lèi)方法中直接訪問(wèn)
- 實(shí)例內(nèi)部類(lèi)當(dāng)中不能有靜態(tài)的成員變量;非要定義,那么只能是被static final修飾的靜態(tài)常量,常量是在程序編譯的時(shí)候就確定的
- 實(shí)例內(nèi)部類(lèi)所處的位置與外部類(lèi)成員位置相同,因此也受public、private等訪問(wèn)限定符的約束
- 實(shí)例內(nèi)部類(lèi)對(duì)象必須在先有外部類(lèi)對(duì)象前提下才能創(chuàng)建
- 實(shí)例內(nèi)部類(lèi)的非靜態(tài)方法中默認(rèn)包含了一個(gè)指向外部類(lèi)對(duì)象的引用和一個(gè)指向自身實(shí)例內(nèi)部類(lèi)對(duì)象的引用
- 在實(shí)例內(nèi)部類(lèi)方法中訪問(wèn)同名的成員時(shí),優(yōu)先訪問(wèn)自己的,如果要訪問(wèn)外部類(lèi)同名的成員,必須:外部類(lèi)名稱(chēng).this.同名成員 來(lái)訪問(wèn)
- 外部類(lèi)中,不能直接訪問(wèn)實(shí)例內(nèi)部類(lèi)中的成員,如果要訪問(wèn)必須先要?jiǎng)?chuàng)建內(nèi)部類(lèi)的對(duì)象。
public class OutClass { private int a; static int b; int c; public void methodA() { a = 10; System.out.println(a); } public static void methodB() { System.out.println(b); } // 實(shí)例內(nèi)部類(lèi):未被static修飾 class InnerClass { int c; //實(shí)例內(nèi)部類(lèi)當(dāng)中 不能有靜態(tài)的成員變量. 非要定義,那么只能是被static final修飾的 public static final int d = 6; public void methodInner() { // 在實(shí)例內(nèi)部類(lèi)中可以直接訪問(wèn)外部類(lèi)中:任意訪問(wèn)限定符修飾的成員 a = 100; b = 200; methodA(); methodB(); System.out.println(d); // 如果外部類(lèi)和實(shí)例內(nèi)部類(lèi)中具有相同名稱(chēng)成員時(shí),優(yōu)先訪問(wèn)的是內(nèi)部類(lèi)自己的 c = 300; System.out.println(c); // 如果要訪問(wèn)外部類(lèi)同名成員時(shí)候,必須:外部類(lèi)名稱(chēng).this.同名成員名字 OutClass.this.c = 400; System.out.println(OutClass.this.c); } } public static void main(String[] args) { // 外部類(lèi):對(duì)象創(chuàng)建 以及 成員訪問(wèn) OutClass outClass = new OutClass(); System.out.println(outClass.a); System.out.println(outClass.b); System.out.println(outClass.c); outClass.methodA(); outClass.methodB(); System.out.println("=============實(shí)例內(nèi)部類(lèi)的訪問(wèn)============="); // 要訪問(wèn)實(shí)例內(nèi)部類(lèi)中成員,必須要?jiǎng)?chuàng)建實(shí)例內(nèi)部類(lèi)的對(duì)象 // 而普通內(nèi)部類(lèi)定義與外部類(lèi)成員定義位置相同,因此創(chuàng)建實(shí)例內(nèi)部類(lèi)對(duì)象時(shí)必須借助外部類(lèi) // 創(chuàng)建實(shí)例內(nèi)部類(lèi)對(duì)象 OutClass.InnerClass innerClass1 = new OutClass().new InnerClass(); innerClass1.methodInner(); // 上述語(yǔ)法比較怪異,也可以先將外部類(lèi)對(duì)象先創(chuàng)建出來(lái),然后再創(chuàng)建實(shí)例內(nèi)部類(lèi)對(duì)象 OutClass.InnerClass innerClass2 = outClass.new InnerClass(); innerClass2.methodInner(); } }
2. 靜態(tài)內(nèi)部類(lèi)
被static修飾的內(nèi)部成員類(lèi)稱(chēng)為靜態(tài)內(nèi)部類(lèi)。、
【注意事項(xiàng)】:
在靜態(tài)內(nèi)部類(lèi)中只能訪問(wèn)外部類(lèi)中的靜態(tài)成員,除非在內(nèi)部類(lèi)當(dāng)中new一個(gè)外部類(lèi)的對(duì)象,通過(guò)外部類(lèi)對(duì)象的引用去訪問(wèn)其中的非靜態(tài)成員。
創(chuàng)建靜態(tài)內(nèi)部類(lèi)對(duì)象時(shí),不需要先創(chuàng)建外部類(lèi)對(duì)象
public class OuterClass2 { public int data1 = 1; int data2 = 2; public static int data3 = 3; public void test() { System.out.println("out::test()"); } // 靜態(tài)內(nèi)部類(lèi):被static修飾的成員內(nèi)部類(lèi) static class InnerClass2 { public int data4 = 4; int data5 = 5; public static int data6 = 6; public void func() { System.out.println("out::func()"); //test(); // 編譯失敗,在靜態(tài)內(nèi)部類(lèi)中不能直接訪問(wèn)外部類(lèi)中的非靜態(tài)成員 //System.out.println(data1); //System.out.println(data2); //外部類(lèi)的非靜態(tài)成員,需要通過(guò)外部類(lèi)的對(duì)象的引用才能訪問(wèn)。 OuterClass2 outerClass = new OuterClass2(); System.out.println(outerClass.data1); System.out.println(outerClass.data2); outerClass.test(); // 在靜態(tài)內(nèi)部類(lèi)中只能訪問(wèn)外部類(lèi)的靜態(tài)成員 System.out.println(data3); System.out.println(data4); System.out.println(data5); System.out.println(data5); System.out.println(data6); } } public static void main(String[] args) { // 靜態(tài)內(nèi)部類(lèi)對(duì)象創(chuàng)建 和 成員訪問(wèn) OuterClass2.InnerClass2 innerClass2 = new OuterClass2.InnerClass2(); innerClass2.func(); } }
3. 局部?jī)?nèi)部類(lèi)
定義在外部類(lèi)的方法體或者{ }中,一般使用的非常少。
【注意事項(xiàng)】
局部?jī)?nèi)部類(lèi)只能在所定義的方法體內(nèi)部使用
不能被public、static等修飾符修飾
局部?jī)?nèi)部類(lèi)生成的字節(jié)碼文件稍有區(qū)別:外部類(lèi)名字$數(shù)字內(nèi)部類(lèi)名字.class
ppublic class OutClass { int a = 10; public void method(){ int b = 10; // 局部?jī)?nèi)部類(lèi):定義在方法體內(nèi)部 // 不能被public、static等訪問(wèn)限定符修飾 class InnerClass{ public void methodInnerClass(){ System.out.println(a); System.out.println(b); } } // 只能在該方法體內(nèi)部使用,其他位置都不能用 InnerClass innerClass = new InnerClass(); innerClass.methodInnerClass(); } public static void main(String[] args) { // OutClass.InnerClass innerClass = null; 編譯失敗 } }
4. 匿名內(nèi)部類(lèi)
匿名內(nèi)部類(lèi),就是沒(méi)有名字的一種嵌套類(lèi)
匿名內(nèi)部類(lèi)形成的字節(jié)碼文件文件名為:外部類(lèi)名字$數(shù)字.class
4.1 使用匿名內(nèi)部的好處與演示
在實(shí)際開(kāi)發(fā)中,我們會(huì)遇到下面的情況:
一個(gè)接口/類(lèi)的方法的某個(gè)執(zhí)行過(guò)程在程序中只會(huì)執(zhí)行一次,但為了使用它,我們需要?jiǎng)?chuàng)建它的實(shí)現(xiàn)類(lèi)/子類(lèi)去實(shí)現(xiàn)/重寫(xiě)方法。
代碼中為了這一次的使用去創(chuàng)建一個(gè)類(lèi),未免太過(guò)麻煩,此時(shí)就可以使用匿名內(nèi)部類(lèi)來(lái)解決這個(gè)問(wèn)題
首先來(lái)看我們正常的實(shí)現(xiàn)邏輯,假設(shè)有一個(gè)接口,接口當(dāng)中只有一個(gè)方法
public interface Interface { void show(); }
為了使用該接口的show方法,我們需要去創(chuàng)建一個(gè)實(shí)現(xiàn)類(lèi),重寫(xiě)show方法的具體實(shí)現(xiàn)
public class Test implements Interface{ @Override public void show() { System.out.println("只執(zhí)行一次show()"); } } public class Main { public static void main(String[] args) { Test test = new Test(); test.show(); } }
如果實(shí)現(xiàn)類(lèi)Test在程序中只使用一次,那么為了這一次的使用去創(chuàng)建一個(gè)類(lèi)太過(guò)繁瑣,這種情況下就可以用匿名內(nèi)部類(lèi)來(lái)實(shí)現(xiàn),無(wú)需創(chuàng)建新的類(lèi),減少代碼冗余,
看下面代碼:
class Main { public static void main(String[] args) { //寫(xiě)法一 Interface in = new Interface() { @Override public void show() { System.out.println("匿名內(nèi)部類(lèi)中重寫(xiě)show()"); } }; //調(diào)用接口方法 in.show(); //寫(xiě)法二 new Interface() { @Override public void show() { System.out.println("匿名內(nèi)部類(lèi)中重寫(xiě)show()"); } }.show();//調(diào)用接口方法 } }
4.2 匿名內(nèi)部類(lèi)的定義格式和使用
定義格式1:
接口名稱(chēng) 引用名 = new 接口名稱(chēng)() {
// 覆蓋重寫(xiě)所有抽象方法
};
引用名.方法調(diào)用
定義格式2:
new 接口名稱(chēng)() {
// 覆蓋重寫(xiě)所有抽象方法
}.方法調(diào)用;
對(duì)格式“new 接口名稱(chēng)() {…}”的理解:
new代表創(chuàng)建一個(gè)新的對(duì)象對(duì)象
接口名稱(chēng)就是匿名內(nèi)部類(lèi)需要實(shí)現(xiàn)哪個(gè)接口
{…}中是匿名內(nèi)部類(lèi)的內(nèi)容
【注意事項(xiàng)】:
- 匿名內(nèi)部類(lèi),在【創(chuàng)建對(duì)象】的時(shí)候,只能使用唯一 一次。
- 匿名對(duì)象,在【調(diào)用方法】的時(shí)候,只能調(diào)用唯一 一次。
- 匿名內(nèi)部類(lèi)是省略了【實(shí)現(xiàn)類(lèi)/子類(lèi)名稱(chēng)】,但是匿名對(duì)象是省略了【對(duì)象名稱(chēng)】
- 匿名內(nèi)部類(lèi)可以用在具體類(lèi)、抽象類(lèi)、接口上,且對(duì)方法個(gè)數(shù)沒(méi)有要求。
public class Class { public void show(String s){ System.out.println("Class::show()"); } } public abstract class AbstractClass { abstract void show(String s); } public interface Interface { void show(String s); } public class TestDome { public static void main(String[] args) { //重寫(xiě)普通類(lèi)的方法 new Class(){ @Override public void show(String s) { System.out.println(s); } }.show("普通類(lèi)"); //重寫(xiě)抽象類(lèi)的抽象方法 new AbstractClass(){ @Override void show(String s) { System.out.println(s); } }.show("抽象類(lèi)"); //實(shí)現(xiàn)接口的抽象方法 new Interface(){ @Override public void show(String s) { System.out.println(s); } }.show("接口"); } }
執(zhí)行結(jié)果:
以上就是詳解Java中static關(guān)鍵字和內(nèi)部類(lèi)的使用的詳細(xì)內(nèi)容,更多關(guān)于Java static關(guān)鍵字 內(nèi)部類(lèi)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java SelectableChannel的使實(shí)例用法講解
在本篇文章里小編給大家整理的是一篇關(guān)于java SelectableChannel的使實(shí)例用法講解內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。2021-03-03SpringCloud?openfeign聲明式服務(wù)調(diào)用實(shí)現(xiàn)方法介紹
在springcloud中,openfeign是取代了feign作為負(fù)載均衡組件的,feign最早是netflix提供的,他是一個(gè)輕量級(jí)的支持RESTful的http服務(wù)調(diào)用框架,內(nèi)置了ribbon,而ribbon可以提供負(fù)載均衡機(jī)制,因此feign可以作為一個(gè)負(fù)載均衡的遠(yuǎn)程服務(wù)調(diào)用框架使用2022-12-12SpringBoot使用Redis對(duì)用戶(hù)IP進(jìn)行接口限流的項(xiàng)目實(shí)踐
本文主要介紹了SpringBoot使用Redis對(duì)用戶(hù)IP進(jìn)行接口限流,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07Java 實(shí)現(xiàn)repalceAll只替換第二個(gè)匹配到的字符串
這篇文章主要介紹了Java 實(shí)現(xiàn)repalceAll只替換第二個(gè)匹配到的字符串,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12Shiro實(shí)現(xiàn)session限制登錄數(shù)量踢人下線(xiàn)功能
這篇文章主要介紹了Shiro實(shí)現(xiàn)session限制登錄數(shù)量踢人下線(xiàn),本文記錄的是shiro采用session作為登錄方案時(shí),對(duì)用戶(hù)進(jìn)行限制數(shù)量登錄,以及剔除下線(xiàn),需要的朋友可以參考下2023-11-11SpringBoot全局異常處理之解決404/500錯(cuò)誤
在搭建項(xiàng)目框架的時(shí)候用的是springboot,想統(tǒng)一處理異常,但是發(fā)現(xiàn)404的錯(cuò)誤總是捕捉不到,總是返回的是springBoot自帶的錯(cuò)誤結(jié)果信息,這篇文章主要給大家介紹了關(guān)于SpringBoot全局異常處理之解決404/500錯(cuò)誤的相關(guān)資料,需要的朋友可以參考下2023-11-11SpringBoot整合mybatis常見(jiàn)問(wèn)題(小結(jié))
這篇文章主要介紹了SpringBoot整合mybatis常見(jiàn)問(wèn)題(小結(jié)),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12SpringBoot整合logback日志的詳細(xì)步驟
這篇文章主要介紹了SpringBoot整合logback日志的詳細(xì)步驟,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-05-05Java實(shí)現(xiàn)Token工具類(lèi)進(jìn)行登錄和攔截
在應(yīng)用的登錄時(shí)需要生成token進(jìn)行驗(yàn)證,并放入信息,之后的話(huà)可以直接使用瀏覽器的session進(jìn)行登錄,本文就來(lái)利用java編寫(xiě)一個(gè)token工具類(lèi),可以很方便的生成和解析token,感興趣的可以了解下2023-12-12