+113
- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Pause extends JFrame{
private int MAX;
private static String s;
Pause(){
this.setSize(300, 300);
this.setVisible(true);
}
public void text(String s, final Thread t){
try {
t.wait();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
JLabel l = new JLabel(s);
l.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
t.notify();
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
});
this.add(l);
}
public int getMAX() {
return MAX;
}
public void setMAX(int mAX) {
MAX = mAX;
}
public String getS() {
return s;
}
public void setS(String s) {
this.s = s;
}
public void appendS(String s) {
this.s += s;
}
public static void main(final String[] args){
final Pause p = new Pause();
final Thread t = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < p.getMAX(); ++i){
p.appendS(i + " ");
if (i+2 <= p.getMAX()){
p.text(s, t); //error
}
}
}
});
t.start();
}
}
Прислала подруга, изучающая потоки в Java, с просьбой подсказать, почему выдаётся ошибка компиляции при использовании переменной t внутри run.
Придётся объяснять, что в этом коде неправильно вообще всё, от первой до последней строки...
Запостил: someone,
03 Мая 2013
wvxvw 03.05.2013 11:10 # 0
t жеж final, компилятор вполне же мог сообразить, что это просто синоним this.
someone 03.05.2013 11:22 # 0
wvxvw 03.05.2013 11:43 # 0
someone 03.05.2013 11:51 # 0
Например, представьте, что в данном примере метод run вызывается из конструктора класса Thread (хоть это и не так, но компилятор об этом не знает). Тогда будет произведено обращение к переменной t до завершения создания объекта и тем более до того, как объект будет ей присвоен.
wvxvw 03.05.2013 12:06 # 0
someone 03.05.2013 12:36 # 0
Как должен вести себя компилятор?
Вот такой пример не компилируется:
Что бы вывелось, если бы он компилировался?
wvxvw 03.05.2013 14:38 # 0
> что бы вывелось?
Точно то же самое, что и при попытке распечатать this. Почему так? - потому что t - ето просто лексическое связывание, и this тождественно t.
Но если бы мы говорили об операции присваивания (и ситуация в которой t и this Test'a различны имела бы смысл), то тогда, конечно, так нельзя делать.
По крайней мере, мой аргумент такой, что новичек, пусть и не осознано, но нашел нетривиальный случай, где размыта семантика языка, и причины по которым мжно было бы сделать так, как автору хотелось, мне видятся вполне легитимными.
someone 03.05.2013 14:44 # 0
Хорошо, в данном случае компилятор может "догадаться" и заменить t на this (кстати, почему бы тогда программисту сразу и не написать this?). Но в общем случае так поступить нельзя.
Например, в приведённом выше коде участвуют два объекта: Thread и Runnable, при этом в тело объекта Runnable передаётся переменная типа Thread. Тут уже this не отделаешься. В момент конструирования объекта Runnable объект Thread ещё не существует.
wvxvw 03.05.2013 15:01 # 0
Во-первых, проблема, которую вы описываете - решаемая.
Во-вторых, вы игнорируете неоднозначность конструкции a = b в Яве. Неоднозначность заключается в том, что иногда ее можно воспринять как разрушающее присваивание, а иногда, как выражение тождества. В первом случае вы бы были правы. Во втором - нет. final имеет отличительную особенность - переменным с таким модификаторм нельзя ничего позже присваивать, и поэтому, интуитивно, хочется верить, что они выражают тождество.
Как вы это тождество реализуете? - уже ваши проблемы, но принципиально можно показать, что это всегда реализуемо.
Это та же проблема, которая возникает при определении рекурсии:
Ведь вы же не считаете эту конструкцию невозможной потому что внутри f f "еще не известно".
someone 03.05.2013 15:17 # 0
В Java - invokevirtual/invokeinterface/invokestatic/invokespecial и пусть дальше JVM разбирается.
В нативном коде компилятор в момент генерации тела функции уже знает её адрес или по крайней мере смещение от текущей инструкции.
Как реализовать вышеупомянутую конструкцию - совершенно непонятно.
Вот ещё кусок кода, Фома ты неверующий:
Что прикажете делать компилятору? Ведь объекты создаются в строгой последовательности: сначала Inner, потом t. В момент выполнения конструктора объекта Inner объект t ещё не существует и, соответственно, не может быть передан по ссылке. А ссылка-то уже нужна!
wvxvw 03.05.2013 15:41 # 0
Вот, смотрите:
И работает ведь! ;)
someone 03.05.2013 15:47 # 0
В последнем моём примере t не тождественно this. Потому что внутри объекта Inner this - это объект Inner, а t - ещё не созданный объект Test.
wvxvw 03.05.2013 15:55 # 0
wvxvw 03.05.2013 16:52 # 0
wvxvw 03.05.2013 18:14 # 0
LispGovno 03.05.2013 18:48 # 0
wvxvw 03.05.2013 18:53 # +3
Или имеется в виду "."? - тогда Баш, наверное.
anonimb84a2f6fd141 03.05.2013 11:54 # −3
Но зачем? Он же уебищен. Как и почти весь гуй на яве, но хотя бы есть SWT.
wvxvw 03.05.2013 12:15 # 0
eth0 03.05.2013 13:12 # 0
wvxvw 03.05.2013 14:43 # 0
anonimb84a2f6fd141 03.05.2013 14:58 # −1
wvxvw 03.05.2013 15:02 # +1
anonimb84a2f6fd141 03.05.2013 15:03 # −1
Потому что всем похуй. И мб SWT тогда еще не вырос.
someone 03.05.2013 14:50 # +1
anonimb84a2f6fd141 03.05.2013 14:57 # −3
someone 03.05.2013 14:58 # 0
anonimb84a2f6fd141 03.05.2013 15:01 # −3
someone 03.05.2013 15:20 # +1
У Swing и SWT разные области применения. Swing (или его современная замена - JavaFX) хорош для приложений, где важен одинаковый вид приложения на разных платформах. SWT - для нативного вида.
anonimb84a2f6fd141 03.05.2013 17:14 # −2
Одинаковое говно на всех платформах, по крайней мере, на винде точно. Может одинаково мако- или прыщеблядский? Я еще не видел нормально смотрящегося на винде кроссплатформенного гуя. Или менее хуевый (QT, SWT), или совсем хуевый (GTK, все оставшиеся варианты явагуя). Ах да, swing еще и тормозной.
А что за look and feel и как его менять?
bormand 03.05.2013 17:18 # 0
someone 03.05.2013 17:38 # 0
Look and feel - тема оформления Swing. Кстати, конкретно под Windows есть и нативная тема оформления Swing. Под Linux/GTK теоретически тоже есть, но выглядит убого.
Как менять - погуглите на тему Nimbus.
anonimb84a2f6fd141 03.05.2013 20:44 # −5
SWT, может быть, тоже тормозной, но ему хоть можно простить, а тормозному кривому уебищу - как-то не хочется.
Lure Of Chaos 05.05.2013 11:53 # +2
LispGovno 05.05.2013 15:23 # +4
В зависимости от того, кто его танцует
defecate-plusplus 05.05.2013 15:43 # +11
Lure Of Chaos 05.05.2013 11:50 # 0
возможно, это связано с однопроходным анализатором.
3Doomer 18.06.2013 13:14 # −1
lammar 18.06.2013 00:43 # 0