Semantik-Warnung, Random

Folgende Methode (etwas vereinfacht):

	Random r = new Random();
	Clazz myClazz = new Clazz(r.nextInt(4));
	// ...
}```

wird im Zuge einer Refactoring-Maßnahme geändert zu:

```private static void tueWas1() {
	Random r = new Random();
	Clazz myClazz = new Clazz(tueWas2(r));
	// ...
}

private static int tueWas2(Random r) {
	return r.nextInt(4);
}```

NB gibt mir an der Stelle eine Warnung, kein Error o. Ä., dass sich dadurch die Semantik änderte. Stimmt das?
Sollte man so ein Refactoring vermeiden?

Nein, sehe ich nicht so. Das ist doch ein simples “Extract Method”, das ändert nichts an der Semantik.

Wie ist die vollständige, nicht-vereinfachte Methode?

Hier noch ein kleiner Vorrat an "andom"s, vielleicht kannst du sie gebrauchen:
andom
andom
andom
andom
andom
andom
andom
andom
andom
andom

andom hab ich doch gar nicht geschrieben? Hab ich was verpasst?

Die komplette Klasse ist komplizierte Vektorrechnung. Tut hier nix zur Sache tun. Andere Refactorings tut NB auch ohne Fehler/Warnings tun.

Darum ging es. Ich finde, ein Random-Objekt kann ruhig random heißen. Genau wie ein JButton mit dem man startet startButton heißen sollte, und nicht einfach b (und auch nicht btnSt oder so… manche Leute scheinen eine seltsame Aversion gegen Vokale zu haben). Aber genug des Bikesheddings:

Ich weiß nicht, wie “schlau” NetBeans an dieser Stelle ist, aber solange man nicht weiß, was dort noch alles steht und ggf. durch das Refactoring geändert wurde, kann man nicht wissen, ob sich die Semantik ändert.

Nagut, ich hab es jetzt auch verstanden, du hast um die Ecke gedacht, ich nicht. :rolleyes:

Mache ich mal ein Faß auf. Ich möchte vektorrechnung “üben”, weil ich nicht weiß, wie ich so etwas, schnell, einfach und sicher mit/ohne Zwischenschritte berechnen kann, und welchen TRICK es dabei gibt:

Hier sinds Java-Methoden:

        Random r = new Random();
        final int r1 = 5;
        final int r2 = 4;
        Matrix4x4String m1 = new Matrix4x4String(
                ""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),
                ""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),
                ""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),
                ""+0,""+0,""+0,""+(r.nextInt(3) < 2 ? 1 : 0)
        );
        Matrix4x4String m2 = new Matrix4x4String(
                ""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),
                ""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),
                ""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),
                ""+0,""+0,""+0,""+(r.nextInt(3) < 2 ? 1 : 0)
        );
        Matrix4x4String m3 = new Matrix4x4String(
                ""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),
                ""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),
                ""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),""+(r.nextInt(r1) < r2 ? zufWert(r) : 0),
                ""+0,""+0,""+0,""+(r.nextInt(3) < 2 ? 1 : 0)
        );
        Matrix4x4String neu = m1.mal( m2.mal(m3));
        System.out.println(m1+"*
"+m2+"*
"+m3+"=
"+neu);
    }

    private static int zufWert(Random r) {
        return r.nextInt(2) < 1 ? r.nextInt(4) : -r.nextInt(4);
    }

    // zufWert(Random r) wurde refactort

class Matrix4x4String {

    String[][] da = new String[4][4];

    public Matrix4x4String(String... a) {
        da[0][0] = a[0];
        da[0][1] = a[1];
        da[0][2] = a[2];
        da[0][3] = a[3];

        da[1][0] = a[4];
        da[1][1] = a[5];
        da[1][2] = a[6];
        da[1][3] = a[7];

        da[2][0] = a[8];
        da[2][1] = a[9];
        da[2][2] = a[10];
        da[2][3] = a[11];

        da[3][0] = a[12];
        da[3][1] = a[13];
        da[3][2] = a[14];
        da[3][3] = a[15];
    }
    
    public Matrix4x4String mal(Matrix4x4String n) {
        Matrix4x4String m = this;
        Matrix4x4String neu = new Matrix4x4String(new String[16]);
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                String s = "";
                for (int k = 0; k < 4; k++) {
                    if (!m.da**[k].equals("0") && !n.da[k][j].equals("0")) {
                        if (m.da**[k].equals("1"))
                            s += n.da[k][j] + " + ";
                        else if (n.da[k][j].equals("1"))
                            s += m.da**[k] + " + ";
                                else
                        s += m.da**[k] + " * " + n.da[k][j] + " + ";
                    }
                }
                if (s.isEmpty()) {
                    s = "0";
                }else {
                s = s.substring(0, s.length()-3);
                }
                neu.da**[j] = s;
            }
        }
        return neu;
    }

    @Override
    public String toString() {```

Das ist jetzt alles Relevantes. Ich wette, jetzt kommt Kritik wegen der Methode mal oder wegen substring...

Eigentlich lese ich hier fast nur, aber du gehst mir schon lange auf den Sack!

Wie kannst du irgendwas anderes erwarten? Entweder du bist lernunwillig, oder einfach zu blöd.
Nach Jahren die du jetzt schon fleißig programmierst, bringst du immer wieder so einen Mist zu Stande.
Mal abgesehen von diesem unlesbaren, unstrukturierten Code schaffst du es immer noch nicht dich an einfachste Konventionen zu halten.

private static void Probe()

Ernsthaft?
Ernsthaft: Lass es einfach sein, such dir was anderes, du hast bestimmt andere Stärken :o

Sorry für den Spam, aber ich verstehe einfach nicht warum CB überhaupt noch von jemandem ernsthafte Antworten bekommt!?

@Bene Genervt zu sein ist jedermanns Recht. Ich lasse wohl auch gelegentlich durchscheinen, dass ich von bestimmten Dingen nicht so begeistert bin, und mir bestimmte Dinge schwerfallen. Aber wenn’s hart auf hart kommt, ist ignorieren immernoch eine Option (und zumindest besser, als Beleidigungen um sich zu werfen, die alles noch schlimmer machen). Die, für die es relevant ist, haben ein Auge drauf, und zuletzt “ging” es ja einigermaßen.

*** Edit ***

Fachliche Kritik ist hier gerechtfertigt. Wenn man (r.nextInt(r1) < r2 ? zufWert(r) : 0) drei mal schreibt, sollte man sich überlegen, ob man das nicht auslagert.

Ansonsten… es gibt keinen “Trick”. Matrixmultiplikation sind drei verschachtelte Schleifen (zumindest auf dieser Ebene, solange sich sowas wie https://de.wikipedia.org/wiki/Strassen-Algorithmus nicht lohnt).

Ich hab’s noch mal formatiert (OT: den Flameware hab ich nicht mitgekriegt):

        Matrix4x4String m = this;
        Matrix4x4String neu = new Matrix4x4String(new String[16]);
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                String s = "";
                for (int k = 0; k < 4; k++) {
                    if (!m.da**[k].equals("0") && !n.da[k][j].equals("0")) {
                        if (m.da**[k].equals("1")) {
                            s += n.da[k][j] + " + ";
                        } else if (n.da[k][j].equals("1")) {
                            s += m.da**[k] + " + ";
                        } else {
                            s += m.da**[k] + " * " + n.da[k][j] + " + ";
                        }
                    }
                }
                if (s.isEmpty()) {
                    s = "0";
                } else {
                    s = s.substring(0, s.length() - 3);
                }
                neu.da**[j] = s;
            }
        }
        return neu;
    }```

Der Algo berechnet also (auch) die Zwischenschritte.

 @Marco13  : Findest du es sinnvoll, diesen Algo während einer Prüfung "manuell per Hand im Kopf durchzuspielen" mit mehreren Matrizen - oder kann man es sich irgendwie einfacher machen? Akute konkrete nicht-abstrakte Gefahr droht hierbei aber (z. Z.) nicht.

Der Algorithmus wird mit 3 Schleifen wohl rechentechnisch für einen PC performant sein.
Wenn man aber das ganze manuell machen möchte dann würde ich hier ein Refactoring empfehlen, welches die Vorgehensweise besser verdeutlicht.

Dazu benötigt es zwei zusätzliche Methoden in der Matrix-klasse. Die jeweils einen einzelnen Vector der Zeile oder Spalte zurückliefern.

String[] getRow(int rowIndex) String[] getColumn(int columnIndex)

Danach bietet sich noch eine Hilfsmethode an die zwei Vektoren entgegennimmt und miteinander multipliziert.

  StringBuilder result = new StringBuilder();
  for(int i = 0; i < 4; i++) {
    if(result.length() > 0) {
      result.append(" + ");
    }
    // Hier könnte man dann noch die Vereinfachungen vornehmen, was jetzt aber mal den Rahmen sprengt.
    result.append(vector1** + " * " + vector2**);
  }
  return result.toString();
}```

Damit bleiben dann in der Multiplikationsmethode der Matrix nur noch zwei Verschachtelte Schleifen, die dann jeweils die Multiplikationsmethode mit den Zeilenvektor aus der einen und Spaltenvektor aus der anderen Matrix aufrufen um das Ergebnis für einen Punkt zu bekommen.

```for(int row; row < 4; row++) {
  for(int column; column < 4; column++) {
    neu.da[row][column] = multiply(this.getRow(row), m.getColumn(column));
  }
}

Das liegt dann eher an der Vorgehensweise die man manuell machen würde. Zeilenvektor nehmen und mit Spaltenvektor multiplizieren. Nächsten Splatenvektor nehmen multiplizieren und Ergebnis daneben schreiben.

Selbes Spiel mit dem nächsten Zeilenvektor und Ergebnisse in der nächsten Zeile eintragen.

Zwei Schleifen plus eine für die jeweilige Multiplikation der Vektoren miteinander in einer Hilfsfunktion.

Yea, man könnte noch den Shunting-yard-Algorithmus einbauen, möchte ich aber im Moment nicht. Man soll ja Zwischenschritte sehen. Danke für Dein Refactoring. Also ich möchte (m,n)-Zelle berechnen. Dann nehme ich Zeile m, drehe um -90° (Uhrzeigersinn) und “multipliziere” sie mit Spalte n. Leider sind meine Berechnungen etwas eingerostet. Zeile ist noch in Ordnung, aber dann wähle ich die falsche Spalte (irgendwann). Naja, muss ich durch. Gibt es denn noch Regeln, außer 0 == Rechnung nicht beachten, 1 == nur den anderen Teil aufschreiben?

Zur eigentlichen Frage:
Ein Random-Objekt ist ja sozusagen ein Mutable, bzw. werden die folgenden Werte immer nach einem Algorithmus berechnet. Bei der Verwendung verschiedener Random-Objekte (die werden ja übergeben) könnte es deswegen vorkommen, dass die Zufalls-Funktion von “nextInt()” ausgehebelt wird und möglicherweise mängelt NB genau diesen Umstand an - einfach mal in den Raum gedacht. Abhilfe könnte eine konstante Klassen- bzw. Objekt-Variable des Typs Random schaffen:

  private static final Random RANDOM = new Random();

  void tuwas1() {
    Clazz myClazz = new Clazz(tuwas2());
  }

  int tuwas2() {
    return RANDOM.nextInt(4);
  }
}```

Leider kann ich das nicht testen, weil Eclipse diese Warnung gar nicht bringt, was aber an einer Einstellung meinerseits liegen könnte.

Daran hatte ich auch schon gedacht, dass bei Kopie der Referenz bei Methodenübergabe i-was am singleton immutable geändert wird . . . … Kann aber eigentlich nicht sein! Naja, NB kritisiert halt die ganze Zeit - was auf der anderen Seite auch gut ist! Aber meine Projekte müssen alle grün sein, Gelb, Grau oder ein Pop-Up(!) versetzt mich in Rage!

Ich möchte noch dazu erwähnen, dass ich es bei mir (Mac mit NetBeans 8.1) nicht nachstellen kann, d.h. ich kriege keine Warnung. Ich kann auch unter “Einstellungen -> Editor -> Hinweise” nichts zu Semantik finden kann

Schade, dass NB blödsinnige Variablenbezeichner nicht kritisiert…

[QUOTE=CyborgBeta]i-was am singleton immutable geändert wird[/QUOTE]Also Random-Obkekte sind keine Singletons, das sollte klar sein. Und je nach Initialisierung und Nutzung hat jedes dieser Random-Objekte sozusagen seine eigene Semantik - sollte klar sein. Kurz gesagt: Zwei Methodenaufrufe, bei denen Random-Objekte übergeben werden, bedeuten nicht unbedingt immer das gleiche - deswegen: Fehler in der Semantik/Logik…