1. 程式人生 > >探祕static——類不需例項化就能用?

探祕static——類不需例項化就能用?

       一般情況下,需要用到某個類的時候,都必須先例項化這個類,才能對其進行呼叫。在程式設計過程中發現,有些類不用例項化就可以直接拿來使用,使用它的欄位、方法等等。

       這時候,靠的就是static作用。static英文意思為“靜止的,靜態的”,在OOP中可以作為修飾符,類、欄位、屬性、方法等被static修飾後,變為靜態類、靜態欄位、靜態屬性、靜態方法……

       static修飾的類成為靜態類,靜態類只能包含靜態成員(被static修飾的欄位、屬性、方法),不能被例項化,不能被繼承;非靜態中可以包含靜態成員。

       1、被呼叫時必須先例項化的情況:

       被呼叫成員為非靜態成員

此時它所屬的類肯定為非靜態類)。如下小例子:

    public class ClassA      //ClassA類(非靜態類)
    {
        public ClassA() { }  //建構函式
        public void Fun() { }//ClassA類中的方法(非靜態方法)
    }

    public class ClassB     //需要呼叫ClassA類中方法的ClassB類
    {
        public ClassB() { }  //建構函式
        public void Fun()  
        {
            ClassA a = new ClassA();//呼叫ClassA類中的方法需要先例項化
            a.Fun();
        }
    }
      說明:ClassA類為非靜態類,其中的方法Fun()也為非靜態方法,所以在ClassB中呼叫時需要先例項化ClassA類。

       2、被呼叫時不需要例項化的情況:

       被呼叫成員為靜態成員此時它所屬的類為靜態類或非靜態類)。如下小例子:

       (1)被呼叫類為非靜態類:

    public class ClassA      //ClassA類(非靜態類)
    {
        public ClassA() { }  //建構函式
        public static void Fun() { }//ClassA類中的方法(靜態方法)
    }

    public class ClassB     //需要呼叫ClassA類中方法的ClassB類
    {
        public ClassB() { }  //建構函式
        public void Fun()  
        {
            ClassA.Fun();  //呼叫ClassA類中的方法直接呼叫:類名.成員
        }
    }
       說明:ClassA類為非靜態類,但其中的方法Fun()為非靜態方法,所以在ClassB中呼叫時不例項化ClassA類(而且不能例項化),直接呼叫其成員,語法為“類名.成員”。 

       (2)被呼叫類為靜態類:

    public static class ClassA      //ClassA類(靜態類)
    {
        //當然靜態類中不能存在建構函式
        public static void Fun() { }//ClassA類中的方法(靜態方法)
    }

    public class ClassB     //需要呼叫ClassA類中方法的ClassB類
    {
        public ClassB() { }  //建構函式
        public void Fun()  
        {
            ClassA.Fun();  //呼叫ClassA類中的方法直接呼叫:類名.成員
        }
    }
       說明:ClassA類為靜態類,其中的方法也Fun()為非靜態方法,所以在ClassB中呼叫時不例項化ClassA類(而且不能例項化),直接呼叫其成員,語法為“類名.成員”。

       3、static修飾符(拓展):

        (1) 用來修飾類或類的成員,這時不需要建立例項就能訪問(而且不能例項化),在被呼叫的時候自動例項化,且在記憶體中產生一個例項。當含有靜態成員的非靜態類例項化出物件後,這些物件公用這些靜態成員,通過類名或物件名都能訪問它們。
        在網上看到兩個有趣的小例子:
        人是一個非靜態類。人有腦子,這是一個用static修飾的屬性。
這個屬性是針對所有的人,是人的共同特徵。而不是某個特點物件所特有的(比如張三有腦子,李四沒腦子),因為只要是個人,他都有腦子(雖然卡洛斯·羅德里格茲只有半個腦子,還有些人比較腦殘→_→,那也算是有腦子),既然是人類共有的,那麼他就不能被例項化。

        
       另外一個能被例項化的例子,還是人這個類,人的身高,就是一個非static的屬性。因為每個人的身高是不同的。比如我身材魁梧,高達1.55米,這個1.55米是描述我的身高,是跟我這個特定的物件有聯絡的。姚明才2.26米,這是姚明這個物件的資料。不管是1.55還是2.26,這都和特定的物件有聯絡,而不是人類所共有的特徵。所以非static的可以被例項化,而static不能被例項化。

  

       (2) 修飾方法內部的靜態變數
       我們的程式碼都是從硬碟載入到記憶體中才能執行的,在記憶體中主要分為三個區域,來存放我們的程式碼,分別是堆、棧和靜態儲存區。堆中存放的是程式碼中的引用型別變數,如類的例項、陣列等;棧中存放的是程式碼中的值型別,如整型、浮點型、布林型等;靜態儲存區中存放靜態變數和全域性變數、常亮。

       整個程式執行時,程式碼都是共用靜態儲存區中的靜態變數的,例如定義存款餘額為靜態變數,同一個銀行卡號,無論你是在銀行取錢、在ATM機取錢,還是網銀消費,用的都是這個靜態的餘額。

       所以,方法內部的靜態變數,執行完靜態變數值不消失,再次執行此物件的方法時,值仍存在,它不是在堆和棧中分配的,是在靜態區非配的, 這是與區域性變數最大的區別。關於記憶體分配問題可參考《靜態儲存區、堆和棧的區別》

相關推薦

探祕static——例項

       一般情況下,需要用到某個類的時候,都必須先例項化這個類,才能對其進行呼叫。在程式設計過程中發現,有些類不用例項化就可以直接拿來使用,使用它的欄位、方法等等。        這時候,靠的

需要例項直接用

  在我以前的意識中,我們需要用到某個類的時候,需要先例項化這個類,例項化出一個物件,然後在使用這個類裡面的方法和屬性,今天偶然的機會了解到,原來有些類是不需要例項化就可以直接用的——靜態(static)類,同時我們可以直接使用靜態類中的方法和屬性。   類、

String(物件例項、字串比較、物件池、字串常量不可變更)

String的兩種例項化方式 直接賦值和傳統例項化: public class Stringob { public static void main(String[] args) { String str1="hello"; //直接賦值 str是一個物

javascript面向物件程式設計--惰性例項(實現按例項

javascript是以物件為基礎,以函式為模型,以原型為繼承機制的開發模式 惰性例項化:避免在頁面中使用javascript初始化執行時就例項化類,而是將一些類的例項化推遲到需要時候才去例項化,避免資源過早的消耗 var myNamespace=function(){   &

根據字串的形式,自動匯入模組並使用反射找到模組中的,並例項物件,利用importlib和getattr實現的

例如: auth資料夾下一個SCRF.py檔案,裡面有一個Cors類 class CORS(object): def process_request(self): print('666') auth資料

讓多個Fragment 切換時重新例項

在專案中需要進行Fragment的切換,一直都是用replace()方法來替換Fragment: 1 2 3 4 5 6 7 8 9 public void s

Android 讓多個Fragment 切換時重新例項

原文: http://www.yrom.net/blog/2013/03/10/fragment-switch-not-restart/# 在專案中需要進行Fragment的切換,一直都是用replace()方法來替換Fragment: public void switc

實現一個只能被例項一次

單例模式:達到只有一個例項 程式碼如下: <?php class C{ private static $_instance; private function __construct(){ } public stat

Java載入與例項過程

0x00 背景知識 1、虛擬機器在首次載入Java類時,會對靜態初始化塊、靜態成員變數、靜態方法(下文將這三種統稱為靜態程式碼塊)進行一次初始化 具體過程是: ①裝(加)載類的載入指的是將類的.class檔案中的二進位制資料讀入到記

java載入和例項:靜態程式碼塊、初始程式碼塊、構造方法的執行順序

java中第一次例項化一個物件時,靜態程式碼塊、初始化塊、屬性的初始化、構造方法,再加上如果父類也有這些東西,天,到底執行順序是什麼? 來一段程式碼試一試就知道了: public class LoadingTest { public static void main(

關於切換Fragment的重新例項的解決方法

我一般用的replace()方法去切換Fragment,當你只寫靜態頁面的時候是看不出什麼區別的,可當你和伺服器互動時你就會發現,即便是已經顯示過的Fragment還是會被重新例項化,因為replace是會先remove然後add的,所以每次都會執行onDestroyVie

java之面向物件:子物件的例項過程詳解

在子類建構函式中,發現,訪問子類建構函式時,父類也運行了。原因是什麼呢? 在子類的建構函式裡第一行有一個預設的隱式語句:super() ExtendsDemo.java class Fu { Fu() { System.out.println("fu run")

fragment重新例項

關於Fragment 在這簡單說一下Fragment,Fragment是Android 3.0以後才出現的,是為了適應不同的手機螢幕、平板和電視機的螢幕的。另外還有一個重要的原因,因為Activity的建立到銷燬需要費時費記憶體,大量的Activity之間的跳轉會造成堆疊飽

載入與例項

類載入與例項化 基本步驟 類裝載分為以下 5 個步驟: 載入:根據查詢路徑找到相應的 class 檔案然後匯入 檢查:檢查載入的 class 檔案的正確性 準備:給類中的靜態變數分配記憶體空間 解析:虛擬機器將常量池中的符號引用替換成直接引用的過程。符號引用理解為一個標示,而直接引用直接指向記憶體中的地址

寫代碼完成一個簡單模塊的組件麽?

object dpa 搜索 就是 pub ror ping 開始學習 ini 開篇四連問 你是否懶得寫普通的增刪改查方法? 你是否不喜歡代碼生成插件的重復代碼? 你是否渴望一個沒有冗余代碼的項目? 你是否渴望一行代碼都不用寫就能完成一個簡單的模塊? 組件由來 作為後端程

七步掌握Python資料準備

摘要:本文主要講述瞭如何在python中用七步就能完成中資料準備。 上圖為CRISP-DM模型中的資料準備 下面七個步驟涵蓋了資料準備的概念,個別任務以及從Python生態系統中處理整個任務過程的不同方法。 維基百科將資料清洗定義為: 它是從記錄集、表或者資料庫檢測和更正

反射機制下的工廠模式(寫完具體,馬上)

先修知識 多型 介面與父類可作返回型別,引用宣告型別. 實現類與繼承類可作構造型別,反射強制轉換型別,反射(子類.class)獲取元型別 反射 反射一定是用在通用的場景,故利用反射機制時不應該出現

Mac由需要重啟才能切換耳機和內建揚聲器變為需要重啟切換(卻還是很low!!!)

不知道什麼原因,我的Mac最令我惱火的一個“特性”是聲音播放裝置的切換需要重啟。比如我當前用內建揚聲器播放聲音,如果我要改用耳機來播放,那麼我直接在此時插入耳機是不可行的。可行的方法是,我先插入耳機,然後重啟電腦,這樣聲音才會從耳機出現。當我要從耳機模式切換回電

SQL程式設計:模糊表關聯求人 ---> concat + like

1、表的結構:​create table A(proj_dept varchar(30)); create table B(dept_id int,dept_name varchar(30));

二分法查詢, 貼上,好使

二分法查詢到條件是: 必須是有序陣列; 時間複雜度(log n); package com.Bianli_learning; /** * @author sunfch * @create 2018-10-07 14:48 * @desc 二分法查詢實現 **/ public cla