开发者

Is it more efficient to use the keyword this when accessing instance variables?

The this keyword is optional when accessing instance fields, properties, and methods in languages like C# and Java.

I've been doing som开发者_运维百科e best practice research on various languages lately, and have noticed many places recommend creating a local reference to instance fields within methods because it's more efficient. The latest mention was in an Android tutorial.

It seems to me that if you specify this._obj, it should be just as efficient as a local variable. Is this correct or is it just as 'costly' as not using this?

Does the answer change from the Android Dalvik VM, to standard Java, to C#?

public class test {
    private Object[] _obj;

    protected void myMethod() {
        Object[] obj = _obj;

        // Is there an appreciable differnce between
        for(int i = 0; i < obj.length; i++) { 
            // do stuff
        }

        // and this?
        for(int i = 0; i < this._obj.length; i++) { 
            // do stuff
        }
    }
}


For at least standard Java, there is a small, small difference.

I modified your example a little to this:

public class test {
    private Object[] _obj;

    protected void myMethodLocal() {
        Object[] obj = _obj;

        // Is there an appreciable differnce between
        for(int i = 0; i < obj.length; i++) { 
            // do stuff
        }
    }

   protected void myMethodMember() {
        // and this?
        for(int i = 0; i < this._obj.length; i++) { 
            // do stuff
        }
   }
}

So myMethodLocal() will cache _obj into a local variable, while myMethodMember() uses the class member _obj.

Now, let's decompile this (using javap):

protected void myMethodLocal();
  Code:
   0:   aload_0
   1:   getfield    #2; //Field _obj:[Ljava/lang/Object;
   4:   astore_1
   5:   iconst_0
   6:   istore_2
   7:   iload_2
   8:   aload_1
   9:   arraylength
   10:  if_icmpge   19
   13:  iinc    2, 1
   16:  goto    7
   19:  return

protected void myMethodMember();
  Code:
   0:   iconst_0
   1:   istore_1
   2:   iload_1
   3:   aload_0
   4:   getfield    #2; //Field _obj:[Ljava/lang/Object;
   7:   arraylength
   8:   if_icmpge   17
   11:  iinc    1, 1
   14:  goto    2
   17:  return

Without going into details, the latter example has to access the _obj field every loop iteration, while the first example already had it cached in a local reference and just needs to access the local reference.

What does this equate to in speed difference?

Not much.

While the difference between accessing a local reference and a class-reference means a lot more in a language like Python, for Java, you really don't need to worry. It's much more important to keep your code readable and maintainable than to fret over details like that.

(Plus, the above bytecode doesn't take into account what the JIT compiler might do, anyway).

If you get the instance field by a function, like getObj(), I would plug that into a variable, so you don't need to keep calling getObj() each time you want to use the same field.


Also, just as a minor note, you should probably call your class Test instead of test. Java tends to favor Upper Camel Case for class names.


No, there is absolutely no change in efficiency. Remember that in many languages, several equivalent expressions will reduce down to identical statements in the underlying bytecode or assembly or whatever the higher level language translates into.

The answer is uniform across the languages and VMs you mention.

Use it when necessary, like when a method parameter has the same name as an instance variable.

Unless CPU cycles (or memory, etc.) are a top priority, value clarity above less expressive but more efficient language syntax.


The this keyword is used for readability and most importantly making variable names unambiguous. It has no affect on performance whatsoever.


On modern PC, this may not make any difference irrespective of languages due to caching - if memory location is cached on on-chip dye then it wouldn't make any difference.


I suspect using local variable is only a single reference (the value is on the stack), while using member variable is 2 reference (reference to this, which is on the stack, then reference to the variable itself, which is on the heap)

Depending on the system, either heap or stack access could be faster.

But like what Jonathon said, unless speed is very important, don't bother yourself with this. It will only reduce readability for negligible performance.


In theory, no. Accessing "this._obj.Length" ends up generating code like:

mov eax, [ecx + offset_of_obj]
mov eax, [eax + offset_of_length]

where as "obj.length" ends up generating code like:

mov eax, [esp + offset_of_obj]
mov eax, [eax + offset_of_length]

In practice, maybe, but probably not. With virtually every x86 calling convention there are only 3 scratch registers "eax", "ecx", and "edx". All other registers must be saved on the stack before they can be updated. If you have a long function, and you don't need to access "this" then the ecx register could be repurposed to hold temporary variables, and could thus reduce the amount of stack spilling that needs to happen. But, you have to push new values on the stack in order to create the locals,so the scenarios where it would make an improvement are limited. I would ignore who ever told you that.


Some of these answers haven't answered the actual question and others are wrong. Accessing a member variable via this.obj requires dereferencing an element on the stack. Accessing a local copy of that reference eliminates the dereference step. So in theory and absent HotSpot the latter has to be more efficient. However unless you are timing nuclear reactions or something the difference will be minimal, and I would deprecate the practice any time I saw it in my shop.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜