java数组的对象化,序列化以及拷贝

来源:互联网 发布:王者荣耀淘宝代充原理 编辑:程序博客网 时间:2024/05/17 07:40

本篇将介绍数组的一些特殊的特性,跟C语言的数组相比,java赋予了数组新的面向对象的性质,比如数组即对象,数组的序列化,数组的拷贝,这也为数组的拷贝提供了新的优雅的方案。

package com.zd.test.java.ds;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;public class ArrayTest {    public static void main(String[] args) throws Exception {        // 1.数组和泛型        int[] data = new int[] { 1, 2, 3 };        /*          List<int[]> asList = Arrays.asList(data); for (int is[] : asList) {          System.out.println(is); }         */        asList(data);        System.out.println("-----------------------");        asList(new String[] { "A", "B", "C" });        System.out.println("-----------------------");        test("zhangsan", data);        System.out.println("-----------------------");        // 此时new char[]{'A','B','C'}为一个char[]数组对象,可以看一下类型        char[] cdata = new char[] { 'A', 'B', 'C' };        asList(cdata);        System.out.println("类名:" + cdata.getClass().getCanonicalName());        System.out.println("父类:"                + cdata.getClass().getSuperclass().getCanonicalName());        Class<?>[] interfaces = cdata.getClass().getInterfaces();        System.out.println("实现的接口:");        for (Class<?> class1 : interfaces) {            System.out.println(class1.getCanonicalName());        }        /**         * 类名:char[] 父类:java.lang.Object 实现的接口: java.lang.Cloneable         * java.io.Serializable         * 可以看出其父类是java.lang.Object,实现了Cloneable和Serializable接口,数组是可复制和可序列化的。         */        // 2.数组的拷贝        Person[] ps = new Person[] { new Person("1", 1), new Person("2", 2) };        Person[] persons = ps.clone();        persons[0].name = "3";// 改变拷贝对象的属性值        // 结果是原来对象的属性值也被改变了,数组的拷贝是浅拷贝,它拷贝的元素的地址,如果是对象元素,只拷贝对象地址,是浅拷贝        System.out.println("before:" + ps[0].name);        // 深拷贝的例子,Man对象,需要实现Cloneable接口        Man m = new Man("1", 1);        Man m1 = (Man) m.clone();        m1.name = "3";// 改变拷贝对象的属性值        System.out.println("before : " + m.name); // 对象的每一个值都改变了        // 对象的序列化        Dog dog = new Dog("旺旺", 2);        Dog dog2 = dog.deepCopy();        System.out.println("dog : " + dog + ", name : " + dog.name + ", age : "                + dog.age);        System.out.println("dog2 : " + dog2 + ", name : " + dog2.name                + ", age : " + dog2.age);        // dog : com.zd.test.java.ds.ArrayTest$Dog@29ba92bb, name : 旺旺, age : 2        // dog2 : com.zd.test.java.ds.ArrayTest$Dog@343abc87, name : 旺旺, age : 2        // 从上面的实例化的例子可以看出来,其实可以利用序列化来实现对象的深拷贝        Cat cat = new Cat("喵喵", 1);        Cat cat2 = cat.clone();        System.out.println("cat : " + cat + ", name : " + cat.name + ", age : "                + cat.age);        System.out.println("cat2 : " + cat2 + ", name : " + cat2.name                + ", age : " + cat2.age);        ///至此数组的性质分析完毕        //下面说一下序列化的一些知识    }    // 普通类    static class Person {        String name;        Integer age;        public Person(String name, Integer age) {            super();            this.name = name;            this.age = age;        }    }    // 测试深克隆实体类    static class Man implements Cloneable {        String name;        Integer age;        public Man(String name, Integer age) {            this.name = name;            this.age = age;        }        public Object clone() {            Man man = new Man(name, age);            return man;        }    }    // 测试序列化实体类    static class Dog implements Serializable {        private static final long serialVersionUID = -7836461280716041801L;        String name;        Integer age;        public Dog(String name, Integer age) {            this.name = name;            this.age = age;        }        // 深拷贝        public Dog deepCopy() throws IOException, ClassNotFoundException {            // 先写进流            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();            ObjectOutputStream objectOutputStream = new ObjectOutputStream(                    outputStream);            objectOutputStream.writeObject(this);            // 再写出流            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(                    outputStream.toByteArray());            ObjectInputStream objectInputStream = new ObjectInputStream(                    byteArrayInputStream);            Dog dog = (Dog) objectInputStream.readObject();            objectInputStream.close();            objectOutputStream.close();            return dog;        }    }    // 使用序列化来实现深拷贝    static class Cat implements Serializable, Cloneable {        private static final long serialVersionUID = 3530119431127324235L;        String name;        Integer age;        public Cat(String name, Integer age) {            this.name = name;            this.age = age;        }        // 深拷贝        public Cat clone() {            Cat cat = null;            cat = deepCopy(this);            return cat;        }    }    public static final void test(String name, int... params) {        System.out.println(name);        for (int i : params) {            System.out.println(i);        }    }    // 简单类型    public static void asList(int... a) {        for (int t : a) {            System.out.println(t);        }    }    // 普通对象    public static void asList(String... a) {        for (String t : a) {            System.out.println(t);        }    }    // Object对象,与泛型一致,是二维数组,原因为a其实是一个数组其实就是一个对象,    // 看作为一个对象,然后java可变参数再次封装这个数组,成为二维数组    public static void asList(Object... a) {        for (Object t : a) {            System.out.println(t.getClass().getName());        }    }    /*     * //泛型 public static <T> void asList(T... ts){ for (T t : ts) {     * System.out.println(t); } }     */    @SuppressWarnings("unchecked")    public static <T extends Serializable & Cloneable> T deepCopy(T t) {        T newInstance = null;        // 先写进流        try {            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();            ObjectOutputStream objectOutputStream = new ObjectOutputStream(                    outputStream);            objectOutputStream.writeObject(t);            // 再写出流            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(                    outputStream.toByteArray());            ObjectInputStream objectInputStream = new ObjectInputStream(                    byteArrayInputStream);            newInstance = (T) objectInputStream.readObject();            objectInputStream.close();            objectOutputStream.close();        } catch (IOException | ClassNotFoundException e) {            e.printStackTrace();        }        return newInstance;    }}

案例输出结果如下:

123-----------------------ABC-----------------------zhangsan123-----------------------[C类名:char[]父类:java.lang.Object实现的接口:java.lang.Cloneablejava.io.Serializablebefore:3before : 1dog : com.zd.test.java.ds.ArrayTest$Dog@4ef53d61, name : 旺旺, age : 2dog2 : com.zd.test.java.ds.ArrayTest$Dog@3fd23632, name : 旺旺, age : 2cat : com.zd.test.java.ds.ArrayTest$Cat@770fba26, name : 喵喵, age : 1cat2 : com.zd.test.java.ds.ArrayTest$Cat@2886f716, name : 喵喵, age : 1

总结如下:
1.泛型和可变参数相遇,我们传过去的数组被包装成了二维数组,因为泛型在java以前的版本中是用Object来代替的,而恰巧的是数组在java中也是一个对象,它是java.lang.Object的子类,可以尝试重载一下,上面的例子我们已经有示范。
2.数组实现了Cloneable和Serializable接口,即数组是可复制和可序列化的。
3.数组的拷贝是浅拷贝,即只拷贝数组中元素的地址,即只拷贝对象的引用。
4.结合Cloneable和Serializable两个接口,可以优雅的实现对象的拷贝和序列化,关于二者的结合使用,上面的范例中已经有解释。之后,我会针对序列化和拷贝再做深入的说明。
个人见解,欢迎指教批评。

1 0
原创粉丝点击