Erste Schritte while Schleife die eigendlich nicht gehen dürfte

-twix-

Mitglied
Guten Morgen an euch alle,

gehe gerade zu meiner java Zertifizierung ein paar Code - Schnipseöl durch und bin dabei auf das gestoßen:

int x = 12;

while (x < 10) {
x--;
}

System.out.print(x);

Meine meinung dazu geht nicht weil 12 nicht kleiner als 10 ist, aber der Compiler weiß es mal wieder besser.... :toll: was sagt ihr dazu?
 
warum soll das dann nicht gehen? es wird halt kein mal der Body ausgeführt (x--) und demnach bei syso 12 ausgegeben.
 
Richtig. Aber das ist kein Grund für den Compiler zu meckern. Eben für soetwas sind Schleifenbedingungen da. Sie können ausgeführt werden, müssen aber nicht (und wenn sie ausgeführt werden, dann eben solange, bis der Wert false ist, oder man "ausbricht").
 
sicher geht er nicht in die schleife, aber das sysout steht ja hinter der Schleife.
Ist so als wenn ein Kasten Wasser hinter deinem Auto steht und du überprüfst erst, ob du den Schlüssel vom Auto in der Tasche hast. Hast du nicht, aber den Kasten Wasser kannst trotzdem in deine Wohnung tragen.
 
genau. ignorieren ist vllt etwas hart. er prüft die bedingung vor jedem durchlauf und nachdem diese schon beim ersten durchlauf false liefert wird die schleife beendet bevor sie überhaupt angefangen hat 🙂
 
Ihr macht es euch etwas zu leicht. Hier muss man schon differenzieren. 😛
Ich denke, dass es darum geht, ob der Compiler meckern würde?

Das wäre dann der Fall, wenn x final wäre. Dies würde also nicht gehen:

Java:
final int x = 12;

while (x < 10) {
	x--;
}

System.out.print(x);

Es ist also nicht so, dass der Compiler die Schleife einfach ignorieren würde. Er sieht durch das
Code:
final
, dass das x an diesem Punkt nie kleiner als 10 sein wird und daher der Block der Schleife unerreichbar ist.

Eigentlich könnte er das ja auch schon ohne final sehen. Gehe mal davon aus, dass dies aber erst durch gewisse Optimierungen bzgl. final möglich wird.
 
ja im grunde genommen geht es um das kompilieren... aber interessanter ansatz mit dem final ^^

ja in dem Fall würde die Konstante ja in jedem Schleifendurchlauf verändert werden.

aber Konstanten können ja nicht verändert werden.
 
eigentlich sollte der compiler auch ohne das final erkennen können das (x--) ein unreachable statement ist da er ja weis das zwischen dem initialisieren von x mit dem wert 12 und dem prüfen ob x kleiner als 10 ist halt NICHTS mehr ist das x verändert
ich denke viel eher das der compiler nicht meckert weil er nur die while() als solches ansieht und nicht prüft ob die bedingung überhaupt jemals true werden kann denn das ist die aufgabe der Runtime und nicht des compilers

was das mit dem final angeht

xehpuk hat nur teilweise recht

der compiler weis durch das final nicht automatisch das die bedingung niemals erfüllt wird
dies bekommt er nur raus weil er mit final deklarierte referenzen anders behandelt
er stellt dann beim compilen der while() fest das x verändert werden MUSS um die bedingung zu erfüllen was aber durch FINAL nicht möglich ist
eigentlich müsste er dann nicht nur einen unreachable statement error werfen sondern auch einen illegal statement error da (x--) eine veränderung von x ist und dies laut definition von FINAL unzulässig wäre
da er diese anweisung aber bereits mit dem error kennzeichnet das sie sowieso nicht erreichbar ist wird dies verschluckt
 
ja in dem Fall würde die Konstante ja in jedem Schleifendurchlauf verändert werden.

aber Konstanten können ja nicht verändert werden.
Darum ging es mir nicht, das meinte ich gar nicht. Es ging darum, dass der Compiler meckert, weil die Schleife nie betreten werden kann. Es gibt also auch ohne
Code:
x--;
Gemecker.

Gemecker der gleichen Sorte würds auch hier für das letzte Statement geben, weil die Schleife nie verlassen wird:
Java:
final int x = 12;

while (x > 10) {
	// x--;
}

System.out.print(x);
 
eigentlich sollte der compiler auch ohne das final erkennen können das (x--) ein unreachable statement ist da er ja weis das zwischen dem initialisieren von x mit dem wert 12 und dem prüfen ob x kleiner als 10 ist halt NICHTS mehr ist das x verändert

Und was wenn da noch weitere Threads laufen, die unter Umständen das x "zufälligerweise" vor dem Betreten der Schleife verändern würden ? Oder dass das x über Sockets oder ähnliches verändert wird ? Das kann und darf der Compiler NICHT ausschließen. Bei final ist das was anderes, da er da zu 100% sicher ist, dass das x nicht mehr verändert werden kann.

Gruß
 
Das ist eine Lokalvariable, die nur ein Thread kennt. Wie sollen mehrere Threads auf sie zugreifen?

Das stimmt. Aber nach eurer Denkensweise, müsste der Compiler genauso bei so etwas meckern (pseudocode):
Java:
public class Test{
int x = 12;

public Test(){
}

//irgend ne Methode, in der allerdigs das x nicht verändert wird.
{
.....
while(x < 10){
//inhalt
}
}
}

Da wird das x doch auch nirgendswo verändert, also müsste die while() auch als unreachable code markiert werden, oder ? Also nach eurer Denkensweise. Soll der Compiler noch extra überprüfen, ob die Variable irgendwo übergeben wurde, oder ob andere Threads ggf. eine Referenz auf das Objekt haben und die Variable verändern oder wie ?
 
Ein Check bei (non-final) Instanzvariablen ist wohl zu weitgehend für den Compiler, weil er eben sicherstellen müsste, dass der Wert der Variable nirgendwo verändert werden kann.
Variablenübergabe ist hier ja kein Thema wegen "call by value".
 
Naja, hier hast du eigentl. einen komplett anderen Fall. Da reicht schon dieses Beispiel:
Java:
public class Sample {
    private int x=12;

    public static void main(String... args) {
          while(x<10) doSomething();
    }
}

Abgesehen von Reflection, (in diesm fall nicht vorhandenen) Setter oder internen Methoden, kann das x noch von JNI-Calls manipuliert werden (mittels JNI und Reflection ist es auch möglich finale Variablen zu ändern).

Auf die schnelle würde mir hier nur bytecodemanipulation einfallen, um dieses x zu verändern, sodass es der Compiler nicht mitbekommt.
 
Variablenübergabe ist hier ja kein Thema wegen "call by value".

In diesem fall ist das kein Thema, das ist schon klar, aber wir können doch nicht erwarten, dass der Compiler guckt, ob es sich bei den Variablen um Call By Value oder Call By Reference handelt, dann noch überprüft ob es getter, setter, referenzen auf das Objekt gibt und sonst etwas.

Zu den Reflections und JNI-Calls kann ich jetzt nichts sagen, da ich auf diesem Gebiet ehrlich gesagt gar keine Ahnung habe.

Worauf ich eigentlich hinaus wollte: Meiner Meinung nach, sollte der Compiler bei solchen Fällen gar nicht meckern (auch bei final nicht - sehe Post von Tomate_Salat ). Als Unreachable code markiert gehört für mich nur Code der hinter einem Return (ohne finally und so etwas) noch eusgeführt werden sollte. Was Variablen und betreten der Schleifen aufgrund von Werten angeht, sollte der sich davon fern halten 🙂
 
Java kennt an sich kein wirkliches Call by Value oder Call by Reference. Es wird normal lediglich die Speicheradresse des Objektes übergeben. Weswegen soetwas auch keine Nachhaltigen Auswirkungen hat:
Java:
public void doSomething(MyObject obj) 
{
    obj=new MyObject("peter");
}

aber das ist ein anderes Thema (kleiner Tipp: um solche Logikfehler zu vermeiden: Parameter einfach final machen und in der IDE die Warnung einstellen).

Das der Compiler bei final meckert ist OK und richtig so. Finale Variablen sollen nicht geändert werden, deswegen ist es richtig, dass der Compiler von einem Konstantem Wert ausgeh (das es Möglichkeiten gibt, habe ich geschrieben, diese lassen sich aber afaik durch einen SecurityManager unterbinden)t. Wenn man also streng nach dem Sinn programmiert, ist der Code tatsächlich deadcode.
 

Zurück
Oben