我习惯于避免局部变量 - 我做得对吗?

时间:2013-12-10 05:41:30

标签: java

我刚刚意识到,当我使用Java进行编程时,我会避免像瘟疫这样的局部变量,如果我真的必须使用小写“L”为成员添加前缀并且有一个方法可以重置该对象(如果对象是我的,我通常有一个名为init的私有方法或构造函数调用的东西

我刚刚意识到这在很多方面都很难看。我做得对吗?

C ++程序员会确切地知道我的意思,没有离开函数范围的本地人会被自动销毁(如果它确实离开了函数范围,使用指针,等等等等)

发生这种情况的模式

我发现每当我将一个适配器安装到一个函数参数并通过这个适配器与它进行交互时,我就会使用它。

我也倾向于让适配器维护它使用的任何对象的池(最多一定数量)

当我想使用需要“new”初始化但仅在方法内的数据类型时,也会发生这种情况。

代码通常是某个主循环的一部分,否则无关紧要,显然(这不是一件事)

GC Collection amount:
Amount (Mb):  |   30|   60|   90|  120|  150|  180|  210|  240|  270|  300|  330|  360|
--------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
With pattern  |## (14)
without       |################################################################### (350)

该程序通过其单元测试推进显示的平均GC量。两者的标准偏差均小于5。

这感觉它与飞轮模式有某种关系......

没有此代码,因为:

它可以在很多方面表现出来!例如,如果您有一个ComplexNumber类,如果您只是根据需要创建它们,那么如果您有任何类型的vectormatrix类,则会产生大量垃圾。

另一个领域是任何涉及某种图形的图形,它被仔细遍历以生成另一个结构,如场景图,关键路径,甚至代表当前目录的堆栈。

基本上如果你有一个“新”来分配一个被调用的方法中的局部变量,你会发现它。

上面使用的示例

它来自我写的一个程序,用来教人们关于有限状态自动机和其他状态机(Markov Chains,等等),我注意到ram使用严重,并决定进行调查。

与其他语言的比较

显然C ++没有这个问题。但是Python也不会很高兴知道。 Python的引用计数意味着(假设你没有任何cricles),方法结束时的东西被删除,实际上有一个元方法,你可以可靠地使用它作为析构函数(前提是你足够纪律,不要从方法泄漏它)

我不能第一个遇到这个问题,看着类似的问题表明没有解决办法,但我不相信以前没有遇到过这个问题!

关于我

我来自C ++和Python(爱他们两个!)到Java,我在Java中“经验丰富”,我可以读/写有用的东西,它遵循一个很好的设计理念等等,但我倾向于要非常注意性能和资源。我正在退出const,我是一个总妓女。

这不是汇集

假设你有一个GroupElement类 - 代表一个代数组的成员,我们将使用加法表示法。

假设g.add(h)返回一个新元素,如果多次执行此操作,则会有很多元素。如果相反,你有:

 GroupElement f = new GroupElement(0); //identity
 g.add(f,h); 

其中:

add的第一个参数是放置结果的地方,我们不生成垃圾。

不遵守上述内容的人

你应该知道复数是多少?假设一个复数有一个名为add的方法,它采用一个复数并返回一个 new 复数。如果你做a=b.add(c);很多次,你会得到A LOT减去1个垃圾复杂数字。

如果您inplaceAdd(ComplexNumber target, ComplexNumber value)说:

target.real = value.real+real;
target.im = value.im+im;

如果您这样做,则不会产生垃圾:b.inplaceAdd(a,c) - 与上面的a=b.add(c)

相同

BTW add可以做到这一点:return new ComplexNumber(real+value.real,im+value.im) - 看看我的意思了吗?

实施示例(严肃的家伙,你怎么没有得到这个!)

public class ComplexNumber {
    private double real;
    private double im;

    public ComplexNumber(double r, double i) {
        real = r;
        im = i;
    }

    public ComplexNumber add(ComplexNumber value) {
        return new ComplexNumber(real + value.real, im + value.im);
    }

    public void inplaceAdd(ComplexNumber target, ComplexNumber value) {
        target.real = real + value.real;
        target.im = im + value.im;
    }
}

1 个答案:

答案 0 :(得分:3)

  

例如,如果您有一个ComplexNumber类,如果您只是根据需要创建它们,那么如果您有任何类型的vectormatrix类,则会产生大量垃圾,同样的事情。

请记住,垃圾是免费的;垃圾收集的成本由必须遍历的 - 垃圾决定。 (我的意思是,VM规范实际上并没有确切地指定GC必须如何实现,但这是主要的工作方式。)这是故意的:显然没有技术原因,Java实现不能< / em>使用引用计数;只是它不被认为非常强大/高效/可靠/等。 (在C ++和Perl以及Python中,引用计数为您提供了可预测的析构函数的优势.Java不提供它;相反,它提供finally块和try - with-resources。)< / p>