/* * Copyright (c) 2007 Mockito contributors * This program is made available under the terms of the MIT License. */ package org.mockito.internal.util.reflection; import org.mockito.internal.util.Checks; import static org.mockito.internal.util.reflection.FieldSetter.setField; import java.lang.annotation.Annotation; import java.lang.reflect.Field; /** * Represents an accessible instance field. * * Contains the instance reference on which the field can be read adn write. */ public class InstanceField { private final Field field; private final Object instance; private FieldReader fieldReader; /** * Create a new InstanceField. * * @param field The field that should be accessed, note that no checks are performed to ensure * the field belong to this instance class. * @param instance The instance from which the field shall be accessed. */ public InstanceField(Field field, Object instance) { this.field = Checks.checkNotNull(field, "field"); this.instance = Checks.checkNotNull(instance, "instance"); } /** * Safely read the field. * * @return the field value. * @see FieldReader */ public Object read() { return reader().read(); } /** * Set the given value to the field of this instance. * * @param value The value that should be written to the field. * @see FieldSetter */ public void set(Object value) { setField(instance, field,value); } /** * Check that the field is not null. * * @return <code>true</code> if <code>null</code>, else <code>false</code>. */ public boolean isNull() { return reader().isNull(); } /** * Check if the field is annotated by the given annotation. * * @param annotationClass The annotation type to check. * @return <code>true</code> if the field is annotated by this annotation, else <code>false</code>. */ public boolean isAnnotatedBy(Class<? extends Annotation> annotationClass) { return field.isAnnotationPresent(annotationClass); } /** * Check if the field is synthetic. * * @return <code>true</code> if the field is synthetic, else <code>false</code>. */ public boolean isSynthetic() { return field.isSynthetic(); } /** * Returns the annotation instance for the given annotation type. * * @param annotationClass Tha annotation type to retrieve. * @param <A> Type of the annotation. * @return The annotation instance. */ public <A extends Annotation> A annotation(Class<A> annotationClass) { return field.getAnnotation(annotationClass); } /** * Returns the JDK {@link Field} instance. * * @return The actual {@link Field} instance. */ public Field jdkField() { return field; } private FieldReader reader() { if (fieldReader == null) { fieldReader = new FieldReader(instance, field); } return fieldReader; } /** * Returns the name of the field. * * @return Name of the field. */ public String name() { return field.getName(); } @Override public String toString() { return name(); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; InstanceField that = (InstanceField) o; return field.equals(that.field) && instance.equals(that.instance); } @Override public int hashCode() { int result = field.hashCode(); result = 31 * result + instance.hashCode(); return result; } }