在下面的工作代码中,
package com.ca.naive;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.List;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class TodoGUI {
public static void main(String[] args) {
List list = new List();
TextField itemField = new TextField();
Button addButton = new Button("Add");
Button removeButton = new Button("Remove");
addButton.addActionListener(e -> list.add(itemField.getText()));
removeButton.addActionListener( e -> list.remove(list.getSelectedIndex()));
Panel buttons = new Panel(new GridLayout(1,0,3,3));
buttons.add(addButton);
buttons.add(removeButton);
Panel bottomPanel = new Panel(new FlowLayout(FlowLayout.RIGHT));
bottomPanel.add(buttons);
Panel centerPanel = new Panel(new BorderLayout());
centerPanel.add(BorderLayout.NORTH, itemField);
centerPanel.add(BorderLayout.SOUTH, buttons);
Frame frame = new Frame();
frame.setLayout( new BorderLayout() );
frame.add(BorderLayout.WEST, list);
frame.add(BorderLayout.CENTER, centerPanel);
frame.pack();
frame.addWindowListener( new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
}
javac是否用
替换addButton.addActionListener(e -> list.add(itemField.getText()));
语法
addButton.addActionListener(new java.awt.Event.ActionListener() {
public void actionPerformed(java.awt.Event.ActionEvent e) {
list.add(itemField.getText());
}
});
答案 0 :(得分:2)
javac是否用
替换addButton.addActionListener(e -> list.add(itemField.getText()));
语法addButton.addActionListener(new java.awt.Event.ActionListener() { public void actionPerformed(java.awt.Event.ActionEvent e) { list.add(itemField.getText()); } });
不,这是不编译器的功能。在您的示例中,将生成并实例化ActionListener
实现,但这不会在编译时发生;它发生在运行时。编译器做了两件事。首先,它将lambda的主体移动到一个看起来像这样的隐藏方法:
void lambda$1(java.util.List list, java.awt.TextField itemField) {
list.add(itemField.getText());
}
其次,在声明lambda的位置,它会发出对 bootstrap 方法的调用。引导方法是一种特殊的工厂方法,它知道如何生成功能接口的实现。需要给出一些基本信息,最值得注意的是:功能接口的类型(已知为ActionListener
);任何捕获变量的类型(在您的情况下,list
和itemField
);以及哪个方法包含实现的逻辑(生成的lambda$1
方法)。
当引导程序调用在运行时被命中时,它将生成ActionListener
实现。下次结束此代码路径时,您不必调用bootsrap方法。相反,替换了引导程序调用,以便最终得到相当于:
addButton.addActionListener(TodoGUI$Lambda$1.getInstance(list, itemField));
TodoGUI$Lambda$1
是一个看起来像这样的类:
static class TodoGUI$Lambda$1 implements java.awt.Event.ActionListener {
private final java.util.List list;
private final java.awt.TextField itemField;
TodoGUI$Lambda$1(java.util.List list, java.awt.TextField itemField) {
this.list = list;
this.itemField = itemField;
}
@Override
public void actionPerformed(java.awt.Event.ActionEvent e) {
TodoGUI.lambda$1(list, itemField);
}
static java.awt.Event.ActionListener getInstance(
java.util.List list,
java.awt.TextField itemField) {
return new TodoGUI$Lambda$1(list, itemField);
}
}
现在,考虑到所有这些,编译器不需要您导入ActionListener
类型。那种类型根本不需要在词法范围内。编译器将查看并在addActionListener
实例上调用名为java.awt.Button
的方法。它将看到您传递的是一个参数,这是一个lambda表达式。在这种情况下,没有重载,因此它知道addActionListener
希望您传递ActionListener
。它看到ActionListener
是一个单方法接口,这意味着它可以绑定到lambda。它尝试推断您的参数类型和返回类型,使它们与ActionListener
的预期内容兼容:单个ActionEvent
参数和void
返回类型。您的lambda是兼容的,因此绑定了调用,并执行上述步骤。
答案 1 :(得分:0)
另一个"非lambda"您描述的效果示例是
之类的调用System.out.println("hello");
您不需要导入java.io.PrintStream
,以便使用println
作为此类实例附带的out
方法。
顺便说一句:你可以在不使用任何import
语句的情况下编写一个类。在这种情况下,如果要使用它,则必须使用包括所有包的完整类名:
java.io.PrintStream outStream = System.out;
outStream.println("Hello");
每次使用类时,import
只会为您节省重复的包规范。