2011-07-16 72 views
22

在開發站點剛纔看了這樣的:Android的性能 - '避免內部getter/setter方法'

Avoid Internal Getters/Setters

在像C母語++是很常見的做法是使用getter方法(例如I = getCount將() )而不是直接訪問字段(i = mCount)。對於C++來說,這是一個很好的習慣,因爲編譯器通常可以內聯訪問,如果需要限制或調試字段訪問,則可以隨時添加代碼。

在Android上,這是一個壞主意。虛擬方法調用比實例字段查找更昂貴。遵循常見的面向對象的編程實踐是合理的,並且在公共接口中有getter和setter,但在一個類中,您應該總是直接訪問字段。

沒有JIT,直接字段訪問速度比調用平凡的getter快大約3倍。使用JIT(直接字段訪問與訪問本地一樣便宜),直接字段訪問比調用一個簡單的getter快7倍。 Froyo確實如此,但在JIT內嵌getter方法時將來會有所改進。

因此,它是說你會使用字段訪問類中:約從另一個對象訪問

public class MyObject { 

    public Object innerObject; // This would be private if I was using a getter 

    public void doSomeStuff(){ 
      if(innerObject){  // Within class access like this 
       // .... 
      } 
    } 

    public Object getInnerObject(){ // This would be removed if I was using field access 
     return innerObject; 
    } 
} 

但是什麼?

public class SecondObject { 

     public void doSecondSomething(){ 
       MyObject ob = new MyObject(); 
       Object inner; 

       //This is my question basically (from an Android performance perspective) 
       inner = ob.getInnerObject(); 
       // OR 
       inner = b.innerObject 

     } 

} 
+0

只需指出這一點,請記住,Dalvik不是JVM,不應將此做法視爲在常規Java開發中執行的常規方法。 – Esko

+1

你的報價說明了一切,不是嗎? **遵循常見的面向對象編程實踐並在公共接口**中有getter和setter是合理的。另外:不要去過度設計。只要使用吸氣劑,除非你進行大量的呼叫。或有速度問題。 – Nanne

回答

27

使用內部getter和setter的性能命中也適用於外部getter和setter的場景圖。

但是,在外部情況下,吸氣劑和安裝劑在其他領域具有顯着的優勢;例如保持封裝,減少有害耦合,使代碼更易於維護等等。因此,儘管可能發生性能下降,但通常認爲它是最佳實踐使用getter和setter。

性能下降是由於 當前代 較舊的Android JIT編譯器的限制造成的。這種情況 肯定會改善 用薑餅有改善。 (參考 - https://stackoverflow.com/a/4930538/139985 ...和注意誰寫了答案!)

一般來說,「調整」劣質平臺的代碼是一個糟糕的主意,特別是如果有合理的機會可以找到更好的代碼。

+0

等等,android JIT不會內聯簡單的函數調用?我的意思是這是對任何JIT的基本優化之一 - 確保它必須確保課程不被覆蓋等,但這是99/100的簡單方法。難以置信。 – Voo

+1

@Voo - 商業上的原因可能需要現在提供第二種價格,而不是等到6個月,直到它是第一流。 Java和Javascript(以及Windows Vista和...)也發生過同樣的事情。如果你忽視歷史,這只是「難以相信」。 –

+0

發貨! @StephenC更新很好 – Blundell

3
// this is faster 
inner = b.innerObject 

// but this won't hurt performance much because 
// it's assumed that it will be rare 
inner = ob.getInnerObject(); 
4

雖然b.innerObject是更快,隨着技術的進步(更好的cpus,JIT等)之間的差異兩個選項變得更小。

可能很重要的唯一一點是在密集循環中完成,而這些循環會一直執行。例如,在遊戲的onDraw方法中,當您循環訪問數百個對象時。

3

請記住,只有在每秒訪問成員數千次的情況下,這些性能考慮纔是相關的。

一個很好的例子,其中直接存取可能是一個好主意,是一種遊戲(libgdx

public abstract class Actor { 
    public Group parent; 
    public final String name; 
    public boolean touchable = true; 

    public float x; 
    public float y; 
    public float width; 
    public float height; 
    public float originX; 
    public float originY; 
    public float scaleX = 1; 
    public float scaleY = 1; 
    public float rotation; 
    public final Color color = new Color(1, 1, 1, 1); 
2

Getters和Setter總是有開銷,因爲它們是函數調用。當你在同一個對象中時,你可以通過不使用它們來優化你的代碼,因爲你知道它們的用途,而且你不需要從它自己的對象中抽象/封裝它們。

我想你也需要看它從不同的角度:

  1. 將一個不具有的getter/setter打破常見哎呀做法?如果您製作其他人將使用的對象/模塊,則不需要直接引用。

  2. 你真的不想在最後使用getters/setter,除非sh!*優化出來的函數調用會有開銷。

你真的需要一個percase基礎上優化,如果我建兩個模塊,其中一些部件只能通過相互訪問我可能會讓其他靜態字段我會堅持getter/setter方法

+1

「Getters和Setters總是有一個開銷,因爲它們是函數調用」在任何現代JIT上都不是這樣 - 在Hotspot中會被內聯,除非在一些極少數情況下(例如setter被真正覆蓋子類和jit不能保證對象的身份之一 - 否則說,幾乎從來沒有) – Voo

2

性能方面,訪問this.fieldthat.field沒有區別。

實例字段更容易被託管它的對象訪問的感覺只是語法錯覺。

OO明智,嚴肅地說,Android應用程序可以變得多麼複雜?許多OO咒語來自構建怪物應用程序。如果你的小應用程序使用結構體這樣的對象,那有什麼大不了的?

即使在一個巨大的應用程序中,只要它在內部,並且訪問某個字段的所有源代碼都可用於重構,則在暴露這些字段時都沒有問題。

0

爲了記錄,setter和getter(Java)的另一個問題是它們使用起來很痛苦。

比方說,接下來的工作中,我們需要修改字段內幕一個對象的字段

在Java中:

object.getField().getSubField().setField3("hello"); // ugly 

雖然在C#中相同的代碼是(甚至封裝)

object.Field.SubField.Field3="hello"; // fine 

所以,在Java(或機器人)使用公共領域是有很多清潔:

object.field.subfield.field3="hello"; // fine too 
+1

啊,但這是TrainWreck反模式,只與最近的鄰居說話,並有代碼'object.setField3(「hello」 );'http://c2.com/cgi/wiki?TrainWreck – Blundell

+1

我發現getter/setter範例已經被賣完了。 99%的時間只是傳遞給成員變量。如果你打算實現它們,只需跳過getter/setter並將變量公開。 工程師經常引用良好的封裝(或更具體的隔離)作爲獲取/設置者的主要益處。代碼被綁定到getter/setter的語法,這與綁定到類成員變量的方式相同。所以沒有收益。如果您在將來更改實施或派生類超載,則獲得收益。當發生這種情況時,請使getter/setter – user1959190

+0

@ user1959190正確。但是,我不同意關於工程師的評論。真正的工程師專注於效率和結果。事實上,一位經驗豐富的工程師會欺騙很多人。然而,有這麼多的程序員不是工程師,而是更接近科學家。我使用setter和getter,因爲它的標準和團隊合作。然而,我因99%的時間無用而感到畏懼,當它有用的時候,它隱藏了實現,它非常危險。 – magallanes