menu

VanThuong.Com

Blog học lập trình Java và SEO miễn phí.

Java Reflection - Làm việc với các Field trong Class

Posted by on
Một trong những điều mà tôi thích nhất từ Java Reflection chính là sự hỗ trợ làm việc hiệu quả với các Field trong một Class bất kỳ. Trước đây, khi thực hiện các thao tác liên quan đến CRUD (create, read, update, delete) tốn khá nhiều thời gian để viết đi viết lại các hàm cho từng lớp DAO. Đến thời điểm hiện tại, bằng việc kết hợp giữa Java Reflection và Annotation trong Java, mọi thứ đã trở nên đơn giản hơn khi các thao tác này được thực hiện trong một lớp GenericDAO. Nói tóm lại, cách để thực hiện nó như thế nào sẽ được tôi chia sẻ trong một bài viết khác.
Java Reflection - Làm việc với các Field trong Class

Trong bài viết này, chúng ta sẽ tìm hiểu về cách làm việc với các Field trong Class như thế nào thông qua Java Reflection. Bằng cách sử dụng Java Reflection, bạn có thể lấy được các fields (member variables) của một Class và get/set chúng trong thời gian Runtime.

Lấy các đối tượng Field được khai báo là public

Bạn có thể lấy được đối tượng Field được khai báo là public của một Class bằng 2 cách là chỉ lấy một Field duy nhất nếu bạn biết chính xác tên của 1 Field, hoặc lấy nguyên 1 mảng danh sách các Field của từ một đối tượng Class. Cụ thể cách thực hiện nó như sau:

Bạn có thể lấy được một field được khai báo là public nếu như bạn biết chính xác tên của nó như bên dưới đây. Phương thức getField() sẽ ném ra NoSuchFieldException nếu như không tồn tại Field với tên bạn đưa vào.
Class  aClass = MyObject.class;
Field field = aClass.getField("tenFieldCanLay"); // Tên field cần lấy

Hoặc bạn có thể lấy một mảng danh sách Field[] bằng cách sau:
Class aClass = ...//obtain class object
Field[] fields = aClass.getFields();

Lấy các đối tượng Field khai báo bất kỳ

Như ở phía trên, tôi đã hướng dẫn các bạn cách lấy đối tượng Field hoặc mảng đối tượng Field[] của những trường được khai báo là public. Vậy làm sao để access được những field được khai báo là private, protected,...? Khá đơn giản, trong Java bạn có thể lấy được chúng thông qua 2 methods là getDeclaredField()getDeclaredFields() như sau:

Class clazz = myObject.getClass();
Field field = clazz.getDeclaredField("tenFieldCanLay"); // Tên field cần lấy

Các exceptions có thể được ném ra khi gọi phương thức này:
  • NoSuchFieldException -- Nếu tên field bạn nhập vào không tìm thấy trong Class của myObject
  • NullPointerException -- Nếu tenFieldCanLay truyền vào là null
  • SecurityException -- Nếu có Security manager được áp dụng ở lớp này

Tương tự, bạn có thể lấy được mảng danh sách Field[] được khai báo trong Class như sau:
Class clazz = myObject.getClass();
Field[] field = clazz.getDeclaredFields();

Field Name

OK, sau khi bạn đã có được đối tượng Field hoặc mảng Field[] bạn muốn biết tên của Field đó thì làm sao nhỉ? Khá đơn giản, chỉ cần gọi phương thức getName() được hỗ trợ bởi đối tượng Field để biết thôi.
Field field = ... //obtain field object
String fieldName = field.getName();

Bên cạnh đó, từ đối tượng Field bạn có thể lấy được kiểu dữ liệu đã khai báo cho Field bằng cách gọi phương thức getType()

Lấy và gán giá trị cho Field

Tất nhiên khi làm việc với các Field trong Class, bạn không chỉ muốn dừng lại ở việc lấy đối tượng, biết tên của Field, kiểu dữ liệu của nó. Bạn có thể làm được nhiều hơn thế nữa là lấy dữ liệu của các field từ đối tượng của mình. Đồng thời có thể tạo ra một đối tượng mới và gán giá trị cho nó. Cụ thể như thế này nhé, tôi có một lớp Person.java được triển khai như sau:
package com.vanthuong.tutorial;

public class Person {
    private Long id;
    private String firstName;
    private String lastName;
    private String address;

    public Person() {
    }

    public Person(Long id, String firstName, String lastName, String address) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.address = address;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Person [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", address=" + address
                + "]";
    }
}


Tại thời điểm Runtime, tôi muốn lấy giá trị của các field từ một đối tượng Person mà tôi đã tạo ra trước đó. Sau khi xử lý các bước a, b, c gì đó bây giờ tôi muốn tạo và trả một một đối tượng Person với dữ liệu mới. Hãy xem ví dụ minh họa đơn giản dưới đây để hiểu thêm.
package com.vanthuong.tutorial;

import java.lang.reflect.Field;

public class Application {
 public static void main(String[] args) {
  try {
   Person person1 = new Person(1L, "Thuong", "Nguyen", "VN");

   // Obtain class object
   Class<?> personClass = person1.getClass();
   // Obtain an array fields
   Field[] fields = personClass.getDeclaredFields();

   // Get value from fields
   System.out.println("====Start get value from fields====");
   for (Field field : fields) {
    field.setAccessible(true);
    System.out.println(field.get(person1));
   }

   // Set value for field
   System.out.println("====Start set value for field====");
   Person person2 = (Person) personClass.newInstance();

   for (Field field : fields) {
    field.setAccessible(true);

    if (field.getName().equals("id")) {
     field.set(person2, 2L);
    } else {
     field.set(person2, "Blah Blah");
    }
   }

   System.out.println("====Print to screen====");
   System.out.println(person1.toString());
   System.out.println(person2.toString());
  } catch (InstantiationException | IllegalAccessException e) {
   // Ignore exception
  }

 }
}
Ở đây bạn sẽ cần lưu ý đến dòng code field.setAccessible(true);. Chúng ta sẽ sử dụng nó để access đến field mà chúng ta đang làm việc khi nó được khai báo là private.

Kết quả màn hình in ra sẽ như thế này
Làm việc với Field trong java reflection

Lời kết

Như vậy là tôi vừa giới thiệu đến các bạn cách làm việc với các Field trong Class. Tuy nhiên, nó chỉ dừng lại ở mức cơ bản, bạn còn có thể khám phá nhiều hơn về các Field bằng cách xem qua bộ Java Doc dành cho Field trên trang chủ của Oracle từ link bên dưới
https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Field.html

Hi vọng rằng bài này sẽ giúp ích nhiều cho các bạn đọc giả. Đừng quên bấm Like và Share nếu như bài viết hữu ích nhé, đón xem những bài viết tiếp theo về Java Reflection từ danh mục Java Core Tutorial.
Đăng bình luận

menu