001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.bcel.classfile; 018 019import java.io.DataInput; 020import java.io.IOException; 021import java.util.Objects; 022 023import org.apache.bcel.Const; 024import org.apache.bcel.generic.Type; 025import org.apache.bcel.util.BCELComparator; 026 027/** 028 * This class represents the field info structure, i.e., the representation for a variable in the class. See JVM 029 * specification for details. 030 */ 031public final class Field extends FieldOrMethod { 032 033 /** 034 * Empty array constant. 035 * 036 * @since 6.6.0 037 */ 038 public static final Field[] EMPTY_ARRAY = {}; 039 040 private static BCELComparator bcelComparator = new BCELComparator() { 041 042 @Override 043 public boolean equals(final Object o1, final Object o2) { 044 final Field THIS = (Field) o1; 045 final Field THAT = (Field) o2; 046 return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature()); 047 } 048 049 @Override 050 public int hashCode(final Object o) { 051 final Field THIS = (Field) o; 052 return THIS.getSignature().hashCode() ^ THIS.getName().hashCode(); 053 } 054 }; 055 056 /** 057 * Empty array. 058 */ 059 static final Field[] EMPTY_FIELD_ARRAY = {}; 060 061 /** 062 * @return Comparison strategy object 063 */ 064 public static BCELComparator getComparator() { 065 return bcelComparator; 066 } 067 068 /** 069 * @param comparator Comparison strategy object 070 */ 071 public static void setComparator(final BCELComparator comparator) { 072 bcelComparator = comparator; 073 } 074 075 /** 076 * Construct object from file stream. 077 * 078 * @param file Input stream 079 */ 080 Field(final DataInput file, final ConstantPool constantPool) throws IOException, ClassFormatException { 081 super(file, constantPool); 082 } 083 084 /** 085 * Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a 086 * physical copy. 087 */ 088 public Field(final Field c) { 089 super(c); 090 } 091 092 /** 093 * @param accessFlags Access rights of field 094 * @param nameIndex Points to field name in constant pool 095 * @param signatureIndex Points to encoded signature 096 * @param attributes Collection of attributes 097 * @param constantPool Array of constants 098 */ 099 public Field(final int accessFlags, final int nameIndex, final int signatureIndex, final Attribute[] attributes, final ConstantPool constantPool) { 100 super(accessFlags, nameIndex, signatureIndex, attributes, constantPool); 101 } 102 103 /** 104 * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. 105 * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. 106 * 107 * @param v Visitor object 108 */ 109 @Override 110 public void accept(final Visitor v) { 111 v.visitField(this); 112 } 113 114 /** 115 * @return deep copy of this field 116 */ 117 public Field copy(final ConstantPool constantPool) { 118 return (Field) copy_(constantPool); 119 } 120 121 /** 122 * Return value as defined by given BCELComparator strategy. By default two Field objects are said to be equal when 123 * their names and signatures are equal. 124 * 125 * @see Object#equals(Object) 126 */ 127 @Override 128 public boolean equals(final Object obj) { 129 return bcelComparator.equals(this, obj); 130 } 131 132 /** 133 * @return constant value associated with this field (may be null) 134 */ 135 public ConstantValue getConstantValue() { 136 for (final Attribute attribute : super.getAttributes()) { 137 if (attribute.getTag() == Const.ATTR_CONSTANT_VALUE) { 138 return (ConstantValue) attribute; 139 } 140 } 141 return null; 142 } 143 144 /** 145 * @return type of field 146 */ 147 public Type getType() { 148 return Type.getReturnType(getSignature()); 149 } 150 151 /** 152 * Return value as defined by given BCELComparator strategy. By default return the hashcode of the field's name XOR 153 * signature. 154 * 155 * @see Object#hashCode() 156 */ 157 @Override 158 public int hashCode() { 159 return bcelComparator.hashCode(this); 160 } 161 162 /** 163 * Return string representation close to declaration format, `public static final short MAX = 100', e.g.. 164 * 165 * @return String representation of field, including the signature. 166 */ 167 @Override 168 public String toString() { 169 String name; 170 String signature; 171 String access; // Short cuts to constant pool 172 173 // Get names from constant pool 174 access = Utility.accessToString(super.getAccessFlags()); 175 access = access.isEmpty() ? "" : access + " "; 176 signature = Utility.signatureToString(getSignature()); 177 name = getName(); 178 final StringBuilder buf = new StringBuilder(64); // CHECKSTYLE IGNORE MagicNumber 179 buf.append(access).append(signature).append(" ").append(name); 180 final ConstantValue cv = getConstantValue(); 181 if (cv != null) { 182 buf.append(" = ").append(cv); 183 } 184 for (final Attribute attribute : super.getAttributes()) { 185 if (!(attribute instanceof ConstantValue)) { 186 buf.append(" [").append(attribute).append("]"); 187 } 188 } 189 return buf.toString(); 190 } 191}