2011-09-06 36 views
16

Tôi có một lớp với các biến khác nhauXem nếu trường tồn tại trong lớp

public class myClass{ 

    public int id; 
    public String category; 
    public String description; 
    public String start; 
    public String end; 
} 

Có cách nào để kiểm tra, hoặc bằng cách tạo ra một chức năng nội bộ hoặc kiểm tra từ các đối tượng gọi điện thoại, có hay không một biến tồn tại?

Ví dụ: Để kiểm tra xem myClass có chứa biến được gọi là "danh mục" hay không. Hoặc cho dù nó có chứa một loại gọi là "foo" (nó không).

Trả lời

29

trình biên dịch của bạn thường biết rằng khá tốt, và thời gian chạy cho phép bạn kiểm tra các lớp được nạp với sự phản ánh.

Object someObject = ... 
Class<?> someClass = someObject.getClass(); 
Field someField = someClass.getField("foo"); 

Phương thức getField() sẽ ném ngoại lệ nếu không tìm thấy trường.

+3

Hoặc một ngoại lệ bảo mật nếu nó không thể truy cập được (ví dụ: 'riêng tư') – CrackerJack9

+0

Hoàn hảo, cảm ơn bạn! – emachine

+2

@ CrackerJack9 không, truy cập các trường riêng với 'getField()' không ném một 'SecurityException'. – Bombe

2

Bạn có thể làm điều đó bằng cách sử dụng reflection, mặc dù tôi khuyên bạn nên kiểm tra xem nó có thực sự cần thiết hay có thể có một cách khác để thực hiện điều đó.

Ví dụ:

Class<?> clz = MyClass.class; 
try { 
    Field f = clz.getField("foo") 
} 
catch (NoSuchFieldException ex) { 
    // field doesn't exist 
} 
catch (SecurityException ex) { 
    // no access to field 
} 
4

Như những người khác phản ánh đã được đề cập là những gì bạn cần.

Nếu bạn cần truy cập vào một lĩnh vực tư nhân bạn có thể sử dụng Class.getDeclaredField(String name)

0

Sử dụng các phương pháp sau đó sử dụng Reflections-

private Set<String> getAllFields(final Class<?> type) { 
     Set<String> fields = new HashSet<String>(); 
     for (Field field : type.getDeclaredFields()) { 
      fields.add(field.getName()); 
     } 

     if (type.getSuperclass() != null) { 
      fields.addAll(getAllFields(type.getSuperclass())); 
     } 
     return fields; 
    }  
    private boolean listHasProperty(final Set<String> properties, final String propertyName) { 
     if (properties.contains(propertyName)) { 
      return true; 
     } 
     return false; 
    } 

Sau đó kiểm tra nếu tài sản là hiện using-

Set<String> fieldSet = getAllFields(object.getClass()); 
boolean isPresent=listHasProperty(fieldSet , sourceProperty) 

Để biết thêm chi tiết, hãy kiểm tra số này post

0

Đây là một chút bất tiện khi thực hiện trong một bước.

Khi chúng ta chuyển sang khái niệm đa hình, có nhiều thách thức như tạo ra các đối tượng cho lớp (ABC Class) lấy dữ liệu động bằng cách tham chiếu các lớp chuyên dụng khác (lớp ABCXMLDOMnodes, lớp ABCHTMLDOMnodes) có cùng trường nhưng kiểu tĩnh và cuối cùng. Hy vọng bạn đã nhận được yêu cầu.

1.Tạo ArrayDanh sách các trường Tên đơn giản của ba lớp này là toàn cục.

private static ArrayList<String> getAllFieldsSimpleNames(Class<?> beanClass) { 
    ArrayList<String> fieldNames = new ArrayList<String>(); 
    Field[] fields = beanClass.getDeclaredFields(); 
    for (Field field : fields) { 
     fieldNames.add(field.getName()); 
    } 
    return fieldNames; 
} 

2.Và sau đó mỗi khi tạo ra một đối tượng chúng ta đang xác nhận lĩnh vực (nói> 10 lĩnh vực) chống lại các lớp helper như dưới đây rất dễ dàng tôi cảm thấy.

for(String a :abcFieldNames){ 
     if(abcXMLfieldnames.contains(a)){ 
     //code here 
     }else if(abcHTMLfieldnames.contains(a){ 
     //code here 
     } 
    } 

đơn giản khác và cách động lực được tạo

 HashMap<Class<?>, ArrayList<String>> = ... 
    hm.put(ABC.class, getAllFieldsSimpleNames(ABC.class)); 
    hm.put(ABCXMLDOMnodes.class, getAllFieldsSimpleNames(ABCXMLDOMnodes.class)); 
if(hm.get(ABCXMLDOMnodes.class).contains("a"){...} 

Đề nghị của tôi để Oracle CorpMạng JAVA là nếu "Class class" có thể cung cấp một phương thức trả về một danh sách các tên trường của Class đã cho dưới dạng kiểu chuỗi chỉ có ích.

12

Cảnh báo: câu trả lời chấp nhận sẽ làm việc, nhưng nó dựa trên trường hợp ngoại lệ như dòng điều khiển, đó là bad practice và nên tránh bất cứ nơi nào có thể.

Thay vào đó, hãy xem xét các lựa chọn sau:

public boolean doesObjectContainField(Object object, String fieldName) { 
    Class<?> objectClass = object.getClass(); 
    for (Field field : objectClass.getFields()) { 
     if (field.getName().equals(fieldName)) { 
      return true; 
     } 
    } 
    return false; 
} 

Hoặc một hình thức ngắn gọn hơn sử dụng Java 8 suối:

public boolean doesObjectContainField(Object object, String fieldName) { 
    return Arrays.stream(object.getClass().getFields()) 
      .anyMatch(f -> f.getName().equals(fieldName)); 
} 

Những đoạn mã không dựa vào trường hợp ngoại lệ như dòng điều khiển và trong thực tế làm không yêu cầu bất kỳ xử lý ngoại lệ nào, điều này sẽ làm cho việc triển khai của bạn đơn giản và dễ đọc hơn. Bạn sẽ chỉ cần gọi một trong những phương pháp trên với một đoạn mã tương tự như sau:

Object someObject = ... ; 
boolean fieldExists = doesObjectContainField(someObject, "foo"); 

Là một mặt lưu ý, nếu bạn cần thiết để truy cập vào các lĩnh vực riêng của lớp học của bạn (nhưng lớp không cha mẹ các trường), bạn chỉ có thể thay thế cuộc gọi thành getFields theo getDeclaredFields.

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