黑马程序员技术交流社区

标题: 关于静态方法调用的一个问题、 [打印本页]

作者: 涂金哲    时间: 2012-6-20 10:24
标题: 关于静态方法调用的一个问题、
本帖最后由 涂金哲 于 2012-7-4 09:33 编辑

当static关键字修饰方法,这个方法属于类,成为静态方法。静态方法可以使用对象来调用或者类调用。静态方法是随着类加载到内存中的,即静态方法可以独立到对象之外。在用对象调用静态方法时有个小问题不明白请大家帮帮忙哈,程序很简单,有个疑惑…
public class StaticTest {
  private static void method()  {
  System.out.println("静态方法");  
}
public void show()  {  
System.out.println("普通方法");
  }
public static void main(String[] args)  {  
StaticTest staticT=null;
  staticT.method();   
//staticT.show();//此处会发生空指针异常
}
} 运行结果看来,当我们用staticT=null,来调用普通方法时,会发生空指针异常,因为空表示引用变量指向的实例不存在,所以就谈不上调用实例的方法。但是,staticT=null却可以调用静态的方法,请问这个时候我们是说类在调用方法呢?还是staticT实例在调用呢???
作者: 唐辉辉    时间: 2012-6-20 10:32
StaticTest staticT=null;

staticT  是StaticTest的引用,引用就相当这个类。就像给一个人取一个绰号一样。 所以这里是相当于是类调用的。并不是实例,因为不存在实例。
作者: 车风波    时间: 2012-6-20 10:36
堆存储的是每个类非静态变量(类的实例成员属性)的值,和一个指向生成该对象的类的指针,所以staticT 应该是找他的类,然后类去调用静态方法吧。
作者: 孙峰    时间: 2012-6-20 10:39
     这里你建了一个 空对象,只有引用,没有实例的class,声明后在栈里会有一个指针,但指向地址为空,没有分配堆内存。所以不能调用非静态方法,因为该非静态方法就没加载的内存中。  但是静态方法已经随着编译加载进去。 我认为这里应该还是 类 在调用静态方法。
作者: 石琪    时间: 2012-6-20 10:50
1,当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,还可以直接被类名调用。格式:类名.静态成员,
2,修饰后占用方法区(数据区,共享区),不占栈堆内存。
你声明了一个指向空的对象,没有实例,所以不能调用非静态方法。
没有实例化不占内存,静态修饰后占用方法区(参见第二条),所以指向空的对象可以调用非静态方法。
作者: 胡大强    时间: 2012-6-20 11:03
本帖最后由 胡大强 于 2012-6-20 12:48 编辑

static:是一个修饰符,用于修饰成员(成员变量、成员函数),当成员被静态修饰后,多了一种调用方式,除了被对象调用外,还可以直接被类名调用:类名.静态成员
静态实用注意事项:
       静态方法只能访问静态成员
       非静态方法可以访问静态也可以访问非静态
      静态方法中不可以定义this,super关键字,因为静态优先于对象存在,所以静态方法不可以出现this。
什么时候使用静态?
   当对象中出现共享数据时,该数据被静态所修饰。对象中特有数     据要定义成非静态存在于堆内存中。
什么时候定义静态函数?
  当功能内部没有访问到非静态数据(对象的特有数据)那么该功能可以定义成静态的;

所以应该是类在调用。。。
作者: 李伟    时间: 2012-6-20 11:14
StaticTest staticT=null//相当于给类取了个名字并没有创建出对象,所以应该是类在调用静态函数
作者: 胡卿    时间: 2012-6-20 11:14
主函数是静态的,只能调用静态方法,即使你不写StaticT=null,这样写
  1. class StaticTest {
  2. private static void method()  {
  3.   System.out.println("静态方法");  
  4. }
  5. public void show()  {  
  6. System.out.println("普通方法");
  7. }
  8. public static void main(String[] args)  {  
  9. //StaticTest staticT=null;
  10. // staticT.method();
  11.   method();
  12. // staticT.show();
  13. }}
复制代码
还是可以调用静态方法,所以调用静态方法可以在创立对象之前调用,不一定非要创建对象,它随着编译就已经加载

而主函数创立了空对象,引用函数时当然会引发空指针异常啦

作者: 涂金哲    时间: 2012-6-20 11:41
staticT 明明可以调用method 方法,您没理解我的问题……
作者: 涂金哲    时间: 2012-6-20 11:43
胡卿 发表于 2012-6-20 11:14
主函数是静态的,只能调用静态方法,即使你不写StaticT=null,这样写还是可以调用静态方法,所以调用静态方 ...

StaticT完全可以调用,您没有理解我的问题
作者: 涂金哲    时间: 2012-6-20 11:45
唐辉辉 发表于 2012-6-20 10:32
StaticTest staticT=null;

staticT  是StaticTest的引用,引用就相当这个类。就像给一个人取一个绰号一样 ...

那staticT.method ()可以打印结果,如何解释?
作者: 贾飞雨    时间: 2012-6-20 11:47
我觉的这是一个对象调用,当你StaticTest staticT=null;
的时候,虽然建立了一类型为StaticTest 名为static的对象,指向为空,所以它的方法是不能被调用的,因为对象名有了,但是他没有被建立,普通方法也就没有被建立,当然不能被调用,但是静态方法却不同,静态方法是随着类的加载而加载,虽然对象名指向为空,但是静态方法已经有了,所以可以被调用,
不知道对不对  ,希望指教
作者: 涂金哲    时间: 2012-6-20 11:48
车风波 发表于 2012-6-20 10:36
堆存储的是每个类非静态变量(类的实例成员属性)的值,和一个指向生成该对象的类的指针,所以staticT 应该 ...

这种说法有点像……这种解释您是自己想的还是有资料可以证明?
作者: 闾丘日月    时间: 2012-6-20 11:50
内存中静态方法都已经加载了,当然可以调用。。
我觉得楼上的回答都挺不错的,楼主不妨把自己的疑问说清楚,为什么别人没理解你的问题?
作者: 车风波    时间: 2012-6-20 12:11
涂金哲 发表于 2012-6-20 11:48
这种说法有点像……这种解释您是自己想的还是有资料可以证明?

以前在网上看到过,有一个指向生成该对象的类的指针
作者: 涂金哲    时间: 2012-6-20 13:17
yufeiant 发表于 2012-6-20 11:47
我觉的这是一个对象调用,当你StaticTest staticT=null;
的时候,虽然建立了一类型为StaticTest 名为stati ...

形式上看是对象调用……结果,不清楚,或许静态方法的类调用和对象调用之间有特殊的关系吧,期待有人指点
作者: 涂金哲    时间: 2012-6-20 13:27
闾丘日月 发表于 2012-6-20 11:50
内存中静态方法都已经加载了,当然可以调用。。
我觉得楼上的回答都挺不错的,楼主不妨把自己的疑问说清楚 ...

可能我的语言表达能力不好,我的问题是:null 对象访问普通方法会发生异常,而访问静态方法却没问题,。staticT .method 写成这种方式是类在调用方法?还是对象在调用方法?
作者: 闾丘日月    时间: 2012-6-20 13:45
涂金哲 发表于 2012-6-20 13:27
可能我的语言表达能力不好,我的问题是:null 对象访问普通方法会发生异常,而访问静态方法却没问题,。stat ...

我的理解是,虚拟机或者说cpu能够正确找到那个方法,那么它就可以调用这个方法,静态方法随着类的加载而被加载,虚拟机只需要根据类名就知道静态方法在哪里从而可以正确调用,即使你用对象来调用静态方法,它还是会先找到对象属于哪个类,然后通过类来调用。
作者: 游洪波    时间: 2012-6-20 18:56
StaticTest staticT=null;
只是创建了这个对象,但是你并没有实例化这个对象,那么这个对象的普通方法你是用不到的,这个可以理解吧,而static修饰的方法是可以用类名直接调用的。
虽然 staticT并没有被实例化,但是他却是 StaticTest类的引用,用 staticT调用static的方法就相当于 StaticTest 调用static方法 可以理解吧!
作者: 游洪波    时间: 2012-6-20 18:56
StaticTest staticT=null;
只是创建了这个对象,但是你并没有实例化这个对象,那么这个对象的普通方法你是用不到的,这个可以理解吧,而static修饰的方法是可以用类名直接调用的。
虽然 staticT并没有被实例化,但是他却是 StaticTest类的引用,用 staticT调用static的方法就相当于 StaticTest 调用static方法 可以理解吧!
作者: rslheima    时间: 2012-6-20 19:54
本帖最后由 rslheima 于 2012-6-20 20:27 编辑

以下为个人总结及个人理解如有错误请更正!

首先了解程序使用对象的过程:

程序使用对象通常包括以下四步:
例子:

一、声明对象
StaticTest staticT ;
确定对象的 名称 ,并指明该对象所属的类
二、创建对象
staticT= new   StaticTest();
通过 new 关键字,为对象分配内存,使对象成为类的实例。
三、使用对象
staticT.show()   

创建后这个对象就拥有了自己的数据成员 成员函数 ,便可以使用。
四、  撤销  



其次 了解  static方法  :
static方法是属于 整个类 的,他在内存中的 代码段 将随着类的定义而分配和装载  。


第三
static的方法是属于某个对象的方法,当这个对象创建(new时)时,在对象的内存中就拥有这个方法的专用代码段。

再看:由于StaticTest staticT=null;只是确定对象的名字而已,并没有为该对象分配内存,所以该对象就没有自己的]数据成员成员函数(也就是没有得到show() ),所以不能调用。
综合看来,并不是类在调用,而是对象在调用。
作者: 孙飞    时间: 2012-6-20 20:21
因为方法method是静态方法,静态方法调用的时候可以不创建类对象,直接StaticTest.method()调用就可以。然而show()是普通的方法,需要创建类对象,此时 StaticTest staticT = null;是空对象,肯定是报空指针异常。

作者: 严明    时间: 2012-6-25 12:09
rslheima 发表于 2012-6-20 19:54
以下为个人总结及个人理解如有错误请更正!
首先了解程序使用对象的过程:

"二、创建对象     staticT= new   StaticTest();                通过 new 关键字,为对象分配内存,使对象成为类的实例。"

在第二步中,并没有创建对象,只声明了对象, 对象没有创建成功,应该是类在调用吧.
作者: 李东升    时间: 2012-6-25 13:39
空指针出现的原因应该是,你上面只有staticTest staticT=null,只有地址,没有内存,肯定会空的。加个new的话应该就好了。

作者: 邵阳    时间: 2012-6-25 17:02
rslheima 发表于 2012-6-20 19:54
以下为个人总结及个人理解如有错误请更正!
首先了解程序使用对象的过程:

综合看来,并不是类在调用,而是对象在调用。        你写错了吧
因该是类调用,而不是对象调用吧




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2