6

(我以 String 为例,但它可以替换为 Object > MB 的内存)

经常这样做:

private static String mTempString = "";

private static void SomeMethod()
{
    mTempString = "Whatever Result";
}

现在我的问题是,如果我要这样写:

private static void SomeMethod()
{
    String mTempString = "Whatever Result";
}

并在循环中使用它(例如每秒执行数百次)Java会知道如何管理内存作为示例吗?记忆会是同样有效的。(对不起,我目前无法自己测试)

哪个内存效率更高(忽略它们是小变量的事实)

--edit--- 在这里找到了一篇很好的文章来解释它http://www.cs.berkeley.edu/~jrs/4/lec/08

4

6 回答 6

9

尽可能缩小变量的范围。

这很重要,原因如下:

  1. 可读性。 如果您在具有四个不同值的三个不同位置使用该变量(如图),您将很难辨别该变量应该用于什么目的。

  2. 错误。 如果将单个变量保留在一个明确指定的范围内,则可以减少应用程序中可能出现的错误数量。假设您有那个字符串,并且您希望它在两种方法中具有一定的价值,但它是完全不同的东西。

  3. 目的的意图。 我在可读性部分提到了这一点,但是如果你有一个static不断被重新定义的变量,它的预期目的就变得不清楚了。通常,静态方法和变量可以独立于对象的状态使用,因此如果对象的状态影响静态变量的值,则意图变得混乱。

在这一点上我不会太担心内存效率(除非你有大量的字符串,但我会说你有件事要担心)。*

*:优化的第一条规则:不要这样做。
优化的第二条规则(仅限专家!):不要这样做

于 2013-05-27T02:49:03.440 回答
3

一般来说,宁愿尽可能限制变量的范围。这使代码更易于理解、调试和重构。

在这种情况下,这两种情况下这些变量所需的内存都非常小。每个变量都是对对象的引用,而不是对象本身。当用作局部变量时,引用可能只占用四个字节。

于 2013-05-27T02:33:21.543 回答
1

局部变量的范围应始终尽可能小。

除非您需要范围之外的变量,否则最好在范围内声明变量。在这种情况下没有性能差异,但建议最佳编码实践在尽可能小的范围内声明变量。看到这个类似和流行的SO 问题

另一种情况是使用不可变类型而不是字符串。哪里会有轻微的性能差异(非常微不足道)。在顶部声明会好一点,因为您不需要在每个循环中初始化变量。但是在字符串中,因为它每次都在创建新对象,所以在您的情况下这不是问题。

于 2013-05-27T02:34:54.677 回答
1

Jvm 应该能够确定这是一个常量,并在必要时对其进行优化,这样您就不必担心任何一种样式。

在算术表达式的情况下,JVM 可以执行常量折叠优化。

如果您只对字符串感兴趣,则常量字符串存储在字符串池中。

你可能知道字符串在java中是不可变的。

因此,如果您在 java 中有常量字符串,它们将只存储一次,并且所有引用都将指向该字符串对象。

例如

    String s = "a" + "bc";

    String t = "ab" + "c";

    System.out.println(s == t);

返回 true 因为 t 和 s 指向同一个字符串对象。

此外,java 类有常量池,所有像这样的常量都被移动到其中。

本质上 JVM 是相当聪明的,我不认为这些玩具示例中的任何一个至少在效率方面都比彼此更好。尽管正如其他答案所提到的,您可能应该考虑一些软件设计注意事项。

于 2013-05-27T02:53:19.447 回答
1

我对此进行了自己的测试,以查看编译器是否真的在每次迭代中创建了一个“新”对象。以下是以下代码的结果:

private static long mStartedTime;

public static void main(String args[])
{
    long TotalTime = 0;
    int NumberOfLoops = 7;

    for(int i = 0; i < NumberOfLoops; i++)
    {
        mStartedTime = System.currentTimeMillis();

        for(float Index = 0; Index < 10000000; Index++)
        {
            test1("wewgwgwegwegwegsd veweewfefw fwefwef wfwefdwvdw wefwe wevwev etbe tbebetbetb evberve");
        }

        System.out.println("Program took: " + String.valueOf(System.currentTimeMillis() - mStartedTime) + " to complete.");
        TotalTime += System.currentTimeMillis() - mStartedTime;
    }

    System.out.println("Average time taken: " + String.valueOf(TotalTime / NumberOfLoops));
}


public static void test1(String THisIsText)
{
    String Test = THisIsText;
    Test = Test.substring(1);
}

private static String mTempString;
public static void test2(String THisIsText)
{
    mTempString = THisIsText;
    mTempString = mTempString.substring(1);
}

他们得出了不同的结果,似乎将变量放在本地范围内会导致性能损失:

我只能猜测本地方法变量被删除了,这需要时间,为什么 test1 需要更长的时间?(任何人都可以证实这一点)

(经过多次测试)

Local-scope average: Average time taken: 1183

Class-scoped reusable variable: Average time taken: 1043

于 2013-05-27T04:10:51.930 回答
0

如果mTempString是一个临时变量,someMethod()那么它必须在方法内声明为局部变量,而不是类的静态成员。原因是您要确保没有其他人会弄乱您的临时变量。

如果您在类中声明它,那么您的代码更容易出错,因为您无法确定谁可以修改该变量。

在您的示例中,临时变量被声明为静态字段。这使得代码不是线程安全的。如果两个不同的线程几乎同时调用同一个方法,那么第二个方法调用将更改影响调用第一个调用的线程的临时变量的值。

于 2013-05-27T02:43:55.310 回答