一、反射
在了解JAVA反射机制以前,首先要了解类是什么,对象是什么!
public class reflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
foo foo1 = new foo();
//1、任何一个类都一个隐含的静态成员变量class
Class c1 = foo.class;
//2、 通过实例化对象的getClass()方法获得该对象的类
Class c2 = foo1.getClass();
//c1,c2都代表了foo类的类类型
System.out.println(c1 == c2);//输出true
//3、使用Class.forName()方法获取类的类类型
Class c3 = null;
c3 = Class.forName("foo");
System.out.println(c2 == c3);//输出true
System.out.println(c2+":"+c3);//输出"class foo:class foo"
//可以通过类的类类型创建foo类的对象实例
try {
foo foo2 = (foo) c1.newInstance();
System.out.println(foo2.getClass());//输出"class foo"
} catch (InstantiationException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class foo{
}
Class c1 = int.class;
Class c2 = Integer.class;
Class c3 = String.class;
Class c4 = void.class;
System.out.println(c1+":"+c2);
System.out.println(c3+":"+c4);
输出:
int:class java.lang.Integer
class java.lang.String:void
import java.lang.reflect.Method;
public class reflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
getClassMessages("Test.java");//可以获取所有String类的方法名称,方法参数
}
public static void getClassMessages(Object obj){
//要获取类的信息,首先要获取类的类类型,
Class c = obj.getClass();//传递的是哪个子类的对象,c就该子类的类类型
//获取类的名称
System.out.println("类的名称:"+c.getName());
/*
* Method类,方法对象
* 一个成员方法就是一个Method对象
* getMethods()获取的是该类所有的public函数,包括从父类继承而来的
* getDeclaredMethods()获取的是所有该类自己声明的方法,不问访问权限
*/
Method[] ms = c.getMethods();
for (int i = 0; i < ms.length; i++) {
//得到方法的返回值类型的类类型
Class returnType = ms[i].getReturnType();
System.out.print(returnType.getName()+" ");
//获取方法的名称
System.out.print(ms[i].getName()+"(");
//获取方法的参数类型,得到的是参数列表的类型的类类型
Class[] parameterTypes = ms[i].getParameterTypes();
for(Class class1:parameterTypes){
System.out.print(class1.getName()+",");
}
System.out.print(")\n");
}
}
}
A a1 = new A();
Method m = getMethod("print",Class[]{int.class,int.class});
Method m = getMethod("print",int.class,int.class);
二、JAVA注解
Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。
注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。包含在 java.lang.annotation 包中。
2.4.1、元注解
元注解是指注解的注解。包括 @Retention @Target @Document @Inherited四种。
2.4.1.1、@Retention: 定义注解的保留策略
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
由以上的源码可以知道,他的elementType 可以有多个,一个注解可以为类的,方法的,字段的等等
作用目标有以下几种:
@Target(ElementType.TYPE) //接口、类、枚举、注解
定义的这个注解是运行时注解,在class字节码文件中存在,在运行时可以通过反射获取到。
因此这个注解可以是类注解,也可以是方法的注解
(1)首先自定义两种注解,当然注解里面的成员可以为基本的数据类型,也可以为数据,Object等等
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.*;
@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Yts {
public enum YtsType{util,entity,service,model}
public YtsType classType() default YtsType.util;
}
import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface HelloWorld {
public String name()default "";
}
(2)注解是定义好了,那么怎么来得到,解析注解呢?
解析注解:通过反射获取类,函数或成员上的运行时注解信息,从而实现动态控制程序运行的逻辑
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ParseAnnotation {
//解析得到方法的注解
public void parseMethod(Class clazz) throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException, SecurityException, NoSuchMethodException, InstantiationException {
@SuppressWarnings("unchecked")
Object obj = clazz.getConstructor(new Class[] {}).newInstance(new Object[] {});//通过类的构造方法实例化对象
for (Method method : clazz.getDeclaredMethods()) {//获取类自己声明的方法
HelloWorld say = method.getAnnotation(HelloWorld.class);
String name = "";
if (say != null) {
name = say.name();
method.invoke(obj, name);
}
Yts yts = (Yts) method.getAnnotation(Yts.class);
if (yts != null) {
if (Yts.YtsType.util.equals(yts.classType())) {
System.out.println("this is a util method");
} else {
System.out.println("this is a other method");
}
}
}
}
//解析得到类的注解
@SuppressWarnings("unchecked")
public void parseType(Class clazz)
throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
Yts yts = (Yts) clazz.getAnnotation(Yts.class);
if (yts != null) {
if (Yts.YtsType.util.equals(yts.classType())) {
System.out.println("this is a util class");
} else {
System.out.println("this is a other class");
}
}
}
//主函数
public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException, InstantiationException {
ParseAnnotation parse = new ParseAnnotation();
parse.parseMethod(SayHell.class);
parse.parseType(SayHell.class);
}
}
//以下是测试方法类
@Yts(classType = Yts.YtsType.util)
class SayHell {
@HelloWorld(name = " 小明 ")
@Yts
public void sayHello(String name) {
if (name == null || name.equals("")) {
System.out.println("hello world!");
} else {
System.out.println(name + "say hello world!");
}
}
public SayHell() {
System.out.println("hell");
}
}
这里是构造方法:SayHell
小明 say hello world!
this is a util method
this is a util class