[转载] java(三)对象的序列化与static、final关键字

参考链接: Java中的final最终变量

java对象的序列化

 

 Java序列化是指把Java对象转换为字节序列的过程;而Java反序列化是指把字节序列恢复为Java对象的过程。java中存有Cloneable接口,实现此接口的类都具有被拷贝能力,比new一个对象要快,拷贝分为浅拷贝和深拷贝,浅拷贝导致对象属性不彻底。

 

 

 

 class Professor 

{

    String name;

    int age;

    Professor(String name,int age)

    {

        this.name=name;

        this.age=age;

    }

}

class student implements Cloneable

{

    String name;

    int age;

    Professor p;

    student(String name,int age,Professor p)

    {

        this.name=name;

        this.age=age;

        this.p=p;

    }

    public Object clone()

    {

        student o=null;

        try

        {

            o=(student)super.clone();

        }

        catch(CloneNotSupportedException e)

        {

            System.out.println(e.toString());

        }

      

        return o;

    }

    public static void main(String[] args)

    {

          Professor p=new Professor("wang",5);

          student s1=new student("zhangsan",1,p);

          student s2=(student)s1.clone();

          s2.p.name="lisi";

         s2.p.age=3;

    System.out.println("name="+s1.p.name+","+"age="+s1.p.age);

    }

}

 如代码中s2变了,s1也变了,说明他们指向同一个对象,这就是浅复制,关键是在clone()方法上,他并不是将对象的所有属性全拷贝过来,而是选择性拷贝,拷贝规则为:1)基本类型,只拷贝其值。2)实例对象,拷贝其地址引用,新拷贝对象原对象共用该实例。3)字符串,拷贝地址引用,修改时会从字符串常量池中新生一个原字符串不变。解决办法在clone里新建一个对象。但是在如果大量对象都是拷贝生成,每个类都写一个clone()方法,工程量就很大。

 

 

 序列化实现对象的复制。通过字节流拷贝对象

 

 

 public class CloneUtils {

    @SuppressWarnings("unchecked")

    public static <T extends Serializable> T clone(T obj){

        T cloneObj = null;

        try {

            //写入字节流

            ByteArrayOutputStream out = new ByteArrayOutputStream();

            ObjectOutputStream obs = new ObjectOutputStream(out);

            obs.writeObject(obj);

            obs.close();

            

            //分配内存,写入原始对象,生成新对象

            ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());

            ObjectInputStream ois = new ObjectInputStream(ios);

            //返回生成的新对象

            cloneObj = (T) ois.readObject();

            ois.close();

        } catch (Exception e) {

            e.printStackTrace();

        }

        return cloneObj;

    }

}

 使用该工具类的对象必须要实现Serializable接口,否则是没有办法实现克隆。无须继承cloneable接口实现clone()方法。

 

 

 Static关键字

 

 

 Static代表全局和静态的意思,可以修饰成员变量和成员方法,也可修饰代码块。java的内存分配有栈和堆,栈中存放基本变量,数组和对象引用,堆中存放对象,当有static修饰的变量或方法,则会为其分配固定区域切既然是静态那他作用于内是不变的,删除了就不会再有。static修饰的变量是为类所共有,不依赖于实例,先于对象而存在,任一实例修改其他实例也会使用修改后的变量值。java编程思想中有一句话"static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。”这段话虽然只是说明了static方法的特殊之处,但是可以看出static关键字的基本作用,简而言之,一句话来描述就是:方便在没有创建对象的情况下来进行调用(方法/变量)。

 

 

 static修饰的变量:静态变量,在类加载时候完成初始化,在内存中仅有一个,jvm也只会为他分配一次内存,所有实例共享,可通过类名直接访问。实例变量与实例共存亡。在对象之间共享数据或方便访问时用静态变量。非静态变量是对象所拥有创建对象时初始化存在多个副本,各个对象的副本相互不影响。静态变量的初始化顺序是按照定义的数序进行初始化。

 

 

 静态方法:可以通过类名直接访问Math类的所有方法都是static的,不依赖于对象 可以进行访问,没有对象那么静态方法是没有this的。静态方法中不可以访问非静态成员方法或变量,但是非静态成员方法可以访问静态/变量。(静态依赖于类普通依赖于对象的创建)。

 

 

 代码块:静态代码块会随着类的加载一块执行,而且他可以随意放,可以存在于该了的任何地方。可以有多个,在类初次被加载时会按照static块的顺序来执行每个块并且只执行一次。

 java中的static和c++中的是不一样的,java中static不会影响到变量或者方法的作用域,能够影响作用域的只有private、public、protected

 public class Test {

    public static void main(String[] args) {

        System.out.println(s.age);//报错The field s.age is not visible

        System.out.println(s.name);

        

    }

}

class s{

    public static String name="zhangsan";

    private static int age=10;

}

 private修饰的原因造成。在静态方法中没有this,在非静态中通过this访问非静态成员变量会怎样。

 

 public class Test {

    static int value = 10;

    public static void main(String[] args) {

        new Test().show();

    }

    private void show() {

        int value = 1;

        System.out.println(this.value);

    }

}

 结果为10.this代表当前对象,new Test()调用show的对象就是new Test()生成的对象。static变量是所有对象共享,show是局部变量不可能与this关联,所以输出10,静态对象独立于对象但是仍可以通过对象访问。java语法规定static不允许修饰局部变量。Static也存在一些缺陷。1)它只能调用static变量。2)它只能调用static方法。3)不能以任何形式引用this、super。

 

 

 

 4)static变量在定义时必须要进行初始化,且初始化时间要早于非静态变量。无论是变量,方法,还是代码块,只要用static修饰,就是在类被加载时就已经准备好了,也就是可以被使用或者已经被执行,都可以脱离对象而执行。反之,如果没有static,则必须要依赖于对象实例。

 public class Test {

    Person person = new Person("Test");

    static{

        System.out.println("test static");

    }    

    public Test() {

        System.out.println("test constructor");

    } 

    public static void main(String[] args) {

        new My();

    }

}

class Person{

    static{

        System.out.println("person static");

    }

    public Person(String str) {

        System.out.println("person "+str);

    }

}

 

class My extends Test {

    Person person = new Person("My");

    static{

        System.out.println("myc static");

    }    

    public My() {

        System.out.println("my constructor");

    }

}

 test static   1、首先加载Test类执行静态代码块,然后执行My()my static 2、因没加载且其继承Test先加载Test,但已加执行my其静态方法person static 3、加载后执行构造函数,生成对象先初始化父类的成员变量,执行new person()但是没有加载person类,先加载就会执行person的静态方法person Test  4、完成成员初始化。test constructor 5、完成父类构造器完成初始化person My      6、自身成员变量初始化my constructor 7/构造函数初始化

 

 

 

 

 

 

 

 final关键字

 

 

 final最终的意思,他修饰的部分不会改变,final修饰数据可以看做常量,编译期常量,永远不改变,运行期初始化希望他也不变。编译期的常量在编译时即可参与运算在类加载完成后不可改变,编译期常量只能用基本类型,在定义时要初始化。运行期常量可以是基本类型和引用类型,基本类型其值不变,引用类型引用不变,应用对象的内容可以变

 

 

 final修饰方法:最终的方法,不可被继承更改,使用final修饰方法,是为了锁定方法,父类的final方法是不能被子类所覆盖的,也就是说子类是不能够存在和父类一模一样的方法的。

 

 

 final修饰类,不能被继承,final修饰的类成员变量可以是final也可以不是,成员方法默认final。

 

 

 如果final修饰参数,代表该参数不可改变。

 

 

 final和static在一起使用时即可修饰成员变量,也可修饰成员方法。对于成员变量,该变量一旦赋值就不能改变,我们称它为“全局常量”。可以通过类名直接访问。对于成员方法,则是不可继承和改变。可以通过类名直接访问。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值