什么是方法内联?

2022-09-01 00:51:57

我一直在努力理解这到底意味着什么:

内联函数

在C++,这指的是在类声明中定义的成员函数。(2) 编译器用函数的实际代码替换的函数调用。关键字 inline 可用于提示编译器对成员或非成员函数的主体执行内联扩展。

内嵌

在编译期间将函数调用替换为函数代码的副本。

例如,它写得像这样:

当方法最终确定时,可以内联该方法。

这里 : http://www.roseindia.net/javatutorials/final_methods.shtml

你能给我举个例子或其他东西,或者基本上帮助我理解“它可能是内联的”是什么意思。

谢谢。


答案 1

内联是由 Java 即时编译器执行的优化。

如果您有方法:

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 中,默认情况下所有方法都是虚拟的,因此您可以显式地将那些不能重写的方法标记为(或将它们放入类中)。这将有助于编译器确定该方法永远不会被重写,并且内联是安全的。(请注意,编译器有时也可以对非最终方法进行此确定。finalfinal

另外,请注意引号中的单词 may。最终方法不能保证是内联的。有多种方法可以保证方法不能内联,但无法强制编译器内联。无论如何,它几乎总是比你更清楚,因为内联将有助于而不是损害结果代码的速度。

请参阅维基百科,了解好处和问题的良好概述。


答案 2

假设您有一个如下所示的类:

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.printMessageSystem.out.println("Hello World");SubDemo

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