Class简介
反射之中所有的核心操作都是通过Class
类对象来展开的, 可以说Class
类对象是反射操作的根源所在.
定义
public final class Class<T> extends Object implements
Seralizable, GenerircDeclaration, Type, AnnotatedElement
Class实例化
-
[Object支持]
Object
类可以根据实例化对象获取Class
对象:- 缺点: 如果现在只是想获得
Class
类对象, 则必须产生指定类对象以后获得, 会造成一个无用的类对象产生
- 缺点: 如果现在只是想获得
public final Class<?> getClass();
-
[JVM直接支持] 采用
类.class
的形式实例化 -
[Class类支持] 在
Class
类中提供了一个static方法:
public static Class <?> forName(String className) throws ClassNotFoundException
反射实例化对象
创建一个单独的package
为cn
, cn
中有一个类叫Person
public class Person {
public Person() {
System.out.println("*********实例化Person***********");
}
@Override
public String toString() {
return "Person.toString";
}
}
-
在
JDK1.9之前
:
public T newInstance() throws InstantiationException, IllegalAccessException
反射实例化Person
public class Main {
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("cn.Person");
Object obj = cls.newInstance();
System.out.println(obj);
}
}
- 在
JDK1.9以后
clazz.getDeclaredConstructor().newInstance();
反射实例化Person
public class Main {
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("cn.Person");
Object obj = cls.getDeclaredConstructor().newInstance();
System.out.println(obj);
}
}
反射与工厂模式
反射与工厂模式代码实现
interface IMessage {
public void send();
}
class INetMessage implements IMessage {
@Override
public void send() {
System.out.println("发送一条消息");
}
}
interface IService {
public void service();
}
class HouseService implements IService {
@Override
public void service() {
System.out.println("发起一个服务");
}
}
class Factory {
private Factory() {}
public static <T> T getInstance(String className, Class<T> clazz) {
T instance = null;
try {
instance = (T)Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return instance;
}
}
public class Main {
public static void main(String[] args) throws Exception {
HouseService service = Factory.getInstance("HouseService", HouseService.class);
service.service();
}
}
反射与工厂模式
反射与单例设计模式
单例设计模式的核心本质在于: 类内部的构造方法私有化, 在类的内部产生实例化对象之后通过static获取实例化对象进行调用.
饿汉式单例设计
class Singleton{
private static Singleton modle = new Singleton ();//声明对象同时私有化
private Singleton (){}//构造函数私有化
public static Singleton getInstance(){//向外声明访问该类对象的方法
return modle;
}
}
懒汉式单例设计
class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
public void print() {
System.out.println("这是一个懒汉式的单例设计");
}
}
public class Main {
public static void main(String[] args) throws Exception {
Singleton single = Singleton.getInstance();
single.print();
}
}
懒汉式单例存在的问题
单例模式的最大特点是在运行当中只存在一个对象, 但是在多线程中就可以产生多个实例化对象了, 那么此时就不是单例设计模式了
问题产生的核心就是多线程进行了多次单例的实例化, 解决问题的核心是进行同步处理,
synchronized
加锁
最标准懒汉式单例
class Singleton {
private static volatile Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
public void print() {
System.out.println("这是一个懒汉式的单例设计");
}
}
public class Main {
public static void main(String[] args) throws Exception {
Singleton single = Singleton.getInstance();
single.print();
}
}
反射获取类结构信息
获取包名称
public Package getPackage();
获取继承父类
public Class <? super T> getSuperclass();
获取实现父接口
public Class<?>[] getInterfaces()
获取构造方法
- 实例化方法替代
clazz.getDeclaredConstructor().newInstance();
- 反射获取所有构造方法
public Constructor<?>[] getDeclaredConstructors() throws SecurityException;
public Constructor<?>[] getConstructors() throws
SecurityException
- 获取指定构造方法
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
throws NoSuchNMethodException, SecurityException;
public Constructor<T> getConstructors(Class<?>... parameterTypes)
throws NoSuchNMethodException, SecurityException;
反射获取普通方法
如果想通过反射调用普通方法, 那么必须类之中要提供实例化对象
- 获取全部方法
public Method[] getMethods() throws SecurityException;
- 获取指定方法
public Method getMethod(String name, Class<?>... paramterTypes)
throws NoSuchMethodException, SecurityException;
- 获取本类全部方法
public Method[] getDeclaredMethods() throws SecurityException;
- 获取本类指定方法
public Method getDeclaredMethod(String name, Class<?>... paramterTypes)
throws NoSuchMethodException, SecurityException;
反射获取成员
- 获取本类全部成员
public Field[] getDeclaredFields() throws SecurityException;
- 获取本类指定成员
public Field getDeclaredField(String name) throws
NoSuchMethodException, SecurityException;
- 获取父类全部成员
public Field[] getFields() throws SecurityException;
- 获取父类指定成员
public Field getField(String name) throws
NoSuchMethodException, SecurityException;
Unsafe工具类(不安全的操作)
Unsafe
的主要特点是可以利用反射来获取对象, 并且直接使用底层的C++
来代替JVM
执行, 即: 可以绕过JVM
的相关对象的管理机制, 如果一旦使用了Unsafe
类, 那么将无法使用JVM
的内存管理机制和垃圾回收处理
构造方法
private Unsafe() {}
私有常量
private static final Unsafe theUnsafe = new Unsafe();
属性自动赋值实现思路
在传统开发之中, 一个类的属性, 要通过setter
和getter
方法赋值和获取值, 如果属性多, 那么将带来大量的重复代码和很大的不方便. 所以要通过反射来实现自动赋值
class Company {
private String name;
private String createDate;
public void setCreateDate(String createDate) {
this.createDate = createDate;
}
public void setName(String name) {
this.name = name;
}
public String getCreateDate() {
return createDate;
}
public String getName() {
return name;
}
}
class Dept {
private String dname;
private String loc;
private Company company;
public void setDname(String dname) {
this.dname = dname;
}
public void setLoc(String loc) {
this.loc = loc;
}
public void setCompany(Company company) {
this.company = company;
}
public Company getCompany() {
return company;
}
public String getLoc() {
return loc;
}
public String getDname() {
return dname;
}
}
class Emp {
private Dept dept;
private String ename;
private String job;
private long empno;
private Double salary;
private Date birthDay;
public void setDept(Dept dept) {
this.dept = dept;
}
public Dept getDept() {
return dept;
}
public void setEname(String ename) {
this.ename = ename;
}
public void setJob(String job) {
this.job = job;
}
public void setBirthDay(Date birthDay) {
this.birthDay = birthDay;
}
public void setEmpno(long empno) {
this.empno = empno;
}
public void setSalary(Double salary) {
this.salary = salary;
}
public String getEname() {
return ename;
}
public String getJob() {
return job;
}
public Date getBirthDay() {
return birthDay;
}
public Double getSalary() {
return salary;
}
public long getEmpno() {
return empno;
}
}
class ClassInstanceFactory {
private ClassInstanceFactory() {
}
/**
* 实例化对象的创建方法, 该对象可以根据传入的字符串结构"属性:内容|属性:内容"
*
* @param clazz 要进行反射实例化的类, 有Class就可以反射实例化对象
* @param value 要设置给对象的属性内容
* return 一个已经配置好属性内容的Java类对象
*/
public static <T> T create(Class<?> clazz, String value) {
try {
Object obj = clazz.getDeclaredConstructor().newInstance();
BeanUtils.setValue(obj, value);
return (T) obj;
} catch (Exception e) {
return null;
}
}
}
// 实现属性的首字母大写
class StringUtils {
/**
* 首字母大写字符串
*
* @param str 传入的字符串
* @return 一个大写首字母的字符串
*/
public static String initcap(String str) {
if (str == null || "".equals(str)) {
return str;
}
if (str.length() == 1) {
return str.toUpperCase();
} else {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
}
}
// 实现赋值
class BeanUtils {
private BeanUtils() {
}
public static void setValue(Object obj, String value) {
String results[] = value.split("\\|"); // 按照|进行分割
for (int i = 0; i < results.length; i++) { // 循环设置属性内容
String attval[] = results[i].split(":"); // 获取属性名称和内容
System.out.println(attval[0].toString());
if (attval[0].contains(".")) { // 多级配置
String temp[] = attval[0].split("\\.");
Object currentObject = obj;
for (int j = 0; j < temp.length - 1; j++) {
try {
// 获取属性对应的get方法
// System.out.println("sss:" + temp[j]);
Method getMethod = currentObject.getClass().getDeclaredMethod("get" +
StringUtils.initcap(temp[j]));
// 调用get方法
Object tempObject = getMethod.invoke(currentObject);
// 调用对于的get方法, 如果返回不是空, 那么就不需要实例化
if (tempObject == null) {
// 获取该属性的类型
Field field = currentObject.getClass().getDeclaredField(temp[j]);
// 获取set方法
Method method = currentObject.getClass().getDeclaredMethod("set" +
StringUtils.initcap(temp[j]), field.getType());
Object newObject = field.getType().getDeclaredConstructor().newInstance();
method.invoke(currentObject, newObject);
// 实例化对象
currentObject = newObject;
} else {
currentObject = tempObject;
}
} catch (Exception e) {
e.printStackTrace();
}
}
try {
Field field = currentObject.getClass().getDeclaredField(temp[temp.length - 1]); // 获取属性
Method setMethod = currentObject.getClass().getDeclaredMethod("set" +
StringUtils.initcap(temp[temp.length - 1]), field.getType()); // 获取方法
// System.out.println("field.getType().getName()::" + field.getType().getName());
Object val = BeanUtils.convertAttributeValue(field.getType().getName(), temp[temp.length - 1]);
setMethod.invoke(currentObject, attval[1]); // 调用方法
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
Field field = obj.getClass().getDeclaredField(attval[0]); // 获取属性
Method setMethod = obj.getClass().getDeclaredMethod("set" +
StringUtils.initcap(attval[0]), field.getType()); // 获取方法
// System.out.println("field.getType().getName()::" + field.getType().getName());
Object val = BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]);
setMethod.invoke(obj, val); // 调用方法
} catch (Exception e) {
// e.printStackTrace();
}
}
}
}
private static Object convertAttributeValue(String type, String value) {
if (type == "int" || "java.lang.Integer".equals(type)) {
return Integer.parseInt(value);
} else if (type == "double" || "java.lang.Double".equals(type)) {
return Double.parseDouble(value);
} else if (type == "long" || "java.lang.long".equals(type)) {
return Long.parseLong(value);
} else if ("java.util.Date".equals(type)) {
SimpleDateFormat format = null;
if (value.matches("\\d{4}-\\d{2}-\\d{2}")) {
System.out.println("???");
format = new SimpleDateFormat("yyyy-MM-dd");
} else if (value.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) {
format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
} else {
return new Date();
}
try {
return format.parse(value);
} catch (ParseException e) {
// e.printStackTrace();
return new Date();
}
} else {
return value;
}
}
}
public class Main {
public static void main(String[] args) throws Exception {
/**
* dept.dname == Emp的实例化对象.getDept().setDname("工程技术部")
* dept.company.name:ayd == Emp的实例化对象.getDept().getCompany().setName("ayd")
*/
Emp emp = ClassInstanceFactory.create(Emp.class, "dept.dname:工程技术部|dept.company.name:ayd" +
"|empno:2827892|ename:小强|job:程序员" +
"|salary:2937829|birthDay:1989-10-10");
System.out.println("部门:" + emp.getDept().getDname() + ",公司:" + emp.getDept().getCompany().getName() + ",编号:" + emp.getEmpno() + ", 姓名:" + emp.getEname() + ", 工作:" + emp.getJob()
+ ", 工资:" + emp.getSalary() + ", 生日:" + emp.getBirthDay());
// System.out.println(emp.getDept());
// System.out.println(emp.getDept().getCompany());
}
}
网友评论