我知道如何使用final关键字。假设如果将一个类设为final,那么它不能被继承,如果一个方法是final,那么它不能被覆盖,如果一个变量是final,那么该值不能被改变。但在这种情况下我有点困惑
final TextField urlTextField = new TextField();
我认为如果将urlTextField设为最终版,则无法重新制作
urlTextField = new textField()。但是在下面的例子中为什么它是最终的
package org.carlfx;
import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.concurrent.Worker.State;
import javafx.print.*;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.transform.Scale;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
/**
* Demo to use JavaFX 8 Printer API.
*
* @author cdea
*/
public class PrintDemo extends Application {
@Override
public void start(Stage primaryStage) {
final TextField urlTextField = new TextField();
final Button printButton = new Button("Print");
final WebView webPage = new WebView();
final WebEngine webEngine = webPage.getEngine();
HBox hbox = new HBox();
hbox.getChildren().addAll(urlTextField, printButton);
BorderPane borderPane = new BorderPane();
borderPane.setTop(hbox);
borderPane.setCenter(webPage);
Scene scene = new Scene(borderPane, 300, 250);
primaryStage.setTitle("Print Demo");
primaryStage.setScene(scene);
// print button pressed, page loaded
final BooleanProperty printButtonClickedProperty = new SimpleBooleanProperty(false);
final BooleanProperty pageLoadedProperty = new SimpleBooleanProperty(false);
// when the a page is loaded and the button was pressed call the print() method.
final BooleanProperty printActionProperty = new SimpleBooleanProperty(false);
printActionProperty.bind(pageLoadedProperty.and(printButtonClickedProperty));
// WebEngine updates flag when finished loading web page.
webEngine.getLoadWorker()
.stateProperty()
.addListener( (ChangeListener) (obsValue, oldState, newState) -> {
if (newState == State.SUCCEEDED) {
pageLoadedProperty.set(true);
}
});
// When user enters a url and hits the enter key.
urlTextField.setOnAction( aEvent -> {
pageLoadedProperty.set(false);
printButtonClickedProperty.set(false);
webEngine.load(urlTextField.getText());
});
// When the user clicks the print button the webview node is printed
printButton.setOnAction( aEvent -> {
printButtonClickedProperty.set(true);
});
// Once the print action hears a true go print the WebView node.
printActionProperty.addListener( (ChangeListener) (obsValue, oldState, newState) -> {
if (newState) {
print(webPage);
}
});
primaryStage.show();
}
/** Scales the node based on the standard letter, portrait paper to be printed.
* @param node The scene node to be printed.
*/
public void print(final Node node) {
Printer printer = Printer.getDefaultPrinter();
PageLayout pageLayout = printer.createPageLayout(Paper.NA_LETTER, PageOrientation.PORTRAIT, Printer.MarginType.DEFAULT);
double scaleX = pageLayout.getPrintableWidth() / node.getBoundsInParent().getWidth();
double scaleY = pageLayout.getPrintableHeight() / node.getBoundsInParent().getHeight();
node.getTransforms().add(new Scale(scaleX, scaleY));
PrinterJob job = PrinterJob.createPrinterJob();
if (job != null) {
boolean success = job.printPage(node);
if (success) {
job.endJob();
}
}
}
/**
* The main() method is ignored in correctly deployed JavaFX application.
* main() serves only as fallback in case the application can not be
* launched through deployment artifacts, e.g., in IDEs with limited FX
* support. NetBeans ignores main().
*
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
答案 0 :(得分:7)
在Java 7之前,你需要声明一个局部变量final来从内部类访问它。
从Java 8开始不再需要:the variable only need to be effectively final(即未更改)。这种改变与lambda语法一致。
从技术上讲,如果您使用的是Java FX 8,那么此处不需要final关键字。
答案 1 :(得分:5)
在Java 7中,当你在一个匿名类中并且你正在尝试使用/接近包装类的变量时 - 该变量应该被声明为final
或者编译器会抱怨。同样的事情适用于Lambda表达式(从Java 8支持)。尝试从声明中删除final
,您将在第4行收到编译器错误:
urlTextField.setOnAction( aEvent -> {
pageLoadedProperty.set(false);
printButtonClickedProperty.set(false);
webEngine.load(urlTextField.getText()); // <-- compile error
});
匿名类无法访问其封闭的局部变量 未被宣布为最终或有效最终的范围。
Lambda expressions和匿名类共享相似的属性(lambda表达式可以定义为两件事的组合:代码和范围)。除此之外,Lambda表达式(如内部类)只能使用在lambda外声明的final
(或“有效最终”)变量。以下是 documentation :
// The following statement causes the compiler to generate
// the error "local variables referenced from a lambda expression
// must be final or effectively final" in statement A:
//
// x = 99;
Block<Integer> myBlock = (y) ->
{
System.out.println("x = " + x); // Statement A
System.out.println("y = " + y);
System.out.println("this.x = " + this.x);
System.out.println("LambdaScopeTest.this.x = " +
LambdaScopeTest.this.x);
};