Java 我应该在重用方法外部还是内部声明变量?
(我以字符串为例,但它可以替换为对象>MB的内存) 经常这样做:Java 我应该在重用方法外部还是内部声明变量?,java,Java,(我以字符串为例,但它可以替换为对象>MB的内存) 经常这样做: private static String mTempString = ""; private static void SomeMethod() { mTempString = "Whatever Result"; } 现在我的问题是,如果我这样写的话: private static void SomeMethod() { String mTempString = "Whatever Result"; } 在
private static String mTempString = "";
private static void SomeMethod()
{
mTempString = "Whatever Result";
}
现在我的问题是,如果我这样写的话:
private static void SomeMethod()
{
String mTempString = "Whatever Result";
}
在循环中使用它(以每秒执行数百次为例),Java知道如何管理内存吗?将是相同的内存。(很抱歉,我现在无法亲自测试)
哪个内存效率更高(忽略它们是小变量的事实)
--编辑---
在这里找到一篇很好的文章来解释它一般来说,我更喜欢尽可能地限制变量的范围。这使得代码更容易理解、调试和重构 在这种情况下,这两种情况下这些变量所需的内存都非常小。每个变量都是对对象的引用,而不是对象本身。当用作局部变量时,引用可能只占用四个字节 局部变量的范围应始终尽可能小 除非需要范围外的变量,否则最好在范围内声明变量。在这种情况下没有性能差异,但建议最佳编码实践在尽可能小的范围内声明变量。看到这个类似的和流行的吗
另一种情况是使用不可变类型而不是字符串。性能差异很小(可以忽略不计)。在顶部声明会更好一些,因为您不需要在每个循环中初始化变量。但是在字符串中,因为它每次都在创建新对象,所以这在您的情况下不是问题。如果
mTempString
是只在someMethod()中需要的临时变量,那么它必须在方法中声明为局部变量,而不能作为类的静态成员。原因是您希望确保没有其他人干扰您的临时变量
如果您在类中声明它,那么您的代码更容易出错,因为您无法确定谁可以修改该变量
在您的示例中,临时变量被声明为静态字段。这使得代码不是线程安全的。如果两个不同的线程几乎同时调用同一个方法,则第二个方法调用将更改临时变量的值,该临时变量会影响调用第一个调用的线程。请尽可能缩小变量的范围。
这一点很重要,原因如下:
可读性。如果你在三个不同的地方用四个不同的值使用该变量(见图),你将很难辨别该变量的用途
错误。如果将单个变量保留在一个指定的范围内,可以减少应用程序中可能出现的错误数量。假设您有那个字符串,并且您希望它在两个方法中都是某个值,但它是完全不同的
目的的意图。我在可读性部分提到了这一点,但是如果您有一个不断被重新定义的静态
变量,那么它的目的就不清楚了。通常,静态方法和变量可以独立于对象的状态使用,因此如果对象的状态影响静态变量的值,那么意图就会变得混乱
在这一点上,我不会太担心内存效率(除非您有大量字符串,但我想说您有两件事需要担心)*
*:第一条优化规则:不要这样做。
第二条优化规则(仅限专家!):不要这样做但Jvm应该能够确定这是一个常量,并在必要时对其进行优化,这样您就不必担心这两种样式
对于算术表达式,JVM可以执行常量折叠优化
如果您只是对字符串感兴趣,常量字符串存储在字符串池中
您可能知道,字符串在java中是不可变的
因此,如果java中有常量字符串,它们将只存储一次,所有引用都将指向该字符串对象
e、 g
返回true,因为t和s指向同一字符串对象
此外,java类有常量池,所有类似的常量都被移动到其中
从本质上讲,JVM是相当聪明的,我不认为这两个玩具示例中的任何一个都比另一个好,至少在效率方面是这样的。尽管正如其他答案所提到的,您可能应该考虑一些软件设计方面的考虑 我对此进行了自己的测试,以查看编译器是否在每次迭代中实际创建了一个“新”对象。以下是以下代码的结果:
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);
}
私有静态长mStartedTime;
公共静态void main(字符串参数[])
{
长总时间=0;
int NumberOfLoops=7;
for(int i=0;i
他们提出了不同的建议
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);
}