静态方法和静态属性

不全都是动态

我们都知道,方法是放在实例里运行的。也就是说方法执行的结果是依据实例属性而来的,而实例的属性是根据当前状态而变化的——我们称其为“动态”。

但真的全都是动态的吗?其实不是,有些方法它会直接根据你的调用而给出结果,并不需要依据实例属性的变化来产生变动——也就是说它是无论如何都会产生确定的结果的,我们称这样的方法为静态方法,它是静态的。

我们来举个栗子看看:

这是一个普通的类和方法,我们创建不同的 Gun 实例,那么 fire() 方法的执行结果也会不同,有的子弹打完了,有的则没有打完。

现在我在这个类里边插入了一个判断两个数字大小的方法,这个方法无论实例在什么状态,它都会返回确定的结果——哪个数字大就返回哪个,和实例的状态——打了多少枪没有关系,我们就说这个方法可以设置为静态方法(用 static 前缀标记出来)。如你所见,静态方法的调用不需要实例,直接使用点运算符来调用。

“一种不依靠实例变量也就不需要对象的行为。”

类型方法

我们使用 static 这个前缀来标记静态方法,由于我们调用静态方法并不是从特定的实例中调用,而是直接从类里调用,我们也说这个方法是在“类”层面执行,所以静态方法也就会被叫做“类型方法”。

同样的原因,也会导致类型方法不针对特定的实例,所以它不能访问到实例属性——类型方法不能访问动态属性。它根本不在堆上,自然找不到堆上的某个实例里的某个属性了!

所以再一次同样的原因,类型方法也是不能调用动态方法的——动态方法在堆上,在实例里边啊!

类型属性

我们说了类型方法不能访问动态的属性,那自然就会有静态的属性出现啦!当然,动态的方法也可以访问静态的属性的——考虑到静态又是类层面的,所以它也会被称作“类型属性”。

同样的原因,对同类的所有对象共享!

没错!同类下的对象互相通信就靠它呢!我们来举个栗子看看:

我们增加了一个监控所有枪发射的子弹数量,一共用三个实例开了五枪,但 total 都记录了下来——也就是说类型属性对同类的实例来说是全局的,它不属于某个对象,而是属于这个类下所遇对象的!

实例属性——每个实例一个;

类型属性——每个类一个!

静态和继承

如果你细心,可能会发现类型属性和类型方法不能够被覆盖!如果你覆盖一个类型方法,则会被提示:你正在覆盖一个标记未 final 的方法!

所以,如果需要能够被覆盖,你需要使用 class 前缀而不是 static 来标记类型方法,这样它就允许被子类覆盖掉了。

anyShare分享到:

发表评论

电子邮件地址不会被公开。 必填项已用*标注