Przekazywanie wektora przez wartość

0

Mam wektor z danymi bazowymi. (Wiem, że wektor jest przestarzały ale z DefaultTableModel (DTM) mozna pobrac dane tylko w postaci wektora). Wektor jest przekazywany w konstruktorze do kilku innych obiektów DTM. Oczywiście w ten sposób tworzone są nowe kopie, jednak operują na tej samej pamięci. Modyfikując komórkę w jednej tabeli modyfikowana jest ona we wszystkich oraz w danych bazowych (które nie powinny byc modyfikowane).

Kombinowalem juz oznaczyc wektor z danymi jako final, jednak szybko zorientowalem sie ze nie bedzie mozna zmienic jedynie wskazywanego obiektu. Probowalem z funkcja clone(), oraz przekazywaniem wektora w postaci tablicy (gdzies tak kiedys wyczytalem), no ale ciagle problem wystepuje.

W skrócie: mam wektor danych który nie może być modyfikowany, a jest przekazywany do konstruktorów DTM. Jak to wykonać aby każdy DTM posiadał swój własny wektor danych a nie wskazywał na dane bazowe? W C++ byłoby to proste, a tutaj nie mogę się odnaleźć.

EDIT: Hmm w wektorze trzymam obiekty String, widze w dokumentacji iz nie implementuja one interfejsu Clonable, zatem jedynym wyjsciem jest serializacja i deserializacja wektora aby uzyskac jego kopie?

0

Nie wystarczy takie coś:

Vector<String> kopia=new Vector<String>(oryginał);
0

Z pozoru wygląda to na bardzo ładne rozwiązanie, gdzie mamy dwa oddzielne wektory, dodając dane do kopii nie zmienia się oryginał.

Niestety tylko z pozoru ponieważ, gdyby w wektorze oryginal zamiescic String "oryginal", a nastepnie wykonac kopie tegoż wektora (w opisany przez Ciebie sposób) i dodać go do DTM jako dane to będziemy w DTM operowali na tej samej referencji Stringu, mimo że referencje wektorów są inne. Zmieniając dane w JTable, zmienia się zatem wektor oryginalny oraz kopię.

0

Sprawdziłeś?

import java.util.*;

public class Wektory
{
    public static void main(String[] args)
    {
        Vector<String> first=new Vector<String>();
        first.add("jasna");
        first.add("dupa");
        Vector<String> second=new Vector<String>(first);
        second.set(0,"ciemna");
        System.out.println(first.get(0)); //jasna
        System.out.println(second.get(0)); //ciemna
    }
}
0

Zauważ, że Ty 'podmieniasz' String w wektorze na 0 pozycji - po set() jest tam inna referencja, jednak nie 'zmieniasz' Stringu "jasna".

W JTable w komórce masz referencje stringu "jasna", zmieniajac go w komórce np. na "jasna_zmiana" w obu wektorach zostanie podmieniony String.

0

Akurat ze stringami to jest zły przykład, bo są immutable. Problem pojawi się w momencie jak w tym wektorze są jakieś obiekty i zmieniamy np. tylko składową takiego obiektu.
Nie wiem czy jest jakaś metoda, którą to zrobisz w jednej linijce. Możesz w pętli pobierać elementy oryginalnego wektora, kopiować je i te kopie wrzucać do nowego wektora.

Vector<Jakas_klasa> first = new Vector<Jakas_klasa>();
first.add(new Jakas_klasa(1, 2, 3));
first.add(new Jakas_klasa(4, 5, 6));

Vector<Jakas_klasa> second = new Vector<Jakas_klasa>();
for(Jakas_klasa jk : first)
{
    second.add(new Jakas_klasa(jk)); //zakładając, że ta klasa ma odpowiedni konstruktor
}
0

Problem jest w tym, że Vector opisujący dane z modelu nie jest typu Vector<String> tylko Vector<Vector<String>>, a obiekty Vector<String> mogą się zmieniać.

    Vector<Vector<String>> kopia=new Vector<Vector<String>>();
    for(int i=0;i<oryginał.size();i++)
    {
        kopia.add(new Vector<String>(first.get(0)));
   }
0

Prosze oto kod w którym występuje problem.

Do konstruktora DTM została przekazana kopia wektora 'data' o nazwie 'kopia'.

Logicznie po zmianie stringu 'oryginal' w tabeli powinien zostać zmieniony tylko wektor kopia.

Przycisk 'check' drukuje w konsoli wektor 'data', ktory takze ulega zmianie.

Wszystko dlatego ponieważ oba wektory działają na tej samej referencji stringu 'oryginal'. Przynajmiej do takich wnioskow doszedlem.

import java.awt.BorderLayout;
import java.awt.event.*;
import java.util.Vector;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;


public class JavaApplication16 {

    public static void main(String[] args) {

        Vector<String> vect = new Vector<String>();
        vect.add("oryginal");

        final Vector data = new Vector();
        data.add(vect);

        Vector columnNames = new Vector();
        columnNames.add("name");

        JButton jButton = new JButton("check");
        jButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println(data);
            }
        });

        Vector kopia = new Vector(data);

        DefaultTableModel defaultTableModel = new DefaultTableModel(kopia, columnNames);
        JTable jTable = new JTable(defaultTableModel);

        JFrame frame = new JFrame();

        frame.add(jButton, BorderLayout.SOUTH);
        frame.add(jTable.getTableHeader(), BorderLayout.NORTH);
        frame.add(jTable, BorderLayout.CENTER);
        
        frame.setSize(200, 200);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1