Java内部类的代码实例分享(java内部私有类)
這篇文章主要介紹了java 內(nèi)部類的實(shí)例詳解的相關(guān)資料,希望通過(guò)本文大家能夠理解掌握java內(nèi)部類的使用,需要的朋友可以參考下
java 內(nèi)部類的實(shí)例詳解
可以將一個(gè)類的定義放在另一個(gè)類的定義內(nèi)部,這就是內(nèi)部類。
內(nèi)部類是一個(gè)非常有用的特性但又比較難理解使用的特性(鄙人到現(xiàn)在都沒(méi)有怎么使用過(guò)內(nèi)部類,對(duì)內(nèi)部類也只是略知一二)。
第一次見(jiàn)面
內(nèi)部類我們從外面看是非常容易理解的,無(wú)非就是在一個(gè)類的內(nèi)部在定義一個(gè)類。
public class OuterClass {
private String name ;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
class InnerClass{
public InnerClass(){
name = "chenssy";
age = 23;
}
}
}
登錄后復(fù)制
在這里InnerClass就是內(nèi)部類,對(duì)于初學(xué)者來(lái)說(shuō)內(nèi)部類實(shí)在是使用的不多,鄙人菜鳥一個(gè)同樣沒(méi)有怎么使用過(guò)(貌似僅僅只在做swing 注冊(cè)事件中使用過(guò)),但是隨著編程能力的提高,我們會(huì)領(lǐng)悟到它的魅力所在,它可以使用能夠更加優(yōu)雅的設(shè)計(jì)我們的程序結(jié)構(gòu)。在使用內(nèi)部類之間我們需要明白為什么要使用內(nèi)部類,內(nèi)部類能夠?yàn)槲覀儙?lái)什么樣的好處。
一、為什么要使用內(nèi)部類
為什么要使用內(nèi)部類?在《Think in java》中有這樣一句話:使用內(nèi)部類最吸引人的原因是:每個(gè)內(nèi)部類都能獨(dú)立地繼承一個(gè)(接口的)實(shí)現(xiàn),所以無(wú)論外圍類是否已經(jīng)繼承了某個(gè)(接口的)實(shí)現(xiàn),對(duì)于內(nèi)部類都沒(méi)有影響。
在我們程序設(shè)計(jì)中有時(shí)候會(huì)存在一些使用接口很難解決的問(wèn)題,這個(gè)時(shí)候我們可以利用內(nèi)部類提供的、可以繼承多個(gè)具體的或者抽象的類的能力來(lái)解決這些程序設(shè)計(jì)問(wèn)題。可以這樣說(shuō),接口只是解決了部分問(wèn)題,而內(nèi)部類使得多重繼承的解決方案變得更加完整。
public interface Father {
}
public interface Mother {
}
public class Son implements Father, Mother {
}
public class Daughter implements Father{
class Mother_ implements Mother{
}
}
登錄后復(fù)制
其實(shí)對(duì)于這個(gè)實(shí)例我們確實(shí)是看不出來(lái)使用內(nèi)部類存在何種優(yōu)點(diǎn),但是如果Father、Mother不是接口,而是抽象類或者具體類呢?這個(gè)時(shí)候我們就只能使用內(nèi)部類才能實(shí)現(xiàn)多重繼承了。
其實(shí)使用內(nèi)部類最大的優(yōu)點(diǎn)就在于它能夠非常好的解決多重繼承的問(wèn)題,但是如果我們不需要解決多重繼承問(wèn)題,那么我們自然可以使用其他的編碼方式,但是使用內(nèi)部類還能夠?yàn)槲覀儙?lái)如下特性(摘自《Think in java》):
1、內(nèi)部類可以用多個(gè)實(shí)例,每個(gè)實(shí)例都有自己的狀態(tài)信息,并且與其他外圍對(duì)象的信息相互獨(dú)立。
2、在單個(gè)外圍類中,可以讓多個(gè)內(nèi)部類以不同的方式實(shí)現(xiàn)同一個(gè)接口,或者繼承同一個(gè)類。
3、創(chuàng)建內(nèi)部類對(duì)象的時(shí)刻并不依賴于外圍類對(duì)象的創(chuàng)建。
4、內(nèi)部類并沒(méi)有令人迷惑的“is-a”關(guān)系,他就是一個(gè)獨(dú)立的實(shí)體。
5、內(nèi)部類提供了更好的封裝,除了該外圍類,其他類都不能訪問(wèn)。
二、內(nèi)部類基礎(chǔ)
在這個(gè)部分主要介紹內(nèi)部類如何使用外部類的屬性和方法,以及使用.this與.new。
當(dāng)我們?cè)趧?chuàng)建一個(gè)內(nèi)部類的時(shí)候,它無(wú)形中就與外圍類有了一種聯(lián)系,依賴于這種聯(lián)系,它可以無(wú)限制地訪問(wèn)外圍類的元素。
public class OuterClass {
private String name ;
private int age;
/**省略getter和setter方法**/
public class InnerClass{
public InnerClass(){
name = "chenssy";
age = 23;
}
public void display(){
System.out.println("name:" + getName() +" ;age:" + getAge());
}
}
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.display();
}
}
--------------
Output:
name:chenssy ;age:23
登錄后復(fù)制
在這個(gè)應(yīng)用程序中,我們可以看到內(nèi)部了InnerClass可以對(duì)外圍類OuterClass的屬性進(jìn)行無(wú)縫的訪問(wèn),盡管它是private修飾的。這是因?yàn)楫?dāng)我們?cè)趧?chuàng)建某個(gè)外圍類的內(nèi)部類對(duì)象時(shí),此時(shí)內(nèi)部類對(duì)象必定會(huì)捕獲一個(gè)指向那個(gè)外圍類對(duì)象的引用,只要我們?cè)谠L問(wèn)外圍類的成員時(shí),就會(huì)用這個(gè)引用來(lái)選擇外圍類的成員。
其實(shí)在這個(gè)應(yīng)用程序中我們還看到了如何來(lái)引用內(nèi)部類:引用內(nèi)部類我們需要指明這個(gè)對(duì)象的類型:OuterClasName.InnerClassName。同時(shí)如果我們需要?jiǎng)?chuàng)建某個(gè)內(nèi)部類對(duì)象,必須要利用外部類的對(duì)象通過(guò).new來(lái)創(chuàng)建內(nèi)部類: OuterClass.InnerClass innerClass = outerClass.new InnerClass();。
同時(shí)如果我們需要生成對(duì)外部類對(duì)象的引用,可以使用OuterClassName.this,這樣就能夠產(chǎn)生一個(gè)正確引用外部類的引用了。當(dāng)然這點(diǎn)實(shí)在編譯期就知曉了,沒(méi)有任何運(yùn)行時(shí)的成本。
/**
* Java學(xué)習(xí)交流QQ群:589809992 我們一起學(xué)Java!
*/
public class OuterClass {
public void display(){
System.out.println("OuterClass...");
}
public class InnerClass{
public OuterClass getOuterClass(){
return OuterClass.this;
}
}
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.getOuterClass().display();
}
}
-------------
Output:
OuterClass...
登錄后復(fù)制
到這里了我們需要明確一點(diǎn),內(nèi)部類是個(gè)編譯時(shí)的概念,一旦編譯成功后,它就與外圍類屬于兩個(gè)完全不同的類(當(dāng)然他們之間還是有聯(lián)系的)。對(duì)于一個(gè)名為OuterClass的外圍類和一個(gè)名為InnerClass的內(nèi)部類,在編譯成功后,會(huì)出現(xiàn)這樣兩個(gè)class文件:OuterClass.class和OuterClass$InnerClass.class。
在Java中內(nèi)部類主要分為成員內(nèi)部類、局部?jī)?nèi)部類、匿名內(nèi)部類、靜態(tài)內(nèi)部類。
三、成員內(nèi)部類
成員內(nèi)部類也是最普通的內(nèi)部類,它是外圍類的一個(gè)成員,所以他是可以無(wú)限制的訪問(wèn)外圍類的所有 成員屬性和方法,盡管是private的,但是外圍類要訪問(wèn)內(nèi)部類的成員屬性和方法則需要通過(guò)內(nèi)部類實(shí)例來(lái)訪問(wèn)。
在成員內(nèi)部類中要注意兩點(diǎn),第一:成員內(nèi)部類中不能存在任何static的變量和方法;第二:成員內(nèi)部類是依附于外圍類的,所以只有先創(chuàng)建了外圍類才能夠創(chuàng)建內(nèi)部類。
public class OuterClass {
private String str;
public void outerDisplay(){
System.out.println("outerClass...");
}
public class InnerClass{
public void innerDisplay(){
//使用外圍內(nèi)的屬性
str = "chenssy...";
System.out.println(str);
//使用外圍內(nèi)的方法
outerDisplay();
}
}
/*推薦使用getxxx()來(lái)獲取成員內(nèi)部類,尤其是該內(nèi)部類的構(gòu)造函數(shù)無(wú)參數(shù)時(shí) */
public InnerClass getInnerClass(){
return new InnerClass();
}
public static void main(String[] args) {
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.getInnerClass();
inner.innerDisplay();
}
}
--------------------
chenssy...
outerClass...
登錄后復(fù)制
推薦使用getxxx()來(lái)獲取成員內(nèi)部類,尤其是該內(nèi)部類的構(gòu)造函數(shù)無(wú)參數(shù)時(shí) 。
四、局部?jī)?nèi)部類
有這樣一種內(nèi)部類,它是嵌套在方法和作用于內(nèi)的,對(duì)于這個(gè)類的使用主要是應(yīng)用與解決比較復(fù)雜的問(wèn)題,想創(chuàng)建一個(gè)類來(lái)輔助我們的解決方案,到那時(shí)又不希望這個(gè)類是公共可用的,所以就產(chǎn)生了局部?jī)?nèi)部類,局部?jī)?nèi)部類和成員內(nèi)部類一樣被編譯,只是它的作用域發(fā)生了改變,它只能在該方法和屬性中被使用,出了該方法和屬性就會(huì)失效。
對(duì)于局部?jī)?nèi)部類實(shí)在是想不出什么好例子,所以就引用《Think in java》中的經(jīng)典例子了。
定義在方法里:
/**
* Java學(xué)習(xí)交流QQ群:589809992 我們一起學(xué)Java!
*/
public class Parcel5 {
public Destionation destionation(String str){
class PDestionation implements Destionation{
private String label;
private PDestionation(String whereTo){
label = whereTo;
}
public String readLabel(){
return label;
}
}
return new PDestionation(str);
}
public static void main(String[] args) {
Parcel5 parcel5 = new Parcel5();
Destionation d = parcel5.destionation("chenssy");
}
}
登錄后復(fù)制
定義在作用域內(nèi):
public class Parcel6 {
private void internalTracking(boolean b){
if(b){
class TrackingSlip{
private String id;
TrackingSlip(String s) {
id = s;
}
String getSlip(){
return id;
}
}
TrackingSlip ts = new TrackingSlip("chenssy");
String string = ts.getSlip();
}
}
public void track(){
internalTracking(true);
}
public static void main(String[] args) {
Parcel6 parcel6 = new Parcel6();
parcel6.track();
}
}
登錄后復(fù)制
五、匿名內(nèi)部類
在做Swing編程中,我們經(jīng)常使用這種方式來(lái)綁定事件
button2.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.out.println("你按了按鈕二");
}
});
登錄后復(fù)制
我們咋一看可能覺(jué)得非常奇怪,因?yàn)檫@個(gè)內(nèi)部類是沒(méi)有名字的,在看如下這個(gè)例子:
/**
* Java學(xué)習(xí)交流QQ群:589809992 我們一起學(xué)Java!
*/
public class OuterClass {
public InnerClass getInnerClass(final int num,String str2){
return new InnerClass(){
int number = num + 3;
public int getNumber(){
return number;
}
}; /* 注意:分號(hào)不能省 */
}
public static void main(String[] args) {
OuterClass out = new OuterClass();
InnerClass inner = out.getInnerClass(2, "chenssy");
System.out.println(inner.getNumber());
}
}
interface InnerClass {
int getNumber();
}
----------------
Output:
登錄后復(fù)制
這里我們就需要看清幾個(gè)地方
1、 匿名內(nèi)部類是沒(méi)有訪問(wèn)修飾符的。
2、 new 匿名內(nèi)部類,這個(gè)類首先是要存在的。如果我們將那個(gè)InnerClass接口注釋掉,就會(huì)出現(xiàn)編譯出錯(cuò)。
3、 注意getInnerClass()方法的形參,第一個(gè)形參是用final修飾的,而第二個(gè)卻沒(méi)有。同時(shí)我們也發(fā)現(xiàn)第二個(gè)形參在匿名內(nèi)部類中沒(méi)有使用過(guò),所以當(dāng)所在方法的形參需要被匿名內(nèi)部類使用,那么這個(gè)形參就必須為final。
4、 匿名內(nèi)部類是沒(méi)有構(gòu)造方法的。因?yàn)樗B名字都沒(méi)有何來(lái)構(gòu)造方法。
六、靜態(tài)內(nèi)部類
在java提高篇——關(guān)鍵字static中提到Static可以修飾成員變量、方法、代碼塊,其他它還可以修飾內(nèi)部類,使用static修飾的內(nèi)部類我們稱之為靜態(tài)內(nèi)部類,不過(guò)我們更喜歡稱之為嵌套內(nèi)部類。靜態(tài)內(nèi)部類與非靜態(tài)內(nèi)部類之間存在一個(gè)最大的區(qū)別,我們知道非靜態(tài)內(nèi)部類在編譯完成之后會(huì)隱含地保存著一個(gè)引用,該引用是指向創(chuàng)建它的外圍內(nèi),但是靜態(tài)內(nèi)部類卻沒(méi)有。沒(méi)有這個(gè)引用就意味著:
1、 它的創(chuàng)建是不需要依賴于外圍類的。
2、 它不能使用任何外圍類的非static成員變量和方法。
/**
* Java學(xué)習(xí)交流QQ群:589809992 我們一起學(xué)Java!
*/
public class OuterClass {
private String sex;
public static String name = "chenssy";
/**
*靜態(tài)內(nèi)部類
*/
static class InnerClass1{
/* 在靜態(tài)內(nèi)部類中可以存在靜態(tài)成員 */
public static String _name1 = "chenssy_static";
public void display(){
/*
* 靜態(tài)內(nèi)部類只能訪問(wèn)外圍類的靜態(tài)成員變量和方法
* 不能訪問(wèn)外圍類的非靜態(tài)成員變量和方法
*/
System.out.println("OutClass name :" + name);
}
}
/**
* 非靜態(tài)內(nèi)部類
*/
class InnerClass2{
/* 非靜態(tài)內(nèi)部類中不能存在靜態(tài)成員 */
public String _name2 = "chenssy_inner";
/* 非靜態(tài)內(nèi)部類中可以調(diào)用外圍類的任何成員,不管是靜態(tài)的還是非靜態(tài)的 */
public void display(){
System.out.println("OuterClass name:" + name);
}
}
/**
* @desc 外圍類方法
* @author chenssy
* @data 2013-10-25
* @return void
*/
public void display(){
/* 外圍類訪問(wèn)靜態(tài)內(nèi)部類:內(nèi)部類. */
System.out.println(InnerClass1._name1);
/* 靜態(tài)內(nèi)部類 可以直接創(chuàng)建實(shí)例不需要依賴于外圍類 */
new InnerClass1().display();
/* 非靜態(tài)內(nèi)部的創(chuàng)建需要依賴于外圍類 */
OuterClass.InnerClass2 inner2 = new OuterClass().new InnerClass2();
/* 方位非靜態(tài)內(nèi)部類的成員需要使用非靜態(tài)內(nèi)部類的實(shí)例 */
System.out.println(inner2._name2);
inner2.display();
}
public static void main(String[] args) {
OuterClass outer = new OuterClass();
outer.display();
}
}
----------------
Output:
chenssy_static
OutClass name :chenssy
chenssy_inner
OuterClass name:chenssy
登錄后復(fù)制
上面這個(gè)例子充分展現(xiàn)了靜態(tài)內(nèi)部類和非靜態(tài)內(nèi)部類的區(qū)別。
到這里內(nèi)部類的介紹就基本結(jié)束了!對(duì)于內(nèi)部類其實(shí)本人認(rèn)識(shí)也只是皮毛,逼近菜鳥一枚,認(rèn)知有限!我會(huì)利用這幾天時(shí)間好好研究?jī)?nèi)部類!
以上就是Java內(nèi)部類的代碼實(shí)例分享的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注風(fēng)君子博客其它相關(guān)文章!
總結(jié)
以上是生活随笔為你收集整理的Java内部类的代码实例分享(java内部私有类)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: [投资习惯对比]投资大师vs失败投资…
- 下一篇: 逾期记录怎么申请消除,有以下几步