//Java中的反射
//Java反射机制是指在运行状态中
//
//对于任意一个类,都能知道这个类的所有属性和方法;
//对于任何一个对象,都能够调用它的任何一个方法和属性;
//这样动态获取新的以及动态调用对象方法的功能就叫做反射。
//反射机制的相关类
//
//Class 代表类实类
//Field 代表类的成员变量
//Method 代表类方法
//Constructor 代表类的构造函数
Class clz = ContentBean.class;
try {//获得公有属性
Field field = clz.getField("content");
System.out.println("field = " + field.getName());
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
//获得所有公有属性
Field[] fields = clz.getFields();
for (Field f :
fields) {
System.out.println("field = " + f.getName());
}
System.out.println("_____________________________________________________________");
try {//获得某个类的属性
Field declaredField = clz.getDeclaredField("author");
System.out.println("修饰符:" + Modifier.toString(declaredField.getModifiers())
+ " declaredField = " + declaredField.getName());
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
//获得所有属性
Field[] declaredFields = clz.getDeclaredFields();
for (Field df :
declaredFields) {
System.out.println("修饰符:" + Modifier.toString(df.getModifiers())
+ " declaredField = " + df.getName());
}
System.out.println("_____________________________________________________________");
//获得与参数匹配的公有注解对象
Annotation annotation = clz.getAnnotation(Deprecated.class);
if (annotation != null)
System.out.println("annotation:" + annotation.annotationType().getName());
//获得所有公有注解对象
Annotation[] annotations = clz.getAnnotations();
for (Annotation a :
annotations) {
System.out.println("修饰符:" + Modifier.toString(a.annotationType().getModifiers()) + " a = " + annotation.annotationType().getName());
}
System.out.println("_____________________________________________________________");
//获得某个匹配的注解对象
Annotation declaredAnnotation = clz.getDeclaredAnnotation(Deprecated.class);
if (declaredAnnotation != null)
System.out.println("declaredAnnotation:" + declaredAnnotation.annotationType().getName());
//获得所有注解对象
Annotation[] declaredAnnotations = clz.getDeclaredAnnotations();
for (Annotation da:
declaredAnnotations) {
System.out.println("修饰符:" + Modifier.toString(da.annotationType().getModifiers()) + " da:" + da.annotationType().getName());
}
System.out.println("_____________________________________________________________");
//获得某个参数类型匹配的公有构造函数
try {
Constructor constructor = ContentBean.class.getConstructor();
System.out.println("constructor = " + constructor.getName());
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
//获得所有公有构造函数
Constructor[] constructors = ContentBean.class.getConstructors();
for (Constructor c :
constructors) {
System.out.println("修饰符:" + Modifier.toString(c.getModifiers()) + " c:" + c.getName());
}
System.out.println("_____________________________________________________________");
//获得某个参数类型匹配的构造函数
try {
Constructor dc = ContentBean.class.getDeclaredConstructor();
System.out.println("dc = " + dc.getName());
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
//获得所有构造函数
Constructor[] dcs = ContentBean.class.getDeclaredConstructors();
for (Constructor dc: dcs) {
System.out.println("修饰符:" + Modifier.toString(dc.getModifiers()));
System.out.println("所有参数:");
Parameter[] parameters = dc.getParameters();
for (Parameter p :
parameters) {
System.out.println("修饰符 = " + p.getType().getSimpleName() + " p = " + p.getName());
}
}
System.out.println("_____________________________________________________________");
//获得某个参数类型与函数名称匹配的函数
try {
Method method = ContentBean.class.getMethod("getName");
System.out.println("method = " + method.getName() + " " + method.getReturnType().getSimpleName());
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
//...........省略getMethods()、getDeclaredMethod(...)、getDeclaredMethods()...........
System.out.println(clz.isAnnotation());//是否是注解类型
System.out.println(clz.isAnnotationPresent(Deprecated.class));//是否被指定注解类型修饰
System.out.println(clz.isAnonymousClass());//是否是匿名类
System.out.println(clz.isArray());//是否是数组
System.out.println(clz.isEnum());//是否是枚举类
System.out.println(clz.isInterface());//是否是接口类
System.out.println(clz.isLocalClass());//是否是局部类
System.out.println(clz.isMemberClass());//是否是内部类
//Field类
//equals(object):属性与obj相等则返回true
//get(object):获得obj中对应的属性值
//set(object, value);设置obj中对应属性值
ContentBean c = new ContentBean();
c.setAuthor("测试");
try {
Field field = clz.getDeclaredField("author");
field.setAccessible(true);
System.out.println("author = " + field.get(c));
field.set(c, "内容变了");
System.out.println("author = " + field.get(c));
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}
//Method类
//invoke(obj, args...)
try {
Method method = clz.getDeclaredMethod("setAuthor", String.class);
method.invoke(c, "内容又变了");
Method method2 = clz.getDeclaredMethod("getAuthor");
System.out.println(method2.invoke(c));
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
//Constructor类
//newInstance方法
try {
Constructor constructor = clz.getDeclaredConstructor(String.class, String.class);
constructor.setAccessible(true);
ContentBean cb = (ContentBean)constructor.newInstance("dragon", "龙博");
System.out.println(cb.getName());
System.out.println(cb.getAuthor());
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
//正确构造反射的步骤
try {
Class> className = Class.forName("com.dragon.devl.test.ContentBean");
//获取到类对象后,自行决定反射其内部哪些方法,比如反射setName方法
Method method = className.getDeclaredMethod("setName", String.class);
//获取到方法对象后,需要构建对应的类实例,才可以反射该方法
Constructor constructor = className.getDeclaredConstructor();
//constructor.setAccessible(true);无参构造函数是public类型,所以不需要设置权限
Object obj = constructor.newInstance();//调用该构造方法获取对象
method.invoke(obj, "测试");//调用setName方法。
//最后我们输出数据
Method getMethod = className.getDeclaredMethod("getName");
System.out.println(getMethod.invoke(obj));
//如果只是调用静态方法,则不需要构造实例,直接使用method.invoke(null, args)调用
Method staticMethod = className.getDeclaredMethod("setDesc", String.class);
staticMethod.invoke(null, "设置静态属性值");
Method getStaticMethod = className.getDeclaredMethod("getDesc");
System.out.println(getStaticMethod.invoke(null));
System.out.println(ContentBean.getDesc());
} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {///由于可能会出现找不到类的情况,所以需要捕获异常
e.printStackTrace();
}
Java注解
Annotation(注解)就是Java提供了一种源程序中的元素关联任何信息或者任何元数据(metadata)的途径和方法。
Annotation是被动的元数据,永远不会有主动行为
//自定义注解,使用@interface表示这是一个注解,Annotation只有成员变量,没有方法
//Annotation的成员变量在Annotation中以无形参的方法形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
@Documented
@Inherited
public @interface BindContent {
String content() default "nothing";
boolean canBeNull() default false;
}
//在自定义注解内部使用的注解称之为元注解
//@Retention 用来标记自定义注解的有效范围
//1、RetentionPolicy.SOURCE:只在源代码中保留,一般是用来增加代码的理解性或者帮助代码检查之类的,例如override
//2、RetentionPolicy.CLASS:默认值,把注解保留到编译后的字节码文件中,但运行时无法得到
//3、RetentionPolicy.RUNTIME:保留到编译后的字节码文件中,同时也能在运行时获取。
//@Target:指定Annotation用于修饰哪些程序元素
//内部包含一个value[]成员变量
//允许传入以下值
//ElementType.TYPE:能修饰类、接口或枚举类
//ElementType.FIELD:修饰成员变量
//ElementType.METHOD:修饰方法
//ElementType.PARAMETER:修饰参数
//ElementType.CONSTRUCTOR:修饰构造器
//ElementType.LOCAL_VARIABLE:修饰局部变量
//ElementType.ANNOTATION_TYPE:修饰注解
//ElementType.PACKAGE:修饰包
//@Documented表示可以在javadoc中被找到
//@Interited:表示注解里的内容可以被子类继承,只针对class类
//类继承关系中,子类会继承父类使用的注解中被@Inherited修饰的注解
//
//接口继承关系中@Inherited的作用
//
//接口继承关系中,子接口不会继承父接口中的任何注解,不管父接口中使用的注解有没有被@Inherited修饰
//
//类实现接口关系中@Inherited的作用
//
//类实现接口时不会继承任何接口中定义的注解
然后通过反射来获取对应的注解内容
@BindContent(content = "Class desc")
public class AnnotationTesting {
@BindContent()
public String content;
public void printInfo() {
System.out.println(content);
}
public static void main(String[] args) {
try {
Class c = Class.forName("com.dragon.devl.test.AnnotationTesting");
AnnotationTesting annotationTesting = (AnnotationTesting)c.newInstance();
Field[] fields = c.getDeclaredFields();
for (Field f :
fields) {
if (f.isAnnotationPresent(BindContent.class)) {
BindContent bc = f.getAnnotation(BindContent.class);
f.set(annotationTesting, bc.content());
}
}
annotationTesting.printInfo();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
}