为什么静态函数不能使用实例字段以及实例函数

阅读本文可以获得以下知识点:

1.      This 指针的用途

2.      实例对象是如何调用实例构造函数以及实例方法的.

3.       CLR如何调用一个类的静态方法

4.      抽象类到底能不能有构造函数,为什么抽象类不能有public构造函数。

 

1.    CLR是如何调用实例构造函数以及实例方法的

 

一个类中可以定义实例字段,方法,也可以定义静态字段和方法,他们的布局如下:

        

        

         当我们使用new操作符创建一个对象时,会在堆中为这个对象分配内存,那么这个实例对象中都有什么呢

         当 CLR实例化一个对象时,首先会初始化一个指向类型对象的指针,然后为所有实例字段初始化为相应的默认值,这个默认值一般是清零,清零只需底层cpu的一个指令就可以了,他的速度是非常快的.然后java虚拟机会调用这个对象的构造函数,将实例字段初始化为正确的值.

现在的问题是,CLR如何为这个对象调用构造函数,因为从上图中可以明显的看出,对象与构造函数在两个不同的地方,对象在堆中,构造函数类型对象中;

事实上,实例构造函数与其他实例方法没有什么区别,从本质来说他们都是方法。因此如果理解了对象是怎么调用构造函数的,也就理解了构造函数是怎么调用实例方法的。

上面说过,对象与方法在两个不同的地方,两者之间肯定有一个桥梁,从而可以通过对象去找到他的方法。这个桥梁就是上面的类型对象指针。

在CLR中,每一个在堆上创建的对象都有一个类型对象指针,CLR负责初始化这个指针,将这个指针指向方法区的类型对象。CLR通过这个类型对象指针,就可以找到这个对象对应的方法。

 

现在讨论一个完整的过程,请看如下代码:

    publicstaticvoid main(String[] args) {

        Point p1=new Point(3,3);

}

 

class Point{

    publicintx;

    publicinty;

    public Point(int x,int y){

        this.x=x;

        this.y=y;

    }

}

 


1.           CLR在堆上分配一块内存,然后初始化类型对象指针,使其指向方法区的Point类型对象。

2.             将Point对象所有实例字段清零。

3.             CLR通过类型对象指针找到方法区的Point类型对象,然后遍历找到public Point(int x,int y)构造函数。

4.            CLR开始调用这个构造函数。Java虚拟机会为这个实例构造函数隐式的传递一个this指针,这个this指针就是p1对象的地址。通过这个this指针,构造函数就可以访问p1对象的x和y了。如下:

 

 

现在我们总结一下,java虚拟机是如何将实例对象与方法区的类型对象联系起来的,这里有两个关键的地方起到了链接作用,一个是类型对象指针,另一个是this指针。

CLR通过类型对象指针找到属于这个对象的方法,通过this指针,实例方法就可以访问实例对象的字段了。

 

2.   CLR是如何调用静态方法的

现在稍加思考就可以明白,为什么静态函数不能使用实例字段,不能调用实例方法。现在也能够明白如下代码为什么不能通过编译了!

classPoint{

    publicintx;

    publicinty;

    public Point(int x,int y){

        this.x=x;

        this.y=y;

    }

 

    publicvoid draw(){

       

    }

   

    publicstaticvoid PP(){

        x=4;

    }

 


当调用一个静态方法时,不会向这个方法传递this指针,因此,这个静态方法就不能访问实例对象的实例字段了。再强调一点,一个方法要想访问对象的实例字段,必须通过this指针。

由于静态方法不能够实用实例字段,因此也就不能够调用实例,因为实例方法可能实用实例字段。

 

3.抽象类的构造方法

现在,再来讨论抽象类可不可以有构造函数,以及为什么抽象类不能有public构造函数。

抽象类中可能会定义实例字段,这些实例字段在使用前必须先被初始化。而初始化实例字段就要用到实例构造函数,因此抽象类可以有实例构造函数,也必须有。

还有,在继承体系中,在创建一个派生类型对象之前,必须先调用基类的构造函数来初始化从基类继承的成员。

 

因为抽象类不能被实例化,也就是不能new 一个抽象类。为了防止用户不小心写出如下的代码 ,CLR规定抽象类不能有public类型的构造函数,从而上述代码在编译期间就可以发现错误。

因此,我们可以知道,抽象类不能有pubic构造函数,这不是硬性规定。但是一般语言中,为了防止用户不小心new 一个抽象类,都会规定抽象类不能定义public构造函数。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值