Hướng dẫn sử dụng Java Reflection
Công ty Vĩnh Cửu tuyển dụng lập trình viên Java

Tài liệu này mới hoàn thành 80% nhưng bạn có thể xem.


 

1- Java Reflection là gì ?

  • TODO

2- Một số class tham gia trong các ví dụ

Đây là một số class tham gia vào các ví dụ trong tài liệu này.
  • Animal.java
package org.o7planning.tutorial.beans;

public abstract class Animal {

    
    public String getLocation() {
        return "Earth";
    }
    
    public abstract int getNumberOfLegs() ;
    
}
  • Say.java
package org.o7planning.tutorial.beans;

public interface Say {
    
    public String say();
}
  • Cat.java
package org.o7planning.tutorial.beans;


public class Cat extends Animal implements Say {

    public static final String SAY = "Meo meo";
    public static final int NUMBER_OF_LEGS = 4;

    // Private field.
    private String name;
    
    // Private field
    public int age;

    public Cat() {

    }

    public Cat(String name) {
        this.name = name;
        this.age = 1;
    }

    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return this.name;
    }

    // Private Method.
    private void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return this.age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    /**
     * Implements from interface Say.
     */
    @Override
    public String say() {
        return SAY;
    }

    /**
     * Implements from Animal.
     */
    @Override
    public int getNumberOfLegs() {
        return NUMBER_OF_LEGS;
    }

}

3- Bắt đầu với một ví dụ đơn giản

Đây là một ví dụ đơn giản lấy ra danh sách các method  public của một class, bao gồm cả các method thừa kế từ các class cha, và các interface.
  • ListMethod.java
package org.o7planning.tutorial.reflect.helloreflect;

import java.lang.reflect.Method;

public class ListMethod {

   // Protected method
   protected void info() {

   }

   public static void testMethod1() {

   }

   public void testMethod2() {

   }

   public static void main(String[] args) {

       // Lấy ra danh sách các method public của class này
       // Bao gồm các các method thừa kế từ class cha, hoặc các interface.
       Method[] methods = ListMethod.class.getMethods();

       for (Method method : methods) {
           System.out.println("Method " + method.getName());
       }

   }
}
Kết quả chạy class:

4- Class

Một số method quan trọng trong Reflection liên quan tới Class.
Ví dụ ghi ra các thông tin cơ bản của class như tên class, package, modifier, ..
  • ShowClassInfo.java
package org.o7planning.tutorial.reflect.clazz;

import java.lang.reflect.Modifier;

public final class ShowClassInfo {

   public static void main(String[] args) {

       // Lấy ra đối tượng 'Class' mô tả class ShowClassInfo
       Class<ShowClassInfo> aClass = ShowClassInfo.class;

       // Ghi ra tên class, bao gồm cả tên package.
       System.out.println("Class Name= " + aClass.getName());

       // Ghi ra tên đơn giản của Class
       System.out.println("Simple Class Name= " + aClass.getSimpleName());

       // Thông tin Package.
       Package pkg = aClass.getPackage();
       System.out.println("Package Name = " + pkg.getName());

       // Modifier
       int modifiers = aClass.getModifiers();

       boolean isPublic = Modifier.isPublic(modifiers);
       boolean isInterface = Modifier.isInterface(modifiers);
       boolean isAbstract = Modifier.isAbstract(modifiers);
       boolean isFinal = Modifier.isFinal(modifiers);

       // true
       System.out.println("Is Public? " + isPublic);
       // true
       System.out.println("Is Final? " + isFinal);
       // false
       System.out.println("Is Interface? " + isInterface);
       // false
       System.out.println("Is Abstract? " + isAbstract);
   }

}
Kết quả chạy class
Ví dụ ghi ra thông tin của class Cat, như tên class, và các Interface mà class này thi hành.
  • ShowClassCatInfo.java
package org.o7planning.tutorial.reflect.clazz;

import org.o7planning.tutorial.beans.Cat;

public class ShowClassCatInfo {

   public static void main(String[] args) {

       // Đối tượng Class mô tả class Cat.
       Class<Cat> aClass = Cat.class;

       // Tên class
       System.out.println("Simple Class Name = " + aClass.getSimpleName());

       // Lấy ra đối tượng class mô tả class cha của class Cat.
       Class<?> aSuperClass = aClass.getSuperclass();

       System.out.println("Simple Class Name of Super class = "
               + aSuperClass.getSimpleName());

       // Lấy ra mảng các Class mô tả các Interface mà Cat thi hành.
       Class<?>[] itfClasses = aClass.getInterfaces();

       for (Class<?> itfClass : itfClasses) {
           System.out.println("Interface: " + itfClass.getSimpleName());
       }

   }
}
Kết quả chạy class:
Ví dụ lấy ra thông tin các constructor, method, field của class (Chỉ public), bao gồm cả các public method, public field, thừa kế từ các class cha, và các interace.
  • ShowMemberInfo.java
package org.o7planning.tutorial.reflect.clazz;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.o7planning.tutorial.beans.Cat;

public class ShowMemberInfo {

   public static void main(String[] args) {

       // Lấy ra đối tượng Class mô tả class Cat
       Class<Cat> aClass = Cat.class;

       // Lấy ra danh sách các cấu tử của Cat.
       Constructor<?>[] constructors = aClass.getConstructors();

       System.out.println(" ==== CONSTRUCTORs:  ===== ");

       for (Constructor<?> constructor : constructors) {
           System.out.println("Constructor: " + constructor.getName());
       }

       // Lấy ra danh sách các method public của Cat
       // Bao gồm cả các method thừa kế từ class cha và các interface
       Method[] methods = aClass.getMethods();

       System.out.println(" ==== METHODs:   ====== ");
       for (Method method : methods) {
           System.out.println("Method: " + method.getName());
       }

       // Lấy ra danh sách các field public
       // Kể các các public field thừa kế từ các class cha, và các interface
       Field[] fields = aClass.getFields();

       System.out.println(" ==== FIELDs:    ====== ");
       for (Field field : fields) {
           System.out.println("Field: " + field.getName());
       }

   }
}
Kết quả

5- Cấu tử (Constructor)

Ví dụ lấy ra một  cấu tử với các tham số chỉ định trước. Và ghi ra thông tin về cấu tử (constructor) này.
  • ConstructorExample.java
package org.o7planning.tutorial.reflect.constructor;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import org.o7planning.tutorial.beans.Cat;

public class ConstructorExample {

   public static void main(String[] args) throws NoSuchMethodException,
           SecurityException, InstantiationException, IllegalAccessException,
           IllegalArgumentException, InvocationTargetException {

       // Lấy ra đối tượng Class mô tả class Cat
       Class<Cat> aClass = Cat.class;

       // Lấy ra cấu tử có tham số (String,int) của class Cat

       Constructor<?> constructor = aClass.getConstructor(String.class,
               int.class);

       // Lấy ra thông tin kiểu tham số của cấu tử.
       Class<?>[] paramClasses = constructor.getParameterTypes();

       for (Class<?> paramClass : paramClasses) {
           System.out.println("Param: " + paramClass.getSimpleName());
       }

       // Khởi tạo đối tượng Cat theo cách thông thường.
       Cat tom = new Cat("Tom", 3);
       System.out
               .println("Cat 1: " + tom.getName() + ", age =" + tom.getAge());

       // Khởi tạo đối tượng Cat theo cách của reflect.
       Cat tom2 = (Cat) constructor.newInstance("Tom", 2);
       System.out.println("Cat 2: " + tom.getName() + ", age ="
               + tom2.getAge());
   }
}
Kết quả chạy class:

6- Trường (Field)

Ví dụ dưới đây lấy ra Field với tên chỉ định sẵn.
  • FieldExample.java
package org.o7planning.tutorial.reflect.field;

import java.lang.reflect.Field;

import org.o7planning.tutorial.beans.Cat;

public class FieldExample {

   public static void main(String[] args) throws NoSuchFieldException,
           SecurityException, IllegalArgumentException, IllegalAccessException {
       
       // Lấy ra đối tượng Class mô tả class Cat
       Class<Cat> aClass = Cat.class;

       // Lấy ra field có tên 'NUMBER_OF_LEGS':
       Field field = aClass.getField("NUMBER_OF_LEGS");

       // Ghi ra kiểu của Field
       Class<?> fieldType = field.getType();

       System.out.println("Field type: " + fieldType.getSimpleName());

       Field ageField = aClass.getField("age");

       Cat tom = new Cat("Tom", 5);

       // Lấy ra giá trị của trường "age" theo cách của Reflect.
       Integer age = (Integer) ageField.get(tom);
       System.out.println("Age = " + age);
       
       // Sét đặt giá trị mới cho trường "age".
       ageField.set(tom, 7);
       
       System.out.println("New Age = "+ tom.getAge());
       

   }

}
Kết quả chạy class:

7- Phương thức (method)

Ví dụ lấy ra một method với tên, các tham số chỉ định trước. Ghi ra thông tin về method này, như kiểu trả về, danh sách các tham số,...
  • MethodExample.java
package org.o7planning.tutorial.reflect.method;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.o7planning.tutorial.beans.Cat;

public class MethodExample {

   public static void main(String[] args) throws NoSuchMethodException,
           SecurityException, IllegalAccessException,
           IllegalArgumentException, InvocationTargetException {

       // Lấy ra đối tượng Class mô tả class Cat
       Class<Cat> aClass = Cat.class;

       // Lấy ra đối tượng 'Method' mô tả method getAge()
       Method getAgeMethod = aClass.getMethod("getAge");
       
       // Kiểu trả về của method getAge
       Class<?> returnType= getAgeMethod.getReturnType();
       System.out.println("Return type of getAge: "+ returnType.getSimpleName());
       

       Cat tom = new Cat("Tom", 7);

       // Gọi method 'getAge' theo cách của Reflect
       // Nó tương đương với gọi: tom.getAge()
       int age = (int) getAgeMethod.invoke(tom);

       System.out.println("Age = " + age);

       // Lấy ra đối tượng 'Method' mô tả method setAge(int) của class Cat.
       Method setAgeMethod = aClass.getMethod("setAge", int.class);

       // Gọi method setAge(int) theo cách của Reflect.
       // Nó tương đương với gọi: tom.setAge(5);
       setAgeMethod.invoke(tom, 5);
       
       System.out.println("New Age = " + tom.getAge());
   }
}
Kết quả chạy class

8- Các method getter và setter

Ví dụ dưới đây, liệt kê ra các public setter method, và các public getter method của class.
  • GetSetExample.java
package org.o7planning.tutorial.reflect.getset;

import java.lang.reflect.Method;

import org.o7planning.tutorial.beans.Cat;

public class GetSetExample {

    // Method là getter nếu có tên bắt đầu bằng get, và không có tham số.
    public static boolean isGetter(Method method) {
        if (!method.getName().startsWith("get")) {
            return false;
        }
        if (method.getParameterTypes().length != 0) {
            return false;
        }
        if (void.class.equals(method.getReturnType())) {
            return false;
        }
        return true;
    }

    
    // Method là setter nếu có tên bắt đầu bằng set, và chỉ có 1 tham số.    
    public static boolean isSetter(Method method) {
        if (!method.getName().startsWith("set")) {
            return false;
        }
        if (method.getParameterTypes().length != 1) {
            return false;
        }
        return true;
    }

    public static void main(String[] args) {

        // Lấy ra đối tượng Class mô tả class Cat
        Class<Cat> aClass = Cat.class;

        // Lấy ra danh sách các public method.
        Method[] methods = aClass.getMethods();

        for (Method method : methods) {
            boolean isSetter = isSetter(method);
            boolean isGetter = isGetter(method);
            System.out.println("Method: " + method.getName());
            System.out.println(" - Is Setter? " + isSetter);
            System.out.println(" - Is Getter? " + isGetter);
        }

    }
    
}
Kết quả chạy chương trình:
Method: getName
 - Is Setter? false
 - Is Getter? true
Method: getNumberOfLegs
 - Is Setter? false
 - Is Getter? true
Method: getAge
 - Is Setter? false
 - Is Getter? true
Method: setAge
 - Is Setter? true
 - Is Getter? false
Method: say
 - Is Setter? false
 - Is Getter? false
Method: getLocation
 - Is Setter? false
 - Is Getter? true
Method: wait
 - Is Setter? false
 - Is Getter? false
Method: wait
 - Is Setter? false
 - Is Getter? false
Method: wait
 - Is Setter? false
 - Is Getter? false
Method: equals
 - Is Setter? false
 - Is Getter? false
Method: toString
 - Is Setter? false
 - Is Getter? false
Method: hashCode
 - Is Setter? false
 - Is Getter? false
Method: getClass
 - Is Setter? false
 - Is Getter? true
Method: notify
 - Is Setter? false
 - Is Getter? false
Method: notifyAll
 - Is Setter? false
 - Is Getter? false

 

9- Truy cập vào các private method, field

Bạn không thể truy cập vào các method hay field mà nó là private theo cách thông thường, quá trình dịch java cũng không cho phép điều đó. Nhưng với reflect điều đó hoàn toàn có thể.

  • AccessPrivateFieldExample.java
package org.o7planning.tutorial.reflect.privateaccess;

import java.lang.reflect.Field;

import org.o7planning.tutorial.beans.Cat;

public class AccessPrivateFieldExample {

    public static void main(String[] args) throws IllegalArgumentException,
            IllegalAccessException, NoSuchFieldException, SecurityException {

        // Tạo một đối tượng Class mô tả class Cat.
        Class<Cat> aClass = Cat.class;

        // Class.getField(String) chỉ lấy được các trường public.
        // Sử dụng Class.getDeclaredField(String):
        // Lấy ra đối tượng Field mô tả trường name của class Cat.
        // (Trường khi báo trong class này).
        Field private_nameField = aClass.getDeclaredField("name");

        // Cho phép để truy cập vào các trường private.
        // Nếu không sẽ bị ngoại lệ IllegalAccessException
        private_nameField.setAccessible(true);

        Cat tom = new Cat("Tom");

        String fieldValue = (String) private_nameField.get(tom);
        System.out.println("Value field name = " + fieldValue);

        // Sét đặt trường name giá trị mới.
        private_nameField.set(tom, "Tom Cat");

        System.out.println("New name = " + tom.getName());
    }

}
Kết quả chạy class:
Tiếp theo ví dụ truy cập vào private method.
  • AccessPrivateMethodExample.java
package org.o7planning.tutorial.reflect.privateaccess;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.o7planning.tutorial.beans.Cat;

public class AccessPrivateMethodExample {

    public static void main(String[] args) throws NoSuchMethodException,
            SecurityException, IllegalAccessException,
            IllegalArgumentException, InvocationTargetException {

        // Tạo một đối tượng Class mô tả class Cat.
        Class<Cat> aClass = Cat.class;

        // Class.getMethod(String) chỉ lấy được các method public.
        // Sử dụng Class.getDeclaredMethod(String):
        // Lấy ra đối tượng Method mô tả method setName(String) của class Cat.
        // (Phương thức khai báo trong class).
        Method private_setNameMethod = aClass.getDeclaredMethod("setName",
                String.class);

        // Cho phép để truy cập vào các method private.
        // Nếu không sẽ bị ngoại lệ IllegalAccessException
        private_setNameMethod.setAccessible(true);

        Cat tom = new Cat("Tom");

        // Gọi private method.
        private_setNameMethod.invoke(tom, "Tom Cat");

        System.out.println("New name = " + tom.getName());
    }
    

}
Kết quả

10- Annotation

  • MyAnnotation.java
package org.o7planning.tutorial.reflect.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

// Annotation này có thể sử dụng tại thời điểm chạy (Runtime) của chương trình.
@Retention(RetentionPolicy.RUNTIME)
// Có thể dùng cho class,interface, method, field, parameter.
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD,
       ElementType.PARAMETER })
public @interface MyAnnotation {

   String name();

   String value() default "";
}
Một ví dụ Annotation với class:
  • ClassAnnotationExample.java
package org.o7planning.tutorial.reflect.annotation;

import java.lang.annotation.Annotation;

@MyAnnotation(name = "Table", value = "Employee")
public class ClassAnnotationExample {

   public static void main(String[] args) {

       Class<?> aClass = ClassAnnotationExample.class;

       // Lấy ra danh sách các Annotation của class.
       Annotation[] annotations = aClass.getAnnotations();

       for (Annotation ann : annotations) {
           System.out.println("Annotation: " + ann.annotationType().getSimpleName());
       }

       // Hoặc lấy cụ thể.
       Annotation ann = aClass.getAnnotation(MyAnnotation.class);
       MyAnnotation myAnn = (MyAnnotation) ann;
       System.out.println("Name = " + myAnn.name());
       System.out.println("Value = " + myAnn.value());
   }
}
Kết quả:
Một ví dụ Annotation với Field & Method:
  • FieldMethodAnnotationExample.java
package org.o7planning.tutorial.reflect.annotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class FieldMethodAnnotationExample {

   @MyAnnotation(name = "My Field")
   private int myField;

   @MyAnnotation(name = "My Method", value = "My Method Value")
   protected void myMethod(String str) {

   }

   public static void main(String[] args) throws NoSuchFieldException,
           SecurityException, NoSuchMethodException {

       Class<?> aClass = FieldMethodAnnotationExample.class;

       //
       System.out.println(" == FIELD == ");
       Field field = aClass.getDeclaredField("myField");

       // Lấy ra danh sách các Annotation của field.
       Annotation[] fieldAnns = field.getAnnotations();

       for (Annotation methodAnn : fieldAnns) {
           System.out.println("Annotation: "
                   + methodAnn.annotationType().getSimpleName());
       }
       // Lấy cụ thể.
       Annotation fieldAnn = field.getAnnotation(MyAnnotation.class);

       MyAnnotation myAnn1 = (MyAnnotation) fieldAnn;

       System.out.println("Name = " + myAnn1.name());
       System.out.println("Value = " + myAnn1.value());

       // Tương tự với method ...
       System.out.println(" == METHOD == ");

       Method method = aClass.getDeclaredMethod("myMethod", String.class);

       // Lấy ra danh sách các Annotation của method.
       Annotation[] methodAnns = method.getAnnotations();

       for (Annotation methodAnn : methodAnns) {
           System.out.println("Annotation: "
                   + methodAnn.annotationType().getSimpleName());
       }

       // Lấy cụ thể.
       Annotation methodAnn = method.getAnnotation(MyAnnotation.class);
       MyAnnotation myAnn2 = (MyAnnotation) methodAnn;

       System.out.println("Name = " + myAnn2.name());
       System.out.println("Value = " + myAnn2.value());

   }
}
Kết quả chạy:
Ví dụ Annotation với tham số của method:
  • ParameterAnnotationExample.java
package org.o7planning.tutorial.reflect.annotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

public class ParameterAnnotationExample {

   // Ví dụ một method có Annotation ở tham số.
   protected void doSomething(int jobType,
           @MyAnnotation(name = "Table", value = "Employee") String info) {

   }

   public static void main(String[] args) throws NoSuchMethodException,
           SecurityException {

       Class<?> aClass = ParameterAnnotationExample.class;

       // Lấy ra đối tượng Method của method doSomething(int,String)
       Method method = aClass.getDeclaredMethod("doSomething", int.class,
               String.class);

       // Lấy ra danh sách các Parameter của method.
       Class<?>[] parameterTypes = method.getParameterTypes();
       for (Class<?> parameterType : parameterTypes) {
           System.out.println("Parametete Type: "
                   + parameterType.getSimpleName());
       }

       System.out.println(" ---- ");
       
       // Lấy ra mảng 2 chiều các Annotation trong các Parameter.
       Annotation[][] annotationss = method.getParameterAnnotations();

       // Lấy ra danh sách các Annotation của Parameter tại vị trí Index =1.
       Annotation[] annotations = annotationss[1];

       for (Annotation ann : annotations) {
           System.out.println("Annotation: "
                   + ann.annotationType().getSimpleName());
       }
   }
}