对象克隆、反射

来源:互联网 发布:淘宝日产手办 编辑:程序博客网 时间:2024/06/05 06:27

对象的克隆


对象的浅克隆:

对象1  实例1 = (对象2)实例2.clone();

注意细节:
  1. 如果一个对象需要调用clone的方法克隆,那么该对象所属的类必须要实现Cloneable接口。  对象2要实现Cloneable接口
  2. Cloneable接口只不过是一个标识接口而已,没有任何方法。
  3. 对象的浅克隆就是克隆一个对象的时候,如果被克隆的对象中维护了其他类的对象,这时候只是克隆其他对象的地址,而没有把其他对象也克隆一份。 如果对象2中引用了对象3,对象1克隆对象2后,只是指向对象3而不会克隆对象3
  4. 对象的浅克隆不会调用到构造方法的。

对象的深克隆:

对象的深克隆就是利用对象序列化的输入输出流把对象先写到文件上,然后再读取对象的信息这个过程就称作为对象的深克隆。
ObjectInputStream
ObjectOutputStream
先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里(腌成咸菜),再从流里读出来(把咸菜回鲜),便可以重建对象。

内存溢出:不再使用的对象,应该不要让变量指向该对象,要让该对象尽快的被垃圾回收期回收。

反射

当一个字节码文件加载到内存的时候,在堆内存中会产生一个Class类型的对象(一个类只有一个Class对象),字节码文件的信息全部都存储到该Class对象中。
字节码的信息包括:类名、声明的方法、声明的字段、构造方法等信息,封装在Class类、Method类、Field类、Constructor类中。一个类的任何成员都有对应的类进行描述
我们只要获取到Class对象,我们就可以通过Class类、Method类、Field类、Constructor类等等类得到这个类型的一些信息,甚至可以不用new关键字就创建一个实例,执行一个对象中的方法,设置或获取字段的值,这就是反射技术
可以在运行时期动态创建对象;获取对象的属性、方法
正常方式: 引入需要的“包.类”名称 --> 通过new实例化 --> 取得实例化对象
反射方式: 实例化对象 --> getClass()方法 --> 得到完整的“包.类”名称
所有类的对象实际上都是Class类的实例。在Java中Object类是一切类的父类,那么所有类的对象实际上也就是java.lang.Class类的实例,所以所有的对象都可以转变为lang.lang.Class类型表示

反射机制中的类
java.lang.Class;         Java反射机制的起源
java.lang.reflect.Constructor;      //构造方法
java.lang.reflect.Field;      //成员变量
java.lang.reflect.Method;     //方法
java.lang.reflect.Modifier;     //修饰符

使用反射机制的步骤:
1.导入java.lang.relfect包
2.遵循三个步骤
第一步是获得你想操作的类的 java.lang.Class 对象
第二步是调用诸如 getDeclaredMethods 的方法
第三步使用 反射API 来操作这些信息

    获取Class对象的三种方式:
  1. forName("完整类名")       forName方法用于加载某个类的字节码到内存中,并使用class对象进行封装。类名在编译期不知道但是在运行期可以获得 推荐使用
  2. 类名.class           在编译期知道类的名字可以使用此方法
  3. 对象.getClass()           已经得到一个类的实例可以使用此方法

反射api
newInstance()        用反射的方式创建一个对象的实例,相当于new
getName()     类的名称(全名,全限定名)
getSimpleName()     类的的简单名称(不带包名)
getModifiers();       类的的修饰符

getConstructors()      获取一个类的所有公共的构造方法
getDeclaredConstructors();      获取到一个类的所有构造方法,包括私有
getConstructor(int.class,String.class);       获取单个指定的构造方法

getMethods()     获取公共方法包括继承的父类的方法,返回一个数组,元素类型是Method
getMethod("setName", String.class);      获取指定参数的公共方法
Method[] getDeclaredMethods()      获得所有的方法,包括私有
Method getDeclaredMethod(String name, Class<?>... parameterTypes)     获得指定参数的方法,包括私有

Field[] getFields()      获取公共成员变量
Field getField(String name)       获取指定参数的公共成员变量
Field[] getDeclaredFields()       获取所有的成员变量
Field getDeclaredField(String name)      获取指定参数的成员变量,包括私有

反射泛型


Type接口         所有类型的默认接口    包括: 引用类型、原始类型、参数化类型···
参数化类型 ParameterizedType:   例  “ArrayList<String>”为参数化类型,“String”为实际的类型

案例
设计一个BaseDao类,所有dao的公用的方法都在里面实现。每个对象的dao继承BaseDao,通过反射泛型将具体的类型给BaseDao
public class AdminDao extends BaseDao<Admin> {}public class AccountDao extends BaseDao<account> {}public class BaseDao<T>{// 参数化类型中的实际的类型private Class clazz;// 表名private String tableName;    // 构造函数: 1. 获取当前运行类的参数化类型; 2. 获取参数化类型中实际类型的定义(class)    public BaseDao(){// this.getClass().getGenericSuperclass(); 当前运行类的父类【BaseDao<Admin>】就是“参数化类型”Type type = this.getClass().getGenericSuperclass();// 强制转换为“参数化类型” 【BaseDao<Admin>】ParameterizedType pt = (ParameterizedType) type;// 获取参数化类型中,实际类型的定义 【new Type[]{Admin.class}】Type types[] = pt.getActualTypeArguments();// 获取数据的第一个元素【Admin.class】clazz = (Class) types[0];// 表名 (与类名一样,只要获取类名就可以)tableName = clazz.getSimpleName();    }    //获取实际类型class 与表名tableName后,根据id查询    public T findById(int id){String sql = "select * from " + tableName + " where id=? ";try {return JdbcUtils.getQuerrRunner().query(sql, new BeanHandler(clazz), id);} catch (SQLException e) {throw new RuntimeException(e);}    }}







原创粉丝点击