View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.bcel.classfile;
20  
21  import java.io.DataInput;
22  import java.io.IOException;
23  import java.util.Objects;
24  
25  import org.apache.bcel.Const;
26  import org.apache.bcel.generic.Type;
27  import org.apache.bcel.util.BCELComparator;
28  
29  /**
30   * This class represents the field info structure, that is, the representation for a variable in the class. See JVM
31   * specification for details.
32   */
33  public final class Field extends FieldOrMethod {
34  
35      /**
36       * Empty array constant.
37       *
38       * @since 6.6.0
39       */
40      public static final Field[] EMPTY_ARRAY = {};
41  
42      private static BCELComparator<Field> bcelComparator = new BCELComparator<Field>() {
43  
44          @Override
45          public boolean equals(final Field a, final Field b) {
46              return a == b || a != null && b != null && Objects.equals(a.getName(), b.getName()) && Objects.equals(a.getSignature(), b.getSignature());
47          }
48  
49          @Override
50          public int hashCode(final Field o) {
51              return o != null ? Objects.hash(o.getSignature(), o.getName()) : 0;
52          }
53      };
54  
55      /**
56       * Gets the comparison strategy object.
57       *
58       * @return Comparison strategy object.
59       */
60      public static BCELComparator<Field> getComparator() {
61          return bcelComparator;
62      }
63  
64      /**
65       * Sets the comparison strategy object.
66       *
67       * @param comparator Comparison strategy object.
68       */
69      public static void setComparator(final BCELComparator<Field> comparator) {
70          bcelComparator = comparator;
71      }
72  
73      /**
74       * Constructs object from file stream.
75       *
76       * @param file Input stream.
77       * @param constantPool the constant pool.
78       */
79      Field(final DataInput file, final ConstantPool constantPool) throws IOException, ClassFormatException {
80          super(file, constantPool);
81      }
82  
83      /**
84       * Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a
85       * physical copy.
86       *
87       * @param c Source to copy.
88       */
89      public Field(final Field c) {
90          super(c);
91      }
92  
93      /**
94       * Constructs a Field.
95       *
96       * @param accessFlags Access rights of field.
97       * @param nameIndex Points to field name in constant pool.
98       * @param signatureIndex Points to encoded signature.
99       * @param attributes Collection of attributes.
100      * @param constantPool Array of constants.
101      */
102     public Field(final int accessFlags, final int nameIndex, final int signatureIndex, final Attribute[] attributes, final ConstantPool constantPool) {
103         super(accessFlags, nameIndex, signatureIndex, attributes, constantPool);
104     }
105 
106     /**
107      * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
108      * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
109      *
110      * @param v Visitor object.
111      */
112     @Override
113     public void accept(final Visitor v) {
114         v.visitField(this);
115     }
116 
117     /**
118      * Creates a deep copy of this field.
119      *
120      * @param constantPool the constant pool.
121      * @return deep copy of this field.
122      */
123     public Field copy(final ConstantPool constantPool) {
124         return (Field) copy_(constantPool);
125     }
126 
127     /**
128      * Return value as defined by given BCELComparator strategy. By default two Field objects are said to be equal when
129      * their names and signatures are equal.
130      *
131      * @see Object#equals(Object)
132      */
133     @Override
134     public boolean equals(final Object obj) {
135         return obj instanceof Field && bcelComparator.equals(this, (Field) obj);
136     }
137 
138     /**
139      * Gets the constant value associated with this field.
140      *
141      * @return constant value associated with this field (may be null).
142      */
143     public ConstantValue getConstantValue() {
144         for (final Attribute attribute : super.getAttributes()) {
145             if (attribute.getTag() == Const.ATTR_CONSTANT_VALUE) {
146                 return (ConstantValue) attribute;
147             }
148         }
149         return null;
150     }
151 
152     /**
153      * See https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.2.2
154      *
155      * @return type of field.
156      */
157     public Type getType() {
158         return Type.getType(getSignature());
159     }
160 
161     /**
162      * Return value as defined by given BCELComparator strategy. By default return the hash code of the field's name XOR
163      * signature.
164      *
165      * @see Object#hashCode()
166      */
167     @Override
168     public int hashCode() {
169         return bcelComparator.hashCode(this);
170     }
171 
172     /**
173      * Return string representation close to declaration format, for example: 'public static final short MAX = 100'.
174      *
175      * @return String representation of field, including the signature.
176      */
177     @Override
178     public String toString() {
179         // Get names from constant pool
180         String access = Utility.accessToString(super.getAccessFlags());
181         access = access.isEmpty() ? "" : access + " ";
182         final String signature = Utility.signatureToString(getSignature());
183         final String name = getName();
184         final StringBuilder buf = new StringBuilder(64); // CHECKSTYLE IGNORE MagicNumber
185         buf.append(access).append(signature).append(" ").append(name);
186         final ConstantValue cv = getConstantValue();
187         if (cv != null) {
188             buf.append(" = ").append(cv);
189         }
190         for (final Attribute attribute : super.getAttributes()) {
191             if (!(attribute instanceof ConstantValue)) {
192                 buf.append(" [").append(attribute).append("]");
193             }
194         }
195         return buf.toString();
196     }
197 }