1. 程式人生 > >java靜態內部類瞭解一下

java靜態內部類瞭解一下

1. java內部類

什麼是內部類?將一個類的定義放在另一個類的內部,就是內部類。Java的內部類主要分為成員內部類、區域性內部類、匿名內部類、靜態內部類。

public class 外部類的名稱{
    //外部類的成員
    public class 內部類的名稱{
             //內部類的成員
    }
}

內部類的作用;
1)實現多重繼承;
2)內部類可以很好的實現隱藏:一般的非內部類,是不允許有 private 與protected許可權的,但內部類可以
3)減少了類檔案編譯後的產生的位元組碼檔案的大小

注意:內部類在編譯完成後也會產生.class檔案,但檔名稱是:外部類名稱$內部類名稱.class
內部類的種類:成員內部類、靜態內部類、區域性內部類、匿名內部類。

1.1 成員內部類

1、成員內部類是最普通的內部類,就是一個普通的類定義在另一個類的內部,也叫例項內部類。應用場合:每一個外部類物件都需要一個內部類的例項,內部類離不開外部類存在(相當於心臟對人體)

2、成員內部類的特徵:

  • 作為外部類的一個成員存在,與外部類的屬性、方法並列
  • 成員內部類持有外部類的引用
  • 成員內部類中不能定義static變數和方法

示例1:

public class StaticInnerClass {
	public static void main(String[] args){
		Body body=new Body("兩個胳膊"
,"兩條腿","血"); Body.Heart heart=body.new Heart(); heart.work(); } } class Body { String arm; String leg; String blood; public Body(String arm, String leg, String blood) { super(); this.arm = arm; this.leg = leg; this.blood = blood; }
//成員內部類Heart class Heart{ String name; void work() { System.out.println("心臟正在給"+arm+leg+"輸"+blood); } } }

執行:

心臟正在給兩個胳膊兩條腿輸血

示例2:

public class StaticInnerClass {
	public static void main(String[] args){
		Outer outer=new Outer();
        outer.print();//呼叫外部類的方法
	}
	
}


class Outer {

    private String name="Hello World";
    
    public class Inner{ 	
        public void print(){
            System.out.println(name);  //內部類呼叫外部類屬性
        }
    }
    
    public void print(){  //定義外部類方法
        new Inner().print();//通過內部類的例項化物件呼叫方法
    }
      
       
}

執行:

Hello World
1.2 靜態內部類

1、內部類如果使用static宣告,則此內部類就稱為靜態內部類。(其實也相當於外部類)可以通過外部類 . 內部類來訪問。
2、靜態內部類使用場合:內部類不需要外部類的例項(注意區分成員內部類),靜態內部類存在僅僅為外部類提供服務或者邏輯上屬於外部類,且邏輯上可以單獨存在。
3、靜態內部類的特徵:

  • 靜態內部類不會持有外部類的引用
  • 靜態內部類可以訪問外部的靜態變數,如果訪問外部類的成員變數必須通過外部類的例項訪問

4、Java中只有內部類才可以是靜態的

使用格式:Outer.Inner inner = new Outer.Inner();

示例1:

public class StaticInnerClass {
	public static void main(String[] args){
		
		Company.Clear zcl=new Company.Clear();
        zcl.work("shen_hua");
	}
	
}


class Company {
	
    String companyNam;
    static String country;
    
    static class Clear{   // 靜態內部類
        String name;
        
       //無引數的建構函式
        public Clear() {    
            // TODO Auto-generated constructor stub
        	System.out.println("無參物件初始化");
        }       
        
       //帶引數的建構函式
        public Clear(String name) {  
            super();
            this.name = name;
        }
        
        // 內部類的非靜態方法
        public void work(String name){
            String na=new Company().companyNam="聯想";   // 靜態內部類例項化外部類,呼叫外部類的非靜態屬性
            country="中國";								// 內部類訪問外部靜態屬性
            System.out.println(name+"為"+na+"打掃衛生,該公司屬於"+country);
        }
    }
    
}


執行:

無參物件初始化
shen_hua為聯想打掃衛生,該公司屬於中國

示例2:

public class StaticInnerClass {
	
	public static void main(String[] args){
		  Outer.Inner inner=new Outer.Inner();
	      inner.show();	
	}
	
}


class Outer {
    private static String info="Hello World";
    private int i=8;
    
    static class Inner{
        int num=new Outer().i; //通過新建外部類獲取外部類的非靜態成員變數,而靜態成員變數可以直接使用
        public  void show() {
            System.out.println(info+"---"+num);
        }
    };
}

執行:

Hello World---8
1.3 區域性內部類

1、區域性內部類也叫區域內嵌類,區域性內部類與成員內部類類似,不過,區域內嵌類是定義在一個方法中的內嵌類。
2、使用場合:如果內部類物件僅僅為外部類的某個方法使用,使用區域性內部類
3、特徵:

  • 用在方法內部,作用範圍僅限於該方法中
  • 根據情況決定持有外部類物件引用
  • 不能使用private,protected,public修飾符
  • 不能包含靜態成員
public class StaticInnerClass {
	
	public static void main(String[] args){
		 School qinghua=new School("清華","網際網路培訓",1000);	        
	     qinghua.show();
	}	
}


class School {

    String schoolName;
    String buss="培養人才";
    int studentNum;
    
    public School() {
        // TODO Auto-generated constructor stub
    }
    
    public School(String schoolName, String buss, int studentNum) {
        super();
        this.schoolName = schoolName;
        this.buss = buss;
        this.studentNum = studentNum;
    }

    // 成員方法:宣傳
    public void show(){
        final double tvMoney=10000;
        final double netMoney=20000;
        // 區域性內部類
        class AdverTeam{
            String teamName="shen_hua";  
            
            public void tvShow(){   //電視宣傳
                System.out.println("宣傳隊是:"+teamName);
                System.out.println("這是電視宣傳,學校名稱"+schoolName+",業務內容:"+buss+",學校人數:"+studentNum+",宣傳所需費用"+tvMoney);
            }
            
            public void netShow(){  //網路宣傳
                System.out.println("宣傳隊是:"+teamName);
                System.out.println("這是網路宣傳,學校名稱"+schoolName+",業務內容:"+buss+",學校人數:"+studentNum+",宣傳所需費用"+netMoney);
            }
        }
        
        new AdverTeam().tvShow();  //新建區域性類,並呼叫區域性類的方法
        new AdverTeam().netShow();
    }
}

執行:

宣傳隊是:shen_hua
這是電視宣傳,學校名稱清華,業務內容:網際網路培訓,學校人數:1000,宣傳所需費用10000.0
宣傳隊是:shen_hua
這是網路宣傳,學校名稱清華,業務內容:網際網路培訓,學校人數:1000,宣傳所需費用20000.0
1.5 匿名內部類

1、如果一個內部類在整個操作中只使用一次的話,就可以定義為匿名內部類。匿名內部類也就是沒有名字的內部類,這是java為了方便我們編寫程式而設計的一個機制,因為有時候有的內部類只需要建立一個它的物件就可以了,以後再不會用到這個類,這時候使用匿名內部類就比較合適。
2、使用場合:簡化內部類的使用
3、特徵:

  • 使用new建立 ,沒有具體位置
  • 建立的匿名類,預設繼承或實現new後面的型別
  • 根據使用情況決定是否持有外部類物件引用
  • 內嵌匿名類編譯後生成的.class檔案的命名方式是”外部類名稱$編號.class”,編號為1,2,3…n,編號為x的檔案對應的就是第x個匿名類
public class StaticInnerClass {
	
	public static void main(String[] args){
		
		Person p=new Person() { 
			
            public void run() {
                System.out.println("匿名內部類實現的");
            }
        };
        p.run();
    }
}	



interface Person {
    public void run();
}

執行:

匿名內部類實現的

2. 另一個學習示例 :

package test;

public class StaticInnerClass {

		public static void main(String[] args){			
			Mother mother=new Mother("lucy");  //例項化母親
			mother.getAge();
			mother.eat("蘋果");                //例項呼叫非靜態方法
			new Mother().motherTest1();              // 非靜態方法的類呼叫形式必須是new XXX().XXX()形式呼叫
			Mother.motherTest2();              // 靜態方法的類呼叫的形式可以直接用類名.XXX()或new XXX().XXX()呼叫
						
			
			Mother.Baby baby=new Mother.Baby(); 
			Mother.Baby.eat();             // 內部靜態類中的類呼叫靜態方法
			baby.eat();					   // 內部靜態類中的例項呼叫靜態方法
			new Mother.Baby().childTest1();// 內部靜態類中的非靜態方法呼叫
			baby.childTest1();             // 內部靜態類中的非靜態方法呼叫
			baby.childTest2();            // 內部靜態類新建外部類物件
						
		}

}


class Mother
{
	    //定義一個例項變數和一個靜態變數
		private String name;
		private int age;             // 私有變數,在類的外部不能訪問
		private static  String food;
		private  String fruit;//母親吃的食物
		
		public Mother(){              // 空參建構函式		
			food="米飯";
		}
		public Mother(String name){   // 帶參建構函式
			this.name=name;
			
		}
	 
		public String getName(){     //定義非靜態方法
			return this.name;
		}
		
		public void setName(String name){
			this.name=name;
		}
			
		public void eat(String fruit)  {
			this.fruit=fruit;
			System.out.println(this.name+" 吃了 "+this.fruit);			
		}
		
		
		public void getAge(){      //定義非靜態方法,外部類物件可以直接私有變數
			age=20;
			System.out.println("年齡:"+age);
		}
		
		public void motherTest1(){      //定義非靜態方法	(例項方法)	
			System.out.println("非靜態方法呼叫靜態變數:"+food);
			System.out.println("類呼叫非靜態方法");
		}
		
		public static void motherTest2(){      //定義靜態方法		
			System.out.println("類呼叫靜態方法");
		}
		
		public static void motherdo(){     //靜態方法呼叫靜態變數
			System.out.println("母親在吃"+food);
		}
		
		// 內部靜態類
		static class Baby{   	
			
			static String childfood;   // 在靜態內部類中定義一個靜態變數
			int dd;          // 一個例項變數
			
			
		    {                //定義一個匿名程式碼塊
		    	System.out.println("我在匿名程式碼塊裡。。");  
		    }      
		    
		    static{         //一個靜態程式碼塊
		    	System.out.println("我在靜態程式碼塊裡。。");  
		    }  
		    
		    public static void run(){    // 非靜態方法呼叫
		    	System.out.println("孩子在奔跑。。");  
		    }
		    
			public static void eat(){  
				System.out.println("孩子從母親吃的 "+ food +" 中吸收營養");
			}
			
			public void childTest1(){	
				
				//dd=age;     								 //在靜態內部類中呼叫外部類的非靜態屬性編譯出錯
				childfood=food;	
				System.out.println("childfood:"+childfood);   //在靜態內部類中呼叫外部類的靜態屬性
				motherdo();									  //可以直接呼叫外部類的靜態方法
				//motherTest1();								 //在靜態內部類中呼叫外部類的非靜態方法編譯出錯
			}	
				
			public void childTest2(){	
				Mother mm=new Mother();
				dd=mm.age;				
				mm.motherTest1();                          //可以通過建立外部類例項來呼叫外部類的非靜態方法
				System.out.println("內部類:"+dd);           //可以通過建立外部類例項來呼叫外部類的非靜態屬性
				                       
			}				
			
		}
	
}

執行:

年齡:20
lucy 吃了 蘋果
非靜態方法呼叫靜態變數:米飯
類呼叫非靜態方法
類呼叫靜態方法
我在靜態程式碼塊裡。。
我在匿名程式碼塊裡。。
孩子從母親吃的 米飯 中吸收營養
孩子從母親吃的 米飯 中吸收營養
我在匿名程式碼塊裡。。
childfood:米飯
母親在吃米飯
childfood:米飯
母親在吃米飯
非靜態方法呼叫靜態變數:米飯
類呼叫非靜態方法
內部類:0

總結:
1、靜態內部類中可以寫哪些內容

  • 匿名程式碼塊
  • 靜態程式碼塊
  • 靜態變數和非靜態變數
  • 靜態方法和非靜態方法
    注意:不能在靜態內部類中寫抽象方法

2、外部類如何呼叫靜態內部類中的屬性和方法

  • 外部類可以通過建立靜態內部類例項的方法來呼叫靜態內部類的非靜態屬性和方法
  • 外部類可以直接通過“ 外部類.內部類.屬性(方法)” 的方式直接呼叫靜態內部類中的靜態屬性和方法

3、靜態內部類如何呼叫外部類的屬性和方法

  • 靜態內部類可以直接呼叫外部類的靜態屬性和方法
  • 靜態內部類可以通過建立外部類例項的方法呼叫外部類的非靜態屬性和方法

4、如何建立靜態內部類例項

  • 在非外部類中:外部類名.內部類名 name = new 外部類名.內部類名();
  • 在外部類中:內部類名 name = new 內部類名();

參考:
https://www.cnblogs.com/shen-hua/p/5440285.html