Java 在我的代码中跳转
Java jumping ahead in my code
我 运行 遇到一个问题,其中 java 完全错误地解释了我的代码,我不知道如何更改它。由于我的程序太复杂,无法真正解释,所以我将对我的问题进行概括性描述,希望您能给我一个概括性的答案。
在我的代码中有一些类似的东西:
function1();
object.function2();
function1();
function1
改变对象。
当我 运行 this 时,我在 function2
内部遇到异常(这意味着代码永远不会到达第三行)。但是,当我删除第三行时,代码 运行s 没有任何问题。这意味着 java 编译器正在编译我的代码,使得 function1
的第二次调用对调用 object.function2
的前一行有一些影响。
同样有趣的是,如果在第 2 行和第 3 行之间插入一个断点,它在调试时始终有效。
这正常吗? java 中是否有任何原则导致了这种情况,以及有什么方法可以阻止这种情况?
该代码可在 Bitbucket Repository 获得,但请注意,它是未记录的意大利面条代码,可能违反 java 代码中的所有约定。描述的问题在 Pool.java 内,从第 41 行开始。
我希望我在这里提供的少量信息足以进行某种解释。
好吧,我认为已经足够了解这个问题,能够创建一个可能对您(当然)和希望对其他人有帮助的答案。
确实涉及到多线程,因为
object.function2();
正在创建一个 JFrame f。该帧 f 内的所有绘图操作都由 AWT-EventQueue-0(或任何其他数字)任务 T。此任务 T 运行 与您的主线程 M 并行。意思是在 f 内的自定义 JPanel p 中绘制的每个数据结构 l(如列表)和由 M 改变可能会导致问题。
例子
public static void main(String[] args) {
List<Integer> l = new ArrayList<Integer>(5);
JFrame gui = new JFrame();
gui.add(new MyPanel());
l.add(10);
}
public class GUI extends JPanel {
private List<Integer> l;
public MyPanel(List<Integer> l) {
this.l = l;
}
@Override
public void paintComponent(Graphics g) { // this is called by JFrame.paint()
super.paintComponent(g);
List<Integer> modifiedL = new ArrayList<Integer>(l.size());
for(Integer i : l) {
modifiedL.add(2 * i);
}
// this is a stupid example, because it makes no sense to
// use this loop with l.size() here, but it shows the main problem.
for(int c = 0; c < l.size(); c++) {
somehowDrawSthWith(modifiedL.get(c));
}
}
}
现在调用创建 JFrame 后更改 l 的大小,我们会导致 ArrayOutOfBoundsException 当试图访问 modifiedL.get(5) 时,因为 modifiedList 可能在 l.add(10)[=64 之前创建=].
(一个可能的)解
请注意,我写了 possible,因为这是 hacky 并且尽可能避免。
我们需要主线程 M 等待所有内容绘制完成。这是一种方法:
Java wait for JFrame to finish
在我们的示例中,我们可以将 main 更改为:
public static void main(String[] args) {
List<Integer> l = new ArrayList<Integer>(5);
CountDownLatch jFrameDrawing = new CountDownLatch(1);
JFrame gui = new JFrame();
gui.add(new MyPanel(), jFrameDrawing); // add the counter
try {
jFrameDrawing.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
l.add(10);
}
然后像这样在绘图方法结束时倒计时
@Override
public void paintComponent(Graphics g) { // this is called by JFrame.paint()
super.paintComponent(g);
// ...
jFrameDrawing.countDown();
}
请注意,在 p 真正完全绘制之前,可能会多次调用此方法。原因如下
因此,如果您的主要内容如下所示:
public static void main(String[] args) {
List<Integer> l = new ArrayList<Integer>(5);
CountDownLatch jFrameDrawing = new CountDownLatch(3); // NOTE 3
JFrame gui = new JFrame();
gui.add(new MyPanel(), jFrameDrawing); // draw once
gui.setSize(100,50); // draw again
gui.setVisible(true); // draw a third time
try {
jFrameDrawing.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
l.add(10);
}
您需要将初始计数器设置为 3。
长话短说:
在
中使用 AWT 类(例如 JFrame)
object.function2();
将创建多线程。这可能会产生竞争条件,例如同时修改列表。
看Java wait for JFrame to finish如何用主代码思考绘图。
我 运行 遇到一个问题,其中 java 完全错误地解释了我的代码,我不知道如何更改它。由于我的程序太复杂,无法真正解释,所以我将对我的问题进行概括性描述,希望您能给我一个概括性的答案。 在我的代码中有一些类似的东西:
function1();
object.function2();
function1();
function1
改变对象。
当我 运行 this 时,我在 function2
内部遇到异常(这意味着代码永远不会到达第三行)。但是,当我删除第三行时,代码 运行s 没有任何问题。这意味着 java 编译器正在编译我的代码,使得 function1
的第二次调用对调用 object.function2
的前一行有一些影响。
同样有趣的是,如果在第 2 行和第 3 行之间插入一个断点,它在调试时始终有效。
这正常吗? java 中是否有任何原则导致了这种情况,以及有什么方法可以阻止这种情况? 该代码可在 Bitbucket Repository 获得,但请注意,它是未记录的意大利面条代码,可能违反 java 代码中的所有约定。描述的问题在 Pool.java 内,从第 41 行开始。
我希望我在这里提供的少量信息足以进行某种解释。
好吧,我认为已经足够了解这个问题,能够创建一个可能对您(当然)和希望对其他人有帮助的答案。
确实涉及到多线程,因为
object.function2();
正在创建一个 JFrame f。该帧 f 内的所有绘图操作都由 AWT-EventQueue-0(或任何其他数字)任务 T。此任务 T 运行 与您的主线程 M 并行。意思是在 f 内的自定义 JPanel p 中绘制的每个数据结构 l(如列表)和由 M 改变可能会导致问题。
例子
public static void main(String[] args) {
List<Integer> l = new ArrayList<Integer>(5);
JFrame gui = new JFrame();
gui.add(new MyPanel());
l.add(10);
}
public class GUI extends JPanel {
private List<Integer> l;
public MyPanel(List<Integer> l) {
this.l = l;
}
@Override
public void paintComponent(Graphics g) { // this is called by JFrame.paint()
super.paintComponent(g);
List<Integer> modifiedL = new ArrayList<Integer>(l.size());
for(Integer i : l) {
modifiedL.add(2 * i);
}
// this is a stupid example, because it makes no sense to
// use this loop with l.size() here, but it shows the main problem.
for(int c = 0; c < l.size(); c++) {
somehowDrawSthWith(modifiedL.get(c));
}
}
}
现在调用创建 JFrame 后更改 l 的大小,我们会导致 ArrayOutOfBoundsException 当试图访问 modifiedL.get(5) 时,因为 modifiedList 可能在 l.add(10)[=64 之前创建=].
(一个可能的)解 请注意,我写了 possible,因为这是 hacky 并且尽可能避免。 我们需要主线程 M 等待所有内容绘制完成。这是一种方法: Java wait for JFrame to finish 在我们的示例中,我们可以将 main 更改为:
public static void main(String[] args) {
List<Integer> l = new ArrayList<Integer>(5);
CountDownLatch jFrameDrawing = new CountDownLatch(1);
JFrame gui = new JFrame();
gui.add(new MyPanel(), jFrameDrawing); // add the counter
try {
jFrameDrawing.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
l.add(10);
}
然后像这样在绘图方法结束时倒计时
@Override
public void paintComponent(Graphics g) { // this is called by JFrame.paint()
super.paintComponent(g);
// ...
jFrameDrawing.countDown();
}
请注意,在 p 真正完全绘制之前,可能会多次调用此方法。原因如下
因此,如果您的主要内容如下所示:
public static void main(String[] args) {
List<Integer> l = new ArrayList<Integer>(5);
CountDownLatch jFrameDrawing = new CountDownLatch(3); // NOTE 3
JFrame gui = new JFrame();
gui.add(new MyPanel(), jFrameDrawing); // draw once
gui.setSize(100,50); // draw again
gui.setVisible(true); // draw a third time
try {
jFrameDrawing.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
l.add(10);
}
您需要将初始计数器设置为 3。
长话短说: 在
中使用 AWT 类(例如 JFrame)object.function2();
将创建多线程。这可能会产生竞争条件,例如同时修改列表。 看Java wait for JFrame to finish如何用主代码思考绘图。