今天接到一個需求,是將公司的一些統計數據文件內容解析出來後,通過mq發給用戶運營平臺,給公司的大佬看,這個還是很簡單,半個小時就碼完了,但自測完後突然發現怎麼建了這麼多DTO(data transform object)!因爲統計文件有很多不同類型,我針對每個類型都建了相應的DTO,因爲這個DTO在其他業務也用不上,而且以後文件類型還有增加的話,那DTO也會增加,僅僅因爲這單個小功能產生這麼多利用率不高的DTO着實不太好(論項目是如何變臃腫的),所以我想到了一個辦法,建一個外部類,然後將這些文件對應的DTO作爲內部類放在裏面。但是內部類是用普通類還是靜態類呢?其實我也不知道,所以我好好研究了一番他們的區別。
我先貼下網上找到的關於普通內部類和靜態內部類的區別:
-
普通內部類持有對外部類的引用,靜態內部類沒有持有外部類的引用。
-
普通內部類能夠訪問外部類的靜態和非靜態成員,靜態內部類不能訪問外部類的非靜態成員,他只能訪問外部類的靜態成員。
-
一個普通內部類不能脫離外部類實體被創建,且可以訪問外部類的數據和方法,因爲他就在外部類裏面。
是不是一臉懵逼,哪裏引用了外部類?我怎麼沒看見?其實我看完後也是一臉懵逼,後來我猜想,這些是不是jdk將java文件編譯成class文件的過程中幫我們做了點手腳?爲了驗證猜想,於是乎做了下面實驗。
我先寫了一個很簡單的普通內部類和靜態內部類的代碼:
package com.yy.demo15_innerClass;
/**
* @Author: 24只羊
* @Date: 2020-02-24
*/
public class OuterClass {
// 普通成員變量
private String outField = "out field";
// 靜態成員變量
private static String outStaticField = "out static field";
// 普通內部類
public class InnerClassA{
}
// 靜態內部類
public static class InnerStaticClassB{
}
}
我們在idea或eclipse編譯這個類所在的項目後,這個OuterClass.java會生成三個Class文件:
OuterClass.class
OuterClass$InnerClassA.class
OuterClass$InnerStaticClassB.class
這個三個文件夾內容是啥呢?我們可以通過反編譯看看(我用的是在線反編譯,鏈接貼文末了)
反編譯後生成了:
OuterClass.java
OuterClass$InnerClassA.java
OuterClass$InnerStaticClassB.java
package com.yy.demo15_innerClass;
public class OuterClass {
private String outField = "out field";
private static String outStaticField = "out static field";
}
package com.yy.demo15_innerClass;
import com.yy.demo15_innerClass.OuterClass;
public class OuterClass$InnerClassA {
// $FF: synthetic field
final OuterClass this$0;
public OuterClass$InnerClassA(OuterClass this$0) {
this.this$0 = this$0;
}
}
package com.yy.demo15_innerClass;
public class OuterClass$InnerStaticClassB {
}
我們可以看到普通內部類InnerClassA在編譯成class文件後,其自動在class文件中引用了外部類OuterClass,而內部靜態類則沒有引用外部類。
這樣普通內部類相比外部內部類有個好處——就是可以引用外部類的屬性以及方法。但凡事有兩面,因爲內部類裏面持有外部類的引用,如果內部類一直在執行,則外部類就不會被GC回收,如果外部類中含有大量資源,有可能會導致內存泄漏(安卓中比較常見,比如外部類中有大量圖片啥的,但是java後端這種情況的場景我還沒想到,可能太菜了吧!!!),所以擔心內存泄漏,就用靜態內部類吧。嗯嗯,我的需求也是用的靜態內部類。
現在我們再看看本文開頭的總結,是不是一目瞭然!
最後貼下我用的在線反編譯鏈接地址:http://javare.cn/