Phản ánh phpunit

Phản chiếu Java là một tính năng (gọi là API hay thư viện cũng được) trong Java. Java Reflection cho phép truy cập các thông tin của đối tượng (tên lớp, các trường, các phương thức) và chỉnh sửa các trường của đối tượng (khai báo cả các trường riêng tư) trong quá trình chạy chương trình.

Ta có thể áp dụng Java Reflection trong những trường hợp không biết đối tượng được xử lý là gì. (tên lớp là gì, ở gói nào, có những trường nào, phương thức nào…)

Phản ánh phpunit
Phản ánh phpunit

Ví dụ mình muốn viết một hàm sao chép 2 đối tượng có thể sử dụng cho các loại đối tượng khác nhau. Thì mình cần biết 2 đối tượng có cùng kiểu không, có những trường nào, lấy và sao chép giá trị từng trường

Ngoài ra, với các trường, phương thức có công cụ sửa đổi là _______13thì ta không thể truy cập bên ngoài lớp đó. Trong những trường hợp bắt buộc phải gọi, truy cập các trường, phương thức private ở bên ngoài lớp đó thì Reflection là một giải pháp

Tuyển dụng Java lương cao cho SV mới ra trường

Một số framework sử dụng Java Reflection

  • Mùa xuân
  • JUnit
  • mèo con
  • Eclipse (use to autocomplete)

Hỏng chế độ, nhược điểm của Java Reflection

Trong trường hợp đã biết rõ cấu trúc lớp, có quyền truy cập các trường, phương thức thì ta không nên sử dụng Java Reflection bởi các lý do sau

  • Low power effect. Ví dụ nó phải quét classpath để tìm lớp
  • Các vấn đề bảo mật. Việc chỉnh sửa lớp/đối tượng đã sửa trong quá trình chạy trình có thể ảnh hưởng đến các luồng… khiến cho ứng dụng bị lỗi
  • Khó bảo trì. Việc phản ánh khá khó hiểu với người mới và không dễ gỡ lỗi, nên sẽ rất khó để có thể tìm ra lỗi. Ngoài ra chúng ta cũng không thể kiểm tra được một số lỗi trong quá trình biên dịch (không tìm thấy lớp, không tìm thấy trường…)

Các thành phần trong Java Reflection

Tương ứng với các thành phần trong một lớp, thì Java Reflection cũng cung cấp các lớp tương ứng để ta có thể xử lý

  • Tầng lớp. Đại diện cho lớp/giao diện để lấy các thông tin của lớp (tên lớp, siêu lớp, công cụ sửa đổi lớp, các phương thức, các trường…)
  • Hàm tạo. Xử lý các khởi tạo chức năng của lớp
  • Cánh đồng. Xử lý các trường của lớp (tên, công cụ sửa đổi của trường, lấy giá trị, thiết lập giá trị cho đối tượng…)
  • Phương pháp. Xử lý các phương thức của lớp (liệt kê các phương thức, thực thi các phương thức…)

Code ví dụ Java Reflection

Giả sử mình có 2 lớp sau

Person.java

package stackjava.com.reflection;
public class Person {
  public String address;
  
 // setter - getter
}

Customer.java

package stackjava.com.reflection;

public class Customer extends Person {
 private int age;
 protected String gender;
 public String name;
 String phone;

 public Customer() {
 }
 public Customer(int age, String name) {
 this.age = age;
 this.name = name;
 }
 // setter - getter

 @Override
 public String toString() {
  return "Customer [age=" + age + ", gender=" + gender + ", name=" + name + ", phone=" + phone + "]";
 }

}

Bây giờ mình sẽ thực hiện liệt kê tất cả các trường, phương thức của Lớp Khách hàng

package stackjava.com.reflection;

import java.lang.reflect.*;

public class Demo1 {
 public static void main(String[] args) throws ClassNotFoundException {
  Customer customer = new Customer();
  customer.setName("kai");
  customer.setAge(25);

 demoReflection(customer);

 }

 public static void demoReflection(Object object) throws ClassNotFoundException {
Class myClass = object.getClass();
//   Class myClass = Class.forName("stackjava.com.reflection.Customer");

   System.out.println("Class name: " + myClass.getName());
   System.out.println("Super Class name: " + myClass.getSuperclass().getName());
   System.out.println("Is interface: " + myClass.isInterface());
   System.out.println("Constructors: ");
   Constructor[] constructors = myClass.getDeclaredConstructors();
   for (Constructor constructor : constructors) {
     System.out.println(" Number of parameters: " + constructor.getParameterCount() + " - modifier: "
         + getModifierName(constructor.getModifiers()));
    }
    
    System.out.println("Fields:");
    Field[] allFields = myClass.getDeclaredFields();
    for (Field field : allFields) {
      System.out.println(" " + field.getName() + " - type: " + field.getType() + " - modifier: "
          + getModifierName(field.getModifiers()));
    }

    System.out.println("Methods: ");
    Method[] methods = myClass.getDeclaredMethods();
    for (Method field : methods) {
      System.out.println(" " + field.getName() + " - modifier: " + getModifierName(field.getModifiers()));
    }
  }
  
  public static String getModifierName(int mod) {
    if (Modifier.isPrivate(mod)) {
      return "private";
    }
    if (Modifier.isProtected(mod)) {
      return "protected";
    }
    if (Modifier.isPublic(mod)) {
       return "public";
    }
    if (Modifier.isPrivate(mod)) {
       return "private";
    }
    return "default";
  }

}

Bạn có thể lấy đối tượng Lớp thông qua đối tượng với phương thức 

package stackjava.com.reflection;
public class Person {
  public String address;
  
 // setter - getter
}
4 hoặc thông qua tên gói + tên lớp với phương thức 
package stackjava.com.reflection;
public class Person {
  public String address;
  
 // setter - getter
}
5

Để lấy danh sách cách tạo hàm khởi động, các trường, phương thức ta có thể sử dụng method 

package stackjava.com.reflection;
public class Person {
  public String address;
  
 // setter - getter
}
6, 
package stackjava.com.reflection;
public class Person {
  public String address;
  
 // setter - getter
}
0 or 
package stackjava.com.reflection;
public class Person {
  public String address;
  
 // setter - getter
}
1. Tuy nhiên, các method không cho phép lấy các constructor, method, field có modifier là private do đó mình sẽ sử dụng 
package stackjava.com.reflection;
public class Person {
  public String address;
  
 // setter - getter
}
2, 
package stackjava.com.reflection;
public class Person {
  public String address;
  
 // setter - getter
}
3, 
package stackjava.com.reflection;
public class Person {
  public String address;
  
 // setter - getter
}
4

Phương thức 

package stackjava.com.reflection;
public class Person {
  public String address;
  
 // setter - getter
}
5 trả về công cụ sửa đổi của lớp, phương thức, trường nhưng ở định dạng số đó mình sẽ viết thêm phương thức getModifierName để hiển thị dưới dạng Chuỗi

Để lấy giá trị hoặc truyền giá trị cho các trường của đối tượng, bạn có thể sử dụng phương pháp 

package stackjava.com.reflection;
public class Person {
  public String address;
  
 // setter - getter
}
6 / 
package stackjava.com.reflection;
public class Person {
  public String address;
  
 // setter - getter
}
7