/*
 * Javassist, a Java-bytecode translator toolkit.
 * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License.  Alternatively, the contents of this file may be used under
 * the terms of the GNU Lesser General Public License Version 2.1 or later,
 * or the Apache License Version 2.0.
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 */

package javassist;

import java.util.List;

import javassist.bytecode.AccessFlag;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.AttributeInfo;
import javassist.bytecode.Bytecode;
import javassist.bytecode.ClassFile;
import javassist.bytecode.ConstPool;
import javassist.bytecode.Descriptor;
import javassist.bytecode.FieldInfo;
import javassist.bytecode.SignatureAttribute;
import javassist.compiler.CompileError;
import javassist.compiler.Javac;
import javassist.compiler.SymbolTable;
import javassist.compiler.ast.ASTree;
import javassist.compiler.ast.DoubleConst;
import javassist.compiler.ast.IntConst;
import javassist.compiler.ast.StringL;

An instance of CtField represents a field.
See Also:
  • getDeclaredFields.getDeclaredFields()
/** * An instance of CtField represents a field. * * @see CtClass#getDeclaredFields() */
public class CtField extends CtMember { static final String javaLangString = "java.lang.String"; protected FieldInfo fieldInfo;
Creates a CtField object. The created field must be added to a class with CtClass.addField(). An initial value of the field is specified by a CtField.Initializer object.

If getter and setter methods are needed, call CtNewMethod.getter() and CtNewMethod.setter().

Params:
  • type – field type
  • name – field name
  • declaring – the class to which the field will be added.
See Also:
/** * Creates a <code>CtField</code> object. * The created field must be added to a class * with <code>CtClass.addField()</code>. * An initial value of the field is specified * by a <code>CtField.Initializer</code> object. * * <p>If getter and setter methods are needed, * call <code>CtNewMethod.getter()</code> and * <code>CtNewMethod.setter()</code>. * * @param type field type * @param name field name * @param declaring the class to which the field will be added. * * @see CtClass#addField(CtField) * @see CtNewMethod#getter(String,CtField) * @see CtNewMethod#setter(String,CtField) * @see CtField.Initializer */
public CtField(CtClass type, String name, CtClass declaring) throws CannotCompileException { this(Descriptor.of(type), name, declaring); }
Creates a copy of the given field. The created field must be added to a class with CtClass.addField(). An initial value of the field is specified by a CtField.Initializer object.

If getter and setter methods are needed, call CtNewMethod.getter() and CtNewMethod.setter().

Params:
  • src – the original field
  • declaring – the class to which the field will be added.
See Also:
/** * Creates a copy of the given field. * The created field must be added to a class * with <code>CtClass.addField()</code>. * An initial value of the field is specified * by a <code>CtField.Initializer</code> object. * * <p>If getter and setter methods are needed, * call <code>CtNewMethod.getter()</code> and * <code>CtNewMethod.setter()</code>. * * @param src the original field * @param declaring the class to which the field will be added. * @see CtNewMethod#getter(String,CtField) * @see CtNewMethod#setter(String,CtField) * @see CtField.Initializer */
public CtField(CtField src, CtClass declaring) throws CannotCompileException { this(src.fieldInfo.getDescriptor(), src.fieldInfo.getName(), declaring); FieldInfo fi = fieldInfo; fi.setAccessFlags(src.fieldInfo.getAccessFlags()); ConstPool cp = fi.getConstPool(); List<AttributeInfo> attributes = src.fieldInfo.getAttributes(); for (AttributeInfo ainfo : attributes) fi.addAttribute(ainfo.copy(cp, null)); } private CtField(String typeDesc, String name, CtClass clazz) throws CannotCompileException { super(clazz); ClassFile cf = clazz.getClassFile2(); if (cf == null) throw new CannotCompileException("bad declaring class: " + clazz.getName()); fieldInfo = new FieldInfo(cf.getConstPool(), name, typeDesc); } CtField(FieldInfo fi, CtClass clazz) { super(clazz); fieldInfo = fi; }
Returns a String representation of the object.
/** * Returns a String representation of the object. */
@Override public String toString() { return getDeclaringClass().getName() + "." + getName() + ":" + fieldInfo.getDescriptor(); } @Override protected void extendToString(StringBuffer buffer) { buffer.append(' '); buffer.append(getName()); buffer.append(' '); buffer.append(fieldInfo.getDescriptor()); } /* Javac.CtFieldWithInit overrides. */ protected ASTree getInitAST() { return null; } /* Called by CtClassType.addField(). */ Initializer getInit() { ASTree tree = getInitAST(); if (tree == null) return null; return Initializer.byExpr(tree); }
Compiles the given source code and creates a field. Examples of the source code are:
"public String name;"
"public int k = 3;"

Note that the source code ends with ';' (semicolon).

Params:
  • src – the source text.
  • declaring – the class to which the created field is added.
/** * Compiles the given source code and creates a field. * Examples of the source code are: * * <pre> * "public String name;" * "public int k = 3;"</pre> * * <p>Note that the source code ends with <code>';'</code> * (semicolon). * * @param src the source text. * @param declaring the class to which the created field is added. */
public static CtField make(String src, CtClass declaring) throws CannotCompileException { Javac compiler = new Javac(declaring); try { CtMember obj = compiler.compile(src); if (obj instanceof CtField) return (CtField)obj; // an instance of Javac.CtFieldWithInit } catch (CompileError e) { throw new CannotCompileException(e); } throw new CannotCompileException("not a field"); }
Returns the FieldInfo representing the field in the class file.
/** * Returns the FieldInfo representing the field in the class file. */
public FieldInfo getFieldInfo() { declaringClass.checkModify(); return fieldInfo; }
Returns the FieldInfo representing the field in the class file (read only). Normal applications do not need calling this method. Use getFieldInfo().

The FieldInfo object obtained by this method is read only. Changes to this object might not be reflected on a class file generated by toBytecode(), toClass(), etc in CtClass.

This method is available even if the CtClass containing this field is frozen. However, if the class is frozen, the FieldInfo might be also pruned.

See Also:
/** * Returns the FieldInfo representing the field in the class * file (read only). * Normal applications do not need calling this method. Use * <code>getFieldInfo()</code>. * * <p>The <code>FieldInfo</code> object obtained by this method * is read only. Changes to this object might not be reflected * on a class file generated by <code>toBytecode()</code>, * <code>toClass()</code>, etc in <code>CtClass</code>. * * <p>This method is available even if the <code>CtClass</code> * containing this field is frozen. However, if the class is * frozen, the <code>FieldInfo</code> might be also pruned. * * @see #getFieldInfo() * @see CtClass#isFrozen() * @see CtClass#prune() */
public FieldInfo getFieldInfo2() { return fieldInfo; }
Returns the class declaring the field.
/** * Returns the class declaring the field. */
@Override public CtClass getDeclaringClass() { // this is redundant but for javadoc. return super.getDeclaringClass(); }
Returns the name of the field.
/** * Returns the name of the field. */
@Override public String getName() { return fieldInfo.getName(); }
Changes the name of the field.
/** * Changes the name of the field. */
public void setName(String newName) { declaringClass.checkModify(); fieldInfo.setName(newName); }
Returns the encoded modifiers of the field.
See Also:
  • Modifier
/** * Returns the encoded modifiers of the field. * * @see Modifier */
@Override public int getModifiers() { return AccessFlag.toModifier(fieldInfo.getAccessFlags()); }
Sets the encoded modifiers of the field.
See Also:
  • Modifier
/** * Sets the encoded modifiers of the field. * * @see Modifier */
@Override public void setModifiers(int mod) { declaringClass.checkModify(); fieldInfo.setAccessFlags(AccessFlag.of(mod)); }
Returns true if the class has the specified annotation type.
Params:
  • typeName – the name of annotation type.
Returns:true if the annotation is found, otherwise false.
Since:3.21
/** * Returns true if the class has the specified annotation type. * * @param typeName the name of annotation type. * @return <code>true</code> if the annotation is found, otherwise <code>false</code>. * @since 3.21 */
@Override public boolean hasAnnotation(String typeName) { FieldInfo fi = getFieldInfo2(); AnnotationsAttribute ainfo = (AnnotationsAttribute) fi.getAttribute(AnnotationsAttribute.invisibleTag); AnnotationsAttribute ainfo2 = (AnnotationsAttribute) fi.getAttribute(AnnotationsAttribute.visibleTag); return CtClassType.hasAnnotationType(typeName, getDeclaringClass().getClassPool(), ainfo, ainfo2); }
Returns the annotation if the class has the specified annotation class. For example, if an annotation @Author is associated with this field, an Author object is returned. The member values can be obtained by calling methods on the Author object.
Params:
  • clz – the annotation class.
Returns:the annotation if found, otherwise null.
Since:3.11
/** * Returns the annotation if the class has the specified annotation class. * For example, if an annotation <code>@Author</code> is associated * with this field, an <code>Author</code> object is returned. * The member values can be obtained by calling methods on * the <code>Author</code> object. * * @param clz the annotation class. * @return the annotation if found, otherwise <code>null</code>. * @since 3.11 */
@Override public Object getAnnotation(Class<?> clz) throws ClassNotFoundException { FieldInfo fi = getFieldInfo2(); AnnotationsAttribute ainfo = (AnnotationsAttribute) fi.getAttribute(AnnotationsAttribute.invisibleTag); AnnotationsAttribute ainfo2 = (AnnotationsAttribute) fi.getAttribute(AnnotationsAttribute.visibleTag); return CtClassType.getAnnotationType(clz, getDeclaringClass().getClassPool(), ainfo, ainfo2); }
Returns the annotations associated with this field.
See Also:
Returns:an array of annotation-type objects.
Since:3.1
/** * Returns the annotations associated with this field. * * @return an array of annotation-type objects. * @see #getAvailableAnnotations() * @since 3.1 */
@Override public Object[] getAnnotations() throws ClassNotFoundException { return getAnnotations(false); }
Returns the annotations associated with this field. If any annotations are not on the classpath, they are not included in the returned array.
See Also:
Returns:an array of annotation-type objects.
Since:3.3
/** * Returns the annotations associated with this field. * If any annotations are not on the classpath, they are not included * in the returned array. * * @return an array of annotation-type objects. * @see #getAnnotations() * @since 3.3 */
@Override public Object[] getAvailableAnnotations(){ try { return getAnnotations(true); } catch (ClassNotFoundException e) { throw new RuntimeException("Unexpected exception", e); } } private Object[] getAnnotations(boolean ignoreNotFound) throws ClassNotFoundException { FieldInfo fi = getFieldInfo2(); AnnotationsAttribute ainfo = (AnnotationsAttribute) fi.getAttribute(AnnotationsAttribute.invisibleTag); AnnotationsAttribute ainfo2 = (AnnotationsAttribute) fi.getAttribute(AnnotationsAttribute.visibleTag); return CtClassType.toAnnotationType(ignoreNotFound, getDeclaringClass().getClassPool(), ainfo, ainfo2); }
Returns the character string representing the type of the field. The field signature is represented by a character string called a field descriptor, which is defined in the JVM specification. If two fields have the same type, getSignature() returns the same string.

Note that the returned string is not the type signature contained in the SignatureAttirbute. It is a descriptor.

See Also:
/** * Returns the character string representing the type of the field. * The field signature is represented by a character string * called a field descriptor, which is defined in the JVM specification. * If two fields have the same type, * <code>getSignature()</code> returns the same string. * * <p>Note that the returned string is not the type signature * contained in the <code>SignatureAttirbute</code>. It is * a descriptor. * * @see javassist.bytecode.Descriptor * @see #getGenericSignature() */
@Override public String getSignature() { return fieldInfo.getDescriptor(); }
Returns the generic signature of the field. It represents a type including type variables.
See Also:
  • toFieldSignature.toFieldSignature(String)
Since:3.17
/** * Returns the generic signature of the field. * It represents a type including type variables. * * @see SignatureAttribute#toFieldSignature(String) * @since 3.17 */
@Override public String getGenericSignature() { SignatureAttribute sa = (SignatureAttribute)fieldInfo.getAttribute(SignatureAttribute.tag); return sa == null ? null : sa.getSignature(); }
Set the generic signature of the field. It represents a type including type variables. See CtClass.setGenericSignature(String) for a code sample.
Params:
  • sig – a new generic signature.
See Also:
Since:3.17
/** * Set the generic signature of the field. * It represents a type including type variables. * See {@link javassist.CtClass#setGenericSignature(String)} * for a code sample. * * @param sig a new generic signature. * @see javassist.bytecode.SignatureAttribute.ObjectType#encode() * @since 3.17 */
@Override public void setGenericSignature(String sig) { declaringClass.checkModify(); fieldInfo.addAttribute(new SignatureAttribute(fieldInfo.getConstPool(), sig)); }
Returns the type of the field.
/** * Returns the type of the field. */
public CtClass getType() throws NotFoundException { return Descriptor.toCtClass(fieldInfo.getDescriptor(), declaringClass.getClassPool()); }
Sets the type of the field.

This method does not automatically update method bodies that access this field. They have to be explicitly updated. For example, if some method contains an expression t.value and the type of the variable t is changed by setType(CtClass) from int to double, then t.value has to be modified as well since the bytecode of t.value contains the type information.

See Also:
/** * Sets the type of the field. * * <p>This method does not automatically update method bodies that access * this field. They have to be explicitly updated. For example, * if some method contains an expression {@code t.value} and the type * of the variable {@code t} is changed by {@link #setType(CtClass)} * from {@code int} to {@code double}, then {@code t.value} has to be modified * as well since the bytecode of {@code t.value} contains the type information. * </p> * * @see CodeConverter * @see javassist.expr.ExprEditor */
public void setType(CtClass clazz) { declaringClass.checkModify(); fieldInfo.setDescriptor(Descriptor.of(clazz)); }
Returns the value of this field if it is a constant field. This method works only if the field type is a primitive type or String type. Otherwise, it returns null. A constant field is static and final.
Returns: a Integer, Long, Float, Double, Boolean, or String object representing the constant value. null if it is not a constant field or if the field type is not a primitive type or String.
/** * Returns the value of this field if it is a constant field. * This method works only if the field type is a primitive type * or <code>String</code> type. Otherwise, it returns <code>null</code>. * A constant field is <code>static</code> and <code>final</code>. * * @return a <code>Integer</code>, <code>Long</code>, <code>Float</code>, * <code>Double</code>, <code>Boolean</code>, * or <code>String</code> object * representing the constant value. * <code>null</code> if it is not a constant field * or if the field type is not a primitive type * or <code>String</code>. */
public Object getConstantValue() { // When this method is modified, // see also getConstantFieldValue() in TypeChecker. int index = fieldInfo.getConstantValue(); if (index == 0) return null; ConstPool cp = fieldInfo.getConstPool(); switch (cp.getTag(index)) { case ConstPool.CONST_Long : return Long.valueOf(cp.getLongInfo(index)); case ConstPool.CONST_Float : return Float.valueOf(cp.getFloatInfo(index)); case ConstPool.CONST_Double : return Double.valueOf(cp.getDoubleInfo(index)); case ConstPool.CONST_Integer : int value = cp.getIntegerInfo(index); // "Z" means boolean type. if ("Z".equals(fieldInfo.getDescriptor())) return Boolean.valueOf(value != 0); return Integer.valueOf(value); case ConstPool.CONST_String : return cp.getStringInfo(index); default : throw new RuntimeException("bad tag: " + cp.getTag(index) + " at " + index); } }
Obtains an attribute with the given name. If that attribute is not found in the class file, this method returns null.

Note that an attribute is a data block specified by the class file format. See AttributeInfo.

Params:
  • name – attribute name
/** * Obtains an attribute with the given name. * If that attribute is not found in the class file, this * method returns null. * * <p>Note that an attribute is a data block specified by * the class file format. * See {@link javassist.bytecode.AttributeInfo}. * * @param name attribute name */
@Override public byte[] getAttribute(String name) { AttributeInfo ai = fieldInfo.getAttribute(name); if (ai == null) return null; return ai.get(); }
Adds an attribute. The attribute is saved in the class file.

Note that an attribute is a data block specified by the class file format. See AttributeInfo.

Params:
  • name – attribute name
  • data – attribute value
/** * Adds an attribute. The attribute is saved in the class file. * * <p>Note that an attribute is a data block specified by * the class file format. * See {@link javassist.bytecode.AttributeInfo}. * * @param name attribute name * @param data attribute value */
@Override public void setAttribute(String name, byte[] data) { declaringClass.checkModify(); fieldInfo.addAttribute(new AttributeInfo(fieldInfo.getConstPool(), name, data)); } // inner classes
Instances of this class specify how to initialize a field. Initializer is passed to CtClass.addField() with a CtField.

This class cannot be instantiated with the new operator. Factory methods such as byParameter() and byNew must be used for the instantiation. They create a new instance with the given parameters and return it.

See Also:
  • addField.addField(CtField, Initializer)
/** * Instances of this class specify how to initialize a field. * <code>Initializer</code> is passed to * <code>CtClass.addField()</code> with a <code>CtField</code>. * * <p>This class cannot be instantiated with the <code>new</code> operator. * Factory methods such as <code>byParameter()</code> and * <code>byNew</code> * must be used for the instantiation. They create a new instance with * the given parameters and return it. * * @see CtClass#addField(CtField,CtField.Initializer) */
public static abstract class Initializer {
Makes an initializer that assigns a constant integer value. The field must be integer, short, char, or byte type.
/** * Makes an initializer that assigns a constant integer value. * The field must be integer, short, char, or byte type. */
public static Initializer constant(int i) { return new IntInitializer(i); }
Makes an initializer that assigns a constant boolean value. The field must be boolean type.
/** * Makes an initializer that assigns a constant boolean value. * The field must be boolean type. */
public static Initializer constant(boolean b) { return new IntInitializer(b ? 1 : 0); }
Makes an initializer that assigns a constant long value. The field must be long type.
/** * Makes an initializer that assigns a constant long value. * The field must be long type. */
public static Initializer constant(long l) { return new LongInitializer(l); }
Makes an initializer that assigns a constant float value. The field must be float type.
/** * Makes an initializer that assigns a constant float value. * The field must be float type. */
public static Initializer constant(float l) { return new FloatInitializer(l); }
Makes an initializer that assigns a constant double value. The field must be double type.
/** * Makes an initializer that assigns a constant double value. * The field must be double type. */
public static Initializer constant(double d) { return new DoubleInitializer(d); }
Makes an initializer that assigns a constant string value. The field must be java.lang.String type.
/** * Makes an initializer that assigns a constant string value. * The field must be <code>java.lang.String</code> type. */
public static Initializer constant(String s) { return new StringInitializer(s); }
Makes an initializer using a constructor parameter.

The initial value is the N-th parameter given to the constructor of the object including the field. If the constructor takes less than N parameters, the field is not initialized. If the field is static, it is never initialized.

Params:
  • nth – the n-th (>= 0) parameter is used as the initial value. If nth is 0, then the first parameter is used.
/** * Makes an initializer using a constructor parameter. * * <p>The initial value is the * N-th parameter given to the constructor of the object including * the field. If the constructor takes less than N parameters, * the field is not initialized. * If the field is static, it is never initialized. * * @param nth the n-th (&gt;= 0) parameter is used as * the initial value. * If nth is 0, then the first parameter is * used. */
public static Initializer byParameter(int nth) { ParamInitializer i = new ParamInitializer(); i.nthParam = nth; return i; }
Makes an initializer creating a new object.

This initializer creates a new object and uses it as the initial value of the field. The constructor of the created object receives the parameter:

Object obj - the object including the field.

If the initialized field is static, then the constructor does not receive any parameters.

Params:
  • objectType – the class instantiated for the initial value.
/** * Makes an initializer creating a new object. * * <p>This initializer creates a new object and uses it as the initial * value of the field. The constructor of the created object receives * the parameter: * * <p><code>Object obj</code> - the object including the field. * * <p>If the initialized field is static, then the constructor does * not receive any parameters. * * @param objectType the class instantiated for the initial value. */
public static Initializer byNew(CtClass objectType) { NewInitializer i = new NewInitializer(); i.objectType = objectType; i.stringParams = null; i.withConstructorParams = false; return i; }
Makes an initializer creating a new object.

This initializer creates a new object and uses it as the initial value of the field. The constructor of the created object receives the parameters:

Object obj - the object including the field.
String[] strs - the character strings specified by stringParams

If the initialized field is static, then the constructor receives only strs.

Params:
  • objectType – the class instantiated for the initial value.
  • stringParams – the array of strings passed to the constructor.
/** * Makes an initializer creating a new object. * * <p>This initializer creates a new object and uses it as the initial * value of the field. The constructor of the created object receives * the parameters: * * <p><code>Object obj</code> - the object including the field.<br> * <code>String[] strs</code> - the character strings specified * by <code>stringParams</code><br> * * <p>If the initialized field is static, then the constructor * receives only <code>strs</code>. * * @param objectType the class instantiated for the initial value. * @param stringParams the array of strings passed to the * constructor. */
public static Initializer byNew(CtClass objectType, String[] stringParams) { NewInitializer i = new NewInitializer(); i.objectType = objectType; i.stringParams = stringParams; i.withConstructorParams = false; return i; }
Makes an initializer creating a new object.

This initializer creates a new object and uses it as the initial value of the field. The constructor of the created object receives the parameters:

Object obj - the object including the field.
Object[] args - the parameters passed to the constructor of the object including the filed.

If the initialized field is static, then the constructor does not receive any parameters.

Params:
  • objectType – the class instantiated for the initial value.
See Also:
/** * Makes an initializer creating a new object. * * <p>This initializer creates a new object and uses it as the initial * value of the field. The constructor of the created object receives * the parameters: * * <p><code>Object obj</code> - the object including the field.<br> * <code>Object[] args</code> - the parameters passed to the * constructor of the object including the * filed. * * <p>If the initialized field is static, then the constructor does * not receive any parameters. * * @param objectType the class instantiated for the initial value. * * @see javassist.CtField.Initializer#byNewArray(CtClass,int) * @see javassist.CtField.Initializer#byNewArray(CtClass,int[]) */
public static Initializer byNewWithParams(CtClass objectType) { NewInitializer i = new NewInitializer(); i.objectType = objectType; i.stringParams = null; i.withConstructorParams = true; return i; }
Makes an initializer creating a new object.

This initializer creates a new object and uses it as the initial value of the field. The constructor of the created object receives the parameters:

Object obj - the object including the field.
String[] strs - the character strings specified by stringParams
Object[] args - the parameters passed to the constructor of the object including the filed.

If the initialized field is static, then the constructor receives only strs.

Params:
  • objectType – the class instantiated for the initial value.
  • stringParams – the array of strings passed to the constructor.
/** * Makes an initializer creating a new object. * * <p>This initializer creates a new object and uses it as the initial * value of the field. The constructor of the created object receives * the parameters: * * <p><code>Object obj</code> - the object including the field.<br> * <code>String[] strs</code> - the character strings specified * by <code>stringParams</code><br> * <code>Object[] args</code> - the parameters passed to the * constructor of the object including the * filed. * * <p>If the initialized field is static, then the constructor receives * only <code>strs</code>. * * @param objectType the class instantiated for the initial value. * @param stringParams the array of strings passed to the * constructor. */
public static Initializer byNewWithParams(CtClass objectType, String[] stringParams) { NewInitializer i = new NewInitializer(); i.objectType = objectType; i.stringParams = stringParams; i.withConstructorParams = true; return i; }
Makes an initializer calling a static method.

This initializer calls a static method and uses the returned value as the initial value of the field. The called method receives the parameters:

Object obj - the object including the field.

If the initialized field is static, then the method does not receive any parameters.

The type of the returned value must be the same as the field type.

Params:
  • methodClass – the class that the static method is declared in.
  • methodName – the name of the satic method.
/** * Makes an initializer calling a static method. * * <p>This initializer calls a static method and uses the returned * value as the initial value of the field. * The called method receives the parameters: * * <p><code>Object obj</code> - the object including the field. * * <p>If the initialized field is static, then the method does * not receive any parameters. * * <p>The type of the returned value must be the same as the field * type. * * @param methodClass the class that the static method is * declared in. * @param methodName the name of the satic method. */
public static Initializer byCall(CtClass methodClass, String methodName) { MethodInitializer i = new MethodInitializer(); i.objectType = methodClass; i.methodName = methodName; i.stringParams = null; i.withConstructorParams = false; return i; }
Makes an initializer calling a static method.

This initializer calls a static method and uses the returned value as the initial value of the field. The called method receives the parameters:

Object obj - the object including the field.
String[] strs - the character strings specified by stringParams

If the initialized field is static, then the method receive only strs.

The type of the returned value must be the same as the field type.

Params:
  • methodClass – the class that the static method is declared in.
  • methodName – the name of the satic method.
  • stringParams – the array of strings passed to the static method.
/** * Makes an initializer calling a static method. * * <p>This initializer calls a static method and uses the returned * value as the initial value of the field. The called method * receives the parameters: * * <p><code>Object obj</code> - the object including the field.<br> * <code>String[] strs</code> - the character strings specified * by <code>stringParams</code><br> * * <p>If the initialized field is static, then the method * receive only <code>strs</code>. * * <p>The type of the returned value must be the same as the field * type. * * @param methodClass the class that the static method is * declared in. * @param methodName the name of the satic method. * @param stringParams the array of strings passed to the * static method. */
public static Initializer byCall(CtClass methodClass, String methodName, String[] stringParams) { MethodInitializer i = new MethodInitializer(); i.objectType = methodClass; i.methodName = methodName; i.stringParams = stringParams; i.withConstructorParams = false; return i; }
Makes an initializer calling a static method.

This initializer calls a static method and uses the returned value as the initial value of the field. The called method receives the parameters:

Object obj - the object including the field.
Object[] args - the parameters passed to the constructor of the object including the filed.

If the initialized field is static, then the method does not receive any parameters.

The type of the returned value must be the same as the field type.

Params:
  • methodClass – the class that the static method is declared in.
  • methodName – the name of the satic method.
/** * Makes an initializer calling a static method. * * <p>This initializer calls a static method and uses the returned * value as the initial value of the field. The called method * receives the parameters: * * <p><code>Object obj</code> - the object including the field.<br> * <code>Object[] args</code> - the parameters passed to the * constructor of the object including the * filed. * * <p>If the initialized field is static, then the method does * not receive any parameters. * * <p>The type of the returned value must be the same as the field * type. * * @param methodClass the class that the static method is * declared in. * @param methodName the name of the satic method. */
public static Initializer byCallWithParams(CtClass methodClass, String methodName) { MethodInitializer i = new MethodInitializer(); i.objectType = methodClass; i.methodName = methodName; i.stringParams = null; i.withConstructorParams = true; return i; }
Makes an initializer calling a static method.

This initializer calls a static method and uses the returned value as the initial value of the field. The called method receives the parameters:

Object obj - the object including the field.
String[] strs - the character strings specified by stringParams
Object[] args - the parameters passed to the constructor of the object including the filed.

If the initialized field is static, then the method receive only strs.

The type of the returned value must be the same as the field type.

Params:
  • methodClass – the class that the static method is declared in.
  • methodName – the name of the satic method.
  • stringParams – the array of strings passed to the static method.
/** * Makes an initializer calling a static method. * * <p>This initializer calls a static method and uses the returned * value as the initial value of the field. The called method * receives the parameters: * * <p><code>Object obj</code> - the object including the field.<br> * <code>String[] strs</code> - the character strings specified * by <code>stringParams</code><br> * <code>Object[] args</code> - the parameters passed to the * constructor of the object including the * filed. * * <p>If the initialized field is static, then the method * receive only <code>strs</code>. * * <p>The type of the returned value must be the same as the field * type. * * @param methodClass the class that the static method is * declared in. * @param methodName the name of the satic method. * @param stringParams the array of strings passed to the * static method. */
public static Initializer byCallWithParams(CtClass methodClass, String methodName, String[] stringParams) { MethodInitializer i = new MethodInitializer(); i.objectType = methodClass; i.methodName = methodName; i.stringParams = stringParams; i.withConstructorParams = true; return i; }
Makes an initializer creating a new array.
Params:
  • type – the type of the array.
  • size – the size of the array.
Throws:
/** * Makes an initializer creating a new array. * * @param type the type of the array. * @param size the size of the array. * @throws NotFoundException if the type of the array components * is not found. */
public static Initializer byNewArray(CtClass type, int size) throws NotFoundException { return new ArrayInitializer(type.getComponentType(), size); }
Makes an initializer creating a new multi-dimensional array.
Params:
  • type – the type of the array.
  • sizes – an int array of the size in every dimension. The first element is the size in the first dimension. The second is in the second, etc.
/** * Makes an initializer creating a new multi-dimensional array. * * @param type the type of the array. * @param sizes an <code>int</code> array of the size in every * dimension. * The first element is the size in the first * dimension. The second is in the second, etc. */
public static Initializer byNewArray(CtClass type, int[] sizes) { return new MultiArrayInitializer(type, sizes); }
Makes an initializer.
Params:
  • source – initializer expression.
/** * Makes an initializer. * * @param source initializer expression. */
public static Initializer byExpr(String source) { return new CodeInitializer(source); } static Initializer byExpr(ASTree source) { return new PtreeInitializer(source); } // Check whether this initializer is valid for the field type. // If it is invaild, this method throws an exception. void check(String desc) throws CannotCompileException {} // produce codes for initialization abstract int compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv) throws CannotCompileException; // produce codes for initialization abstract int compileIfStatic(CtClass type, String name, Bytecode code, Javac drv) throws CannotCompileException; // returns the index of CONSTANT_Integer_info etc // if the value is constant. Otherwise, 0. int getConstantValue(ConstPool cp, CtClass type) { return 0; } } static abstract class CodeInitializer0 extends Initializer { abstract void compileExpr(Javac drv) throws CompileError; @Override int compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv) throws CannotCompileException { try { code.addAload(0); compileExpr(drv); code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); return code.getMaxStack(); } catch (CompileError e) { throw new CannotCompileException(e); } } @Override int compileIfStatic(CtClass type, String name, Bytecode code, Javac drv) throws CannotCompileException { try { compileExpr(drv); code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); return code.getMaxStack(); } catch (CompileError e) { throw new CannotCompileException(e); } } int getConstantValue2(ConstPool cp, CtClass type, ASTree tree) { if (type.isPrimitive()) { if (tree instanceof IntConst) { long value = ((IntConst)tree).get(); if (type == CtClass.doubleType) return cp.addDoubleInfo(value); else if (type == CtClass.floatType) return cp.addFloatInfo(value); else if (type == CtClass.longType) return cp.addLongInfo(value); else if (type != CtClass.voidType) return cp.addIntegerInfo((int)value); } else if (tree instanceof DoubleConst) { double value = ((DoubleConst)tree).get(); if (type == CtClass.floatType) return cp.addFloatInfo((float)value); else if (type == CtClass.doubleType) return cp.addDoubleInfo(value); } } else if (tree instanceof StringL && type.getName().equals(javaLangString)) return cp.addStringInfo(((StringL)tree).get()); return 0; } } static class CodeInitializer extends CodeInitializer0 { private String expression; CodeInitializer(String expr) { expression = expr; } @Override void compileExpr(Javac drv) throws CompileError { drv.compileExpr(expression); } @Override int getConstantValue(ConstPool cp, CtClass type) { try { ASTree t = Javac.parseExpr(expression, new SymbolTable()); return getConstantValue2(cp, type, t); } catch (CompileError e) { return 0; } } } static class PtreeInitializer extends CodeInitializer0 { private ASTree expression; PtreeInitializer(ASTree expr) { expression = expr; } @Override void compileExpr(Javac drv) throws CompileError { drv.compileExpr(expression); } @Override int getConstantValue(ConstPool cp, CtClass type) { return getConstantValue2(cp, type, expression); } }
A field initialized with a parameter passed to the constructor of the class containing that field.
/** * A field initialized with a parameter passed to the constructor * of the class containing that field. */
static class ParamInitializer extends Initializer { int nthParam; ParamInitializer() {} @Override int compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv) throws CannotCompileException { if (parameters != null && nthParam < parameters.length) { code.addAload(0); int nth = nthParamToLocal(nthParam, parameters, false); int s = code.addLoad(nth, type) + 1; code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); return s; // stack size } return 0; // do not initialize }
Computes the index of the local variable that the n-th parameter is assigned to.
Params:
  • nth – n-th parameter
  • params – list of parameter types
  • isStatic – true if the method is static.
/** * Computes the index of the local variable that the n-th parameter * is assigned to. * * @param nth n-th parameter * @param params list of parameter types * @param isStatic true if the method is static. */
static int nthParamToLocal(int nth, CtClass[] params, boolean isStatic) { CtClass longType = CtClass.longType; CtClass doubleType = CtClass.doubleType; int k; if (isStatic) k = 0; else k = 1; // 0 is THIS. for (int i = 0; i < nth; ++i) { CtClass type = params[i]; if (type == longType || type == doubleType) k += 2; else ++k; } return k; } @Override int compileIfStatic(CtClass type, String name, Bytecode code, Javac drv) throws CannotCompileException { return 0; } }
A field initialized with an object created by the new operator.
/** * A field initialized with an object created by the new operator. */
static class NewInitializer extends Initializer { CtClass objectType; String[] stringParams; boolean withConstructorParams; NewInitializer() {}
Produces codes in which a new object is created and assigned to the field as the initial value.
/** * Produces codes in which a new object is created and assigned to * the field as the initial value. */
@Override int compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv) throws CannotCompileException { int stacksize; code.addAload(0); code.addNew(objectType); code.add(Bytecode.DUP); code.addAload(0); if (stringParams == null) stacksize = 4; else stacksize = compileStringParameter(code) + 4; if (withConstructorParams) stacksize += CtNewWrappedMethod.compileParameterList(code, parameters, 1); code.addInvokespecial(objectType, "<init>", getDescriptor()); code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); return stacksize; } private String getDescriptor() { final String desc3 = "(Ljava/lang/Object;[Ljava/lang/String;[Ljava/lang/Object;)V"; if (stringParams == null) if (withConstructorParams) return "(Ljava/lang/Object;[Ljava/lang/Object;)V"; else return "(Ljava/lang/Object;)V"; if (withConstructorParams) return desc3; return "(Ljava/lang/Object;[Ljava/lang/String;)V"; }
Produces codes for a static field.
/** * Produces codes for a static field. */
@Override int compileIfStatic(CtClass type, String name, Bytecode code, Javac drv) throws CannotCompileException { String desc; code.addNew(objectType); code.add(Bytecode.DUP); int stacksize = 2; if (stringParams == null) desc = "()V"; else { desc = "([Ljava/lang/String;)V"; stacksize += compileStringParameter(code); } code.addInvokespecial(objectType, "<init>", desc); code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); return stacksize; } protected final int compileStringParameter(Bytecode code) throws CannotCompileException { int nparam = stringParams.length; code.addIconst(nparam); code.addAnewarray(javaLangString); for (int j = 0; j < nparam; ++j) { code.add(Bytecode.DUP); // dup code.addIconst(j); // iconst_<j> code.addLdc(stringParams[j]); // ldc ... code.add(Bytecode.AASTORE); // aastore } return 4; } }
A field initialized with the result of a static method call.
/** * A field initialized with the result of a static method call. */
static class MethodInitializer extends NewInitializer { String methodName; // the method class is specified by objectType. MethodInitializer() {}
Produces codes in which a new object is created and assigned to the field as the initial value.
/** * Produces codes in which a new object is created and assigned to * the field as the initial value. */
@Override int compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv) throws CannotCompileException { int stacksize; code.addAload(0); code.addAload(0); if (stringParams == null) stacksize = 2; else stacksize = compileStringParameter(code) + 2; if (withConstructorParams) stacksize += CtNewWrappedMethod.compileParameterList(code, parameters, 1); String typeDesc = Descriptor.of(type); String mDesc = getDescriptor() + typeDesc; code.addInvokestatic(objectType, methodName, mDesc); code.addPutfield(Bytecode.THIS, name, typeDesc); return stacksize; } private String getDescriptor() { final String desc3 = "(Ljava/lang/Object;[Ljava/lang/String;[Ljava/lang/Object;)"; if (stringParams == null) if (withConstructorParams) return "(Ljava/lang/Object;[Ljava/lang/Object;)"; else return "(Ljava/lang/Object;)"; if (withConstructorParams) return desc3; return "(Ljava/lang/Object;[Ljava/lang/String;)"; }
Produces codes for a static field.
/** * Produces codes for a static field. */
@Override int compileIfStatic(CtClass type, String name, Bytecode code, Javac drv) throws CannotCompileException { String desc; int stacksize = 1; if (stringParams == null) desc = "()"; else { desc = "([Ljava/lang/String;)"; stacksize += compileStringParameter(code); } String typeDesc = Descriptor.of(type); code.addInvokestatic(objectType, methodName, desc + typeDesc); code.addPutstatic(Bytecode.THIS, name, typeDesc); return stacksize; } } static class IntInitializer extends Initializer { int value; IntInitializer(int v) { value = v; } @Override void check(String desc) throws CannotCompileException { char c = desc.charAt(0); if (c != 'I' && c != 'S' && c != 'B' && c != 'C' && c != 'Z') throw new CannotCompileException("type mismatch"); } @Override int compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv) throws CannotCompileException { code.addAload(0); code.addIconst(value); code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); return 2; // stack size } @Override int compileIfStatic(CtClass type, String name, Bytecode code, Javac drv) throws CannotCompileException { code.addIconst(value); code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); return 1; // stack size } @Override int getConstantValue(ConstPool cp, CtClass type) { return cp.addIntegerInfo(value); } } static class LongInitializer extends Initializer { long value; LongInitializer(long v) { value = v; } @Override void check(String desc) throws CannotCompileException { if (!desc.equals("J")) throw new CannotCompileException("type mismatch"); } @Override int compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv) throws CannotCompileException { code.addAload(0); code.addLdc2w(value); code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); return 3; // stack size } @Override int compileIfStatic(CtClass type, String name, Bytecode code, Javac drv) throws CannotCompileException { code.addLdc2w(value); code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); return 2; // stack size } @Override int getConstantValue(ConstPool cp, CtClass type) { if (type == CtClass.longType) return cp.addLongInfo(value); return 0; } } static class FloatInitializer extends Initializer { float value; FloatInitializer(float v) { value = v; } @Override void check(String desc) throws CannotCompileException { if (!desc.equals("F")) throw new CannotCompileException("type mismatch"); } @Override int compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv) throws CannotCompileException { code.addAload(0); code.addFconst(value); code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); return 3; // stack size } @Override int compileIfStatic(CtClass type, String name, Bytecode code, Javac drv) throws CannotCompileException { code.addFconst(value); code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); return 2; // stack size } @Override int getConstantValue(ConstPool cp, CtClass type) { if (type == CtClass.floatType) return cp.addFloatInfo(value); return 0; } } static class DoubleInitializer extends Initializer { double value; DoubleInitializer(double v) { value = v; } @Override void check(String desc) throws CannotCompileException { if (!desc.equals("D")) throw new CannotCompileException("type mismatch"); } @Override int compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv) throws CannotCompileException { code.addAload(0); code.addLdc2w(value); code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); return 3; // stack size } @Override int compileIfStatic(CtClass type, String name, Bytecode code, Javac drv) throws CannotCompileException { code.addLdc2w(value); code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); return 2; // stack size } @Override int getConstantValue(ConstPool cp, CtClass type) { if (type == CtClass.doubleType) return cp.addDoubleInfo(value); return 0; } } static class StringInitializer extends Initializer { String value; StringInitializer(String v) { value = v; } @Override int compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv) throws CannotCompileException { code.addAload(0); code.addLdc(value); code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); return 2; // stack size } @Override int compileIfStatic(CtClass type, String name, Bytecode code, Javac drv) throws CannotCompileException { code.addLdc(value); code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); return 1; // stack size } @Override int getConstantValue(ConstPool cp, CtClass type) { if (type.getName().equals(javaLangString)) return cp.addStringInfo(value); return 0; } } static class ArrayInitializer extends Initializer { CtClass type; int size; ArrayInitializer(CtClass t, int s) { type = t; size = s; } private void addNewarray(Bytecode code) { if (type.isPrimitive()) code.addNewarray(((CtPrimitiveType)type).getArrayType(), size); else code.addAnewarray(type, size); } @Override int compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv) throws CannotCompileException { code.addAload(0); addNewarray(code); code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); return 2; // stack size } @Override int compileIfStatic(CtClass type, String name, Bytecode code, Javac drv) throws CannotCompileException { addNewarray(code); code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); return 1; // stack size } } static class MultiArrayInitializer extends Initializer { CtClass type; int[] dim; MultiArrayInitializer(CtClass t, int[] d) { type = t; dim = d; } @Override void check(String desc) throws CannotCompileException { if (desc.charAt(0) != '[') throw new CannotCompileException("type mismatch"); } @Override int compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv) throws CannotCompileException { code.addAload(0); int s = code.addMultiNewarray(type, dim); code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); return s + 1; // stack size } @Override int compileIfStatic(CtClass type, String name, Bytecode code, Javac drv) throws CannotCompileException { int s = code.addMultiNewarray(type, dim); code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); return s; // stack size } } }