Question

I'm just starting out in Java and I would like to make sure that my format and conventions are all OK from the get-go.

Basically, my teacher does this (which annoys me because it's unreadable)

public class MyClass
{   
    String name;
    int age;

    public MyClass (String n, int a)
    {
        name = n;
        age = a;
    }
}

Whereas I prefer to do something like this:

public class MyClass
{   
    private String name;
    private int age;

    public MyClass (String name, int age)
    {
        this.name = name;
        this.age = age;
    }
}

I just want to know if there is a performance difference between the two and which is more accepted.

Was it helpful?

Solution 2

The bytecode for accessing the fields is exactly the same in both cases. For the first one, javap -c returns:

public MyClass(java.lang.String, int);
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   aload_1
   6:   putfield        #2; //Field name:Ljava/lang/String;
   9:   aload_0
   10:  iload_2
   11:  putfield        #3; //Field age:I
   14:  return

}

The second one:

public MyClass(java.lang.String, int);
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   aload_1
   6:   putfield        #2; //Field name:Ljava/lang/String;
   9:   aload_0
   10:  iload_2
   11:  putfield        #3; //Field age:I
   14:  return

}

As you can see, they are functionally equivalent. The important thing is being able to understand the code. For constructors and setters, the standard in the Java community is to use name shadowing (the parameters share their names with the fields) and then the fields are accessed using this. as the qualifier. However, in logical methods, it's highly recommended that you never shadow fields. For example, I would avoid something like this:

public class MyClass {

    // ...

    public int calculateAgeDifference(MyClass other) {
        int age = other.age; // This hides this.age, don't do this
        return this.age - age;
    }
}

Instead, do:

int otherAge = other.age;

This makes your code more readable. So only use shadowing in setters and constructors if you use it, I highly recommend avoiding it everywhere else.

OTHER TIPS

There is absolutely no performance difference between the two snippets. It comes down only to readability.

The second variant is generally preferred because you're using meaningful names for the constructor parameters, as opposed to n and a which really have no meaning. It looks like your teacher is using different names only to get out of having to use this., which I wouldn't recommend because the explicit this. emphasizes that you're assigning fields of the class, and not just arbitrary variables, which can an important distinction within a constructor.

I used a decompiler to decompile this source:

public class Test {

    String s;

    public void a(String p){
        s=p;
    }

    public void b(String p){
        this.s=p;
    }

}

the decompiler created this source from the bytecode:

public class Test {

    String s;

    public void a(String p){
        this.s=p;
    }

    public void b(String p){
        this.s=p;
    }

}

As @Brian sayd in the comment above. Its exactly the same in both methods.

The byte code generated by the two forms is identical, thus the performance will be the same.

If you javap -v your MyClass object after compiling it the header in both cases will have the same md5 checksum value.

Both the form this.name and an unqualifed form name generate the same putfield opcode shown in the output below by 6: putfield #2

The full output of javap -v MyClass

Classfile /tmp/java/MyClass.class
  Last modified Aug 14, 2013; size 309 bytes
  MD5 checksum a6981396520454dd2aeb9a474dd92c90
  Compiled from "MyClass.java"
public class MyClass
  SourceFile: "MyClass.java"
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #5.#16         //  java/lang/Object."<init>":()V
   #2 = Fieldref           #4.#17         //  MyClass.name:Ljava/lang/String;
   #3 = Fieldref           #4.#18         //  MyClass.age:I
   #4 = Class              #19            //  MyClass
   #5 = Class              #20            //  java/lang/Object
   #6 = Utf8               name
   #7 = Utf8               Ljava/lang/String;
   #8 = Utf8               age
   #9 = Utf8               I
  #10 = Utf8               <init>
  #11 = Utf8               (Ljava/lang/String;I)V
  #12 = Utf8               Code
  #13 = Utf8               LineNumberTable
  #14 = Utf8               SourceFile
  #15 = Utf8               MyClass.java
  #16 = NameAndType        #10:#21        //  "<init>":()V
  #17 = NameAndType        #6:#7          //  name:Ljava/lang/String;
  #18 = NameAndType        #8:#9          //  age:I
  #19 = Utf8               MyClass
  #20 = Utf8               java/lang/Object
  #21 = Utf8               ()V
{
  java.lang.String name;
    flags: 

  int age;
    flags: 

  public MyClass(java.lang.String, int);
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=3
         0: aload_0       
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0       
         5: aload_1       
         6: putfield      #2                  // Field name:Ljava/lang/String;
         9: aload_0       
        10: iload_2       
        11: putfield      #3                  // Field age:I
        14: return        
      LineNumberTable:
        line 7: 0
        line 8: 4
        line 9: 9
        line 10: 14
}

There is no performance difference. In fact, the compiler is essentially pre-pending every member variable with this. each time it is referenced. Its a matter of preference which way you like to do it

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top