Java反射和註解一些總結
阿新 • • 發佈:2019-01-02
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
);