什么是内联方法?

时间:2010-10-13 14:53:34

标签: java function methods

我一直试图了解这意味着什么:

  

内联功能

     

在C ++中,定义了一个成员函数   类声明。 (2)功能   调用编译器替换的   该函数的实际代码。该   关键字内联可用于提示   编译器执行内联   扩大成员的身体或   非成员函数。

     

内联

     

用副本替换函数调用   函数的代码期间   汇编

例如,它写成:

  

当方法是最终的时,可能是   内联。

此处:http://www.roseindia.net/javatutorials/final_methods.shtml

你能给我一个例子或者什么,或者基本上帮助我理解“它可能被内联”的含义。

感谢。

3 个答案:

答案 0 :(得分:60)

内联是由Java Just-In-Time编译器执行的优化。

如果您有方法:

public int addPlusOne(int a, int b) {
  return a + b + 1;
}

你这样称呼:

public void testAddPlusOne() {
  int v1 = addPlusOne(2, 5);
  int v2 = addPlusOne(7, 13);

  // do something with v1, v2
}

编译器可能会决定用函数体替换你的函数调用,所以结果实际上如下所示:

public void testAddPlusOne() {
  int v1 = 2 + 5 + 1;
  int v2 = 7 + 13 + 1

  // do something with v1, v2
}

编译器这样做是为了节省实际进行函数调用的开销,这将涉及将每个参数推送到堆栈。

这显然只能用于非虚拟功能。考虑如果方法在子类中被覆盖会发生什么,并且直到运行时才知道包含该方法的对象的类型...编译器将如何知道要复制的代码:基类的方法体或子类的方法体?由于默认情况下所有方法在Java中都是虚拟的,因此您可以明确标记那些不能被覆盖为final的方法(或将它们放入final类)。这将有助于编译器确定该方法永远不会被覆盖,并且内联是安全的。 (请注意,编译器有时也可以对非最终方法进行此确定。)

另外,请注意引号中的可能一词。最终方法不保证可以内联。有多种方法可以保证方法无法内联,但无法强制编译器内联。无论如何,当内联将有助于破坏最终代码的速度时,它几乎总会比你更清楚。

有关优势和问题的详细概述,请参阅wikipedia

答案 1 :(得分:11)

调用函数不是免费的。机器必须保持堆栈帧,以便在被调用函数完成时它可以返回到代码的调用部分。维护堆栈(包括在此堆栈上传递函数参数)需要时间。

当函数内联时,编译器用函数的代码替换对函数的调用,这样可以避免在运行时调用函数调用的性能损失。这是编程中经典的权衡之一:运行时代码变得更大(占用更多内存),但运行速度更快。

答案 2 :(得分:10)

假设你有一个看起来像这样的课程:

public class Demo {
    public void method() {
        // call printMessage
        printMessage();
    }

    public void printMessage() {
        System.out.println("Hello World");
    }
}

printMessage的调用可以通过以下方式“内联”:

public class Demo {
    public void method() {
        // call printMessage
        System.out.println("Hello World"); // <-- inlined
    }

    public void printMessage() {
        System.out.println("Hello World");
    }
}

(实际上这不是在Java级别上完成的(甚至在字节码级别上),而是在JIT编译期间,但上面的示例说明了内联的概念。)

现在考虑如果printMessage方法被另一个类重载会发生什么,例如:

class SubDemo extends Demo {
    public void printMessage() {
        System.out.println("Something else");
    }
}

现在,如果编译器内联对Demo.printMessage的调用,那么如果对象实际上是{{1}的实例,它将会被System.out.println("Hello World");所困,这将是错误 }。

但是,如果声明SubDemo方法,则在任何情况下都不会这样。如果方法是“最终”,则意味着它永远不会被新定义覆盖,因此,内联它是安全的!