Java 将代码作为函数参数传递

Java 将代码作为函数参数传递,java,swing,Java,Swing,我在读一本教科书,我想知道为什么我们传递给函数的参数既不是基元,也不是类的用户定义实例 SwingUtilities.invokeLater(new Runnable() { public void run() { new ButtonDemo(); } }); 我了解到这两种情况中的任何一种。但在这里,它似乎传递了一个用户定义的构造函数方法,例如Runnable。看起来他们想在以后运行线程,但是什么时候?我想这是合法的,但我从来没有在我的Java类中听说过这

我在读一本教科书,我想知道为什么我们传递给函数的参数既不是基元,也不是类的用户定义实例

SwingUtilities.invokeLater(new Runnable() 
{
    public void run() {
        new ButtonDemo();
    }
});

我了解到这两种情况中的任何一种。但在这里,它似乎传递了一个用户定义的构造函数方法,例如Runnable。看起来他们想在以后运行线程,但是什么时候?我想这是合法的,但我从来没有在我的Java类中听说过这样的事情。

这实际上是在传递一个实现Runnable接口的匿名内部类的实例。阅读中的相关内容。

这实际上是在传递实现可运行接口的匿名内部类的实例。阅读有关他们的文章

我想知道为什么我们传递给函数的参数既不是基元,也不是类的用户定义实例

SwingUtilities.invokeLater(new Runnable() 
{
    public void run() {
        new ButtonDemo();
    }
});
它是用户定义类的实例。唯一的区别是该类没有名称*

不过,它是一个类的真实实例——它可以完成命名类可以完成的大部分事情。除此之外,它还可以提供其基类或接口的方法实现,该接口用于将一段可执行代码传递给方法

*至少,不是用户可见的:Java编译器确实为每个匿名类分配了一个内部名称,该名称通常包含一个美元符号

我想知道为什么我们传递给函数的参数既不是基元,也不是类的用户定义实例

SwingUtilities.invokeLater(new Runnable() 
{
    public void run() {
        new ButtonDemo();
    }
});
它是用户定义类的实例。唯一的区别是该类没有名称*

不过,它是一个类的真实实例——它可以完成命名类可以完成的大部分事情。除此之外,它还可以提供其基类或接口的方法实现,该接口用于将一段可执行代码传递给方法


*至少,不是用户可见的:Java编译器为每个匿名类分配了一个内部名称,通常包含一个美元符号。

阅读。这被视为单独的类。如果编译代码并说文件名为Test.java。通过编译,将有两个类文件Test.class和Test$1.class,如果有更多的内部类,则将有Test$2.class、Test$3.class等等。

阅读相关内容。这被视为单独的类。如果编译代码并说文件名为Test.java。通过编译,将有两个类文件Test.class和Test$1.class,如果您有更多的内部类,则将有Test$2.class、Test$3.class等等。

这称为匿名类,您可以定义一个单独使用的类,而不提供名称


为了更好地理解它们,请参阅本教程:

这是一个匿名类,您可以在其中定义一个只供一次使用的类,而不提供名称


要更好地理解它们,请参阅本教程:

SwingUtilities中的代码如下

private Runnable runnable;

private void invoke(){//called at some point from inside the runnable
     runable.run();
}
public void invokeLater(Runnable runnable){
     this.runnable=runnable;
}

这些被称为回调。

SwingUtilities中的代码如下

private Runnable runnable;

private void invoke(){//called at some point from inside the runnable
     runable.run();
}
public void invokeLater(Runnable runnable){
     this.runnable=runnable;
}
这些被称为回调

将代码作为函数参数传递

Java在第8版中将有lambda表达式。这也值得一看:

将代码作为函数参数传递


Java在第8版中将有lambda表达式。这也值得一看:

它只运行一次,对吗?new ButtonDemo创建一个按钮运行一次,但为什么它在线程中?runnable不是线程。它是一个具有run方法的对象。然后将其传递给SwingUtilities.invokeLater,以便在事件分派线程中执行此run方法,因为与swing组件的所有交互都必须从该线程完成。它只运行一次,对吗?new ButtonDemo创建一个按钮运行一次,但为什么它在线程中?runnable不是线程。它是一个具有run方法的对象。然后将其传递给SwingUtilities.invokeLater,以便在事件分派线程中执行此run方法,因为与swing组件的所有交互都必须从该线程完成。相对于invokeLater的工作方式,这介于过度简化和不正确之间。实际上,SwingUtilities只是将调用转发到EventQueue。EventQueue是一个链表,调用invokeLater会向其追加一个新的InvokeEvent。InvocationEvent是当EventDispatchThread泵送事件时调用运行的。@Radiodef,不知道SwingUtilities内部到底发生了什么,但是如果我不知道回调是如何工作的,上面的代码将是一个很好的例子,向我展示了它们背后的逻辑。这是介于过度简化和不正确的vis-a-vis-vis invokeLater工作方式之间。实际上,SwingUtilities只是将调用转发到EventQueue。EventQueue是一个链表,调用invokeLater会向其追加一个新的InvokeEvent。InvocationEvent是当EventDispatchThread启动时运行的调用
事件@Radiodef,不知道SwingUtilities内部到底发生了什么,但是如果我不知道回调是如何工作的,上面的代码将是一个很好的例子,向我展示它们背后的逻辑。