目录
一、注解
一、什么是注解
二、内置注解
三、元注解
重点掌握
二、对象克隆
一、为什么要克隆
误区:
二、如何实现克隆
三、浅克隆和深克隆
1、浅克隆
2、深克隆
四、解决多层克隆问题
Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。 Java 语言中的类、方法、变量、参数和包等都可以被标注,然后让编译器或运行时其他类解析完成某个功能,注解也可以编译到字节码文件中。
Java中已经定义好的注解。
@Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接 口中并没有该方法时,会报编译错误。 @Deprecated - 标记过时方法。如果使用该方法,会报编译警告。 @SuppressWarnings - 指示编译器去忽略注解中声明的警告。 @FunctionalInterface 用于指示被修饰的接口是函数式接口。
用于修饰注解的注解,通常用在注解的定义上。
@Retention - 标识这个注解怎么保存,是只在代码中,还是编入 class 文件中, 或者是在运行时可以通过反射访问。 @Documented - 标记这些注解是否包含在用户文档中。 @Target - 标记这个注解应该是哪种 Java 成员。 @Inherited - 标记这个注解是继承于哪个注解类(默认注解并没有继承于任何 子类) @Repeatable - 标识某注解可以在同一个声明上使用多次。
@Target:注解范围可以用在那些元素上。
ElementType.TYPE 可以应用于类的任何元素。 ElementType.CONSTRUCTOR 可以应用于构造函数。 ElementType.FIELD 可以应用于字段或属性。 ElementType.LOCAL_VARIABLE 可以应用于局部变量。 ElementType.METHOD 可以应用于方法级注释。 ElementType.PACKAGE 可以应用于包声明。 ElementType.PARAMETER 可以应用于方法的参数。
@Retention:注解生效范围。
1.SOURCE:在源文件中有效(即源文件保留) 2.CLASS:在 class 文件中有效(即 class 保留) 3.RUNTIME:在运行时有效(即运行时保留)
需要一个新的对象来保存当前对象的“状态”要靠 clone 方法。
例如:以下方法是引用,stu1和stu2都是指向同一个地址,同一个对象。
Student stu1 = new Student ();
Student stu2 = stu1 ;
基本类型的值可以直接复制,引用类型只能复制引用地址。(引用类型包括 类、接口、数组等复杂类型)
例如:
Person p1 = new Person(100,"jim");
Person p2 =p1.clone();//clone方法 返回一个新对象
克隆一个对象时,如果对象中有关联的对象,只将关联对象的地址复制过来。
实现方式:Java 语言中,通过覆盖 Object 类的 clone()方法;
spring 框架中提供, BeanUtils.copyProperties(source,target)。
克隆一个对象时,如果对象中有关联的对象,如果将关联的对象也一同克隆(创建一个新的)。
实现方式:在每一层类中都重写clone方法,类实现 Cloneable接口, 但层级多了就比较麻烦。
通过序列化(Serialization)实现 Serializable 接口方式来实现。
序列化就是将对象写到流的过程,写到流中的对象是原有对象的一个拷贝,而原 对象仍然存在于内存中。通过序列化实现的拷贝不仅可以复制对象本身,而且可 以复制其引用的成员对象,因此通过序列化将对象写到一个流中,再从流里将其 读出来,可以实现深克隆。
例如:
public class Person implements Serializable {//实现Serializable接口
int num;
String name;
Address address;
public Person() {
}
public Person(int num, String name) {
this.num = num;
this.name = name;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
/**
* 自定义克隆方法
* @return
*/
public Person myclone() {
Person person = null;
try { // 将该对象序列化成流,因为写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。所以利用这个特性可以实现对象的深拷贝
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
// 将流序列化成对象
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
person = (Person) ois.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return person;
}
@Override
public String toString() {
return "Person{" +
"num=" + num +
", name='" + name + '\'' +
", address=" + address +
'}';
}
}