Pytanie Powinniśmy użyć clone lub BeanUtils.copyProperties i dlaczego


Z wyglądu - BeanUtils.copyProperties wydaje się tworzyć klon obiektu. Jeśli tak, to co z obawami związanymi z implementacją interfejsu Cloneable (tylko niezmienne obiekty są nowe, gdzie jako obiekty zmienne mają odwołania do referencji), które są najlepsze i dlaczego?

Wczoraj wdrożyłem możliwość klonowania, a następnie zdałem sobie sprawę, że muszę wprowadzić własne modyfikacje dla nie String / Primative elementy. Zostałem wtedy poinformowany BeanUtils.copyProperties którego teraz używam. Obie implementacje wydają się zapewniać podobną funkcjonalność.

Dzięki


21
2018-03-21 08:24


pochodzenie


Więc jakie jest dokładnie pytanie? - Olivier Croisier
Powinniśmy użyć clone lub BeanUtils.copyProperties i dlaczego - Biscuit128


Odpowiedzi:


Josh Bloch podaje dość dobre argumenty (w tym te, które dostarczyłeś), potwierdzając to Cloneable jest zasadniczo wadliwy, zamiast tego faworyzuje konstruktor kopii. Widzieć tutaj.

Jeszcze nie spotkałem się z praktycznym przypadkiem użycia do kopiowania niezmiennego obiektu. Kopiujesz obiekty z konkretnego powodu, prawdopodobnie w celu odizolowania niektórych zestawów zmiennych obiektów do pojedynczej transakcji w celu przetworzenia, gwarantując, że nic nie może ich zmienić, dopóki ta jednostka przetwarzania nie zostanie ukończona. Jeśli są już niezmienne, odwołanie jest tak samo dobre jak kopia.

BeanUtils.copyProperties jest często mniej inwazyjnym sposobem kopiowania bez konieczności zmiany klas, które mają być obsługiwane, i oferuje wyjątkową elastyczność w komponowaniu obiektów.

To mówi, copyProperties nie zawsze ma rozmiar uniwersalny. Możesz w pewnym momencie obsługiwać obiekty zawierające typy, które mają wyspecjalizowane konstruktory, ale nadal mogą być modyfikowane. Twoje obiekty mogą obsługiwać wewnętrzne metody lub konstruktory w celu obejścia tych wyjątków lub możesz zarejestrować określone typy w jakimś zewnętrznym narzędziu do kopiowania, ale nie może dotrzeć do niektórych miejsc, które nawet clone() mogą. To dobrze, ale wciąż ma ograniczenia.


20
2018-03-23 19:29



Dobra odpowiedź jak Josh Bloch's Effective Java notatki. Czy mogę podsumować, że "oba mogą być używane w zależności od senarios"? ale oba mają ograniczenia. - Henry Leu


BeanUtils jest bardziej elastyczny niż standardowy klon, który po prostu kopiuje wartości pól z obiektu do innego. Metoda klonowania kopiuje pola z fasoli tej samej klasy, ale BeanUtils może to zrobić dla 2 wystąpień różnych klas o tych samych nazwach atrybutów.

Na przykład załóżmy, że masz Bean A, który ma pole Data String i komponent B, które mają to samo pole java.util.Date date. z BeanUtils możesz skopiować wartość ciągu i przekonwertować ją automatycznie do daty używając DateFormat.

Użyłem tego do przekonwertowania obiektu SOAP do obiektów Hibernate, które nie mają tych samych typów danych.


4
2018-03-24 09:51



Teraz po wiosce 4.x porównuje prymitywny rodzaj soruce i fasoli docelowej. Strzeż się więc, używając właściwości kopiowania BeanUtils. Pamiętaj, że masz takie same typy pierwotne, które można przypisać od źródła do miejsca przeznaczenia - Mohammed Irfan Tirupattur


Myślę, że szukasz głębokiej kopii. możesz mieć poniższą metodę w klasie util i użyć jej do dowolnego typu obiektu.

public static <T extends Serializable> T copy(T input) {
    ByteArrayOutputStream baos = null;
    ObjectOutputStream oos = null;
    ByteArrayInputStream bis = null;
    ObjectInputStream ois = null;
    try {
        baos = new ByteArrayOutputStream();
        oos = new ObjectOutputStream(baos);
        oos.writeObject(input);
        oos.flush();

        byte[] bytes = baos.toByteArray();
        bis = new ByteArrayInputStream(bytes);
        ois = new ObjectInputStream(bis);
        Object result = ois.readObject();
        return (T) result;
    } catch (IOException e) {
        throw new IllegalArgumentException("Object can't be copied", e);
    } catch (ClassNotFoundException e) {
        throw new IllegalArgumentException("Unable to reconstruct serialized object due to invalid class definition", e);
    } finally {
        closeQuietly(oos);
        closeQuietly(baos);
        closeQuietly(bis);
        closeQuietly(ois);
    }
}

2
2018-03-28 11:21





Z twojego pytania domyślam się, że potrzebujesz głęboka kopia obiektu. W takim przypadku nie używaj clone metoda jak jest już określona w oracle docs że zapewnia płytka kopia powiązanego obiektu. I nie mam na to dość pomysłu BeanUtils.copyProperties API.
Poniżej znajduje się krótki demo deep copy. Tutaj głęboko kopiuję a primitive array. Możesz wypróbować ten kod z dowolnym typem obiektu.

import java.io.*;
class ArrayDeepCopy 
{
    ByteArrayOutputStream baos;
    ByteArrayInputStream bins;
    public void saveState(Object obj)throws Exception //saving the stream of bytes of object to `ObjectOutputStream`.
    {
        baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(obj);
        oos.close();
    }
    public int[][] readState()throws Exception //reading the state back to object using `ObjectInputStream`
    {
        bins = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream oins = new ObjectInputStream(bins);
        Object obj = oins.readObject();
        oins.close();
        return (int[][])obj;
    }
    public static void main(String[] args) throws Exception
    {
        int arr[][]= {
                        {1,2,3},
                        {4,5,7}
                    };
        ArrayDeepCopy ars = new ArrayDeepCopy();
        System.out.println("Saving state...");
        ars.saveState(arr);
        System.out.println("State saved..");
        System.out.println("Retrieving state..");
        int j[][] = ars.readState();
        System.out.println("State retrieved..And the retrieved array is:");
        for (int i =0 ; i < j.length ; i++ )
        {
            for (int k = 0 ; k < j[i].length ; k++)
            {
                System.out.print(j[i][k]+"\t");
            }
            System.out.print("\n");
        }

    }
}

1
2018-03-24 09:05





klon tworzy płytką kopię obiektu, obiekt klonu jest zawsze tej samej klasy co oryginalny. Wszystkie pola, prywatne lub nie, są kopiowane.

BeanUtils.copyProperties API Skopiuj wartości właściwości z komponentu źródłowego komponentu bean do komponentu bean docelowej we wszystkich przypadkach, w których nazwy właściwości są takie same.

Jeśli chodzi o mnie, te dwa pojęcia mają niewiele wspólnego.


0
2018-03-21 08:43



Cześć. Nie kwestionuję twojego osądu po prostu grając w adwokatów diabła. Czy celem klonowania nie jest stworzenie obiektu tego samego typu z tymi samymi danymi? Jeśli używasz utworzyć pusty obiekt (puste płótno) i skopiować właściwości - czy zasadniczo nie robimy tego samego? - Biscuit128


Klonowanie jest wykonywane przez ciebie. Jeśli instancja, z której próbujesz klon zawiera odniesienie do innej instancji, musisz również napisać kod do tego kodu. Co jeśli instancje zawierają łańcuch odniesień do innych instancji? Jeśli więc klonujesz sam, są szanse, że stracisz trochę szczegółów.

BeanUtils.copyProperties z drugiej strony same zajmują się wszystkim. Zmniejsza twój wysiłek.


0
2018-03-28 09:07