1/* 2 * Copyright (c) 2007 Mockito contributors 3 * This program is made available under the terms of the MIT License. 4 */ 5package org.mockito.internal.util.reflection; 6 7import org.mockito.internal.util.Checks; 8 9import java.lang.annotation.Annotation; 10import java.lang.reflect.Field; 11 12/** 13 * Represents an accessible instance field. 14 * 15 * Contains the instance reference on which the field can be read adn write. 16 */ 17public class InstanceField { 18 private final Field field; 19 private final Object instance; 20 private FieldReader fieldReader; 21 22 /** 23 * Create a new InstanceField. 24 * 25 * @param field The field that should be accessed, note that no checks are performed to ensure 26 * the field belong to this instance class. 27 * @param instance The instance from which the field shall be accessed. 28 */ 29 public InstanceField(Field field, Object instance) { 30 this.field = Checks.checkNotNull(field, "field"); 31 this.instance = Checks.checkNotNull(instance, "instance"); 32 } 33 34 /** 35 * Safely read the field. 36 * 37 * @return the field value. 38 * @see FieldReader 39 */ 40 public Object read() { 41 return reader().read(); 42 } 43 44 /** 45 * Set the given value to the field of this instance. 46 * 47 * @param value The value that should be written to the field. 48 * @see FieldSetter 49 */ 50 public void set(Object value) { 51 new FieldSetter(instance, field).set(value); 52 } 53 54 /** 55 * Check that the field is not null. 56 * 57 * @return <code>true</code> if <code>null</code>, else <code>false</code>. 58 */ 59 public boolean isNull() { 60 return reader().isNull(); 61 } 62 63 /** 64 * Check if the field is annotated by the given annotation. 65 * 66 * @param annotationClass The annotation type to check. 67 * @return <code>true</code> if the field is annotated by this annotation, else <code>false</code>. 68 */ 69 public boolean isAnnotatedBy(Class<? extends Annotation> annotationClass) { 70 return field.isAnnotationPresent(annotationClass); 71 } 72 73 /** 74 * Returns the annotation instance for the given annotation type. 75 * 76 * @param annotationClass Tha annotation type to retrieve. 77 * @param <A> Type of the annotation. 78 * @return The annotation instance. 79 */ 80 public <A extends Annotation> A annotation(Class<A> annotationClass) { 81 return field.getAnnotation(annotationClass); 82 } 83 84 /** 85 * Returns the JDK {@link Field} instance. 86 * 87 * @return The actual {@link Field} instance. 88 */ 89 public Field jdkField() { 90 return field; 91 } 92 93 private FieldReader reader() { 94 if (fieldReader == null) { 95 fieldReader = new FieldReader(instance, field); 96 } 97 return fieldReader; 98 } 99 100 /** 101 * Returns the name of the field. 102 * 103 * @return Name of the field. 104 */ 105 public String name() { 106 return field.getName(); 107 } 108 109 @Override 110 public boolean equals(Object o) { 111 if (this == o) return true; 112 if (o == null || getClass() != o.getClass()) return false; 113 114 InstanceField that = (InstanceField) o; 115 116 if (!field.equals(that.field)) return false; 117 if (!instance.equals(that.instance)) return false; 118 119 return true; 120 } 121 122 @Override 123 public int hashCode() { 124 int result = field.hashCode(); 125 result = 31 * result + instance.hashCode(); 126 return result; 127 } 128} 129