反射与注解
1.反射 reflect
读取类的信息:(扫描classpath路径下面的class文件 )
classpath包含以下三个位置:
- 项目的bin目录
- 项目里添加的jar包
- 系统环境变量classpath指向的目录
类的三种获取方式
1. Class cls = Class.forName("my.Student");
2. Class cls = Student.class;
3. Integer a = 123;
Class cls2 = a.getClass();
获取字段的描述
Field[] fields = cls.getDeclaredFields();//cls类里定义的属性 得到所有属性
for(Field f : fields)
{
String name = f.getName();
Type type = f.getType(); //字段类型
int mod = f.getModifiers();//修饰符 pulic:1 private:2 ...
System.out.println(name+ "," + type.getTypeName()+ "," + mod);
}
Field nameField = cls.getDeclaredField("name"); //得到指定属性
getFields() //可以得到父类的属性(字段)
/*属性的访问,赋值 */
Object stu = cls.newInstance(); //仍以my.Student类为例 实例化对象stu
Field nameField = cls.getDeclaredField("name"); //得到指定属性
nameField.set(stu, "xyz"); //字段为public时,可以直接给该字段赋值
String name = (String) nameField.get(stu); //得到stu的属性name的值
获取方法描述
Method[] methods = cls.getMethods();
for(Method m : methods)
{
String name = m.getName();
Type type = m.getReturnType();
Class[] paramTypes = m.getParameterTypes();//方法参数类型
System.out.println(name + "方法返回值类型:" + type.getTypeName() );
}
Method method2 = cls.getMethod(methodName, xxx.class ,xxx.class);//获取指定方法
创建实例
Object obj = cls.newInstance();
//有默认的无参构造方法时
方法的调用
Class cls = Class.forName("classpath") //ex:my.Student
Object obj = cls.newInstance();
Class[] param = {double.class,double.class};//methodName方法的参数类型
Method method = cls.getMethod("methodName",param ); //通过上面方法查找方法名
Object[] argValues = {1.1,1.1};
method.invoke(obj,argValues );
返回值及类型判断
Object returnValue = method.invoke(obj,argValues );
if(returnValue instanceof Double) // object instanceof Double
System.out.println("yes"+ returnValue);
Class ccc = returnValue.getClass();
if(ccc.isAssignableFrom(Double.class)) //object.isAssignableFrom(Double.class)
System.out.println(2);
if(Double.class.isInstance(returnValue)) //class.isInstance(object)
System.out.println(3);
好了,有个这么多反射基础,我们来写一个工具方法实现 pojo->json
public static JSONObject pojo2json(Object obj) throws Exception
{
JSONObject json = new JSONObject();
Class cls = obj.getClass(); //obj 为pojo对象 得到类
Field[] fields = cls.getDeclaredFields(); //得到属性字段
for(Field f:fields)
{
String fieldName = f.getName();
//得到fieldName属性的 getter()方法名
String getterName = "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
Method getterMethod = cls.getDeclaredMethod(getterName);
Object value = getterMethod.invoke(obj);
json.put(fieldName,value);
}
return json;
}
那么,自己来实现下json->pojo吧!(tips:利用setter方法/直接给public属性赋值 )
Appendix
反射中常用的一些技术
1.类判断
* if(obj instanceof Student)
{
}
* if(Student.class.isInstance(obj))
{
}
* Class cls = obj.getClass();
if(cls.isAssignableFrom(Student.class))
{
}
* Class cls = obj.getClass();
if(cls.equals(Student.class))
{
}
2.注解 Annotation
一种配置信息,可以注册到.class文件里
@Documented
@Retention(RUNTIME)
public @interface Example
{
String name();
int type() default "1" //默认值
}
//默认参数,注解里只有一个值,且叫value() ex:String value();
元注解
用于注解其它注解类的注解
@Rentention ,保留
- SOURCE :源代码级,不会编译到class文件中
- CLASS: 会被编译到class文件中,但加载时忽略
- RUNTIME:会被编译到class文件中,并被加载到JVM(在反射技术中必须使用此项)
@Target
- TYPE:可以修饰一个类、接口、枚举等
- FIELD:可以修饰一个属性
- METHOD:可以修饰一个方法
@Documented javaDoc
@Inherited 继承
java内置注解
java.lang.*
@deprecated 过时的
@override 重写
元空间
metaspace 不会被销毁 Class对象创建后放在元空间
普通对象是存在堆区的,会被GC回收
java内置注解
java.lang.*
@deprecated 过时的
@override 重写
元空间
metaspace 不会被销毁 Class对象创建后放在元空间
普通对象是存在堆区的,会被GC回收