我一直试图了解这意味着什么:
内联功能
在C ++中,定义了一个成员函数 类声明。 (2)功能 调用编译器替换的 该函数的实际代码。该 关键字内联可用于提示 编译器执行内联 扩大成员的身体或 非成员函数。
内联
用副本替换函数调用 函数的代码期间 汇编
例如,它写成:
当方法是最终的时,可能是 内联。
此处:http://www.roseindia.net/javatutorials/final_methods.shtml
你能给我一个例子或者什么,或者基本上帮助我理解“它可能被内联”的含义。
感谢。
答案 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
方法,则在任何情况下都不会这样。如果方法是“最终”,则意味着它永远不会被新定义覆盖,因此,内联它是安全的!