Array verwirrung !

JavArray()

Mitglied
Hey Leute ,
Wieso zu Teufel wird hier der index 0 ausgegeben ?
ich kann es absolut nicht nachvollziehen 🙄
Code:
    public static void main(String[] args) {

        int[] a = { 1, 2, 3, 4 };
        int[] b = { 2, 3, 1, 0 };
        System.out.println(a[(a = b)[3]]);
    }
 
Ich nehme folgendes an:
Durch ( a = b ) wird das Array "a" zu Array "b" und übernimmt dessen Elemente. Und daher das 4. Element des Array`s "b" ( b[3] )
0 ist bekommst du das als Ausgabe.
 
Ich nehme folgendes an:
Durch ( a = b ) wird das Array "a" zu Array "b" und übernimmt dessen Elemente. Und daher das 4. Element des Array`s "b" ( b[3] )
0 ist bekommst du das als Ausgabe.
Die Antwort ist schon recht gut, jedoch wurde hier so wie ich das sehe nur der Inhalt von dem a[....] behandelt. Das Beispiel zeigt recht gut, dass gewisse Konstrukte schlicht nicht verwendet werden sollten, weil schwer verständlich!

Das Ganze ist lässt sich meiner Meinung nach recht gut aufteilen in:
- 1. Von dem Array a soll ein Element ausgegeben werden:
- 2. (a=b) -> Die Variable a verweist nun auf das Array, auf das auch b verweist.
- 3. a[3] ist nun das 4. Element von b -> 0!
- 4. Nun wird das erste Element (index 0) von a ausgegeben. (Dabei wird aber noch die alte a Referenz genommen, denn das Array für die Ausgabe wurde in Schritt 1 festgelegt) -> Ausgabe 1!

Sowas ist nicht immer so leicht zu sehen. Im Clean Code hat man daher oft so Regeln wie "Keine verschachtelten Befehle".
Bei Java geht es prinzipiell noch, denn ich meine, dass da die Abarbeitungsreihenfolge immer klar definiert ist. Aber in C / C++ gibt es dann z.B. Konstrukte, deren Verhalten undefiniert ist (und wo dann je nach Compiler unterschiedliche Ergebnisse zustande kommen können).
 
Code:
Compiled from "A.java"
public class A {
  public A();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_4
       1: newarray       int       // Array festlegen
       3: dup
       4: iconst_0
       5: iconst_1
       6: iastore
       7: dup
       8: iconst_1
       9: iconst_2
      10: iastore
      11: dup
      12: iconst_2
      13: iconst_3
      14: iastore
      15: dup
      16: iconst_3
      17: iconst_4
      18: iastore
      19: astore_1
      20: iconst_4
      21: newarray       int       // Array festlegen
      23: dup
      24: iconst_0
      25: iconst_2
      26: iastore
      27: dup
      28: iconst_1
      29: iconst_3
      30: iastore
      31: dup
      32: iconst_2
      33: iconst_1
      34: iastore
      35: dup
      36: iconst_3
      37: iconst_0
      38: iastore
      39: astore_2
      40: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      43: aload_1       // Array a
      44: aload_2       // Array b
      45: dup
      46: astore_1
      47: iconst_3
      48: iaload
      49: iaload
      50: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
      53: return
}

( Etwas kommentiert )
 
Meinen ist immer gut, wissen ist besser... ja, das ist klar definiert.

Nunja - ist wirklich alles klar definiert? Ich selbst erlaube mir da kein sicheres Urteil, denn auch wenn ich die Spezifikationen der Sprache und der VM gelesen habe ist es leicht, etwas zu übersehen.

Aber wenn man dann z.B. Tabellen für die Reihenfolge von Operatoren ansieht, dann findet man im Web z.B.:
https://introcs.cs.princeton.edu/java/11precedence/
Und da steht dann unter der Tabelle:
"There is no explicit operator precedence table in the Java Language Specification. Different tables on the web and in textbooks disagree in some minor ways."

Da es leider keine Ausführung, was für Abweichungen es speziell gibt, kann ich auch nicht bewerten, ob dies dann auf Fehler in einer Tabelle zurück zu führen ist, oder ob es ggf. doch Unklarheiten in der Spezifikation gibt. Aber ich habe genug Vertrauen zu den Fachleuten der Princeton Universität, so dass ich da zumindest vorsichtiger formuliere. => Ich meine somit nur noch, dass in Java die Reihenfolge immer sicher definiert ist und es keine Konstrukte gibt, deren Verhalten nicht klar definiert ist.
 
Gut, dann will ich es mal so formulieren, es gibt keinen Term, dessen Auswertung s Reihenfolge nicht eindeutig ist.

Oder anders: Was irgendein Student auf eine Website mal geschrieben hatte, tangiert mein Interesse nur peripher.

Oder anders: Bitte heute keine Verschwörungstheorien.
 
Also gut: Bitte belege Deine Aussage. Du kannst mir dies dann doch sicher darlegen.

Und was deine "oder anders" amgeht:
-> Ja, diese Sichtweise hast Du schon öfters gezeigt. Aber das ist mir egal. Ich selbst schaue mir Aussagen an und bewerte diese. (So ist mir z.B. egal, was Du hier meinst schreiben zu müssen. Ohne klare Argumente ist das einfach nur eine Meinung, die ich zur Kenntnis nehme und ohne Argumente einfach belächle ...)
-> Wo Du Verschwörungstheorien siehst, ist wieder etwas, was wir nicht verstehen müssen ... Die zitierte Aussage ist zumindest im ersten Teil sehr einfach nachzuvollziehen: Gibt es eine solche Tabelle in der JLS oder nicht? Da könnte man jetzt Kapitel 15 der JLS betrachten ... Nur um einen Anfang zu nennen ...

Generell kannst Du so auftreten, wie Du willst. Du kannst Meinungen als Wahrheiten verkaufen und so.... Du darfst dann auch gerne an diese "Wahrheiten" glauben. Das ist Dir überlassen.
Aber bitte lass mir auch meine Ausdrucksweise. Ich trete etwas vorsichtiger auf. Dafür habe ich gute Gründe und diese konnte ich sogar auch darlegen. Das auf diese Art und Weise - vor allem ohne wirkliche Argumente - zu behandeln, das ist schlicht etwas, das Du Dir sparen kannst. Wenn Du keine Argumente hast, dann lass es bleiben.
 
Das ist nunmal per Definition festgelegt. Es gibt dabei nix zu argumentieren. Natürlich kann ich Unsicherheiten verstehen - andererseits wird man aber auch nicht bei Unsicherheit gezwungen, zu antworten...

Ach so und noch etwas, es gibt (gegenüber dem Forum) keine Pflicht "zur Auskunft" - oder in einer bestimmten und von dir gewünschten Art zu antworten.
 
Ich weiß vielleicht, wo diese Unsicherheit herrührt. Es wäre etwas anderes wenn das in Funktionsaufrufen geschehe: f(g((a=b))) oder f((a=b)[3]), dann "sieht" er das Array erst "spät".
 
Allerdings war die Grammatik anscheinend nicht immer eindeutig (es gibt einen Absatz, der darauf hindeutet); wenn man sich die JLS Version 6 ansieht, wird einem schlecht 🙂
 
Das ist nunmal per Definition festgelegt. Es gibt dabei nix zu argumentieren. Natürlich kann ich Unsicherheiten verstehen - andererseits wird man aber auch nicht bei Unsicherheit gezwungen, zu antworten...

Ach so und noch etwas, es gibt (gegenüber dem Forum) keine Pflicht "zur Auskunft" - oder in einer bestimmten und von dir gewünschten Art zu antworten.
Also darauf einzugehen verkneifen ich mir lieber... Wobei ich schon gerne einmal paar Zitate aus anderen Threads bringen würde 🙂

Die Operatorenreihenfolge ist definiert über die Grammatik, https://docs.oracle.com/javase/specs/jls/se11/html/jls-15.html#jls-15.2 schreibt dazu:
Die Operatoren Reihenfolge ist aber nicht das entscheidene ... Wichtiger ist hier aus meiner Sicht die Auswerte-Reihenfolge.

Bin jetzt leider nur am Handy und da werde ich das nicht im Detail heraus suchen. Da schreibe ich später am Computer noch etwas dazu.
 
Operatorenreihenfolge bestimmt, in welcher Reihenfolge die Operatoren ausgeführt werden müssen. Also vergleichbar mit einer Klammerung.

Aber das Beispiel zeigt ja recht gut, dass es nicht nur um die Operatoren selbst geht sondern auch um die Reihenfolge der Auswertung der Operanden.

So kann man a() + b() * c() nehmen. Hier besagt die Operatornreihenfolge, dass die Multiplikation vor der Addition ausgeführt wird.
Aber bezüglich der Aufrufe ist nicht die Ausführung der Operatoren verantwortlich sondern hier kommt die Auswertung der Operanden zum tragen. (Also nicht 15.2 sondern 15.7 der JLS).

Dies ist gerade bei diesen Fällen, wie sie hier besprochen werden, aus meiner Sicht existenziell.

Die Reihenfolge, in der etwas gemacht wird, wird also von beidem - der Operatoren Reihenfolge und der Auswertung der Operanden bestimmt.

Hier kommt aber jetzt die große Frage von mir:
Bei dem Beispiel mit a[....(a=b)...]: Wo findet sich die Definition des Array Zugriffs. dass halt erst das Array selbst bestimmt wird und dann das Element bestimmt wird - so dass die Zuweisung des b-Arrays nichts mehr verändert?
- Ist dies Bestanteil der JLS oder JVMS?
- Falls das dort nicht festgelegt wurde: Ist es evtl. woanders festgelegt? Ist es Bestandteil der Offiziellen Tests von Oracle?
Evtl. hat das ja jemand gerade parat ... @Tobias-nrw: Da Du so sicher bist, dass alles definiert ist, wirst Du das evtl. wissen?
 
Wo findet sich die Definition des Array Zugriffs. dass halt erst das Array selbst bestimmt wird und dann das Element bestimmt wird - so dass die Zuweisung des b-Arrays nichts mehr verändert?
JLS 15.10.4:
At run time, evaluation of an array access expression behaves as follows:

  • First, the array reference expression is evaluated. If this evaluation completes abruptly, then the array access completes abruptly for the same reason and the index expression is not evaluated.
  • Otherwise, the index expression is evaluated. If this evaluation completes abruptly, then the array access completes abruptly for the same reason.
  • ...
 

Neue Themen


Zurück
Oben