在对象的情况下使用final关键字

Spr*_*ner 2 java java-8

我知道如何使用final keywords.Suppose如果使一个类成为final,则它不能被继承,如果一个方法是final,那么它不能被覆盖,如果一个变量是final,那么该值不能被改变.但是我在这种情况下我有点困惑

    final TextField urlTextField = new TextField();
Run Code Online (Sandbox Code Playgroud)

我认为如果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);
    }
}
Run Code Online (Sandbox Code Playgroud)

ass*_*ias 7

在Java 7之前,您需要声明一个局部变量fi​​nal来从内部类访问它.

从Java 8开始,这不再是必需的:变量只需要有效地最终(即不变).该更改与lambda语法一致.

因此,从技术上讲,如果您使用Java FX 8,则不需要最终关键字.

  • @assylias你是对的 - 即使支持闭包,Java 7中也不支持lambda表达式(` - >`).要更新我的答案 (2认同)

alf*_*sin 5

在Java 7中,当你在一个匿名类中并且你正在尝试使用/接近包装类的变量时 - 应该声明该变量final或者编译器会抱怨.同样的事情适用于Lambda表达式(从Java 8支持).尝试final从声明中删除,您将在第4行遇到编译器错误:

    urlTextField.setOnAction( aEvent ->  {
        pageLoadedProperty.set(false);
        printButtonClickedProperty.set(false);
        webEngine.load(urlTextField.getText()); // <-- compile error 
    });  
Run Code Online (Sandbox Code Playgroud)

文档:

匿名类无法访问其封闭范围中未声明为final或者有效final的局部变量.

Lambda表达式和匿名类共享相似的属性(lambda表达式可以定义为两件事的组合:代码和范围).除此之外,Lambda表达式(如内部类)只能使用final在lambda外声明的(或"有效最终")变量.以下是文档中的示例:

        // 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);
        };
Run Code Online (Sandbox Code Playgroud)