Java 反射和注解的一些总结
反射
// There are five kinds of classes (or interfaces):
// a) Top level classes
// b) Nested classes (static member classes)
// c) Inner classes (non-static member classes)
// d) Local classes (named classes declared within a method)
// e) Anonymous classes
五种类或接口
- 顶层类 Top level classes
- 嵌套类Nested classes / 静态成员类static member classes
- 内部类Inner classes/ 非静态成员类non-static member classes
- 局部类Local classes 类的声明在一个方法中
- 匿名类Anonymous classes
Class对象的方法
Class getEnclosingClass(); //嵌套类、内部类调用,获取其所在的外围类的类字面常量(Class对象)
Method getEnclosingMethod(); //局部类、匿名类调用,获取其所在的外围方法
Class[] getDeclaredClasses(); //获取当前类的所有声明的内部类
newInstance();//实例化对象
//公有构造函数
Constructor<T> getConstructor(Class<?>... parameterTypes);
Constructor[] getCounstructors();
//所有声明的构造函数
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes);
Constructor[] getDeclaredCounstructors();
//获取声明的作用域(不包含父类)
Field getDeclaredField(String name);
Field[] getDeclaredFields()
//获取公有作用域(包含父类)
Field getField(String name);
Field[] getFields();
//获取声明的方法(不包含父类)
Method getDeclaredMethod(String name, Class<?>... parameterTypes);
Method[] getDeclaredMethods();
//获取公有的方法(包含父类)
Method getMethod(String name, Class<?>... parameterTypes);
Method[] getMethods();
public int getModifiers(); //修饰符
//声明在该类上的注解 @Target(ElementType.TYPE)
<A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass)
Annotation[] getDeclaredAnnotations()
Field对象方法
public void set(Object obj, Object value) //设置作用域的值,obj为目标对象,value为带设置的值
public Object get(Object obj) //获取对象在该作用域的值
public int getModifiers(); //修饰符
//声明在该作用域上的注解 @Target(ElementType.FIELD)
<A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass)
Annotation[] getDeclaredAnnotations()
Constructor对象的方法
public T newInstance(Object ... initargs) //调用构造函数实例化对象
public int getModifiers(); //修饰符
//声明在构造器上的注解@Target(ElementType.CONSTRUCTOR)
<A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass)
public Annotation[] getDeclaredAnnotations()
Method 对象的方法
public Object invoke(Object obj, Object... args) //反射执行方法,obj为对象,args为参数
//如果是静态方法的话,obj为null, 不需要实例对象
public int getModifiers() //修饰符
//参数类型
public Class<?>[] getParameterTypes() { return parameterTypes.clone(); }
public int getParameterCount() { return parameterTypes.length; }
//参数上的注解@Target(ElementType.PARAMETER)
//因为一个方法上可能有多个参数,一个参数可能有多个注解,所以返回的是二维数组
public Annotation[][] getParameterAnnotations()
//获取方法上的注解@Target(ElementType.METHOD)
<A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass);
public Annotation[] getDeclaredAnnotations();
Modifier工具类
Java自带的类,可以用于判段某个类,方法,作用域的修饰符
public static boolean isPublic(int mod) { return (mod & PUBLIC) != 0; }
public static boolean isPrivate(int mod) { return (mod & PRIVATE) != 0; }
public static boolean isProtected(int mod) { return (mod & PROTECTED) != 0; }
public static boolean isStatic(int mod) { return (mod & STATIC) != 0; }
public static boolean isFinal(int mod) { return (mod & FINAL) != 0; }
....
public static final int PUBLIC = 0x00000001;
public static final int PRIVATE = 0x00000002;
public static final int PROTECTED = 0x00000004;
public static final int STATIC = 0x00000008;
public static final int FINAL = 0x00000010;
public static final int SYNCHRONIZED = 0x00000020;
public static final int VOLATILE = 0x00000040;
public static final int TRANSIENT = 0x00000080;
public static final int NATIVE = 0x00000100;
public static final int INTERFACE = 0x00000200;
public static final int ABSTRACT = 0x00000400;
public static final int STRICT = 0x00000800;
注解Annotation
元注解
Java目前内置了四种元注解,负责注解其它的注解
@Target
表示该注解可以用在的地方
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
public enum ElementType {
//类,接口(包含注解类型) 或者枚举enum声明
TYPE,
//域声明,包含(enum实例)
FIELD,
//方法声明
METHOD,
//参数声明
PARAMETER,
//构造器声明
CONSTRUCTOR,
//局部变量声明
LOCAL_VARIABLE,
//注解类型
ANNOTATION_TYPE,
//包声明
PACKAGE,
/**
* Type parameter declaration
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
* @since 1.8
*/
TYPE_USE
}
@Retention
注解信息的保留级别
可选的RetentionPolicy参数包括
SOURCE: 源代码中,编译时将被丢弃
CLASS:类文件中,在运行时会被VM丢弃
RUNTIME:运行时,也能够保留,可以通过反射机制读取注解的信息
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
@Documented
将注解包含在javadoc中
@Inherited
允许子类继承父类中的注解
一个简单的例子
如下面是一个简单的根据注解生成SQL语句的例子
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
/**
* (可选) 列名
* Defaults to the field name
*/
String name() default "";
/**
* (可选) 唯一性
*/
boolean unique() default false;
/**
* (可选)能否为空
*/
boolean nullable() default true;
/**
* 长度
*/
int length() default 255;
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Id {
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
/**
* (可选) 表名
* Defaults to the entity name;
*/
String name() default "";
}
@Table(name="employee")
public class Employee {
@Id
private Long id;
@Column(name="name", length = 20, nullable = false)
private String name;
@Column(name="address", unique = true)
private String address;
private Double salary;
}
public class Main {
private static Map<Class, String> map;
static {
map = new HashMap<>();
map.put(byte.class, "TINYINT");
map.put(Byte.class, "TINYINT");
map.put(short.class, "INTEGER");
map.put(Short.class, "SMALLINT");
map.put(int.class, "INTEGER");
map.put(Integer.class, "INTEGER");
map.put(long.class, "BIGINT");
map.put(Long.class, "BIGINT");
map.put(char.class, "CHAR");
map.put(Character.class, "CHAR");
map.put(String.class, "VARCHAR");
map.put(double.class, "DOUBLE");
map.put(Double.class, "DOUBLE");
map.put(float.class, "FLOAT");
map.put(Float.class, "FLOAT");
}
public static void main(String[] args) {
System.out.println(new Main().sql(Employee.class));
}
private String sql(Class clazz) {
Table table = (Table)clazz.getDeclaredAnnotation(Table.class);
if(table == null) return "";
String tableName = table.name();
if(tableName.length() == 0)
tableName = clazz.getName();
Field[] fields = clazz.getDeclaredFields();
int fieldsLen = fields.length;
StringBuilder column_sql = new StringBuilder();
for(int i = 0; i < fieldsLen; i ++) {
Field currentField = fields[i];
String columnName = currentField.getName();
Column column = currentField.getAnnotation(Column.class);
if(column != null && column.name().length() > 0) {
columnName = column.name();
}
column_sql.append("\t").append(columnName).append(" ");
Class cla = currentField.getType();
column_sql.append(map.get(cla));
if(cla.equals(String.class))
column_sql.append("(").append(column == null ? 255 : column.length()).append(")");
column_sql.append(" ");
if(column != null) {
if(!column.nullable())
column_sql.append("NOT NULL ");
if(column.unique())
column_sql.append("UNIQUE ");
}
Annotation idAnt = currentField.getAnnotation(Id.class);
if(idAnt != null) {
column_sql.append("PRIMARY KEY ");
}
if( i + 1 != fieldsLen)
column_sql.append(",\n");
}
return "CREATE TABLE " + tableName + "(\n" + column_sql.toString() +"\n);";
}
}
//程序输出
CREATE TABLE employee(
id BIGINT PRIMARY KEY ,
name VARCHAR(20) NOT NULL ,
address VARCHAR(255) UNIQUE ,
salary DOUBLE
);