日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java内部类(Inner Class)小记

發布時間:2025/3/21 java 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java内部类(Inner Class)小记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、引子

看到Trinea的博文Junit單測代碼中java序列化失敗的解決,讓我想到Java內部類的一些小Gocha,初學Java時很迷惑。這里記錄一下。

就以Trinea的博文中的序列化失敗的例子做為引子吧。

方便演示先準備一個工具方法:

package com.oldratlee.io.s; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class?Util?{public?static?void?writeObject(T?data)?throws?IOException?{ObjectOutputStream out = null;try {out = new ObjectOutputStream(new ByteArrayOutputStream());out.writeObject(data);} finally {if (null != out) {try {out.close();} catch (Exception e) {}}}} }

下面的測試運行失敗:

package com.oldratlee.io.s; import java.io.Serializable; import org.junit.Test; public class?InnnerClassSerialization_FailTest?{interface?GetDataInterface?extends?Serializable?{public?Object?getData();}GetDataInterface attributeData = new GetDataInterface() {private static final long serialVersionUID = 1L;public?Object?getData()?{return null;}};public class?InnerClassSerialize?implements?Serializable?{private static final long serialVersionUID = 1L;}@Testpublic?void?testSerializable_Attribute_AnonymousClass()?throws?Exception?{Util.writeObject(attributeData);}@Testpublic?void?testSerializable_LocalVar_AnonymousClass()?throws?Exception?{GetDataInterface local = new GetDataInterface() {private static final long serialVersionUID = 1L;public?Object?getData()?{return null;}};Util.writeObject(local);}@Testpublic?void?testSerializable_InnerClass()?throws?Exception?{InnerClassSerialize data = new InnerClassSerialize();Util.writeObject(data);} }

上面的3個測試用例全部運行失敗。

出錯異常相同:

java.io.NotSerializableException: com.oldratlee.io.s.InnnerClassSerialization_FailTestat java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164)at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)at com.oldratlee.io.s.Util.writeObject(Util.java:12)at com.oldratlee.io.s.InnnerClassSerialization_FailTest.testSerializable_Attribute_AnonymousClass(InnnerClassSerialization_FailTest.java:26)......

異常信息里,可以看到報的類com.oldratlee.io.s.InnnerClassSerialization_FailTest類不可序列化。

三個Test Case序列化是操作沒有顯式涉及這個類,為什么序列化時要用到這個類呢?后說到內部類的特性會給出原因。在本文的最后一節給出了解決方法。

二、內部類特性

1) 內部類和外部類可以互相訪問所有成員(屬性&方法)

示例如下,只演示了可以互相訪問Private屬性。

package com.oldratlee.io.s; public class?A?{private int attrib;private static int staticAttrib;public class?Inner1?{private int a1;public?int?method1()?{return attrib;}}public static class?StaticInner2?{private int sa1;public?int?method2()?{return staticAttrib;}}public?int?method()?{int a = new Inner1().a1;a += new StaticInner2().sa1;return a;} }

2) 非靜態內部類隱含了一個指向外部類引用

內部類實例通過這個指向外部類引用,與外部類實例關聯起來,才能夠訪問外部類實例的成員。

可以通過 外部類名.this 來在內部類中訪問這個引用。當內部類的成員和外部類成員重名時,就通過外部類引用來訪問外部類的成員;不重名的外部類屬性可以省去寫上這個引用。

代碼示例:

package com.oldratlee.io.s; public class?B?{private int foo;private int age;public class?Inner?{private int foo;public?int?method()?{return foo + B.this.foo + age;}} }

這一點就是引子里,UT運行失敗的原因。

3) 靜態成員沒有隱含了一個指向外部類引用

4) 匿名內部類如何聲明靜態

三、內部類使用方法

四、內部類的使用場景

五、總結

六、引子問題的解決

1) 修改外部類

外部類(UT類)實現了Serializable接口,這樣外部類可以序列化,下面UT通過。

package com.oldratlee.io.s; import java.io.Serializable; import org.junit.Test; public class?InnnerClassSerializationTest?implements?Serializable?{private static final long serialVersionUID = 1L;interface?GetDataInterface?extends?Serializable?{public?Object?getData();}GetDataInterface attributeData = new GetDataInterface() {private static final long serialVersionUID = 1L;public?Object?getData()?{return null;}};public class?InnerClassSerialize?implements?Serializable?{private static final long serialVersionUID = 88940079192401092L;}@Testpublic?void?testSerializable_Attribute_AnonymousClass()?throws?Exception?{Util.writeObject(attributeData);}@Testpublic?void?testSerializable_LocalVar_AnonymousClass()?throws?Exception?{GetDataInterface local = new GetDataInterface() {private static final long serialVersionUID = 1L;public?Object?getData()?{return null;}};Util.writeObject(local);}@Testpublic?void?testSerializable_InnerClass()?throws?Exception?{InnerClassSerialize data = new InnerClassSerialize();Util.writeObject(data);} }

2) 修改內部類成為靜態

這樣就不會引用外部類,沒有報外部類沒有序列化的異常。

演示了聲明靜態內部類的方法:

非匿名內部類,在類聲明上加上static關鍵字即可 匿名內部類,a) 類屬性用到匿名內部類時,把類屬性聲明成靜態 b) 方法里用到匿名內部類時,把方法聲明成靜態
# 如果類屬性、方法不是靜態的,生成匿名內部類則不是靜態類。

package com.oldratlee.io.s; import java.io.Serializable; import junit.framework.TestCase; public class?StaticClassSerialization_JUnit3_Test?extends?TestCase?{interface?GetDataInterface?extends?Serializable?{public?Object?getData();}static GetDataInterface getData = new GetDataInterface() {private static final long serialVersionUID = 1L;public?Object?getData()?{return null;}};public static class?ClassImplSerialize?implements?Serializable?{private static final long serialVersionUID = 88940079192401092L;}public?void?testSerializable_Attribute_StaticAnonymousClass()?throws?Exception?{Util.writeObject(getData);}public?static?void?testSerializable_LocalVar_StaticAnonymousClass()?throws?Exception?{GetDataInterface local = new GetDataInterface() {private static final long serialVersionUID = 1L;public?Object?getData()?{return null;}};Util.writeObject(local);}public?void?testSerializable_StaticInnerClass()?throws?Exception?{ClassImplSerialize data = new ClassImplSerialize();Util.writeObject(data);} }

【注】這里使用了JUnit 3,因為JUnit 3允許UT方法為靜態;JUnit 4的UT方法,不能為靜態,運行時會拋Exception中止。


from:?http://oldratlee.com/516/tech/java/java-inner-class-tips.html

總結

以上是生活随笔為你收集整理的Java内部类(Inner Class)小记的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。