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