Erste Schritte Frage zu Instanzierung und Referenzen

Bigbob9

Mitglied
Guten Tag Zusammen,

ich habe ein paar Fragen zu folgendem Code aus dem Buch Java head First Seite 420. Vielleicht kann mir jemand helfen. Danke

1.
Die Klasse Beatbox wird in der main über folgenen Befehl instanziert und ruft die Methode guiErstellen() auf.(oder verstehe ich was falsch)

Java:
  new BeatBox().guiErstellen();

Bisher kannte ich nur folgende Möglichkeit
Java:
BeatBox beat = new BeatBox();
beat.guiErstellen();

Welche vor bzw. Nachteile ergeben sich hierdurch bzw. wie nennt man diese Art der Instanzierung?

2.
Wie läuft das hier ab?

Da jede JCheckBox auf c referenziert wird,
müssten doch alle JCheckBoxen die Referenz vom letzten erhalten?
Java:
  for (int i=0; i<256; i++){

            JCheckBox c=new JCheckBox();

            c.setSelected(false);

            checkboxListe.add(c);

            hauptPanel.add(c);

            

        }

Vielen Dank für die Hilfe

Mit freundlichen Grüßen


Java:
import java.awt.*;
import javax.swing.*;
import javax.sound.midi.*;
import java.util.*;
import java.awt.event.*;

public class BeatBox {
    
    JPanel hauptPanel;
    ArrayList<JCheckBox> checkboxListe;
    Sequencer sequencer;
    Sequence sequence;
    Track track;
    JFrame derFrame;
    
    String[] instrumentNamen = {"Bassdrum", "Hi-Hat, geschlossen", "Hi-Hat, offen", "Snaredrum", "Crashbecken", "Händeklatschen", "Hohes Tom-Tom", "Hohes Bongo", "Maracas", "Trillerpfeife", "Tiefe Conga", "Kuhglocke", "Vibraslap" , "Tieferes Tom-Tom", "Hohes Agogo", "Hohe Conga, offen"};
    int[] instrumente ={35,42,46,38,49,39,50,60,70,72,64,56,58,47,67,63};
    
    public static void main (String[]args){
        new BeatBox().guiErstellen();

    }
    public void guiErstellen(){
        derFrame=new JFrame("Cyber-BeatBox");
        derFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        BorderLayout layout=new BorderLayout();
        JPanel hintergrund=new JPanel (layout);
        hintergrund.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
        
        checkboxListe=new ArrayList<JCheckBox>();
        Box buttonBox=new Box(BoxLayout.Y_AXIS);
        
        JButton start=new JButton("Starten");
        start.addActionListener(new MeinStartListener());
        buttonBox.add(start);
        
        JButton stopp=new JButton("Stoppen");
        stopp.addActionListener(new MeinStoppListener());
        buttonBox.add(stopp);
        
        JButton schneller=new JButton("Schneller");
        schneller.addActionListener(new MeinSchnellerListener());
        buttonBox.add(schneller);
        
        JButton langsamer=new JButton("Langsamer");
        langsamer.addActionListener(new MeinLangsamerListener());
        buttonBox.add(langsamer);
        
        Box namensBox=new Box(BoxLayout.Y_AXIS);
        for (int i=0;i<16;i++){
            namensBox.add(new Label(instrumentNamen[i]));
            
        }
        
        hintergrund.add(BorderLayout.EAST, buttonBox);
        hintergrund.add(BorderLayout.WEST, namensBox);
        
        derFrame.getContentPane().add(hintergrund);
        
        GridLayout raster = new GridLayout(16,16);
        raster.setVgap(1);
        raster.setHgap(2);
        hauptPanel=new JPanel(raster);
        hintergrund.add(BorderLayout.CENTER, hauptPanel);
        
        for (int i=0; i<256; i++){
            JCheckBox c=new JCheckBox();
            c.setSelected(false);
            checkboxListe.add(c);
            hauptPanel.add(c);
            
        }
        midiEinrichten();
        
        derFrame.setBounds(50,50,300,300);
        derFrame.pack();
        derFrame.setVisible(true);
                
    }
public void midiEinrichten(){
    try {
        sequencer=MidiSystem.getSequencer();
        sequencer.open();
        sequence=new Sequence(Sequence.PPQ,4);
        track=sequence.createTrack();
        sequencer.setTempoInBPM(120);
    
    }catch (Exception e) {e.printStackTrace();}
}
public void trackErstellenUndStarten(){
    int[]trackListe=null;
    
    sequence.deleteTrack(track);
    track=sequence.createTrack();
    
    for (int i=0; i<16; i++){
        trackListe=new int[16];
        
        int taste=instrumente[i];
        
        for (int j=0; j<16;j++){
            JCheckBox jc=checkboxListe.get(j+(16*i));
            if (jc.isSelected()){
                trackListe[j]=taste;
            }else{
                trackListe[j]=0;
        
            }
        }
        tracksErzeugen(trackListe);
        
    }
    
    track.add(eventErzeugen(192,9,1,0,16));
    try{
        sequencer.setSequence(sequence);
        sequencer.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
        sequencer.start();
        sequencer.setTempoInBPM(120);
        
    } catch (Exception e) {e.printStackTrace();}
}
public class MeinStartListener implements ActionListener{
    public void actionPerformed(ActionEvent a){
        trackErstellenUndStarten();
        
    }
}
public class MeinStoppListener implements ActionListener{
    public void actionPerformed (ActionEvent a){
        sequencer.stop();
        
    }
}
public class MeinSchnellerListener implements ActionListener{
    public void actionPerformed(ActionEvent a){
        float tempoFactor=sequencer.getTempoFactor();
        sequencer.setTempoFactor((float)(tempoFactor*1.03));
    }
}
public class MeinLangsamerListener implements ActionListener{
    public void actionPerformed(ActionEvent a){
        float tempoFactor=sequencer.getTempoFactor();
        sequencer.setTempoFactor((float)(tempoFactor*.97));
    }
}
public void tracksErzeugen(int[]liste){
    for(int i=0;i<16;i++){
        int taste=liste[i];
        
        if (taste!=0){
            track.add(eventErzeugen(14,9,taste, 100, i));
            track.add(eventErzeugen(128,9,taste, 100, i+1));
        }
    }
}
public MidiEvent eventErzeugen (int comd, int chan, int one, int two, int tick){
    MidiEvent event=null;
    try{
        ShortMessage a=new ShortMessage();
        a.setMessage (comd, chan, one, two);
        event = new MidiEvent (a, tick);
    } catch (Exception e) {e.printStackTrace();}
    return event;
}
}
 
Welche vor bzw. Nachteile ergeben sich hierdurch bzw. wie nennt man diese Art der Instanzierung?
In der ersten Variante wird eine Instanz erzeugt, aber keine Referenz darauf gespeichert. Du kannst auf diese Instanz also danach nicht mehr zugreifen. Wenn das nicht notwendig ist, kannst du das so machen, andernfalls brauchst du z. B. Variante 2. Wie du richtig erkannt hast, wird dabei eine Instanz erzeugt und auf diese eine Methode aufgerufen.

Die Referenz könnte natürlich auch auf eine andere Art gespeichert werden, als in einer Variablen, z. B. in einer Datenstruktur wie die Liste:
Java:
ArrayList<BeatBox> beatBoxes = new ArrayList<>();

beatBoxes.add(new BeatBox()); // fügt die erstelle Instanz der Liste hinzu

beatBoxes.get(0).guiErstellen(); // holt die Instanz an Position 0 und führt eine Methode darauf aus
 
In der ersten Variante wird eine Instanz erzeugt, aber keine Referenz darauf gespeichert. Du kannst auf diese Instanz also danach nicht mehr zugreifen. Wenn das nicht notwendig ist, kannst du das so machen, andernfalls brauchst du z. B. Variante 2. Wie du richtig erkannt hast, wird dabei eine Instanz erzeugt und auf diese eine Methode aufgerufen.

Die Referenz könnte natürlich auch auf eine andere Art gespeichert werden, als in einer Variablen, z. B. in einer Datenstruktur wie die Liste:
Java:
ArrayList<BeatBox> beatBoxes = new ArrayList<>();

beatBoxes.add(new BeatBox()); // fügt die erstelle Instanz der Liste hinzu

beatBoxes.get(0).guiErstellen(); // holt die Instanz an Position 0 und führt eine Methode darauf aus
Dankeschön,

Das erklärt wohl auch die zweite Frage.

Datenstruktur? Das Wort ist mir neu.

Kann man in dieser DatenStruktur die Position der gespeicherten Referenz als Variable verstehen?
 
Da jede JCheckBox auf c referenziert wird,
müssten doch alle JCheckBoxen die Referenz vom letzten erhalten?
Jain. In der Schleife wird jedesmal eine neue Instanz erzeugt und der Variablen c zugewiesen. Die Variable c ist allerdings eine lokale Variable, die nach der Schleife nicht mehr existiert, weil sie ihren Gültigkeitsbereich verlässt.
Java:
for (int i=0; i<256; i++) { // mit der geschweiften Klammer beginnt der Gültigkeitsbereich
    JCheckBox c=new JCheckBox(); // "c" wird in diesem Gültigkeitsbereich deklariert
    c.setSelected(false);
    checkboxListe.add(c);
    hauptPanel.add(c);
} // hier endet er. Danach ist c nicht mehr gültig
Allerdings werden die erzeugten Referenzen innerhalb der Schleife auch in der Liste gespeichert. Diese Liste hat einen anderen Gültigkeitsbereich und ist nach der Schleife noch gültig, so dass auch dann noch auf die Instanzen zugegriffen werden kann.

Nur zum Vergleich:
Java:
    JCheckBox c = null; // Deklaration vor der Schleife in einem größeren Gültigkeitsbereich
    for (int i=0; i<256; i++) { // mit der geschweiften Klammer beginnt der kleinere Gültigkeitsbereich
        c = new JCheckBox(); // Zuweisung an "c"
        c.setSelected(false);
        checkboxListe.add(c);
        hauptPanel.add(c);
    } // hier endet der kleinere Gültigkeitsbereich

    // hier ist "c" weiterhin gültig und enthält eine Referenz auf die zuletzt erzeugte Instanz.

} // hier endet z. B. die Methode und der größere Gültigkeitsbereich. Ab hier ist "c" nicht mehr gültig


ArrayList<> verwendet intern ein Array zum Speichern der Elemente, also ja irgendwie gibt es da auch eine Art Variable. Nur nicht im klassischen Sinne einer "benannten" Variable, wie es beispielsweise "c" ist. Es gibt aber auch andere Datenstrukturen, die eine verkettete Liste oder Bäume intern verwenden. Das wird sicher irgendwann noch Thema im Buch werden.
 
Zuletzt bearbeitet:
Jain. In der Schleife wird jedesmal eine neue Instanz erzeugt und der Variablen c zugewiesen. Die Variable c ist allerdings eine lokale Variable, die nach der Schleife nicht mehr existiert, weil sie ihren Gültigkeitsbereich verlässt.
Java:
for (int i=0; i<256; i++) { // mit der geschweiften Klammer beginnt der Gültigkeitsbereich
    JCheckBox c=new JCheckBox(); // "c" wird in diesem Gültigkeitsbereich deklariert
    c.setSelected(false);
    checkboxListe.add(c);
    hauptPanel.add(c);
} // hier endet er. Danach ist c nicht mehr gültig
Allerdings werden die erzeugten Referenzen innerhalb der Schleife auch in der Liste gespeichert. Diese Liste hat einen anderen Gültigkeitsbereich und ist nach der Schleife noch gültig, so dass auch dann noch auf die Instanzen zugegriffen werden kann.

Nur zum Vergleich:
Java:
    JCheckBox c = null; // Deklaration vor der Schleife in einem größeren Gültigkeitsbereich
    for (int i=0; i<256; i++) { // mit der geschweiften Klammer beginnt der kleinere Gültigkeitsbereich
        c = new JCheckBox(); // Zuweisung an "c"
        c.setSelected(false);
        checkboxListe.add(c);
        hauptPanel.add(c);
    } // hier endet der kleinere Gültigkeitsbereich

    // hier ist "c" weiterhin gültig und enthält eine Referenz auf die zuletzt erzeugte Instanz.

} // hier endet z. B. die Methode und der größere Gültigkeitsbereich. Ab hier ist "c" nicht mehr gültig


ArrayList<> verwendet intern ein Array zum Speichern der Elemente, also ja irgendwie gibt es da auch eine Art Variable. Nur nicht im klassischen Sinne einer "benannten" Variable, wie es beispielsweise "c" ist. Es gibt aber auch andere Datenstrukturen, die eine verkettete Liste oder Bäume intern verwenden. Das wird sicher irgendwann noch Thema im Buch werden.
Nochmals vielen Dank temi.

Was würde passieren wenn ich

Java:
 CheckboxListe.remove(c);

schreibe?

Mit freundlichen Grüßen
 
Wenn die Instanz in c in der checkboxListe enthalten ist, dann würde der Eintrag aus der Liste entfernt.

Und bitte auf die Gross-/Kleinschreibung aufpassen. Die Variable fing, so wie es in Java üblich ist, mit einem kleinen Buchstaben an.
 
Was würde passieren
Hier hilft ein Blick in die Dokumentation, die ich dir sehr ans Herz legen möchte. Bei solchen Fragen ist sie die erste Anlaufstelle und sie ist recht gut und übersichtlich.

Du findest sie meist sofort in Suchmaschinen, wenn du als Suchbegriffe "java klassenname", z. B. "java arraylist" verwendest und dann auf eine Seite gehst, deren URL mit docs.oracle.com beginnt.

Und was passiert, hängt davon ab, wo du den Befehl im ursprünglichen obigen Code schreibst. Innerhalb der Schleife wird das Element aus der Liste gelöscht, wie Konrad geschrieben hat. Außerhalb der Schleife ist "c" keine gültige Variable und würde zu einem Compilerfehler führen, es sei denn du deklarierst eine andere Variable "c".
 
Zuletzt bearbeitet:
Hier hilft ein Blick in die Dokumentation, die ich dir sehr ans Herz legen möchte. Bei solchen Fragen ist sie die erste Anlaufstelle und sie ist recht gut und übersichtlich.

Du findest sie meist sofort in Suchmaschinen, wenn du als Suchbegriffe "java klassenname", z. B. "java arraylist" verwendest und dann auf eine Seite gehst, deren URL mit docs.oracle.com beginnt.

Und was passiert, hängt davon ab, wo du den Befehl im ursprünglichen obigen Code schreibst. Innerhalb der Schleife wird das Element aus der Liste gelöscht, wie Konrad geschrieben hat. Außerhalb der Schleife ist "c" keine gültige Variable und würde zu einem Compilerfehler führen, es sei denn du deklarierst eine andere Variable "c".
Danke temi,

für Zeit und Rat.

Mit freundlichen Grüßen
 

Neue Themen


Zurück
Oben