背景
開發(fā)新項(xiàng)目舅逸,寫Swager的mode的時(shí)候用到了嵌套Model刽严,于是在代碼中蹬碧,出現(xiàn)了靜態(tài)內(nèi)部類舱禽。在codeReview的時(shí)候稍微和大家聊了一下。尤其是Static 修飾類和修飾對(duì)象和變量不一樣呢恩沽?
定義
1. 內(nèi)部類
1.可以將一個(gè)類的定義放在另一個(gè)類的定義內(nèi)部誊稚,這就是內(nèi)部類;
2.嵌套類是其封閉類的成員罗心。非靜態(tài)嵌套類(內(nèi)部類)可以訪問封閉類的其他成員里伯,即使它們被聲明為私有的也是如此。靜態(tài)嵌套類無(wú)權(quán)訪問封閉類的其他成員渤闷。為一體的一個(gè)部件OuterClass疾瓮,一個(gè)嵌套類可以聲明private,public飒箭,protected狼电,或包專用蜒灰。(回想一下,只能聲明外部類public或?qū)⑵浒b為私有肩碟。)
2. 靜態(tài)內(nèi)部類
1.再一個(gè)普通類里面强窖,給內(nèi)部類加上static關(guān)鍵字的修飾;
2.與類方法和變量一樣削祈,靜態(tài)嵌套類與其外部類相關(guān)聯(lián)翅溺。與靜態(tài)類方法一樣,靜態(tài)嵌套類不能直接引用其封閉類中定義的實(shí)例變量或方法:它只能通過對(duì)象引用來(lái)使用它們髓抑。(就和兩個(gè)普通不同的類之間的使用)
3. 兩者的區(qū)別
1.內(nèi)部類只是外部類的成員變量未巫,通俗講,就是你只能通過先調(diào)用外部類才能去拿到這個(gè)類(但是這是和組合還是有區(qū)別的)启昧。
2.但是靜態(tài)內(nèi)部類就像是一個(gè)普通類一樣叙凡。可以直接調(diào)用密末,直接去new對(duì)象握爷。
4. Java 擁有嵌套類有什么作用呢?
1.這是一種對(duì)僅在一個(gè)地方使用的類進(jìn)行邏輯分組的方法:如果一個(gè)類僅對(duì)另一個(gè)類有用严里,那么將其嵌入該類并將兩者保持在一起是合乎邏輯的新啼。嵌套此類“幫助程序類”可使它們的程序包更加簡(jiǎn)化。
2.它增加了封裝:考慮兩個(gè)頂級(jí)類A和B刹碾,其中B需要訪問A的成員燥撞,否則將對(duì)其進(jìn)行聲明private。通過將類B隱藏在類A中迷帜,可以將A的成員聲明為私有物舒,而B可以訪問它們。另外戏锹,B本身可以對(duì)外界隱藏冠胯。
3.這可能會(huì)導(dǎo)致代碼更具可讀性和可維護(hù)性:在頂級(jí)類中嵌套小類會(huì)使代碼更靠近使用位置。
Demo
talk is cheap 锦针,Show me Code荠察;
package 靜態(tài)內(nèi)部類;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIConversion;
import javassist.runtime.Inner;
import lombok.Data;
/**
* @authoryuanxindong
* @date: 2020/6/19 10:25 下午
*/
@Data
public class OuterClassDemo {
String outerStr;
public OuterClassDemo(String outerStr) {
this.outerStr = outerStr;
}
@Data
public static class StaticInnerClass{
public StaticInnerClass(String innerStr) {
this.innerStr = innerStr;
}
private String innerStr;
}
@Data
public class InnerClass{
private String innerClassStr;
public InnerClass(String outerStr) {
//可以和外部類通訊
this.innerClassStr = getOuterStr();
}
}
public static void main(String[] args) {
OuterClassDemo staticClassDemo =new OuterClassDemo("Outer");
staticClassDemo.getOuterStr();
// 內(nèi)部正常類是不能直接new出來(lái)的
// OuterClass outerClass = new OuterClass();
StaticInnerClass innerClass = new StaticInnerClass("StaticInner");
System.out.println(innerClass.getInnerStr());
initInnerClass();
}
public static void initInnerClass(){
OuterClassDemo staticClassDemo1 = new OuterClassDemo("OuterClassDemo");
InnerClass innerClass = staticClassDemo1.new InnerClass("outerStr");
System.out.println(innerClass.getInnerClassStr());
}
}
注意事項(xiàng)
1.序列化強(qiáng)烈建議不要對(duì)內(nèi)部類(包括 本地和 匿名類)進(jìn)行序列化。當(dāng)Java編譯器編譯某些構(gòu)造(例如內(nèi)部類)時(shí)奈搜,它會(huì)創(chuàng)建綜合構(gòu)造悉盆。
2.這些是類,方法馋吗,字段以及其他在源代碼中沒有相應(yīng)構(gòu)造的構(gòu)造焕盟。合成構(gòu)造使Java編譯器無(wú)需更改JVM就可以實(shí)現(xiàn)新的Java語(yǔ)言功能。但是耗美,合成構(gòu)造在不同的Java編譯器實(shí)現(xiàn)中可能有所不同京髓,這意味著.class文件在不同的實(shí)現(xiàn)中也可能有所不同航缀。因此,如果序列化一個(gè)內(nèi)部類堰怨,然后使用其他JRE實(shí)現(xiàn)對(duì)其進(jìn)行反序列化芥玉,則可能會(huì)遇到兼容性問題。
核心討論
1.了解了靜態(tài)內(nèi)部類后备图,那static為什么修飾了類灿巧,對(duì)于這個(gè)類也是起了一個(gè)全局可用的一個(gè)作用?
2.越想問題越多揽涮,還有就是為什么被Static 修飾的方法可以被類直接引用到抠藕?而static 修飾的類也可以被其他的類直接使用,而不依賴于對(duì)象蒋困。
答 :我們得明確一下
1.static修飾類的方法盾似,表示這個(gè)方法和這個(gè)類對(duì)象沒有關(guān)系,只是和這個(gè)類有關(guān)系
2.static 修飾變量雪标,按照是否靜態(tài)的對(duì)類成員變量進(jìn)行分類可分兩種:一種是被static修飾的變量零院,叫靜態(tài)變量或類變量;另一種是沒有被static修飾的變量村刨,叫實(shí)例變量告抄。兩者的區(qū)別是:
3.對(duì)于靜態(tài)變量在內(nèi)存中只有一個(gè)拷貝(節(jié)省內(nèi)存),JVM只為靜態(tài)分配一次內(nèi)存嵌牺,在加載類的過程中完成靜態(tài)變量的內(nèi)存分配打洼,可用類名直接訪問(方便),當(dāng)然也可以通過對(duì)象來(lái)訪問(但是這是不推薦的)逆粹。
4.好的募疮,是這樣的。static修飾對(duì)象 可以全局使用枯饿,修飾方法可以不依賴于對(duì)象酝锅,修飾類诡必,也不用依賴與他的對(duì)象奢方,也可以被其他的類直接使用,或者自己進(jìn)行初始化爸舒。
總結(jié)
1.嵌套類:內(nèi)部類和靜態(tài)內(nèi)部類
2.內(nèi)部類屬于外部類的成員蟋字,必須依賴與外部對(duì)象來(lái)實(shí)現(xiàn),靜態(tài)內(nèi)部類扭勉,不依賴鹊奖,可以自己?jiǎn)为?dú)實(shí)現(xiàn)。
3.static 的修飾 變量涂炎,類忠聚,方法设哗,代碼塊。 共性全局性两蟀。變量的話也就是全劇唯一性网梢,會(huì)出現(xiàn)多個(gè)飲用,但不會(huì)出現(xiàn)多個(gè)存儲(chǔ)赂毯。