1. 程式人生 > >Java反射和註解一些總結

Java反射和註解一些總結

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

五種類或介面

  1. 頂層類 Top level classes
  2. 巢狀類Nested classes / 靜態成員類static member classes
  3. 內部類Inner classes/ 非靜態成員類non-static member classes
  4. 區域性類Local classes 類的宣告在一個方法中
  5. 匿名類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
);