`
ZangXT
  • 浏览: 116486 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

无聊:为啥可以使用空引用调用static方法或者访问static field

JVM 
阅读更多

先看代码:

public class Test {

public static void testStatic(){

    System.out.println("testStatic()");

}

public void testNonStatic(){

    System.out.println("testNonStatic()");

}

public static void main(String[] args) {

    Test.testStatic();

    Test test = null;

    test.testStatic();

    test = new Test();

    test.testStatic();

    test.testNonStatic();

}

}

结果:

testStatic()

testStatic()

testStatic()

testNonStatic()

       原因其实很简单,调用静态方法或者访问静态数据时根本不需要实例,如例子中test.testStatic(); ,这里的test是否为空根本无所谓,因为它存在的目的就是向编译器传达一个信号,"我要调用的是Test类的testStatic()方法,别给我搞错了啊!"。虽然java是面向对象的语言,但到底层执行依然是过程式的,这是计算机的本质决定的。因此,实例方法的调用不过是换了个形式而已,就是把对象引用本身作为第一个参数,比如test.testNonStatic();其实可以看作Test::testNonStatic(test);这里传入的参数test就是非静态方法中可以拿来用的this了。

       换个形式可能更容易理解:

public void Test::testNonStatic(final Test this){……}

      非静态方法里就可以使用this这个形参来访问数据了。调用非静态方法的时候会检查该实例是否为null。

最后,看一下main方法反编译代码:

public static void main(java.lang.String[]);

Code:

0:    invokestatic    #6; //Method testStatic:()V

3:    aconst_null

4:    astore_1

5:    aload_1

6:    pop

7:    invokestatic    #6; //Method testStatic:()V

10:    new    #7; //class Test

13:    dup

14:    invokespecial    #8; //Method "":()V

17:    astore_1

18:    aload_1

19:    pop

20:    invokestatic    #6; //Method testStatic:()V

23:    aload_1

24:    invokevirtual    #9; //Method testNonStatic:()V

27:    return

      这里可以发现一个问题,当用类直接调用方法时,只需要1条指令:

invokestatic    #6; //Method testStatic:()V

      而用对象引用来调用却需要3条指令,而且前两条完全是无用功:

5:    aload_1

6:    pop  //干嘛,耍我呢?

7:    invokestatic    #6; //Method testStatic:()V

      刚把引用test放到栈顶就立马弹出去了,瞎折腾了一下。剩下的才是真正起作用的调用指令。很明显,test是否为null根本不用理会了。

      这里发现一个问题,使用类直接调用静态方法不但是一个好的编码习惯,还可能有性能上的优势,毕竟使用对象引用来调用时白白浪费了两条指令。之所以说是"可能",因为jvm编译器完全有可能把这种无用指令优化掉。

      还是非静态方法的调用规矩啊,

23:    aload_1

24:    invokevirtual    #9; //Method testNonStatic:()V

      将test作为唯一的参数,调用testNonStatic方法。invokevirtual会检查该参数,为null时抛异常。

分享到:
评论
2 楼 hunter4java 2009-11-04  
精辟。。
我等望其项背啊。。

哎,汇编我大2的时候全部逃课去了,害我现在不会汇编。我要加油了。
1 楼 patrickyao1988 2009-09-12  
每次来看博主的文章都有收获啊~~~顶下

相关推荐

    findbug 常见异常处理

    描述:调用的方法中不会抛出异常,但是调用方法的时候尝试使用try catch 捕获异常; 处理方式:确认此方法的调用会不会导致异常的发生,如果不会抛出异常请去 掉try catch,确认方法调用会不会抛出异常关键是对方法...

    【05-面向对象(下)】

    则需要提供一个public方法作为该类的访问点,用于创建该类的对象,且必须使用static修饰  –3.该类还必须缓存已经创建的对象,必须用static修饰 final变量 •final修饰变量时,表示该变量一旦获得 ...

    day021-反射和注解笔记和代码.rar

    2. FIELD:可以在字段上使用注解 3. LOCAL_VARIABLE:可以在局部变量上使用注解 4. METHOD:可以在普通方法上使用注解 5. PACKAGE:可以在包上使用注解 6. PARAMETER:可以在参数...

    android jni使用static变量

    这是我自己写的android jni调用java static属性的例子

    jQuery ajax调用后台aspx后台文件的两种常见方法(不是ashx)

    在asp.net webForm开发中,用Jquery ajax调用aspx页面的方法常用的有两种:下面我来简单介绍一下。 (1)通过aspx.cs的静态方法+WebMethod进行处理 简单的介绍下WebMethod方法的用法 1.修饰符主要用public static修饰...

    java常用工具类的使用

    DateFormat是一个抽象类,不能直接实例化,可以使用下表中的静态方法得到DateFormat的对象。 方法 说明 getDateInstance() 返回默认地区,默认格式的关于日期的DateFormat对象。 getDateInstance(int) 返回指定...

    java 异常总结

    当一个应用试图访问、修改某个类的域(Field)或者调用其方法,但是又违反域或方法的可见性声明,则抛出该异常。 java.lang.IncompatibleClassChangeError 不兼容的类变化错误。当正在执行的方法所依赖的类定义发生...

    Java高级程序设计实战教程第三章-Java反射机制.pptx

    不用每一次都要在代码里面去new或者做其他的事情,以后要改的话直接改配置文件,代码维护起来就很方便了,同时有时候要适应某些需求,Java类里面不一定能直接调用另外的方法,这时候也可以通过反射机制来实现。...

    用于在Java层验证数据的合法性

    3. 需要添加新的规则时,首先需要在static静态块里添加需要验证的规则名以及默认提示信息,如果你有想调用自定义的配置信息的话,可以在自己写类似代码: result+=(StrNotNull(value2)?PropertyUtil....

    php 类中的常量、静态属性、非静态属性的区别

    类的常量不能使用访问限制修饰符,他是 public 的,可继承,可以被子类重写,访问类的常量必须使用双冒号 :: ,可以使用类名或类的实例来访问,因为是常量,所以名称不能使用表示变量的符号 $. 可以把在类中始终保持...

    C#版编写的俄罗斯方块游戏

    其实步骤很简单,先引用System.Media空间,然后创建一个SoundPlayer 对象,用SoundLocation 属性设置声音文件的地址,然后调用Play()方法即可播放。不过注意,这个类可以播放的声音格式只有Wav文件。 保存游戏设置...

    Javascript 类与静态类的实现(续)

    这次我们直接看例子: 代码如下: /***定义静态类***/ var StaticClass = (function(){ var Return = { Property: “Test Static Property”, //公有属性 Method: function(){ //公有方法 alert(_Field); //...

    Tricks.jl:Julia编译器内部的狡猾技巧

    技巧 Tricks.jl特别是邪恶的狡猾的程序包,可以对Julia边缘系统起到欺骗作用。 目前,它具有以下技巧: static_hasmethod 。...static_fieldnames , static_fieldtypes , static_fieldcount 就像Base.fiel

    java将平铺的List<T>数据转换成二叉树结构

    此文件是一个工具类,方法为一个静态方法,调用后可以直接转换想要的结果,调用方法为 public static &lt;T&gt; List&lt;T&gt; buildTree(List&lt;T&gt; list)或者 public static &lt;T&gt; List&lt;T&gt; buildTree(List&lt;T&gt; list, String fieldName,...

    .Net Word文件操作Aspose.Words破解

    只需在使用前调用一下Crack方法即可达到Patch的目的,不破坏原dll的完整性,无需反编译原dll。 private static void Crack() { var stModule = new[] { "\u000E\u2008\u200A\u2001", "\u000F\u2008\u200A\u...

    VB课程设计俄罗斯方块

    将它的形状编号为0和1,在后面方便调用,其他的方块造型同样的方法。 2.1.3俄罗斯方块的旋转 俄罗斯方块的旋转主要将方块的位置加以变换得到的,例如上述范例,长条型有两中样式,根据小方块的编号变动来实现整个...

    Java 高级特性.doc

    通配符定义的变量主要用作引用,调用与参数化无关的方法,如果要调用与参数化相关的方法,那么必须在使用?通配符引用之前调用,否则就与java 5提供泛型的目的背道而驰了。 b..向下限定通配符: 正确:Vector...

    java语言与面向对象程序设计作业题与参考答案汇编.doc

    }}若已经使用AA类创建对象a和BB类创建对象b,则下面哪一个方法调用是正确的:()。 A、a.Show( ) B、AA.Show( ); b.Show( ); BB.Show( ); C、AA.Show( ) D、a.show( ); b.show( ); ; bb.show( ); 答案:C 第10题 ...

    javaSE代码实例

    6.6.2 用空引用进行调用 88 6.6.3 数组的空引用问题 89 6.7 局部变量 89 6.7.1 局部变量的作用域 89 6.7.2 局部变量的初始化 90 6.8 this预定义对象引用 92 6.9 擅用系统已有的类 94 6.9.1 Java中的...

    千方百计笔试题大全

    34、是否可以从一个static 方法内部发出对非static 方法的调用? 11 35、写clone()方法时,通常都有一行代码,是什么? 11 36、GC 是什么? 为什么要有GC? 11 37、垃圾回收的优点和原理。并考虑2 种回收机制。 11 38...

Global site tag (gtag.js) - Google Analytics