上完Java课,虽然也写了不少的Java代码,但是一直有不少的疑惑,而static关键字一直困惑着我很久,今天无意探究竟,上知乎再仔细查了一下,发现了这个话题的优秀答案https://www.zhihu.com/question/36615154

  这篇文章彻底把我之前对static的理解概念土崩瓦解,看来我还是低估了设计语言大师的智慧,老以为非静态声明函数会造成实例化多个实例时会造成内存空间的浪费,实际上每个实例里面的函数方法在实例的内存区域中仅仅只有个引用而已,并且此引用指向了该函数方法的内存头地址。看完文章后再想想之前我写的代码,整个人都有点傻逼了,写出的所谓优化,反而是不符合面向对象编程的规范。

  但是后来我又思考了一下,在面向对象编程已经流行了20多年的今天,为何static关键字还有存在的意义呢?在一顿饭时间的思考之后,我发现静态函数在对象的功能扩展上有着很强大的功能,使用恰当的话,确实可以优化内存的占用。

  比方说,拿个游戏举个例子,假设我们对士兵的基本装备有定性的要求(在类中定义各种非静态属性),因此训练出来的士兵,都有各自的基本装备(对象的属性与方法),但是你总不可能在基本属性里写士兵带AT火箭筒,m240重机枪,m320步枪榴弹,便携无线电基站。。。如果真这样,训练出来的士兵要重死了(实例化对象占用内存大),结果在任务中就一个持刀歹徒,拿个手枪突突两下就解决了,那什么火箭筒完全是摆设,有点小题大作了。

  于是,在面向对象中有种比较好的解决方法,比如基础类就是防具+人组成的士兵,这时我可以用继承的方式分化成医疗兵带步枪,工程兵带冲锋枪+火箭筒,补给兵机枪+弹药袋,侦察兵狙击枪+望远镜。如此分配兵种,士兵装备也刚刚好不会过重,能充分利用好。但是这些士兵是需要训练的(实例化,new操作,要单独给一片内存空间),要资源的,一个任务需要1个人绝不用2个。这种情况,一个专门为装有静态方法的类就起到拓展的作用。

  虽然说静态方法在程序启动的时候就占用了内存了,而且static用多了也不是好习惯,容易导致内存溢出。但是按需求来重外部扩展静态方法,是一个不错的方法。比方说地面的步兵呼叫飞行员进行地面打击(消息传递,一个对象使用另一个的对象的方法,需要实例化的对象),但也可以呼叫总部,用远程导弹进行地面打击(调用公共类中的静态方法,不需要实例化对象,用公共类调用,但静态方法同样要占用内存,且要在程序结束后才能释放)。区别就在于,对于这个军事系统来说,外派的资源前者多了架飞机,如果用不到空中打击,还废油呢。。。

  因此对于一些经常使用的公共方法,且这些公共方法可以作为扩展的话,可以已静态方法的形式单独写在一个类中,当其他类需要使用的时候,单独封装一个方法调用公共类的静态方法,以便形成最小的扩展,节约内存资源。

  代码例子:

  在Map类中封装一个方法,实现面向对象编程的规范,此方法调用KruskalMap类中的静态方法KruskalAlgo,并把此Map实例传入此静态函数。如果不想用Kruskal算法了,还可以修改代码,换用Prime类的静态方法。注意,静态方法会常驻内存,只有jvm关闭后内存才会释放,因此只扩展经常需要调用的函数。

静态方法的执行效率比非静态更高,因为在堆中是地址是连续,而非静态是离散的,使用的函数才会申请内存。

  另一种是针对函数很少使用的情况,该类的函数是非静态的,利用实例,用完就释放方法的内存,相比直接面向对象的写法慢一些,因为涉及到new:

测试用例:

测试结果:

Java static关键字的重新思考的更多相关文章

  1. Java Static关键字详解

    提起static关键字,相信大家绝对不会陌生,但是,想要完全说明白,猛的一想,发现自己好像又说不太明白... ...比方说,昨天被一个同学问起的时候... ... 当然,不是所有人都像我一样学艺不精的 ...

  2. java static关键字

    方便在没有创建对象的情况下来进行调用(方法/变量). 很显然,被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了,就可以通过类名去进行访问. static可以用来修饰类的 ...

  3. Java static 关键字详解

    引言 在<Java编程思想>中有这样一段话:static方法就是没有this的方法.在static方法内部不能调用非静态方法,反过来是可以的.而且可以在没有创建任何对象的前提下,仅仅通过类 ...

  4. 【转载】java static 关键字的四种用法

    原文链接点这里,感谢博主分享 在java的关键字中,static和final是两个我们必须掌握的关键字.不同于其他关键字,他们都有多种用法,而且在一定环境下使用,可以提高程序的运行性能,优化程序的结构 ...

  5. [java]static关键字的四种用法

    在java的关键字中,static和final是两个我们必须掌握的关键字.不同于其他关键字,他们都有多种用法,而且在一定环境下使用,可以提高程序的运行性能,优化程序的结构.下面我们先来了解一下stat ...

  6. Java——static关键字

    前言 static关键字算是Java中比较复杂的关键字之一,它可以修饰变量.方法.类以及代码块.下面将介绍static的具体使用. static引入的目的 static的作用 static修饰变量 s ...

  7. Java——static关键字---18.09.27

    static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但在Java语言中没有全局变量的概念. static关键字主要有两种作用: 一.为某特定数据类 ...

  8. java static关键字和代码块

    static关键字 代码块 方法重写 1. 方法重写的特点: 2. 注意事项: static关键字 为什么需要学习static关键字? 针对某一个变量属于类而不属于某一个具体的对象的时候,我们可以考虑 ...

  9. java static关键字的使用

    static关键字    通常来说,创建类的时候,是用new创建此类的对象才可以获得,执行new创建对象时数据存储空间才被分配,其方法才被外界调用    有两种情况用new无法解决:        1 ...

随机推荐

  1. centos .7x service iptables save 错误解决方案

    保存转发规则的时候,发现service iptables save 无效,而且报错[root@localhost bin]# service iptables saveThe service comm ...

  2. 模拟输入(ADC-A0)

    ESP8266具有内置的10位ADC,只有一个ADC通道(A0引脚),即只有一个ADC输入引脚可读取来自外部器件的模拟电压 ESP8266上的ADC通道和芯片供电电压复用,也就是说我们可以将其设置为测 ...

  3. 消息中间件之 RocketMQ

    参考文档: http://jm.taobao.org/2017/01/12/rocketmq-quick-start-in-10-minutes/ http://rocketmq.apache.org ...

  4. 0-4评价一个语言模型Evaluating Language Models:Perplexity

    有了一个语言模型,就要判断这个模型的好坏. 现在假设: 我们有一些测试数据,test data.测试数据中有m个句子;s1,s2,s3-,sm 我们可以查看在某个模型下面的概率: 我们也知道,如果计算 ...

  5. overload(重载) 和 override(重写)的区别

    overload(重载): 重载是基于一个类中,方法名相同,参数列表不同(如果参数列表相同时,参数的类型要不同),与返回值和访问修饰符都无关 如果在面试中就直接说:"同名不同参"  ...

  6. 3D Computer Grapihcs Using OpenGL - 03 OpenGL Buffer Data

    本节绘制一个三角形,并讲解Buffer Object-缓冲对象 OpenGL的窗口坐标 屏幕中心为坐标原点,横向朝右为x正方向,纵向朝上为y正方向,最大值最小值分别为1,-1. Buffer Obje ...

  7. 解决Acunetix 12中文汉化的方法

    最近下载一款测试软件acunetix,苦于满屏英文的苦恼,看不懂,于是乎就问度娘,结果度娘就是给中文破解包: 我是12版的,网上提供的都是11版的,没法用.怎么办呢?还好我是做测试的,平时做兼容性测试 ...

  8. 【转】SQL Pretty Printer for SSMS 很不错的SQL格式化插件

    源地址:https://www.cnblogs.com/leospace/archive/2012/09/04/SQL_Pretty_Printer_for_SSMS.html 写SQL语句或者脚本时 ...

  9. Maps.newHashMap 和 new HashMap的区别

    区别: (1)Map<String, Object> result = new HashMap<String,Object>(); 这种是java原生API写法,需要你手动加泛 ...

  10. svn 服务器操作

    mkdir /var/svn/svnrepos/aaasvnadmin create /var/svn/svnrepos/aaasvnserve -d -r /var/svn/svnrepos #启动 ...