一直依赖对于php中static关键字比较模糊,只是在单例模式中用过几次。上网查了查,没有找到很全的介绍,自己总结一下。

根据使用位置分为两部分 1、函数体中的静态变量 2、类中的静态属性和方法

1 函数体中的静态变量

static $a = ;
function num1(){
static $a = ;
return $a++;
} function num2(){
$a = ;
global $a;
echo $a++;
} function num3(){
static $a = ;
return $a++;
} echo num1();    //0 num2();       //1
echo $a;       //2 echo num3();    //100
echo num3();    //101
echo num3();    //102

从中我们看出几点

1 函数体中的静态变量与全局中的静态变量不冲突,只有在关键字global作用下才会使局部与全局统一

2 函数体中的静态变量在函数调用的时候只会被初始化一次

因为静态变量在全局数据区分配内存;此处要提一下 缓存在逻辑上大致区分为 栈 堆 全局区  程序代码区 文字常量区

栈 存放变量名(会有一部分的整型,浮点型,字符串存放在此处)

堆 存放变量值

全局区 存放静态变量,全局变量

程序代码区 存放要执行的函数及方法

文字常量区 存放常量等

大致是上面的样子,相当相当不严格,但是可以很好的帮助我们记忆数据间的关系。

2 类中的静态成员

类中的静态成员包含静态属性和静态方法

class first{    public $num = 1;

//声明一个静态属性
static $name = '456';
//声明一个静态方法
public static function self_use(){
     echo self::$name;
echo self::out();
}
public static function static_use(){
echo static::out();
}
public static function method(){
echo 'first';
} //这是一个错误的调用
public function my_wrong(){
//echo self::dis();
}
public function dis(){
echo '只是做一个展示';
} }
class second extends first
{
public static function method(){
echo 'second';
}
} $one = new first();
$one::$name;
$one->self_use();
$one->static_use();


$two = new second();
$two->self_use();
$two->static_use();

关于类中的静态方法我们从两个角度介绍 1 使用角度 2 理论角度

1 在实际使用中我们需要注意几点

a. 静态方法可以调用静态属性,禁止调用非静态属性。

b. 静态方法内不允许出现$this,出现就停掉脚本。

c. 在静态方法中调用类中其他静态方法有两种格式 self:: 和 static 。根据输出结果我们了解到两种方式的区别是 使用 self::method() 调用本方法所在类的 method() 方法。使用static::method(),会调用整个继承家族最后定义的方法。

这个感觉很绕绕啊,形象点理解就是在父类中声明一个静态方法A,子类中重写了这个静态方法A。在父类其他方法中使用self调用A,会执行父类中A的方法;但是使用static调用,就会执行子类A的方法;

2 从理论角度介绍

早期的结构化编程几乎都是静态方法,出现面向对象之后,才有了实例化方法的感念。而面向对象并不能完全解决掉静态方法使用的问题。我们可以这样理解,静态方法和实例化方法虽然都是类的,但是二者的调用方式是不同的,静态方法和属性在类在使用class::就会被存进内存,然后使用。但是实例化方法和非静态属性,需要实例化 new之后才会被存进内存使用。这就解释了a 中静态方法不能调用非静态属性,你静态方法喊一嗓子就出来了,我非静态属性不行啊,没批准(new)我出不来啊;而b中的$this是面向对象出来之后的产物专门用于实例化对象时候调用对象中的属性和方法用的,是对象的专属技能,这个技能静态方法不能使用。

总结此处为看了之后总结的,我木有那么高水平:

大家对这个问题都有一个共识:那就是实例化方法更多被使用和稳妥,静态方法少使用。有时候我们对静态方法和实例化方法会有一些误解。

1、大家都以为“ 静态方法常驻内存,实例方法不是,所以静态方法效率高但占内存。

事实上,他们都是一样的,在加载时机和占用内存上,静态方法和实例方法是一样的,在类型第一次被使用时加载。调用的速度基本上没有差别。

2、大家都以为“ 静态方法在堆上分配内存,实例方法在堆栈上

事实上所有的方法都不可能在堆或者堆栈上分配内存,方法作为代码是被加载到特殊的代码内存区域,这个内存区域是不可写的。

方法占不占用更多内存,和它是不是static没什么关系。   
  因为字段是用来存储每个实例对象的信息的,所以字段会占有内存,并且因为每个实例对象的状态都不一致(至少不能认为它们是一致的),所以每个实例对象的所有字段都会在内存中有一分拷贝,也因为这样你才能用它们来区分你现在操作的是哪个对象。   
  但方法不一样,不论有多少个实例对象,它的方法的代码都是一样的,所以只要有一份代码就够了。因此无论是static还是non-static的方法,都只存在一份代码,也就是只占用一份内存空间。   
  同样的代码,为什么运行起来表现却不一样?这就依赖于方法所用的数据了。主要有两种数据来源,一种就是通过方法的参数传进来,另一种就是使用class的成员变量的值……

3、大家都以为“实例方法需要先创建实例才可以调用,比较麻烦,静态方法不用,比较简单

事实上如果一个方法与他所在类的实例对象无关,那么它就应该是静态的,而不应该把它写成实例方法。所以所有的实例方法都与实例有关,既然与实例有关,那么创建实例就是必然的步骤,没有麻烦简单一说。

当然你完全可以把所有的实例方法都写成静态的,将实例作为参数传入即可,一般情况下可能不会出什么问题。

从面向对象的角度上来说,在抉择使用实例化方法或静态方法时,应该根据是否该方法和实例化对象具有逻辑上的相关性,如果是就应该使用实例化对象  反之使用静态方法。这只是从面向对象角度上来说的。

如果从线程安全、性能、兼容性上来看  也是选用实例化方法为宜。

我们为什么要把方法区分为:静态方法和实例化方法 ?

如果我们继续深入研究的话,就要脱离技术谈理论了。早期的结构化编程,几乎所有的方法都是“静态方法”,引入实例化方法概念是面向对象概念出现以后的事情了,区分静态方法和实例化方法不能单单从性能上去理解,创建c++,java,c#这样面向对象语言的大师引入实例化方法一定不是要解决什么性能、内存的问题,而是为了让开发更加模式化、面向对象化。这样说的话,静态方法和实例化方式的区分是为了解决模式的问题。

拿别人一个例子说事:

比如说“人”这个类,每个人都有姓名、年龄、性别、身高等,这些属性就应该是非静态的,因为每个人都的这些属性都不相同;但人在生物学上属于哪个门哪个纲哪个目等,这个属性是属于整个人类,所以就应该是静态的——它不依赖与某个特定的人,不会有某个人是“脊椎动物门哺乳动物纲灵长目”而某个人却是“偶蹄目”的。

参考文献:

PHP中静态方法和实例化方法的区别

static关键字及变量存储位置总结 

php中static 静态关键字的更多相关文章

  1. Java中static静态关键字的使用

    我们可以基于一个类创建多个对象,每个对象都拥有自己的成员,所有成员变量的值是根据对象而存在的,有些时候我们希望一个类的所有对象共享一个成员,这就用到了static静态关键字 被静态关键字修饰的成员属于 ...

  2. php中static静态关键字的使用

    php中除了常规类和方法的使用,访问控制之外,还有静态关键字static,静态变量可以是局部变量也可以是全局变量,当一个程序段执行完毕时,静态变量并没有消失,它依然存在于内存中,下次在定义时还是以前的 ...

  3. php中static静态关键字的使用方法和应用场景

    php中除了常规类和方法的使用,访问控制之外,还有静态关键字static,静态变量可以是局部变量也可以是全局变量,当一个程序段执行完毕时,静态变量并没有消失,它依然存在于内存中,下次在定义时还是以前的 ...

  4. php笔记(二)PHP类和对象之Static静态关键字

      PHP类和对象之Static静态关键字 静态属性与方法可以在不实例化类的情况下调用,直接使用类名::方法名的方式进行调用.静态属性不允许对象使用->操作符调用. class Car { pr ...

  5. php面向对象中static静态属性和静态方法的调用

    这篇文章主要介绍了php面向对象中static静态属性和静态方法的调用,实例分析了static静态属性和静态方法的原理与调用技巧,需要的朋友可以参考下 本文实例讲述了php中static静态属性和静态 ...

  6. C#中static静态变量的用法

    使用 static 修饰符声明属于类型本身而不是属于特定对象的静态成员static修饰符可用于类.字段.方法.属性.运算符.事件和构造函数,但不能用于索引器.析构函数或类以外的类型 静态全局变量 定义 ...

  7. 关于C#中static静态变量

    C#静态变量使用static 修饰符进行声明,在类被实例化时创建,通过类进行访问不带有 static 修饰符声明的变量称做非静态变量,在对象被实例化时创建,通过对象进行访问一个类的所有实例的同一C#静 ...

  8. Java static静态关键字 有啥用

    #static有啥用 在Java语言中,static表示“静态”的意思,使用场景可以用来修饰成员变量和成员方法,当然也可以是静态代码块.static的主要作用在于创建独立于具体对象的域变量或者方法. ...

  9. Java之static静态关键字详解|final关键字详解

    前言 在Java语言中,static表示"静态"的意思,使用场景可以用来修饰成员变量和成员方法,当然也可以是静态代码块.static的主要作用在于创建独立于具体对象的域变量或者方法 ...

随机推荐

  1. 开源项目 log4android 使用方式详解

    话不多说, 直接上主题. log4android 是一个类似于log4j的开源android 日志记录项目. 项目基于 microlog 改编而来, 新加入了对文件输出的各种定义方式. 项目地址: 点 ...

  2. 安卓自定义控件(三)实现自定义View

    前面两篇博客,把View绘制的方法说了一下,但是,我们只在onDraw里面做文章,控件都是直接传入一个Context,还不能在布局文件里使用自定义View.这一篇博客,就不再讲绘制,在我们原先的基础上 ...

  3. NullSafe基于Runtime的深度解析

    Objective-C是一门动态语言,一个函数是由一个selector(SEL),和一个implement(IML)组成的. 执行一个方法时如果系统找不到方法会给几次机会寻找方法,实在没有此方法就会抛 ...

  4. 2017计算机学科夏令营上机考试-A判决素数个数

    A:判决素数个数 总时间限制:  1000ms 内存限制:  65536kB 描述 输入两个整数X和Y,输出两者之间的素数个数(包括X和Y). 输入 两个整数X和Y(1 <= X,Y <= ...

  5. Uncaught TypeError: download is not a function at HTMLAnchorElement.onclick (index.html:25)

    前段时间调试html报了这样的一个错误 Uncaught TypeError: download is not a function     at HTMLAnchorElement.onclick ...

  6. win10解决乱码问题

    Unicode是Unicode.org制定的编码标准,目前得到了绝大部分操作系统和编程语言的支持.Unicode.org官方对Unicode的定义是:Unicode provides a unique ...

  7. CS Round#53 E Maxor

    题意:给你N个数,你可以从中选出两个数将它们or起来得到M,求M的最大值及得到最大值的方案数. 刚了半个小时得到了一个貌似时O(N log max(Ai)^2)的方法,想了想发现貌似只能做出第一问,但 ...

  8. 集训 D1T1 clique

    将点(xi,wi)看成区间(xi-wi,xi+wi),那么两个点有连边当且仅当两个区间没有公共点.删去所有包含其它区间的区间,在剩下的区间中每次贪心取一个能取的坐标最小的区间. #include< ...

  9. Python+Selenium webdriver Api

    # -*- coding: utf-8 -*- from selenium import webdriver browser = webdriver.Firefox() #browser.set_wi ...

  10. Python爬虫(九)_非结构化数据与结构化数据

    爬虫的一个重要步骤就是页面解析与数据提取.更多内容请参考:Python学习指南 页面解析与数据提取 实际上爬虫一共就四个主要步骤: 定(要知道你准备在哪个范围或者网站去搜索) 爬(将所有的网站的内容全 ...