java 从另一个类访问静态变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12398887/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Access static variable from another class
提问by RK.
I have two classes in same package. i have declared a static variable
in one class and want to access that variable in another class.
我在同一个包中有两个类。我static variable
在一个类中声明了 a并想在另一个类中访问该变量。
Here is my code in which i have declared the static variable
这是我在其中声明了静态变量的代码
public class wampusGUI extends javax.swing.JFrame {
static String userCommand;
public wampusGUI() {
initComponents();
}
public void setTextArea(String text) {
displayTextArea.append(text);
}
private void enterButtonActionPerformed(java.awt.event.ActionEvent evt) {
userCommand = commandText.getText();
}
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
wampusGUI w = new wampusGUI();
w.setVisible(true);
Game g = new Game(w);
g.play();
}
});
}
}
Here is the code in which i want to access variable
这是我想访问变量的代码
public class Game {
private wampusGUI gui;
public Game(wampusGUI w) {
world = new World();
world.start();
gui = w;
}
public void play() {
gui.setTextArea(welcome());
gui.setTextArea(describe());
for (;;) {
String s = userCommand; // here value should come should
System.out.println(userCommand);
Command c = Command.create(s);
String r = c.perform(world);
// is game over?
if (r == null) {
break;
}
System.out.println(r);
}
System.out.println("Game over");
}
}
However, i can pass the variable from first class as a argument. but the problem is that, when i will run program the value is going null first time, which i dont want. i want when i enter value in textfield
then it should go to another class.
但是,我可以将第一类的变量作为参数传递。但问题是,当我运行程序时,该值第一次变为空值,这是我不想要的。我希望当我输入值时textfield
它应该转到另一个类。
Thank you.
谢谢你。
采纳答案by Hovercraft Full Of Eels
I suggest that you use a listener of one sort or another to allow the Game object to listen for and respond to changes in the state of the GUI object. There are several ways to do this, but one of the most elegant and useful I've found is to use Swing's own innate PropertyChangeSupport to allow you to use PropertyChangeListeners. All Swing components will allow you to add a PropertyChangeListener to it. And so I suggest that you do this, that you have Game add one to your WampusGUI class (which should be capitalized) object like so:
我建议您使用一种或另一种侦听器来允许 Game 对象侦听并响应 GUI 对象状态的变化。有几种方法可以做到这一点,但我发现的最优雅和最有用的方法之一是使用 Swing 自己的固有 PropertyChangeSupport 来允许您使用 PropertyChangeListeners。所有 Swing 组件都允许您向其添加 PropertyChangeListener。所以我建议你这样做,你让 Game 添加一个到你的 WampusGUI 类(应该大写)对象,如下所示:
public Game(WampusGUI w) {
gui = w;
gui.addPropertyChangeListener(new PropertyChangeListener() {
// ....
}
This will allow Game to listen for changes in the gui's state.
这将允许 Game 监听 gui 状态的变化。
You'll then want to make the gui's userCommand String a "bound property" which means giving it a setter method that will fire the property change support notifying all listeners of change. I would do this like so:
然后,您需要使 gui 的 userCommand 字符串成为“绑定属性”,这意味着给它一个 setter 方法,该方法将触发属性更改支持,通知所有更改的侦听器。我会这样做:
public class WampusGUI extends JFrame {
public static final String USER_COMMAND = "user command";
// ....
private void setUserCommand(String userCommand) {
String oldValue = this.userCommand;
String newValue = userCommand;
this.userCommand = userCommand;
firePropertyChange(USER_COMMAND, oldValue, newValue);
}
Then you would only change this String's value via this setter method:
然后你只能通过这个 setter 方法改变这个 String 的值:
private void enterButtonActionPerformed(java.awt.event.ActionEvent evt) {
setUserCommand(commandText.getText());
}
The Game's property change listener would then respond like so:
然后游戏的属性更改侦听器将响应如下:
gui.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent pcEvt) {
// is the property being changed the one we're interested in?
if (WampusGUI.USER_COMMAND.equals(pcEvt.getPropertyName())) {
// get user command:
String userCommand = pcEvt.getNewValue().toString();
// then we can do with it what we want
play(userCommand);
}
}
});
One of the beauties of this technique is that the observed class, the GUI, doesn't have to have any knowledge about the observer class (the Game). A small runnable example of this is like so:
这种技术的优点之一是被观察类,即 GUI,不必了解观察者类(游戏)。一个可运行的小例子是这样的:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
public class WampusGUI extends JFrame {
public static final String USER_COMMAND = "user command";
private String userCommand;
private JTextArea displayTextArea = new JTextArea(10, 30);
private JTextField commandText = new JTextField(10);
public WampusGUI() {
initComponents();
}
private void setUserCommand(String userCommand) {
String oldValue = this.userCommand;
String newValue = userCommand;
this.userCommand = userCommand;
firePropertyChange(USER_COMMAND, oldValue, newValue);
}
private void initComponents() {
displayTextArea.setEditable(false);
displayTextArea.setFocusable(false);
JButton enterButton = new JButton("Enter Command");
enterButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
enterButtonActionPerformed(evt);
}
});
JPanel commandPanel = new JPanel();
commandPanel.add(commandText);
commandPanel.add(Box.createHorizontalStrut(15));
commandPanel.add(enterButton);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
mainPanel.add(new JScrollPane(displayTextArea));
mainPanel.add(commandPanel, BorderLayout.SOUTH);
add(mainPanel);
}
public void setTextArea(String text) {
displayTextArea.append(text);
}
private void enterButtonActionPerformed(java.awt.event.ActionEvent evt) {
setUserCommand(commandText.getText());
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
WampusGUI w = new WampusGUI();
w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
w.pack();
w.setLocationRelativeTo(null);
w.setVisible(true);
Game g = new Game(w);
g.play();
}
});
}
}
class Game {
private WampusGUI gui;
public Game(WampusGUI w) {
gui = w;
gui.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent pcEvt) {
// is the property being changed the one we're interested in?
if (WampusGUI.USER_COMMAND.equals(pcEvt.getPropertyName())) {
// get user command:
String userCommand = pcEvt.getNewValue().toString();
// then we can do with it what we want
play(userCommand);
}
}
});
}
public void play() {
gui.setTextArea("Welcome!\n");
gui.setTextArea("Please enjoy the game!\n");
}
public void play(String userCommand) {
// here we can do what we want with the String. For instance we can display it in the gui:
gui.setTextArea("User entered: " + userCommand + "\n");
}
}
回答by Robin
Looking at your code, it seems you want to show dialogs to your user with a certain text
查看您的代码,您似乎想使用特定文本向用户显示对话框
gui.setTextArea(welcome());
gui.setTextArea(describe());
and sometimes, that dialog should capture user input which is handled afterwards.
有时,该对话框应该捕获随后处理的用户输入。
- Those
setTextArea
calls are not what you want to use. The user will never see the welcome message as it will immediately be replaced by the describe message. - Make sure you do not block the Event Dispatch Thread (EDT) or nothing will be shown at all. I do not know what your
Command
class will do, but I see an infinite loop on theEvent Dispatch Thread
which is never a good thing. Take a look at the Concurrency in Swing tutorialfor more information - Thanks to that
for
loop, the user will simply not be capable to input any command as the EDT is busy handling your loop. What you need is a blocking call allowing the user to provide input (not blocking the EDT, but just blocking the execution of your code). The static methods in theJOptionPane
class are perfectly suited for this (e.g. theJOptionPane#showInputDialog
). These methods also have a mechanism to pass the user input back to the calling code without any static variables, which solves your problem.
- 这些
setTextArea
调用不是您想要使用的。用户永远不会看到欢迎消息,因为它会立即被描述消息替换。 - 确保您没有阻塞事件调度线程 (EDT),否则根本不会显示任何内容。我不知道你的
Command
班级会做什么,但我看到了一个无限循环,Event Dispatch Thread
这从来都不是一件好事。查看Swing中的并发教程以获取更多信息 - 由于该
for
循环,用户将无法输入任何命令,因为 EDT 正忙于处理您的循环。您需要的是一个阻塞调用,允许用户提供输入(不阻塞 EDT,而只是阻塞代码的执行)。JOptionPane
类中的静态方法非常适合于此(例如JOptionPane#showInputDialog
)。这些方法还具有将用户输入传递回调用代码的机制,无需任何静态变量,从而解决了您的问题。
回答by PC.
I agree with Jon Skeet that this is not a good solution...
我同意 Jon Skeet 的观点,这不是一个好的解决方案......
But in case u want an dirty solution to ur problem then u can try this:
但是如果你想要一个肮脏的解决方案来解决你的问题,那么你可以试试这个:
public class wampusGUI extends javax.swing.JFrame
{
private static wampusGUI myInstance;
public wampusGUI( )
{
myInstance = this;
initComponents();
}
public static void getUserCommand()
{
if(myInstance!=null)
{
return myInstance.commandText.getText();
}
else
{
return null;
}
}
......
......
}
in the other class use:
在另一个类中使用:
public void play()
{
.....
//String s = userCommand; // here value should come should
String s = wampusGUI.getUserCommand();
.....
}
This kind of code is there in some of our legacy projects... and I hate this.
这种代码存在于我们的一些遗留项目中……我讨厌这种情况。