欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

一个类解耦成多个类,从实例化一个类到要实例化多个类,这样是不是增加了内存的消耗?

程序员文章站 2022-05-28 23:17:00
...

一个类解耦成多个类,从实例化一个类到要实例化多个类,这样是不是增加了内存的消耗?

回复内容:

一个类解耦成多个类,从实例化一个类到要实例化多个类,这样是不是增加了内存的消耗?

如果解耦得当,基本不会增加内存消耗,因为对象中的方法和参数虽然被分成到了不同的类中,但每个方法和参数占用空间都没有变,所有总体内存也没有变。只是在对象信息栈和指针上多占一些内存,不过这些基本都是可以忽略的。

内存可以批量生产,人要计划生育

如果所有用到这一个类的地方,都需要实例化解耦后的所有类,那这个类就没有必要解耦

但人工比内存贵得多

就单从语义来看,这是肯定的。
但是内存的消耗只是开发的一部分,毕竟还要考虑开发成本,维护成本

一个类解耦成多个类,从实例化一个类到要实例化多个类,这样是不是增加了内存的消耗?
一个类解耦成多个类,从实例化一个类到要实例化多个类,这样是不是增加了内存的消耗?

看起来没有太大的差别,只是CPU占用率后者明显大一些,当然我只是随便测了一下,仅供参考~

这种过程可以将功能更加细化,这样维护起来就能更加轻松

因为一个类,就算什么都不定义,也是会有固定的内存消耗的(主要就是class的一些meta信息了),所以理论上类越多这部分开销越大。

然而这部分能占多少呢?几个字节而已~

就像前面提到的,内存可以批量,人要计划生育,解耦的目标是为了让程序的可读性增强,进而有助于后续的迭代——有良好结构的代码,带来的不仅仅是人力的节省,也会带来程序的扩展性良好,长期看来,能够实现相同功能的前提下,程序对硬件资源的消耗也会因为良好的设计而减少。

不会有太大的变化,解耦后,将属性和方法都分到不同的类里面,内存使用率不会有太大的变化,即使有,可以忽略不计了。总之,利大于弊,何乐而不为呢。

纯粹为了可读性来把一个class分出新的class,而且新的class的生命周期与原本的class完全一样,则增加memory的耗损。

  • Metaspace/PermGen会变大

  • 原本的class需要记录新的reference value。

当然,这些损耗是很小的。可以忽略。

如果新的类的cohesion更好,而且可以late initialization,那么可以优化内存使用,减少内存损耗。
比如说,

class User {
  private String name;
  private Integer age;
  private String gender;

  private String country;  
  private String address;
  private String zipCode;

  private String companyName;
  private String occupation;
  private String companyAddress;

  private String favoriteSports;
  private String favoriteFoods;
  private String favoriteMovie;
}

任何一个User object就要分配12个fields的内存空间。

split class后,

class User {
  private PersonalInfo personal;
  private Address addr;
  private WorkInfo work;
  private Favorites favorites;
}

首先,初始化User只需要4个reference的内存,不需要初始化12个fields。如果一个用户的favorites是空的,就无需初始化Favorites的内存了。

当然,以上的是很琐碎的东西。真正有价值的是,不必要再把一大托User传来传去,User类驻留内存的时间变短:

//假设有一个module只对WorkInfo有兴趣
class WorkInfoPresentation {
  void displayWorkInfo(String userId) {
    // #L0: 
    final User user = SomeUserDAO.getUser(userId);
    final WorkInfo work = user.getWorkInfo();    
    // #L1: user的生命周期到此为止,可以被Garbage Collect掉了。
    
    callSomeComplicatedHTMLRenderingService(work);
    // #L2: 假设传入的不是work而是user, 那么user的内存就要一直驻留。
  }

  private void callSomeComplicatedHTMLRenderingService(WorkInfo work) {
    // 假定要花很久时间来运算
  }
}

较耗费内存的User的生命周期在#L0 - #L1,而较轻量的WorkInfo的生命周期在#L0 - #L2。User可能在进入callSomeComplicatedHTMLRenderingService之前就被GC掉了,从而节省了#L1 - #L2阶段的内存。

从绝对意义上来说是的,消耗的内存增加了。
但是,对象信息栈和指针上多占一些内存这种消耗是没必要考虑的,就像是
if (a==b){echo a;} 比 if (a==b) echo a; 需要执行更多的指令一样。
随着项目源码的增加、功能的扩展,维护是非常重要的问题,所以不可能丢了西瓜去捡芝麻。解耦对于维护来说价值就是西瓜,消耗的内存就是芝麻(何况还不如芝麻)。