都知道声明为static的方法可以在类没有被实例化的时候调用
但是php有个很有趣的现象,静态调用非静态方法:
<?php
class A {
public function test(){
echo "hello";
}
}
A::test();
?>
php可以对没有声明static的方法实现静态调用。
然后看到了有人说没有加static的方法采用静态调用时会更慢,效率更低
我测试了一下:
<?php
class A {
public function test(){
$start = microtime(true);//加true会返回浮点数
$i = 100000000;
while($i--){}
$end = microtime(true);
echo "耗时:".round($end-$start,3)."秒";//保留三位
}
public static function staticTest(){
$start = microtime(true);
$i = 100000000;
while($i--){}
$end = microtime(true);
echo "耗时:".round($end-$start,3)."秒";
}
}
A::test();//耗时:1.839秒
A::staticTest();//耗时:1.818秒
?>
以上数据大概做了20组,每个结果都是带static修饰的方法更快一点。
所以当我们要使用静态调用的时候,应为所调用方法增加static修饰。
但是以上的静态调用非静态方法的方式还有局限,并不是所有的方法都可以,须是该方法原本就是一个静态方法。
再谈谈静态
带static修饰的数据在类第一次被加载时就分配到内存中,
而非static修饰的变量是在类实例化后才存在的。
(详细解释:静态变量属于静态存储方式,其存储空间为内存中的静态数据区(在静态存储区内分配存储单元),该 区域中的数据在整个程序的运行期间一直占用这些存储空间(在程序整个运行期间都不释放),也可以认为是其内存地址不变,直到整个程序运行结束)
因此,静态方法里不能访问非静态的成员变量。在一个类的静态成员中去访问其非静态成员之所以会出错是因为在类的非静态成员不存在的时候类的静态成员就已经存在了,访问一个内存中不存在的东西当然会出错。
静态的成员变量要用类名去访问(也可用self,在类里表示本类),不用对象访问($this).
另外,构造方法不能声明为静态,即不能静态调用构造方法(注:php5以前,构造方法是方法名与类名相同的函数,现在基本都是使用__construct()).
php类内方法内访问其他方法都是用$this进行调用,但是因为伪变量$this在静态方法中不可用,所以静态方法中不能调用非静态方法?
不是说不能调用,应该说静态方法中不能直接调用非静态方法
php有两种方法可以实现间接调用
第一种方法就是利用静态调用非静态方法的方式:
<?php
class demo{
public function nonStaticMethod(){
echo "this is a non-static method";
}
public static function staticMethod(){
self::nonStaticMethod();
}
}
demo::staticMethod();//result:this is a non-static method
?>
虽然这种方法能调用成功,但是追究下去,你会发现nonStaticMethod()其实是一个没有带static修饰的静态方法。
验证方法:使nonStaticMethod()的本质不能是一个静态方法就可以了
class demo{
private $var = "this is a non-static method";
public function nonStaticMethod(){
echo $this->var;
}
public static function staticMethod(){
self::nonStaticMethod();
}
}
demo::staticMethod();
运行结果:
Fatal error: Using $this when not in object context
.
第二种方法就是间接将一个对象的引用传入static方法中:
class demo{
private $var = "this is a non-static method";
public function nonStaticMethod(){
echo $this->var;
}
public static function staticMethod($demobj){
$demobj->nonStaticMethod();
}
}
demo::staticMethod(new demo());//result:this is a non-static method
这种方法虽然消除了静态调用非静态方法的局限,但是本质上还是实例化了一个对象去调用非静态方法。
参考资料: