コードでstatemet.executeUpdate()
を実行しようとすると、次のエラーが表示されます。
Local variable statement defined in an enclosing scope must be final or effectively final.
これはこれまでの私のコードです:
import Java.sql.Connection;
import Java.sql.DriverManager;
import Java.sql.ResultSet;
import Java.sql.SQLException;
import Java.sql.Statement;.
import org.Eclipse.swt.SWT;
import org.Eclipse.swt.events.MouseAdapter;
import org.Eclipse.swt.events.MouseEvent;
import org.Eclipse.swt.widgets.Button;
import org.Eclipse.swt.widgets.Display;
import org.Eclipse.swt.widgets.Label;
import org.Eclipse.swt.widgets.Shell;
import org.Eclipse.swt.widgets.Text;
public class a1 {
protected Shell shell;
private Text text;
private Text text_1;
private Text text_2;
private Text text_3;
/**
* Launch the application.
* @param args
*/
public static void main(String[] args) {
try {
a1 window = new a1();
window.open();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Open the window.
*/
public void open() {
Display display = Display.getDefault();
createContents();
Shell.open();
Shell.layout();
while (!Shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
/**
* Create contents of the window.
*/
protected void createContents() {
Connection connect = null;
ResultSet resultSet = null;
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
connect = DriverManager.getConnection("jdbc:mysql://localhost/railwaydb", "root", "");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Statement statement = null;
// statements allow to issue SQL queries to the database
try {
statement = connect.createStatement();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Shell = new Shell();
Shell.setSize(450, 300);
Shell.setText("SWT Application");
Label lblName = new Label(Shell, SWT.NONE);
lblName.setBounds(10, 43, 47, 15);
lblName.setText("Name");
Label lblFrom = new Label(Shell, SWT.NONE);
lblFrom.setBounds(10, 74, 55, 15);
lblFrom.setText("From");
Label lblTo = new Label(Shell, SWT.NONE);
lblTo.setBounds(10, 105, 55, 15);
lblTo.setText("To");
Label lblPrice = new Label(Shell, SWT.NONE);
lblPrice.setBounds(10, 137, 55, 15);
lblPrice.setText("Price");
text = new Text(Shell, SWT.BORDER);
text.setBounds(64, 43, 76, 21);
text_1 = new Text(Shell, SWT.BORDER);
text_1.setBounds(64, 74, 76, 21);
text_2 = new Text(Shell, SWT.BORDER);
text_2.setBounds(64, 105, 76, 21);
text_3 = new Text(Shell, SWT.BORDER);
text_3.setBounds(64, 137, 76, 21);
Label lblRailwayDatabase = new Label(Shell, SWT.NONE);
lblRailwayDatabase.setBounds(174, 10, 97, 15);
lblRailwayDatabase.setText("Railway Database");
Label lblCreateView = new Label(Shell, SWT.NONE);
lblCreateView.setBounds(189, 43, 76, 15);
lblCreateView.setText("Create View");
Button btnName = new Button(Shell, SWT.CHECK);
btnName.setBounds(189, 73, 93, 16);
btnName.setText("Name");
Button btnFrom = new Button(Shell, SWT.CHECK);
btnFrom.setBounds(189, 105, 93, 16);
btnFrom.setText("From");
Button btnTo = new Button(Shell, SWT.CHECK);
btnTo.setBounds(189, 137, 93, 16);
btnTo.setText("To");
Button btnPrice = new Button(Shell, SWT.CHECK);
btnPrice.setBounds(189, 171, 93, 16);
btnPrice.setText("Price");
Button btnInsert = new Button(Shell, SWT.NONE);
btnInsert.addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(MouseEvent e) {
String name = text.getText();
String from = text_1.getText();
String to = text_2.getText();
String price = text_3.getText();
String query = "INSERT INTO booking (name, fromst, tost, price) VALUES ('"+name+"', '"+from+"', '"+to+"', '"+price+"')";
try {
statement.executeUpdate(query);
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
btnInsert.setBounds(10, 171, 75, 25);
btnInsert.setText("Insert");
Button btnView = new Button(Shell, SWT.NONE);
btnView.setBounds(307, 74, 75, 25);
btnView.setText("View");
Button btnIndex = new Button(Shell, SWT.NONE);
btnIndex.setBounds(307, 127, 75, 25);
btnIndex.setText("Index");
}
}
statement
finalを設定しようとしましたが、宣言によって別のエラーが発生しました。
statement
はここで定義されたローカルメソッド変数であるため、実際にスコープの問題があります。
protected void createContents() {
...
Statement statement = null; // local variable
...
btnInsert.addMouseListener(new MouseAdapter() { // anonymous inner class
@Override
public void mouseDown(MouseEvent e) {
...
try {
statement.executeUpdate(query); // local variable out of scope here
} catch (SQLException e1) {
e1.printStackTrace();
}
...
});
}
mouseDown()
メソッド内でこの変数にアクセスしようとすると、匿名の内部クラス内からローカル変数にアクセスしようとしていて、スコープが十分ではありません。したがって、それは間違いなくfinal
(コードが不可能な場合)またはクラスメンバとして宣言されている必要があります。そうすると、内部クラスはこのstatement
変数にアクセスできます。
ソース:
statement
をローカル変数ではなくクラスメンバーにします。
public class A1 { // Note Java Code Convention, also class name should be meaningful
private Statement statement;
...
}
@HotLicksが示唆するように、別の最終変数を定義し、代わりにこの変数を使用します。
protected void createContents() {
...
Statement statement = null;
try {
statement = connect.createStatement();
final Statement innerStatement = statement;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
...
}
あなたのアプローチを再考してください。 statement
変数がbtnInsert
ボタンが押されるまで使用されない場合、接続を作成する意味がありませんbeforeこれは実際に起こります。次のようなすべてのローカル変数を使用できます。
btnInsert.addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(MouseEvent e) {
try {
Class.forName("com.mysql.jdbc.Driver");
try (Connection connect = DriverManager.getConnection(...);
Statement statement = connect.createStatement()) {
// execute the statement here
} catch (SQLException ex) {
ex.printStackTrace();
}
} catch (ClassNotFoundException ex) {
e.printStackTrace();
}
});
まず、変数はプログラムの実行中に状態が変化する可能性があり、内部クラスオーバーライド内の決定は現在の状態に依存する可能性があるため、変数をfinalにすることはできません。
第二に、オブジェクト指向プログラミングの優れた実践では、クラス定義としてクラスメンバーとして不可欠な変数/定数のみを使用することを推奨しています。これは、匿名の内部クラスオーバーライド内で参照している変数が単なるユーティリティ変数である場合、クラスメンバーにリストされるべきではないことを意味します。
しかし– Java 8の時点では、ここで説明する3番目のオプションがあります。
https://docs.Oracle.com/javase/tutorial/Java/javaOO/localclasses.html
Java SE 8以降、メソッドでローカルクラスを宣言すると、メソッドのパラメーターにアクセスできます。
したがって、新しい内部クラスとそのメソッドオーバーライドを含むコードを、オーバーライド内から呼び出す変数をパラメーターに含むプライベートメソッドに単純に配置できます。この静的メソッドは、btnInsert宣言ステートメントの後に呼び出されます。
. . . .
. . . .
Statement statement = null;
. . . .
. . . .
Button btnInsert = new Button(Shell, SWT.NONE);
addMouseListener(Button btnInsert, Statement statement); // Call new private method
. . .
. . .
. . .
private static void addMouseListener(Button btn, Statement st) // New private method giving access to statement
{
btn.addMouseListener(new MouseAdapter()
{
@Override
public void mouseDown(MouseEvent e)
{
String name = text.getText();
String from = text_1.getText();
String to = text_2.getText();
String price = text_3.getText();
String query = "INSERT INTO booking (name, fromst, tost,price) VALUES ('"+name+"', '"+from+"', '"+to+"', '"+price+"')";
try
{
st.executeUpdate(query);
}
catch (SQLException e1)
{
e1.printStackTrace(); // TODO Auto-generated catch block
}
}
});
return;
}
. . . .
. . . .
. . . .
エラーではありません:
JSONObject json1 = getJsonX();
エラー:
JSONObject json2 = null;
if(x == y)
json2 = getJSONX();
エラー: 囲みスコープで定義されたローカル変数ステートメントは、最終または実質的に最終でなければなりません。
しかし、あなたは書くことができます:
JSONObject json2 = (x == y) ? json2 = getJSONX() : null;
このアプローチは便利だと思いました。このように、クラスもfinalも必要ありません
btnInsert.addMouseListener(new MouseAdapter() {
private Statement _statement;
public MouseAdapter setStatement(Statement _stmnt)
{
_statement = _stmnt;
return this;
}
@Override
public void mouseDown(MouseEvent e) {
String name = text.getText();
String from = text_1.getText();
String to = text_2.getText();
String price = text_3.getText();
String query = "INSERT INTO booking (name, fromst, tost, price) VALUES ('"+name+"', '"+from+"', '"+to+"', '"+price+"')";
try {
_statement.executeUpdate(query);
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}.setStatement(statement));