1.什么是反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够获取这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取类信息以及动态调用对象内容就称为java语言的反射机制。
2.反射的作用
-
在运行时判断任意一个对象所属的类;
-
在运行时构造任意一个类的对象;
-
在运行时判断任意一个类所具有的成员变量和方法;
-
在运行时调用任意一个对象的方法;
3.反射的实现
我们知道,要使用一个类,就要先把它加载到虚拟机中,生成一个Class对象。这个class对象就保存了这个类的一切信息。
反射机制的实现,就是获取这个Class对象,通过Class对象去访问类、对象的元数据以及运行时的数据。
**有三种方法获得类的Class对象:**Class.forName(String className)、className.class、实例对象.getClass();
4.什么是 Java 序列化?什么情况下需要序列化?
Java 序列化是为了保存各种对象在内存中的状态,并且可以把保存的对象状态再读出来。
以下情况需要使用 Java 序列化:
- 想把的内存中的对象状态保存到一个文件中或者数据库中时候;
- 想用套接字在网络上传送对象的时候;
- 想通过RMI(远程方法调用)传输对象的时候。
5.动态代理是什么?有哪些应用?
动态代理是运行时动态生成代理类。
动态代理的应用有 spring aop、hibernate 数据查询、测试框架的后端 mock、rpc,Java注解对象获取等。
6.怎么实现动态代理?
JDK 原生动态代理和 cglib 动态代理。JDK 原生动态代理是基于接口实现的,而 cglib 是基于继承当前类的子类实现的。
7.为什么要使用克隆对象?
在java中,我们使用对象的时候直接去new一个对象就好了,为什么还要克隆对象呢?
当我们new一个对象之后是要对该对象进行初始化的,不然这个对象是空的没有内容。而使用克隆,则会得到一个原对象以及原对象里面包含的内容。例如,你有一个User对象,里面的包含了相关的属性。此时你想要修改里面的某一属性,但又不想破坏原对象里面的数据,此时就可以克隆User这个对象,然后在克隆的这个User对象上进行修改操作。除此,如果你在操作完之后判断一下属性是否更改成功,则使用克隆的对象和原对象做一下对比即可。
8.如何克隆一个对象?
8.1浅复制
浅克隆就是把原对象中的一些属性值克隆过来。使用clone()方法进行浅克隆。但注意:必须要在被克隆类上实现Cloneable接口,并重写clone方法。若不没有实现该接口,则会抛出CloneNotSupportedException异常!
1package interview; 2 3public class CloneTest { 4 5 public static void main(String[] args) throws CloneNotSupportedException { 6 // TODO Auto-generated method stub 7 User user = new User(); 8 user.setName("张三"); 9 user.setAge(18); 10 System.out.println("原对象(user)的属性值:"); 11 System.out.println("姓名为:" + user.getName() + ",年龄为:" + user.getAge()+"\n"); 12 13 // 对user对象进行克隆 14 User user1 = (User) user.clone(); 15 // 查看一下克隆对象中的属性值 16 System.out.println("克隆后user1对象中的属性值:"); 17 System.out.println("姓名为:" + user1.getName() + ",年龄为:" + user1.getAge()+"\n"); // 结果和原对象中属性值相同 18 19 // 对user1对象进行修改 20 user1.setName("李四"); 21 // 查看修改后的结果 22 System.out.println("user1对象进行修改后的属性值:"); 23 System.out.println("姓名为:" + user1.getName() + ",年龄为:" + user1.getAge()+"\n"); 24 25 System.out.println("user1对象进行修改后user对象的属性值:"); 26 System.out.println("姓名为:" + user.getName() + ",年龄为:" + user.getAge()+"\n"); 27 } 28 29} 30 31class User implements Cloneable { 32 private String name; 33 private int age; 34 35 public String getName() { 36 return name; 37 } 38 39 public void setName(String name) { 40 this.name = name; 41 } 42 43 public int getAge() { 44 return age; 45 } 46 47 public void setAge(int age) { 48 this.age = age; 49 } 50 51 @Override 52 protected Object clone() throws CloneNotSupportedException { 53 // TODO Auto-generated method stub 54 return super.clone(); 55 } 56}

从结果上可以看出,克隆对象user1和原对象user在修改属性数据时,两个对象之间的数据互不受影响。
那么如果后期需要调整代码,需要在原有的user对象中添加一个引用类型Address字段,那么克隆的user1对象会能受到影响吗?能和原对象user中的数据一致吗?
看下面代码演示,在原有基础代码上加入一个Address的类,并分别在User类和Address类中加入重写Object的方法。注意:User类中的引用address字段的权限修饰符为public,否则无法运行!
1package interview; 2 3public class CloneTest { 4 5 public static void main(String[] args) throws CloneNotSupportedException { 6 // TODO Auto-generated method stub 7 // 创建原对象,并为原对象中的属性进行赋值,然后打印出结果 8 Address address = new Address("中国", "山东"); 9 User user = new User("张三", 18, address); 10 System.out.println("原对象(user)的属性值:"); 11 System.out.println("姓名为:" + user.getName() + ",年龄为:" + user.getAge() + ",地址为:" + user.getAddress() + "\n"); 12 13 // 对user对象进行克隆 14 User user1 = (User) user.clone(); 15 // 查看一下克隆对象中的属性值 16 System.out.println("克隆后user1对象中的属性值:"); 17 System.out.println("姓名为:" + user1.getName() + ",年龄为:" + user1.getAge() + ",地址为:" + user1.getAddress() + "\n"); 18 19 // 对user1对象进行修改 20 user1.setName("李四"); 21 user1.getAddress().setCity("北京"); 22 // 查看修改后的结果 23 System.out.println("user1对象进行修改后的属性值:"); 24 System.out.println("姓名为:" + user1.getName() + ",年龄为:" + user1.getAge() +",地址为:" + user1.getAddress() + "\n"); 25 26 System.out.println("user1对象进行修改后user对象的属性值:"); 27 System.out.println("姓名为:" + user.getName() + ",年龄为:" + user.getAge() + ",地址为:" + user.getAddress() + "\n"); 28 } 29 30} 31 32class User implements Cloneable { 33 private String name; 34 private int age; 35 private Address address; 36 37 public User(String name, int age, Address address) { 38 this.name = name; 39 this.age = age; 40 this.address = address; 41 } 42 43 public Address getAddress() { 44 return address; 45 } 46 47 public void setAddress(Address address) { 48 this.address = address; 49 } 50 51 public String getName() { 52 return name; 53 } 54 55 public void setName(String name) { 56 this.name = name; 57 } 58 59 public int getAge() { 60 return age; 61 } 62 63 public void setAge(int age) { 64 this.age = age; 65 } 66 67 @Override 68 protected Object clone() throws CloneNotSupportedException { 69 // TODO Auto-generated method stub 70 return super.clone(); 71 } 72} 73 74// 定义一个address类 75class Address { 76 private String country; 77 private String city; 78 79 public Address(String country, String city) { 80 this.country = country; 81 this.city = city; 82 } 83 84 public String getCountry() { 85 return country; 86 } 87 88 public void setCountry(String country) { 89 this.country = country; 90 } 91 92 public String getCity() { 93 return city; 94 } 95 96 public void setCity(String city) { 97 this.city = city; 98 } 99 100 @Override 101 public String toString() { 102 return "Address [country=" + country + ", city=" + city + "]"; 103 } 104 105}

从结果上看,user1在克隆完后修改了姓名和地址值,修改后和原对象对比,发现姓名和地址的确发生了改变。但再次查看原对象的结果时,发现原对象的姓名值虽没变,但地址值却随着user1对象的改变而改变了!这样的话反而失去了克隆的意义。那么为什么会出现这种情况呢?因为浅克隆只是克隆原对象中的引用类型指向,并非克隆了原对象中的全部数据。
3.2 深克隆
深克隆和浅克隆的区别在于:浅克隆只克隆了原对象的引用类型的指向。深克隆则是克隆了原对象的所有。也就是说像上面案例所示,如果使两个对象之间互不影响,则使用深克隆。
深克隆的使用:在引用类型所在的类使其实现Cloneable接口,并使用public修饰符重写Clone()方法。
1package interview; 2 3public class CloneTest { 4 5 public static void main(String[] args) throws CloneNotSupportedException { 6 // TODO Auto-generated method stub 7 // 创建原对象,并为原对象中的属性进行赋值,然后打印出结果 8 Address address = new Address("中国", "山东"); 9 User user = new User("张三", 18, address); 10 System.out.println("原对象(user)的属性值:"); 11 System.out.println("姓名为:" + user.getName() + ",年龄为:" + user.getAge() + ",地址为:" + user.getAddress() + "\n"); 12 13 // 对user对象进行克隆 14 User user1 = (User) user.clone(); 15 // 查看一下克隆对象中的属性值 16 System.out.println("克隆后user1对象中的属性值:"); 17 System.out.println("姓名为:" + user1.getName() + ",年龄为:" + user1.getAge() + ",地址为:" + user1.getAddress() + "\n"); 18 19 // 对user1对象进行修改 20 user1.setName("李四"); 21 user1.getAddress().setCity("北京"); 22 // 查看修改后的结果 23 System.out.println("user1对象进行修改后的属性值:"); 24 System.out.println("姓名为:" + user1.getName() + ",年龄为:" + user1.getAge() + ",地址为:" + user1.getAddress() + "\n"); 25 26 System.out.println("user1对象进行修改后user对象的属性值:"); 27 System.out.println("姓名为:" + user.getName() + ",年龄为:" + user.getAge() + ",地址为:" + user.getAddress() + "\n"); 28 } 29 30} 31 32class User implements Cloneable { 33 private String name; 34 private int age; 35 private Address address; 36 37 public User(String name, int age, Address address) { 38 this.name = name; 39 this.age = age; 40 this.address = address; 41 } 42 43 public Address getAddress() { 44 return address; 45 } 46 47 public void setAddress(Address address) { 48 this.address = address; 49 } 50 51 public String getName() { 52 return name; 53 } 54 55 public void setName(String name) { 56 this.name = name; 57 } 58 59 public int getAge() { 60 return age; 61 } 62 63 public void setAge(int age) { 64 this.age = age; 65 } 66 67 @Override 68 protected Object clone() throws CloneNotSupportedException { 69 // TODO Auto-generated method stub 70 // 这一步返回的这个user对象还只是一个浅克隆, 71 User user = (User) super.clone(); 72 // 然后克隆的过程中获得这个克隆的user,然后调用这个getAddress()这个方方法得到这个Addrress对象。然后实现克隆。在设置到这个user中的Address。 73 // 这样实现了双层克隆使得那个Address对象也得到了复制。 74 user.setAddress((Address) user.getAddress().clone()); 75 return user; 76 } 77} 78 79// 定义一个address类 80class Address implements Cloneable { 81 private String country; 82 private String city; 83 84 public Address(String country, String city) { 85 this.country = country; 86 this.city = city; 87 } 88 89 public String getCountry() { 90 return country; 91 } 92 93 public void setCountry(String country) { 94 this.country = country; 95 } 96 97 public String getCity() { 98 return city; 99 } 100 101 public void setCity(String city) { 102 this.city = city; 103 } 104 105 @Override 106 public String toString() { 107 return "Address [country=" + country + ", city=" + city + "]"; 108 } 109 110 @Override 111 protected Object clone() throws CloneNotSupportedException { 112 // TODO Auto-generated method stub 113 return super.clone(); 114 } 115 116}

9.如何实现对象克隆?
- 实现 Cloneable 接口并重写 Object 类中的 clone() 方法。
- 实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。