Java 使用“时有无性能差异”;这是“xxx”;指向字段?
我刚刚开始使用Java,我想确保我的格式和约定从一开始就都是正确的 基本上,我的老师就是这么做的(这让我很恼火,因为它不可读) 而我更喜欢这样做:Java 使用“时有无性能差异”;这是“xxx”;指向字段?,java,performance,this,conventions,Java,Performance,This,Conventions,我刚刚开始使用Java,我想确保我的格式和约定从一开始就都是正确的 基本上,我的老师就是这么做的(这让我很恼火,因为它不可读) 而我更喜欢这样做: public class MyClass { private String name; private int age; public MyClass (String name, int age) { this.name = name; this.age = age; }
public class MyClass
{
private String name;
private int age;
public MyClass (String name, int age)
{
this.name = name;
this.age = age;
}
}
public class MyClass {
// ...
public int calculateAgeDifference(MyClass other) {
int age = other.age; // This hides this.age, don't do this
return this.age - age;
}
}
我只是想知道两者之间是否存在性能差异,以及哪一个更容易被接受。我使用a来反编译此源代码:
public class Test {
String s;
public void a(String p){
s=p;
}
public void b(String p){
this.s=p;
}
}
反编译器根据字节码创建了此源:
public class Test {
String s;
public void a(String p){
this.s=p;
}
public void b(String p){
this.s=p;
}
}
正如@Brian在上面的评论中所说的那样。这两种方法完全相同。两种形式生成的字节码相同,因此性能相同 如果编译后
javap-v
您的MyClass
对象,则这两种情况下的头将具有相同的md5校验和值
表单this.name
和不符合条件的表单name
都会生成与下面的输出相同的putfield操作码,如6:putfield#2
javap-vmyclass的完整输出
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
}
Classfile/tmp/java/MyClass.class
最后修改日期:2013年8月14日;大小309字节
MD5校验和a6981396520454dd2aeb9a474dd92c90
从“MyClass.java”编译而来
公共类MyClass
源文件:“MyClass.java”
次要版本:0
主要版本:51
旗帜:ACC_公共、ACC_超级
固定池:
#1=Methodref#5.#16//java/lang/Object.“:()V
#2=Fieldref#4.#17//MyClass.name:Ljava/lang/String;
#3=Fieldref#4.#18//MyClass.年龄:I
#4=类别#19//MyClass
#5=类#20//java/lang/Object
#6=Utf8名称
#7=Utf8 Ljava/lang/String;
#8=Utf8年龄
#9=Utf8 I
#10=Utf8
#11=Utf8(Ljava/lang/String;I)V
#12=Utf8代码
#13=Utf8行号表
#14=Utf8源文件
#15=Utf8 MyClass.java
#16=名称和类型#10:#21/“”:()V
#17=name和type#6:#7//name:Ljava/lang/String;
#18=姓名和类型#8:#9//年龄:I
#19=Utf8 MyClass
#20=Utf8 java/lang/Object
#21=Utf8()V
{
java.lang.String名称;
旗帜:
智力年龄;
旗帜:
公共MyClass(java.lang.String,int);
旗帜:ACC_PUBLIC
代码:
堆栈=2,局部变量=3,参数大小=3
0:aload_0
1:invokespecial#1//方法java/lang/Object。“:()V
4:aload_0
5:aload_1
6:putfield#2//字段名:Ljava/lang/String;
9:aload_0
10:iload_2
11:putfield#3//现场年龄:I
14:返回
LineNumberTable:
第7行:0
第8行:4
第9行:9
第10行:14
}
这两个代码片段之间绝对没有性能差异。这只能归结为可读性
第二种变体通常是首选的,因为您对构造函数参数使用有意义的名称,而不是真正没有意义的n
和a
。看起来你的老师使用不同的名字只是为了避免使用这个。
,我不建议这样做,因为显式的这个。
强调你在分配类的字段,而不仅仅是任意变量,这可能是构造函数中的一个重要区别。在这两种情况下,访问字段的字节码完全相同。对于第一个,javap-c
返回:
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
}
相反,要:
int otherAge = other.age;
这使您的代码更具可读性。因此,如果您使用阴影,请仅在setter和constructor中使用阴影,我强烈建议在其他地方避免使用阴影。没有性能差异。事实上,编译器在每次引用每个成员变量时都会使用this.
预先挂起它。这是一个你喜欢用哪种方式来做的问题没有任何区别-后者是标准的。事实上,使用变量名隐藏字段是唯一可以接受的。生成的字节码实际上是完全相同的。我真的是指这里。所以,没有性能差异。你所说的配置文件是什么意思?使用像“jprofiler”这样的配置文件器
public class MyClass {
// ...
public int calculateAgeDifference(MyClass other) {
int age = other.age; // This hides this.age, don't do this
return this.age - age;
}
}
int otherAge = other.age;