Field.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  *  Unless required by applicable law or agreed to in writing, software
  12.  *  distributed under the License is distributed on an "AS IS" BASIS,
  13.  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  *  See the License for the specific language governing permissions and
  15.  *  limitations under the License.
  16.  */
  17. package org.apache.bcel.classfile;

  18. import java.io.DataInput;
  19. import java.io.IOException;
  20. import java.util.Objects;

  21. import org.apache.bcel.Const;
  22. import org.apache.bcel.generic.Type;
  23. import org.apache.bcel.util.BCELComparator;

  24. /**
  25.  * This class represents the field info structure, i.e., the representation for a variable in the class. See JVM
  26.  * specification for details.
  27.  */
  28. public final class Field extends FieldOrMethod {

  29.     /**
  30.      * Empty array constant.
  31.      *
  32.      * @since 6.6.0
  33.      */
  34.     public static final Field[] EMPTY_ARRAY = {};

  35.     private static BCELComparator<Field> bcelComparator = new BCELComparator<Field>() {

  36.         @Override
  37.         public boolean equals(final Field a, final Field b) {
  38.             return a == b || a != null && b != null && Objects.equals(a.getName(), b.getName()) && Objects.equals(a.getSignature(), b.getSignature());
  39.         }

  40.         @Override
  41.         public int hashCode(final Field o) {
  42.             return o != null ? Objects.hash(o.getSignature(), o.getName()) : 0;
  43.         }
  44.     };

  45.     /**
  46.      * @return Comparison strategy object.
  47.      */
  48.     public static BCELComparator<Field> getComparator() {
  49.         return bcelComparator;
  50.     }

  51.     /**
  52.      * @param comparator Comparison strategy object.
  53.      */
  54.     public static void setComparator(final BCELComparator<Field> comparator) {
  55.         bcelComparator = comparator;
  56.     }

  57.     /**
  58.      * Constructs object from file stream.
  59.      *
  60.      * @param file Input stream.
  61.      */
  62.     Field(final DataInput file, final ConstantPool constantPool) throws IOException, ClassFormatException {
  63.         super(file, constantPool);
  64.     }

  65.     /**
  66.      * Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a
  67.      * physical copy.
  68.      *
  69.      * @param c Source to copy.
  70.      */
  71.     public Field(final Field c) {
  72.         super(c);
  73.     }

  74.     /**
  75.      * @param accessFlags Access rights of field
  76.      * @param nameIndex Points to field name in constant pool
  77.      * @param signatureIndex Points to encoded signature
  78.      * @param attributes Collection of attributes
  79.      * @param constantPool Array of constants
  80.      */
  81.     public Field(final int accessFlags, final int nameIndex, final int signatureIndex, final Attribute[] attributes, final ConstantPool constantPool) {
  82.         super(accessFlags, nameIndex, signatureIndex, attributes, constantPool);
  83.     }

  84.     /**
  85.      * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
  86.      * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
  87.      *
  88.      * @param v Visitor object
  89.      */
  90.     @Override
  91.     public void accept(final Visitor v) {
  92.         v.visitField(this);
  93.     }

  94.     /**
  95.      * @return deep copy of this field
  96.      */
  97.     public Field copy(final ConstantPool constantPool) {
  98.         return (Field) copy_(constantPool);
  99.     }

  100.     /**
  101.      * Return value as defined by given BCELComparator strategy. By default two Field objects are said to be equal when
  102.      * their names and signatures are equal.
  103.      *
  104.      * @see Object#equals(Object)
  105.      */
  106.     @Override
  107.     public boolean equals(final Object obj) {
  108.         return obj instanceof Field && bcelComparator.equals(this, (Field) obj);
  109.     }

  110.     /**
  111.      * @return constant value associated with this field (may be null)
  112.      */
  113.     public ConstantValue getConstantValue() {
  114.         for (final Attribute attribute : super.getAttributes()) {
  115.             if (attribute.getTag() == Const.ATTR_CONSTANT_VALUE) {
  116.                 return (ConstantValue) attribute;
  117.             }
  118.         }
  119.         return null;
  120.     }

  121.     /**
  122.      * See https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.2.2
  123.      *
  124.      * @return type of field
  125.      */
  126.     public Type getType() {
  127.         return Type.getType(getSignature());
  128.     }

  129.     /**
  130.      * Return value as defined by given BCELComparator strategy. By default return the hash code of the field's name XOR
  131.      * signature.
  132.      *
  133.      * @see Object#hashCode()
  134.      */
  135.     @Override
  136.     public int hashCode() {
  137.         return bcelComparator.hashCode(this);
  138.     }

  139.     /**
  140.      * Return string representation close to declaration format, 'public static final short MAX = 100', e.g..
  141.      *
  142.      * @return String representation of field, including the signature.
  143.      */
  144.     @Override
  145.     public String toString() {
  146.         String name;
  147.         String signature;
  148.         String access; // Short cuts to constant pool

  149.         // Get names from constant pool
  150.         access = Utility.accessToString(super.getAccessFlags());
  151.         access = access.isEmpty() ? "" : access + " ";
  152.         signature = Utility.signatureToString(getSignature());
  153.         name = getName();
  154.         final StringBuilder buf = new StringBuilder(64); // CHECKSTYLE IGNORE MagicNumber
  155.         buf.append(access).append(signature).append(" ").append(name);
  156.         final ConstantValue cv = getConstantValue();
  157.         if (cv != null) {
  158.             buf.append(" = ").append(cv);
  159.         }
  160.         for (final Attribute attribute : super.getAttributes()) {
  161.             if (!(attribute instanceof ConstantValue)) {
  162.                 buf.append(" [").append(attribute).append("]");
  163.             }
  164.         }
  165.         return buf.toString();
  166.     }
  167. }