基础篇-java优势,类初始化,克隆
1 java与C和C++相比的优势------------------------------begin----------------------------------
1.1 java纯面向对象,万事万物皆对象
1.2 平台无关性: 编译器把java代码编译为中间代码(字节码),字节码与平台无关,在java虚拟机(JVM)上即可执行
1.3 提供了很多内置类库,简化了开发人员的程序设计工作,缩短了项目开发时间:如多线程,网络通信,垃圾回收(GC),最重要的是提供了GC,这是得开发人员从对内存的管理中解脱出来。
1.4 提供了web应用开发的支持
Applet,Servlet和JSP可以用来开发web应用程序
Socket,RMI可以用来开发分布式应用程序的类库
1.5 具有较好的安全性和健壮性
java提供了一个防止恶意代码工具的安全机制,强制类型转换,垃圾回收器,异常处理,安全检查机制,使得java程序有很好的健壮性。
1.6 去除了c++中难以理解,容易混淆的特性,如头文件,指针,结构,单元,运算符重载,多重继承等,使程序根据严谨,简洁。
2 类初始化顺序-----------------------------begin-------------------------------------
实例化对象时,对象所在类的所有成员变量首先要进行初始化,初始化完成后,才会调用构造函数创建对象
原则:1 静态优先 2父类优先于子类 3 按成员变量定义顺序初始化
顺序:
父类静态变量>父类静态代码块>子类静态变量>子类静态代码块>父类非静态变量>父类非静态代码块
>父类构造函数>子类非静态变量>子类非静态代码块>子类构造函数
3 克隆对象-------------------------------begin-----------------------------------------
3.1 目的:
我们总会需要某个新的对象B,拥有和原对象A一样的状态,但修改新对象B时不改变原对象A的状态。
我们可以new一个新对象B,然后把原对象A的属性一个个手动赋值给新对象B,但很繁琐。
所以才有了 克隆 用克隆造出一个对象副本。
3.2 如何实现:
方法1 Object 自带浅克隆方法
protected native Object clone() throws CloneNotSupportedException;
说明:1.这是一个navtive方法 2.要使用该方法必须继承Object类,因为修饰符为protected 3.返回值为Object,需要强转
浅度克隆
public class Empolyee implements Serializable,Cloneable { private static final long serialVersionUID = 199958867467854597L; //职位 private String title; //人员 private Person person; /** * 克隆方法 * @return */ @Override protected Object clone() { Empolyee empolyee = null; try { empolyee = (Empolyee) super.clone(); //引用类型 // empolyee.setPerson((Person)person.clone()); return empolyee; } catch (CloneNotSupportedException e) { e.printStackTrace(); } return null; }
如上图,调用了超类的clone方法
//克隆测试类 public void shallowCloneTest() throws Exception { //初始化对象 Empolyee empolyeeOld = new Empolyee(); Person person = new Person(); person.setAge("18"); person.setSex("男"); person.setName("小铁"); empolyeeOld.setPerson(person); empolyeeOld.setTitle("高中学生"); //克隆对象 Empolyee employeeNew = (Empolyee)empolyeeOld.clone(); System.out.println("原对象="+JsonUtils.toJson(empolyeeOld)); employeeNew.getPerson().setAge("40"); employeeNew.getPerson().setName("老铁"); System.out.println("修改新对象 年龄=40,姓名=老铁"); System.out.println("原对象="+JsonUtils.toJson(empolyeeOld)); System.out.println("新对象="+JsonUtils.toJson(employeeNew)); }
浅克隆测试,输出结果
原对象={"person":{"age":"18","name":"小铁","sex":"男"},"title":"高中学生"}
修改新对象 年龄=40,姓名=老铁,职位=上市公司CEO
原对象={"person":{"age":"40","name":"老铁","sex":"男"},"title":"高中学生"}
新对象={"person":{"age":"40","name":"老铁","sex":"男"},"title":"上市公司CEO"}
可以看到改了新对象的Person属性 年龄,姓名 原对象也改了
改了新对象的职位,原对象职位值未变
得出结论 Object的clone 方法是浅克隆,只克隆基础数据类型,其中新对象中引用类型和数组都还是指向原对象的引用。
方法2 用clone做深度克隆
还是用clone方法,但对复杂类型的属性,单独再克隆一次
/** * 克隆方法 * @return */ @Override public Object clone() { Empolyee empolyee = null; try { empolyee = (Empolyee) super.clone(); //复杂类型属性克隆 empolyee.setPerson((Person)person.clone()); return empolyee; } catch (CloneNotSupportedException e) { e.printStackTrace(); } return null; }
继续运行克隆测试类
测试结果
原对象={"person":{"age":"18","name":"小铁","sex":"男"},"title":"高中学生"}
修改新对象 年龄=40,姓名=老铁,职位=上市公司CEO
原对象={"person":{"age":"18","name":"小铁","sex":"男"},"title":"高中学生"}
新对象={"person":{"age":"40","name":"老铁","sex":"男"},"title":"上市公司CEO"}
可以看出,修改了新对象不管是基本数据类型,还是引用类型的值,原对象都不会改变
可以得出结论,此为深度克隆
但是这种方式很繁琐,如果有大量复杂类型的成员变量(类属性),那就要分别对各属性克隆。所以我们应该找更好的方法来做 深度克隆。
方法3 用序列化方式做深度克隆
/** * 深度克隆方法 * * @param needCloneObject 需要克隆对象 * @return */ public static Object deepClone(Object needCloneObject) throws Exception { Object objNewOne = null; if (needCloneObject != null) { //把对象序列化为字节流 ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(needCloneObject); oos.close(); //把字节流反序列化为对象 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); objNewOne = ois.readObject(); ois.close(); } return objNewOne; }
调用测试方法
@Test public void cloneTest() throws Exception { //初始化对象 Empolyee empolyeeOld = new Empolyee(); Person person = new Person(); person.setAge("18"); person.setSex("男"); person.setName("小铁"); empolyeeOld.setPerson(person); empolyeeOld.setTitle("高中学生"); //调用序列化深度克隆方法 克隆对象 Empolyee employeeNew = (Empolyee)deepClone(empolyeeOld); System.out.println("原对象="+JsonUtils.toJson(empolyeeOld)); employeeNew.getPerson().setAge("40"); employeeNew.getPerson().setName("老铁"); employeeNew.setTitle("上市公司CEO"); System.out.println("修改新对象 年龄=40,姓名=老铁,职位=上市公司CEO"); System.out.println("原对象="+JsonUtils.toJson(empolyeeOld)); System.out.println("新对象="+JsonUtils.toJson(employeeNew)); }
输出结果
原对象={"person":{"age":"18","name":"小铁","sex":"男"},"title":"高中学生"}
修改新对象 年龄=40,姓名=老铁,职位=上市公司CEO
原对象={"person":{"age":"18","name":"小铁","sex":"男"},"title":"高中学生"}
新对象={"person":{"age":"40","name":"老铁","sex":"男"},"title":"上市公司CEO"}
可以看出,修改了新对象不管是基本数据类型,还是引用类型的值,原对象都不会改变,为深度克隆。
而且此种方式的性能也做好,所以强烈推荐使用。
------------------------------------------克隆 end-----------------------------------------