优化的变量声明原语vs null对象

时间:2014-05-06 07:15:39

标签: java memory optimization

我有一个名为Location的类,它有两种类型的信息,一个是nodeID(一个整数),另一个是diskPosition(long)。 我的应用程序需要创建此Location类的许多对象,但大多数时候我会在类Location中为这两个变量之一分配一个默认值(比如-1)。

我的问题是“我应该将这些nodeID和diskPosition声明为Integer和Long并指定默认值null而不是将它们保持为原始值并将默认值指定为-1”“

我担心的是我的Location对象占用的内存量,我希望将其最小化。

以下是Location类的代码片段:

public class Location
{
    private int     nodeID  = -1;
    private long    diskPos = -1;

    public Location(long diskPos)
    {
        this.diskPos = diskPos;
    }

    public Location(Node node)
    {
        this.nodeID = node.getNodeID();
    }

    // Test main method to elaborate usage of Location object
    public void main(String[] args)
    {
        Map<Integer, Location> cellIDToLocationMap = new HashMap<Integer, Location>();

        // Consider there is a list of nodes which is obtained from somewhere
        List<Node> nodeList = getNodeList();

        Location loc = null;
        for (int i = 1; i <= 10000; i++)
        {
            if (i % 2 == 0)
                loc = new Location(nodeList.get(i));
            else
                loc = new Location(i);

            // Put in map
            cellIDToLocationMap.put(i, loc);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

答案取决于您创建的实例数以及nodeIDdiskPos值的分布情况。让我们看看这些数字,假设一个32位JVM(或指针压缩的64位)。这些值可能仍然与您的JVM实现不匹配,但它们对于HotSpot应该是正确的。

使用intlong Location实例需要24个字节。对于IntegerLong,它取决于。 Location个实例需要16个字节,而IntegerLong个对象可能各占16个,除非它们是共享的。如果如你所说的那样,其中一个在大多数时间内保持-1(或null),那就不占用内存,因此总共需要16或32个字节。是否共享IntegerLong个实例取决于值和JVM设置。由于diskPos需要很长,因此实例不太可能被缓存。

所以答案是:primitive = 24个字节,盒装很可能是32个字节。坚持原始。

如果您使用实现公共接口的不同类, 可以将每个实例的内存消耗降低到16个字节。我不会这样做是为了节省内存(在你注意之前你需要数百万个实例),但是对于更易读的代码,因为,在字段-1之一中,Location实际上是一个联合类型,你可能有这样的代码:

if (location.getNodeId() >= 0) {
    // do something with node id
} else {
    // do something with diskPos
}

更面向对象的设计可以让您将不同的行为合并到各自的类中。