将变量的范围限制为Java中的循环会导致额外的分配吗?

时间:2015-04-28 09:14:14

标签: java

在代码审查期间,我讨论了以下方法:

private String getAccessToken(HttpServletRequest request) {
    Enumeration<String> authHeaders = request.getHeaders("Authorization");

    for (; authHeaders.hasMoreElements(); ) {
        String header = authHeaders.nextElement();
        if (header.startsWith(BEARER_PREFIX)) {
            return header.substring(BEARER_PREFIX.length());
        }
    }
    return null;
}

一个建议是,从绩效的角度来看,这样做会更好:

String header;
for (; authHeaders.hasMoreElements(); ) {
    header = authHeaders.nextElement();
    //...
}

为了避免多次分配header。作为一名C ++程序员,这让我感到惊讶。我的假设是函数正在做这样的事情:

for (; authHeaders.hasMoreElements(); ) {
    char* header = authHeaders.nextElement();
    //...
}

即。 header是一个堆栈变量,指向堆上的某些内容,并且不需要进行任何分配。但我必须承认,我比使用Java更了解C / C ++,特别是当涉及到语言在分配时所做的保证时。

将循环外的字符串变量的声明移动到某种方式?

3 个答案:

答案 0 :(得分:2)

由于对象的分配authHeaders.nextElement()中完成,因此没有区别。

因此,无论声明变量在哪里,都会创建对象。

之后,无论变量如何声明,垃圾收集器都将删除现在未使用的对象。

答案 1 :(得分:2)

如果您不确定如何分配名称为“header”的REFERENCE,那么:

根据JVM规范:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.6

  

2.6。帧

     

框架用于存储数据和部分结果,以及   执行动态链接,返回方法的值和调度   异常。

     

每次调用方法时都会创建一个新帧。一个框架是   在方法调用完成时销毁,无论是否   完成是正常的或突然的(它抛出未捕获的异常)。   帧是从Java虚拟机堆栈(第2.5.2节)中分配的   创建框架的线程。每个帧都有自己的本地数组   变量(第2.6.1节),它自己的操作数堆栈(第2.6.2节)和对它的引用   当前类的运行时常量池(第2.5.5节)   方法。

     

2.6.1。局部变量

     

每个帧(第2.6节)包含一个称为本地的变量数组   变量。 帧的局部变量数组的长度是   在编译时确定并在二进制表示中提供   类或接口以及相关方法的代码   与框架(§4.7.3)。

因此,声明标头引用的位置无关紧要 - 字节代码包含有关它的信息,并且堆栈中的空间仅分配一次。

不需要将变量放在循环之外,并且由于其可见范围大于所需,因此编码实践不好。

答案 2 :(得分:0)

当您说String header = authHeaders.nextElement();时,您每次都会通过名称标题引用新位置。

将变量的声明移出循环意味着您使用相同的内存位置而不是使用多个内存位置并将其留给垃圾收集器来删除它们。当您处理大量数据集时,这会有很大帮助。