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

本篇将介绍数组的一些特殊的特性,跟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;
    }
}

案例输出结果如下:

1
2
3
-----------------------
A
B
C
-----------------------
zhangsan
1
2
3
-----------------------
[C
类名:char[]
父类:java.lang.Object
实现的接口:
java.lang.Cloneable
java.io.Serializable
before:3
before : 1
dog : com.zd.test.java.ds.ArrayTest$Dog@4ef53d61, name : 旺旺, age : 2
dog2 : com.zd.test.java.ds.ArrayTest$Dog@3fd23632, name : 旺旺, age : 2
cat : com.zd.test.java.ds.ArrayTest$Cat@770fba26, name : 喵喵, age : 1
cat2 : 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两个接口,可以优雅的实现对象的拷贝和序列化,关于二者的结合使用,上面的范例中已经有解释。之后,我会针对序列化和拷贝再做深入的说明。
个人见解,欢迎指教批评。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值