Java希望某些对象是最终的
我正在构建一个GUI应用程序,我需要从我编写的其他类中获得两个对象 GUI是用主方法调用的方法编写的,在该方法中我初始化了两个对象 基本上Eclipse告诉我Java希望某些对象是最终的,java,swing,oop,Java,Swing,Oop,我正在构建一个GUI应用程序,我需要从我编写的其他类中获得两个对象 GUI是用主方法调用的方法编写的,在该方法中我初始化了两个对象 基本上Eclipse告诉我 "Cannot refer to the non-final local variable user defined in an enclosing scope" GUI有一个按钮,按下该按钮会弹出另一个窗口,用户可以在其中输入登录信息 然后,登录信息在java/eclipse告诉我使用final的一个对象的帮助下被获取和处理,但是当
"Cannot refer to the non-final local variable user defined in an enclosing scope"
GUI有一个按钮,按下该按钮会弹出另一个窗口,用户可以在其中输入登录信息
然后,登录信息在java/eclipse告诉我使用final的一个对象的帮助下被获取和处理,但是当它们是final时,我不能以我想要的方式使用它们
我还应该在哪里初始化我的对象,或者我可以做些什么来利用这些对象,这样它们就不是最终的了
以下是相关代码:
Usermanager和Player是我所说的有问题的对象
包de.unistuttgart.iaas.icetea.gui
import java.awt.Component;
import java.awt.ComponentOrientation;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JProgressBar;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import de.unistuttgart.iaas.icetea.player.Player;
import de.unistuttgart.iaas.icetea.user.UserManager;
@SuppressWarnings("serial")
public class ICT_mainGUI extends JFrame {
private final JPanel panel = new JPanel();
/**
* Launch the application. should open a window (hopefully)
*/
public static void main(String[] args) {
// java eventq shit
// TODO DONT TOUCH THIS SHIT
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
ICT_mainGUI frame = new ICT_mainGUI();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
@SuppressWarnings("unused")
public ICT_mainGUI() {
// initializing needed objects
// user manager for admin and user shit
// player for player manipulation
// TODO DONT TOUCH THIS EITHER
UserManager user = new UserManager();
Player player = new Player();
getContentPane().setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 933, 112);
getContentPane().setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
JPanel panel_1 = new JPanel();
panel_1.setFocusCycleRoot(true);
panel_1.setAlignmentX(Component.RIGHT_ALIGNMENT);
panel_1.setFocusTraversalPolicyProvider(true);
getContentPane().add(panel_1);
panel_1.setLayout(new FlowLayout(FlowLayout.RIGHT, 5, 5));
JButton playButton = new JButton("Play");
panel_1.add(playButton);
JButton btnPause = new JButton("Pause");
panel_1.add(btnPause);
JButton btnStop = new JButton("Stop");
panel_1.add(btnStop);
JProgressBar progressBar = new JProgressBar();
panel_1.add(progressBar);
JMenuBar menuBar = new JMenuBar();
menuBar.setBorderPainted(false);
setJMenuBar(menuBar);
menuBar.add(panel);
JButton signInButton = new JButton("Anmelden");
signInButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//seting up our window
final JFrame frame = new JFrame("Login User");
frame.setSize(300, 200);
JPanel panel = new JPanel();
frame.add(panel);
panel.setLayout(null);
//userlabel
JLabel userLabel = new JLabel("User");
userLabel.setBounds(10, 10, 80, 25);
panel.add(userLabel);
JTextField userText = new JTextField(20);
userText.setBounds(100, 10, 160, 25);
panel.add(userText);
JLabel passwordLabel = new JLabel("Password");
passwordLabel.setBounds(10, 40, 80, 25);
panel.add(passwordLabel);
JPasswordField passwordText = new JPasswordField(20);
passwordText.setBounds(100, 40, 160, 25);
panel.add(passwordText);
//PASSWORDREPEAT
JPasswordField passwordrepeat = new JPasswordField(20);
//TODO fix orientation
passwordrepeat.setBounds(100, 70, 160,25);
panel.add(passwordrepeat);
passwordrepeat.setEnabled(false);
//passwordtextrepeat
JLabel passwordtextrepeat = new JLabel("Repeat Password");
//TODO fix orientation
passwordtextrepeat.setBounds(10, 70, 80, 25);
panel.add(passwordtextrepeat);
passwordtextrepeat.setEnabled(false);
JButton loginButton = new JButton("login");
loginButton.setBounds(10, 100, 90, 25);
panel.add(loginButton);
JButton registerButton = new JButton("add User");
registerButton.setBounds(180, 100, 80, 25);
panel.add(registerButton);
registerButton.setEnabled(false);
frame.setVisible(true);
//doing verification stuff
final String username = userText.getText();
final String password = passwordLabel.getText();
loginButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
user.addUser(username, password);
if (user.getCurrentUser().equals(username)) {
String stringfordialog = "Login sucessful \n Current User:\n" + user.getCurrentUser();
JOptionPane.showMessageDialog(frame, stringfordialog);
} else {
}
}
});
}
});
panel.add(signInButton);
JButton signOutButton = new JButton("Abmelden");
panel.add(signOutButton);
JButton adduserButton = new JButton("AddUser");
if (user.isAdmin()) {
adduserButton.setEnabled(true);
} else {
adduserButton.setEnabled(false);
}
panel.add(adduserButton);
adduserButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JFrame adduserdialog = new JFrame("AddUser");
adduserdialog.setSize(400, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
// TODO promote User
JButton promoteUserButton = new JButton("Promote User");
if (user.isAdmin()) {
promoteUserButton.setEnabled(true);
} else {
promoteUserButton.setEnabled(false);
}
panel.add(promoteUserButton);
JSlider volumeSlider = new JSlider();
menuBar.add(volumeSlider);
// close button
JButton btnClose = new JButton("Close");
btnClose.setHorizontalAlignment(SwingConstants.LEFT);
menuBar.add(btnClose);
// TODO **finished** close the window
btnClose.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
}
}
匿名内部类(侦听器)通过复制局部变量来引用其封闭范围。
当匿名方法返回时,您的局部变量将从中清除,因此它们将不再存在。但是匿名类对象
UserManager
和Player
引用这些变量。这是错误的行为,所以Java不允许您这样做
在它是最终的之后,它变成一个常数。因此它存储在堆中,可以安全地用于匿名类。我以前见过这种情况。下面是正在发生的事情
Foo bar = new Foo();
ActionListener al = new ActionListener(ActionEvent ae) {
actopnPerformed(ActionEvent ae) {
bar.setX(x);
}
}
问题是动作监听器中的代码不会立即被调用,而foo变量在调用bar.setX时可能已经更改了。。。它们在两个不同的范围内。因此,为了确保ActionListener中的代码对它将调用setX的对象具有正确的引用,您需要将bar声明为final-即它不会、不能更改。到底是什么问题?将
user
和player
标记为final。这可能有助于进一步了解如何分解代码-通读这些代码以找出在哪里使用哪些变量有点像噩梦。好吧,我想我在自己的想法中感到困惑,最终对象是否仍然可以被操纵,它们是否与其他对象一样工作良好?最终对象并不能使对象不变。这只是意味着声明为final的变量/参数不能被重新分配(即使用xxx=somethingNew
所以我可以将它们保留为final?因为我害怕我不能调用对象方法,我想我通过编写类{private UserManager user;private Player;}来修复它在方法this.user=newusermanager();this.player=newplayer()中;那不知何故使任何错误消失了对象也会正常运行,因为我在对象中有一个hashset和一个hashmap,我不知道它发生了什么对不起,我不知道如何更好地表达我自己当你键入长代码时,请编辑你的问题,因为这样很难理解。总之是的,我很高兴它成功了!我也很高兴能提供帮助(:@zython-顺便说一句,在Java 8中,限制放宽了:局部变量实际上是final就足够了,而不需要显式声明为final。