黑马程序员技术交流社区

标题: 一个关于静态使用的疑问 [打印本页]

作者: 韩伟    时间: 2012-7-17 08:39
标题: 一个关于静态使用的疑问
本帖最后由 韩伟 于 2012-7-17 11:34 编辑

刚才敲代码的时候突然想到这样一个问题:
毕老师曾经这样总结静态
1、静态方法只能访问静态成员(方法、变量)。
           非静态方法可以访问静态成员吗?可以!!!即可以访问静态,也可以访问非静态。
2、静态方法中不可以定义this,super关键字。
            因为静态优先于对象存在,所以静态方法中不可以出现this。
3、主函数是静态的。

那我我想问的就是:
静态方法不允许调用非静态的属性和方法,只能调用静态的属性和方法。但是主函数也是静态啊,那么主函数(static方法)调用非静态方法的原理是什么呀?难道就是因为它是主函数所以有特权!
另外在主函数(static方法)中我们经常创建某个类的实例,再利用其引用变量调用它的非静态方法?是不是说明在主函数中可以通过某种方法实现调用非静态方法?具体是什么原理?

作者: 樊佰轩    时间: 2012-7-17 08:44
从我们之前写的程序中,我们找不出一个是主函数调用非静态方法的例子,在主函数类中,往往定义和主函数并列的静态函数并在主函数中调用,而其他函数的使用都是通过创建其他类的对象,然后通过该对象调用该类的方法。(这里可能你是误解的调用了非静态函数)
作者: 夏儒日    时间: 2012-7-17 08:58
      静态虽好但只能访问静态,主函数也没有例外。虽然在定义主函数的时候我们调用了非静态的成员,但是你忽略了一点:在你调用非静态的成员之前是不是要先创建一个对象呀?你如果不创建对象是不能访问静态的成员的! 既然你都创建了对象那么不论是静态还是非静态都能调用了!
      主函数也是不能直接调用非静态方法的,可以分两种情况说明:
(1)当该非静态方法与主函数在一个类中,示例代码如下:
class StaticDemo
    {
        public void run()
       {
             System.out.println("run");
        }
    public static void main(String[] args)
   {
     //调用run方法的方式
  }
}
对于这种情况,如果想调用非静态的run方法,只能是创建本类的对象,StaticDemo sd = new StaticDemo();然后对象调用sd.run();如果run方法是静态的,那直接调用run()。
(2)该静态方法与主函数不在同一类中,示例代码如下

class Static
{
     public void run()
    {
        System.out.println("run");
     }
}
class StaticDemo
{
     public static void main(String[] args)
    {
       //调用run()方法的方式
   }
}
        如果在主函数中调用非静态run方法,也是只能创建所属类的对象,Static s = new Static();然后对象调用s.run();这都和上面是一样的。
如果如果run方法是静态的,那直接类名调用Static.run()(思想与上面是一样的)。所以可以看出主函数也是不能直接调用非静态的方法的。
作者: 刘真    时间: 2012-7-17 10:24
夏儒日 发表于 2012-7-17 08:58
静态虽好但只能访问静态,主函数也没有例外。虽然在定义主函数的时候我们调用了非静态的成员,但是你 ...

学习了,只知道要创建对象来调用属性或方法,还从来没思考过这个问题,恍然大悟!
作者: 陈冲    时间: 2012-7-17 10:36
主函数并不是直接调用静态方法,而是通过实例化对象之后,通过对象来调用方法;
这样就不存在静态函数调用非静态方法了
作者: 王宝康    时间: 2012-7-17 10:47
夏儒日 发表于 2012-7-17 08:58
静态虽好但只能访问静态,主函数也没有例外。虽然在定义主函数的时候我们调用了非静态的成员,但是你 ...

学习了,逛论坛的意义就在于此,能发现自己的好多疑问,以及比自己对某一问题更深入,更全面的认识。
作者: 王宝康    时间: 2012-7-17 11:18
咱也来一段,作为程序入口的main()方法,把main()方法定义为静态方法,这样java虚拟机只要加载来main()方法所属的类,就能执行main()方法,而无需先创建这个类的实例,在main()静态方法中不能访问实例变量和实例方法。
  1. package demo;

  2. public class Sample {
  3.        
  4.         /**
  5.          * @param args
  6.          */
  7.         int x ;
  8.         void method(){};
  9.         public static void main(String[] args) {
  10.                 // TODO Auto-generated method stub
  11.                 x = 9;//实例变量x不是静态的,不能直接使用,这样会没有所属的,出现编译错误
  12.                 this.x = 9;//main方法为静态方法,不会不能出现this关键字,编译错误
  13.                 method();//实例方法method()非静态,不能直接调用,出现编译错误
  14.                 this.method();//编译错误
  15.         }
  16. }
复制代码
正确的做法是:通过Sample实例的引用来访问实例方法和实例变量
  1. public class Sample {
  2.                
  3.                 /**
  4.                  * @param args
  5.                  */
  6.                 int x ;
  7.                 void method(){};
  8.                 public static void main(String[] args) {
  9.                         Sample s = new Sample();
  10.                         s.x = 9;//合法,因为不是静态的,所以就应该有个所属,即实例s的变量
  11.                         s.method();//合法,原因同上
  12.                         }
  13. }
复制代码

作者: 周坤    时间: 2012-7-17 11:19
static是一个修饰符,只用于修饰成员方法和成员变量。它的出现就是为了共享那需要共享的数据,那么当然,静态方法中的属性同样需要是静态的。
在加载类时,静态和非静态方法都会被加载,不执行。只要记住,静态方法存放在内存的方法区的静态区,它是属于类的,而非静态方法存放方法区的非静态区,它是属于对象的。没有对象,是无法调用非静态方法的。





作者: 党巾水    时间: 2012-7-17 11:53
主函数调用静态方法时直接调用,调用非静态方法时先创建对象,这也是面向对象思想的体现。对象一般是通过一个类去创建,类的加载有类加载器解决。类加载的终极母亲不是java写的,而是用系统环境语言写的。所以主函数中可以创建对象,然后再用对象去调用其拥有的非静态方法。





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