2012-01-17 44 views
18

Có thư viện nào có thể thực hiện những việc sau không ?:Đặt trường đối tượng từ HashMap

Cho một đối tượng và một HashMap, nó liệt kê các khóa của Hashmap và tra cứu các bộ định vị cho các phím này trong Đối tượng và bộ các giá trị được liên kết. Một cái gì đó trông như rằng:

public Object setData(Object object, HashMap<String, Object> fields) { 
    for (Entry<String, Object> entry : fields.entrySet()) { 
     Method m = object.getClass().getMethod("set" + entry.getKey(), entry.getValue().getClass()); 
     if (m != null) { 
     m.invoke(object, entry.getValue()); 
     } 
    } 
    return object; 
} 

Nhiệm vụ trông đơn giản ở cái nhìn đầu tiên nhưng có một số sắc thái mà tôi hy vọng ai đó đã đưa về chăm sóc. Như bạn đã biết, việc phát minh lại bánh xe (bánh xe tốt) là một cách tiếp cận tồi tệ.

Trả lời

17

Nhìn vào Apache Commons BeanUtils

org.apache.commons.beanutils.BeanUtils.populate(Object bean, Map properties) 

Javadoc:
Điền vào JavaBeans thuộc tính của bean chỉ định, dựa trên các cặp tên/giá trị quy định. Phương thức này sử dụng các API phản chiếu Java để xác định các tên phương thức "property setter" tương ứng và giao dịch với các đối số setter của kiểu String, boolean, int, long, float và double.

+2

Cảnh báo "chỉ đề cập đến các đối số setter của kiểu String, boolean, int, long, flat và double" là rất đáng chú ý, vì lý do đó tôi tin rằng câu trả lời dưới đây (nhưng sử dụng BeanUtils.copyProperty() chứ không phải BeanUtils.setProperty()) là giải pháp thay thế tốt hơn. – fragorl

6

Better sử dụng BeanUtils lớp:

public Object setData(Object object, HashMap<String, Object> fields) { 
    for(Entry<String, Object> entry : fields.entrySet()) { 
     BeanUtils.setProperty(object, entry.getKey(), entry.getValue()); 
    } 
    return object; 
} 
+0

Cảm ơn @Wojtek O., với gợi ý của bạn, tôi đã tìm thấy phương thức phổ biến ngay trước khi e-kẽm trả lời với nó! – forker

3

Tôi có một lớp BeanAsMap mà tôi đã viết một thời gian dài trước đây. Phương thức asMap trả về một Map là chế độ xem trên một bean Java (POJO). Bạn có thể gọi số putAll trên số Map, chuyển số Map mà bạn muốn sao chép dữ liệu từ đó.

Vui lòng sử dụng mã của tôi được đề cập ở trên.

Ví dụ:

MyClass bean = ...; 
Map<String, Object> inputData = ...; 

Map<String, Object> view = BeanAsMap.asMap(bean); 
view.putAll(inputData); 
+0

Mã của bạn là tốt @Jesper, nhưng câu hỏi là 'Bản đồ -> Bean' và ** KHÔNG **' Bean -> Bản đồ ' –

+1

@FelipeConde Mã của tôi hoạt động theo hai cách - bạn có thể tạo một thể hiện mới của một lớp bean, sau đó bọc nó với 'BeanAsMap' và gọi' put' trên bản đồ sẽ thiết lập các thuộc tính bean.Nếu bạn có một bản đồ hiện có, bạn có thể gọi 'putAll' trên bản đồ trình bao bọc để sao chép các giá trị bản đồ hiện có của bạn sang bean. – Jesper

2

BeanUtils là tốt.

Nhưng, thực hành tốt, tôi sẽ không viết mã sử dụng sự phản chiếu. Hoặc như là giải pháp cuối cùng tôi có, nếu không có khác đã được tìm thấy.

Mã này không thể được theo dõi trong IDE như Eclipse (không có phân cấp cuộc gọi), làm cho nhà phát triển nghĩ rằng những người định cư không bao giờ được gọi. Anh ta có thể phá vỡ mã của bạn và nó vẫn sẽ biên dịch.

Mức trừu tượng quá cao như thế làm cho mã khó hiểu.

Mã đang bị làm xáo trộn sẽ bị phá vỡ bởi chính bộ obfuscator khi viết những thứ như vậy.

Giải pháp tốt nhất là suy nghĩ lại cách sử dụng phản chiếu để đặt trường đối tượng.

+0

Không thể đồng ý hơn. –

+1

Mặc dù tôi đồng ý rằng phản chiếu không nên được sử dụng như một công cụ đa năng, đôi khi có những lý do tốt để sử dụng nó (ví dụ, thiết lập các thuộc tính của đối tượng Bean từ JSON hoặc nguồn động khác). –

Các vấn đề liên quan