Browse Source

implemented JASSIST-170

git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@639 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
tags/rel_3_17_1_ga
chiba 12 years ago
parent
commit
e2cfbeaed7

+ 1
- 1
Readme.html View File

@@ -284,7 +284,7 @@ see javassist.Dump.
<p>-version 3.17
<ul>
<li>OSGi bundle info is now included in the jar file.
<li>JIRA JASSIST-166, 168 have been fixed.
<li>JIRA JASSIST-166, 168, 170 have been fixed.
</ul>

<p>-version 3.16.1 on March 6, 2012

+ 30
- 6
src/main/javassist/CtBehavior.java View File

@@ -314,19 +314,43 @@ public abstract class CtBehavior extends CtMember {
*
* <p>Note that the returned string is not the type signature
* contained in the <code>SignatureAttirbute</code>. It is
* a descriptor. To obtain a type signature, call the following
* methods:
*
* <ul><pre>getMethodInfo().getAttribute(SignatureAttribute.tag)
* </pre></ul>
* a descriptor.
*
* @see javassist.bytecode.Descriptor
* @see javassist.bytecode.SignatureAttribute
* @see #getGenericSignature()
*/
public String getSignature() {
return methodInfo.getDescriptor();
}

/**
* Returns the generic signature of the method.
* It represents parameter types including type variables.
*
* @see SignatureAttribute#toMethodSignature(String)
* @since 3.17
*/
public String getGenericSignature() {
SignatureAttribute sa
= (SignatureAttribute)methodInfo.getAttribute(SignatureAttribute.tag);
return sa == null ? null : sa.getSignature();
}

/**
* Set the generic signature of the method.
* It represents parameter types including type variables.
* See {@link javassist.CtClass#setGenericSignature(String)}
* for a code sample.
*
* @param sig a new generic signature.
* @see javassist.bytecode.SignatureAttribute.MethodSignature#encode()
* @since 3.17
*/
public void setGenericSignature(String sig) {
declaringClass.checkModify();
methodInfo.addAttribute(new SignatureAttribute(methodInfo.getConstPool(), sig));
}

/**
* Obtains exceptions that this method/constructor may throw.
*

+ 84
- 0
src/main/javassist/CtClass.java View File

@@ -29,6 +29,7 @@ import java.util.Collection;
import javassist.bytecode.ClassFile;
import javassist.bytecode.Descriptor;
import javassist.bytecode.Opcode;
import javassist.bytecode.SignatureAttribute;
import javassist.expr.ExprEditor;

/* Note:
@@ -387,6 +388,89 @@ public abstract class CtClass {
qualifiedName = name;
}

/**
* Returns the generic signature of the class.
*
* <p>The generics of Java is implemented by the erasure technique.
* After compilation, all type parameters are dropped off from the
* main part of a class file. However, for reflection, the type
* parameters are encoded into generic signatures and attached
* to a class file.
*
* @return null if the generic signature is not included.
* @see javassist.bytecode.SignatureAttribute#toClassSignature(String)
* @see CtMember#getGenericSignature()
* @since 3.17
*/
public String getGenericSignature() { return null; }

/**
* Sets the generic signature of the class.
*
* <p>The generics of Java is implemented by the erasure technique.
* After compilation, all type parameters are dropped off from the
* main part of a class file. However, for reflection, the type
* parameters must be encoded into generic signatures and attached
* to a class file.
*
* <p>For example,
*
* <pre>class List<T> {
* T value;
* T get() { return value; }
* void set(T v) { value = v; }
* }
* </pre>
*
* <p>this class is generated by the following code:
*
* <pre>
* ClassPool pool = ClassPool.getDefault();
* CtClass cc = pool.makeClass("List");
* CtClass objectClass = pool.get(CtClass.javaLangObject);
* ClassSignature cs = new ClassSignature(
* new TypeParameter[] { new TypeParameter("T") });
* cc.setGenericSignature(cs.encode()); // &lt;T:Ljava/lang/Object;&gt;Ljava/lang/Object;
*
* CtField f = new CtField(objClass, "value", cc);
* TypeVariable tvar = new TypeVariable("T");
* f.setGenericSignature(tvar.encode()); // TT;
* cc.addField(f);
*
* CtMethod m = CtNewMethod.make("public Object get(){return value;}", cc);
* MethodSignature ms = new MethodSignature(null, null, tvar, null);
* m.setGenericSignature(ms.encode()); // ()TT;
* cc.addMethod(m);
*
* CtMethod m2 = CtNewMethod.make("public void set(Object v){value = v;}", cc);
* MethodSignature ms2 = new MethodSignature(null, new Type[] { tvar },
* new BaseType("void"), null);
* m2.setGenericSignature(ms2.encode()); // (TT;)V;
* cc.addMethod(m2);
*
* cc.writeFile();
* </pre>
*
* <p>The generated class file is equivalent to the following:
*
* <pre>class List {
* Object value;
* Object get() { return value; }
* void set(Object v) { value = v; }
* }</pre>
*
* <p>but it includes generic signatures for the class, the field,
* and the methods so that the type variable <code>T</code> can be
* accessible through reflection.
*
* @param sig a generic signature.
* @see javassist.bytecode.SignatureAttribute.ClassSignature#encode()
* @see javassist.bytecode.SignatureAttribute.MethodSignature#encode()
* @see CtMember#setGenericSignature(String)
* @since 3.17
*/
public void setGenericSignature(String sig) { checkModify(); }

/**
* Substitutes <code>newName</code> for all occurrences of a class
* name <code>oldName</code> in the class file.

+ 13
- 0
src/main/javassist/CtClassType.java View File

@@ -47,6 +47,7 @@ import javassist.bytecode.FieldInfo;
import javassist.bytecode.InnerClassesAttribute;
import javassist.bytecode.MethodInfo;
import javassist.bytecode.ParameterAnnotationsAttribute;
import javassist.bytecode.SignatureAttribute;
import javassist.bytecode.annotation.Annotation;
import javassist.compiler.AccessorMaker;
import javassist.compiler.CompileError;
@@ -336,6 +337,18 @@ class CtClassType extends CtClass {
classPool.classNameChanged(oldname, this);
}

public String getGenericSignature() {
SignatureAttribute sa
= (SignatureAttribute)getClassFile2().getAttribute(SignatureAttribute.tag);
return sa == null ? null : sa.getSignature();
}

public void setGenericSignature(String sig) {
ClassFile cf = getClassFile();
SignatureAttribute sa = new SignatureAttribute(cf.getConstPool(), sig);
cf.addAttribute(sa);
}

public void replaceClassName(ClassMap classnames)
throws RuntimeException
{

+ 30
- 6
src/main/javassist/CtField.java View File

@@ -327,19 +327,43 @@ public class CtField extends CtMember {
*
* <p>Note that the returned string is not the type signature
* contained in the <code>SignatureAttirbute</code>. It is
* a descriptor. To obtain a type signature, call the following
* methods:
*
* <ul><pre>getFieldInfo().getAttribute(SignatureAttribute.tag)
* </pre></ul>
* a descriptor.
*
* @see javassist.bytecode.Descriptor
* @see javassist.bytecode.SignatureAttribute
* @see #getGenericSignature()
*/
public String getSignature() {
return fieldInfo.getDescriptor();
}

/**
* Returns the generic signature of the field.
* It represents a type including type variables.
*
* @see SignatureAttribute#toFieldSignature(String)
* @since 3.17
*/
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 {@link javassist.CtClass#setGenericSignature(String)}
* for a code sample.
*
* @param sig a new generic signature.
* @see javassist.bytecode.SignatureAttribute.ObjectType#encode()
* @since 3.17
*/
public void setGenericSignature(String sig) {
declaringClass.checkModify();
fieldInfo.addAttribute(new SignatureAttribute(fieldInfo.getConstPool(), sig));
}

/**
* Returns the type of the field.
*/

+ 23
- 0
src/main/javassist/CtMember.java View File

@@ -42,6 +42,8 @@ public abstract class CtMember {
public String getSignature() { return null; }
public void setAttribute(String name, byte[] data) {}
public void setModifiers(int mod) {}
public String getGenericSignature() { return null; }
public void setGenericSignature(String sig) {}

private CtMember methodTail;
private CtMember consTail; // constructor tail
@@ -269,6 +271,27 @@ public abstract class CtMember {
*/
public abstract String getSignature();

/**
* Returns the generic signature of the member.
*
* @see javassist.bytecode.SignatureAttribute#toFieldSignature(String)
* @see javassist.bytecode.SignatureAttribute#toMethodSignature(String)
* @see CtClass#getGenericSignature()
* @since 3.17
*/
public abstract String getGenericSignature();

/**
* Sets the generic signature of the member.
*
* @param sig a new generic signature.
* @see javassist.bytecode.SignatureAttribute.ObjectType#encode()
* @see javassist.bytecode.SignatureAttribute.MethodSignature#encode()
* @see CtClass#setGenericSignature(String)
* @since 3.17
*/
public abstract void setGenericSignature(String sig);

/**
* Obtains a user-defined attribute with the given name.
* If that attribute is not found in the class file, this

+ 297
- 18
src/main/javassist/bytecode/SignatureAttribute.java View File

@@ -38,7 +38,7 @@ public class SignatureAttribute extends AttributeInfo {
}

/**
* Constructs a Signature attribute.
* Constructs a <code>Signature</code> attribute.
*
* @param cp a constant pool table.
* @param signature the signature represented by this attribute.
@@ -53,17 +53,18 @@ public class SignatureAttribute extends AttributeInfo {
}

/**
* Returns the signature indicated by <code>signature_index</code>.
* Returns the generic signature indicated by <code>signature_index</code>.
*
* @see #toClassSignature(String)
* @see #toMethodSignature(String)
* @see #toFieldSignature(String)
*/
public String getSignature() {
return getConstPool().getUtf8Info(ByteArray.readU16bit(get(), 0));
}

/**
* Sets <code>signature_index</code> to the index of the given signature,
* Sets <code>signature_index</code> to the index of the given generic signature,
* which is added to a constant pool.
*
* @param sig new signature.
@@ -177,10 +178,27 @@ public class SignatureAttribute extends AttributeInfo {
TypeParameter[] params;
ClassType superClass;
ClassType[] interfaces;
ClassSignature(TypeParameter[] p, ClassType s, ClassType[] i) {
params = p;
superClass = s;
interfaces = i;

/**
* Constructs a class signature.
*
* @param p type parameters.
* @param s the super class.
* @param i the interface types.
*/
public ClassSignature(TypeParameter[] p, ClassType s, ClassType[] i) {
params = p == null ? new TypeParameter[0] : p;
superClass = s == null ? ClassType.OBJECT : s;
interfaces = i == null ? new ClassType[0] : i;
}

/**
* Constructs a class signature.
*
* @param p type parameters.
*/
public ClassSignature(TypeParameter[] p) {
this(p, null, null);
}

/**
@@ -219,6 +237,26 @@ public class SignatureAttribute extends AttributeInfo {

return sbuf.toString();
}

/**
* Returns the encoded string representing the method type signature.
*/
public String encode() {
StringBuffer sbuf = new StringBuffer();
if (params.length > 0) {
sbuf.append('<');
for (int i = 0; i < params.length; i++)
params[i].encode(sbuf);

sbuf.append('>');
}

superClass.encode(sbuf);
for (int i = 0; i < interfaces.length; i++)
interfaces[i].encode(sbuf);

return sbuf.toString();
}
}

/**
@@ -230,11 +268,20 @@ public class SignatureAttribute extends AttributeInfo {
Type retType;
ObjectType[] exceptions;

MethodSignature(TypeParameter[] tp, Type[] p, Type ret, ObjectType[] ex) {
typeParams = tp;
params = p;
retType = ret;
exceptions = ex;
/**
* Constructs a method type signature. Any parameter can be null
* to represent <code>void</code> or nothing.
*
* @param tp type parameters.
* @param p parameter types.
* @param ret a return type.
* @param ex exception types.
*/
public MethodSignature(TypeParameter[] tp, Type[] p, Type ret, ObjectType[] ex) {
typeParams = tp == null ? new TypeParameter[0] : tp;
params = p == null ? new Type[0] : p;
retType = ret == null ? new BaseType("void") : ret;
exceptions = ex == null ? new ObjectType[0] : ex;
}

/**
@@ -282,10 +329,40 @@ public class SignatureAttribute extends AttributeInfo {

return sbuf.toString();
}

/**
* Returns the encoded string representing the method type signature.
*/
public String encode() {
StringBuffer sbuf = new StringBuffer();
if (typeParams.length > 0) {
sbuf.append('<');
for (int i = 0; i < typeParams.length; i++)
typeParams[i].encode(sbuf);

sbuf.append('>');
}

sbuf.append('(');
for (int i = 0; i < params.length; i++)
params[i].encode(sbuf);

sbuf.append(')');
retType.encode(sbuf);
if (exceptions.length > 0)
for (int i = 0; i < exceptions.length; i++) {
sbuf.append('^');
exceptions[i].encode(sbuf);
}

return sbuf.toString();
}
}

/**
* Formal type parameters.
*
* @see TypeArgument
*/
public static class TypeParameter {
String name;
@@ -298,6 +375,33 @@ public class SignatureAttribute extends AttributeInfo {
superInterfaces = si;
}

/**
* Constructs a <code>TypeParameter</code> representing a type parametre
* like <code>&lt;T extends ... &gt;<code>.
*
* @param name parameter name.
* @param superClass an upper bound class-type (or null).
* @param superInterfaces an upper bound interface-type (or null).
*/
public TypeParameter(String name, ObjectType superClass, ObjectType[] superInterfaces) {
this.name = name;
this.superClass = superClass;
if (superInterfaces == null)
this.superInterfaces = new ObjectType[0];
else
this.superInterfaces = superInterfaces;
}

/**
* Constructs a <code>TypeParameter</code> representing a type parameter
* like <code>&lt;T&gt;<code>.
*
* @param name parameter name.
*/
public TypeParameter(String name) {
this(name, null, null);
}

/**
* Returns the name of the type parameter.
*/
@@ -307,8 +411,6 @@ public class SignatureAttribute extends AttributeInfo {

/**
* Returns the class bound of this parameter.
*
* @return null if the class bound is not specified.
*/
public ObjectType getClassBound() { return superClass; }

@@ -353,10 +455,27 @@ public class SignatureAttribute extends AttributeInfo {

sbuf.append('>');
}

void encode(StringBuffer sb) {
sb.append(name);
if (superClass == null)
sb.append(":Ljava/lang/Object;");
else {
sb.append(':');
superClass.encode(sb);
}

for (int i = 0; i < superInterfaces.length; i++) {
sb.append(':');
superInterfaces[i].encode(sb);
}
}
}

/**
* Type argument.
*
* @see TypeParameter
*/
public static class TypeArgument {
ObjectType arg;
@@ -367,6 +486,44 @@ public class SignatureAttribute extends AttributeInfo {
wildcard = w;
}

/**
* Constructs a <code>TypeArgument</code>.
* A type argument is <code>&lt;String&gt;</code>, <code>&lt;int[]&gt;</code>,
* or a type variable <code>&lt;T&gt;</code>, etc.
*
* @param t a class type, an array type, or a type variable.
*/
public TypeArgument(ObjectType t) {
this(t, ' ');
}

/**
* Constructs a <code>TypeArgument</code> representing <code>&lt;?&gt;</code>.
*/
public TypeArgument() {
this(null, '*');
}

/**
* A factory method constructing a <code>TypeArgument</code> with an upper bound.
* It represents <code>&lt;? extends ... &gt;</code>
*
* @param t an upper bound type.
*/
public static TypeArgument subclassOf(ObjectType t) {
return new TypeArgument(t, '+');
}

/**
* A factory method constructing a <code>TypeArgument</code> with an lower bound.
* It represents <code>&lt;? super ... &gt;</code>
*
* @param t an lower bbound type.
*/
public static TypeArgument superOf(ObjectType t) {
return new TypeArgument(t, '-');
}

/**
* Returns the kind of this type argument.
*
@@ -405,12 +562,27 @@ public class SignatureAttribute extends AttributeInfo {
else
return "? super " + type;
}

static void encode(StringBuffer sb, TypeArgument[] args) {
sb.append('<');
for (int i = 0; i < args.length; i++) {
TypeArgument ta = args[i];
if (ta.isWildcard())
sb.append(ta.wildcard);

if (ta.getType() != null)
ta.getType().encode(sb);
}

sb.append('>');
}
}

/**
* Primitive types and object types.
*/
public static abstract class Type {
abstract void encode(StringBuffer sb);
static void toString(StringBuffer sbuf, Type[] ts) {
for (int i = 0; i < ts.length; i++) {
if (i > 0)
@@ -428,6 +600,15 @@ public class SignatureAttribute extends AttributeInfo {
char descriptor;
BaseType(char c) { descriptor = c; }

/**
* Constructs a <code>BaseType</code>.
*
* @param typeName <code>void</code>, <code>int</code>, ...
*/
public BaseType(String typeName) {
this(Descriptor.of(typeName).charAt(0));
}

/**
* Returns the descriptor representing this primitive type.
*
@@ -449,12 +630,26 @@ public class SignatureAttribute extends AttributeInfo {
public String toString() {
return Descriptor.toClassName(Character.toString(descriptor));
}

void encode(StringBuffer sb) {
sb.append(descriptor);
}
}

/**
* Class types, array types, and type variables.
* This class is also used for representing a field type.
*/
public static abstract class ObjectType extends Type {}
public static abstract class ObjectType extends Type {
/**
* Returns the encoded string representing the object type signature.
*/
public String encode() {
StringBuffer sb = new StringBuffer();
encode(sb);
return sb.toString();
}
}

/**
* Class types.
@@ -476,6 +671,23 @@ public class SignatureAttribute extends AttributeInfo {
arguments = targs;
}

/**
* A class type representing <code>java.lang.Object</code>.
*/
public static ClassType OBJECT = new ClassType("java.lang.Object", null);

/**
* Constructs a <code>ClassType</code>. It represents
* the name of a non-nested class.
*
* @param className a fully qualified class name.
* @param args type arguments or null.
*/
public ClassType(String className, TypeArgument[] args) {
name = className;
arguments = args;
}

/**
* Returns the class name.
*/
@@ -523,6 +735,24 @@ public class SignatureAttribute extends AttributeInfo {

return sbuf.toString();
}

void encode(StringBuffer sb) {
sb.append('L');
encode2(sb);
sb.append(';');
}

void encode2(StringBuffer sb) {
ClassType parent = getDeclaringClass();
if (parent != null) {
parent.encode2(sb);
sb.append('$');
}

sb.append(name.replace('.', '/'));
if (arguments != null)
TypeArgument.encode(sb, arguments);
}
}

/**
@@ -536,6 +766,19 @@ public class SignatureAttribute extends AttributeInfo {
parent = p;
}

/**
* Constructs a <code>NestedClassType</code>.
*
* @param parent the class surrounding this class type.
* @param className a simple class name. It does not include
* a package name or a parent's class name.
* @param args type parameters or null.
*/
public NestedClassType(ClassType parent, String className, TypeArgument[] args) {
super(className, args);
this.parent = parent;
}

/**
* Returns the class that declares this nested class.
* This nested class is a member of that declaring class.
@@ -550,6 +793,12 @@ public class SignatureAttribute extends AttributeInfo {
int dim;
Type componentType;

/**
* Constructs an <code>ArrayType</code>.
*
* @param d dimension.
* @param comp the component type.
*/
public ArrayType(int d, Type comp) {
dim = d;
componentType = comp;
@@ -577,6 +826,13 @@ public class SignatureAttribute extends AttributeInfo {

return sbuf.toString();
}

void encode(StringBuffer sb) {
for (int i = 0; i < dim; i++)
sb.append('[');

componentType.encode(sb);
}
}

/**
@@ -589,6 +845,15 @@ public class SignatureAttribute extends AttributeInfo {
name = sig.substring(begin, end);
}

/**
* Constructs a <code>TypeVariable</code>.
*
* @param name the name of a type variable.
*/
public TypeVariable(String name) {
this.name = name;
}

/**
* Returns the variable name.
*/
@@ -602,13 +867,21 @@ public class SignatureAttribute extends AttributeInfo {
public String toString() {
return name;
}

void encode(StringBuffer sb) {
sb.append('T').append(name).append(';');
}
}

/**
* Parses the given signature string as a class signature.
*
* @param sig the signature.
* @param sig the signature obtained from the <code>SignatureAttribute</code>
* of a <code>ClassFile</code>.
* @return a tree-like data structure representing a class signature. It provides
* convenient accessor methods.
* @throws BadBytecode thrown when a syntactical error is found.
* @see #getSignature()
* @since 3.5
*/
public static ClassSignature toClassSignature(String sig) throws BadBytecode {
@@ -623,8 +896,12 @@ public class SignatureAttribute extends AttributeInfo {
/**
* Parses the given signature string as a method type signature.
*
* @param sig the signature.
* @param sig the signature obtained from the <code>SignatureAttribute</code>
* of a <code>MethodInfo</code>.
* @return @return a tree-like data structure representing a method signature. It provides
* convenient accessor methods.
* @throws BadBytecode thrown when a syntactical error is found.
* @see #getSignature()
* @since 3.5
*/
public static MethodSignature toMethodSignature(String sig) throws BadBytecode {
@@ -639,9 +916,11 @@ public class SignatureAttribute extends AttributeInfo {
/**
* Parses the given signature string as a field type signature.
*
* @param sig the signature string.
* @param sig the signature string obtained from the <code>SignatureAttribute</code>
* of a <code>FieldInfo</code>.
* @return the field type signature.
* @throws BadBytecode thrown when a syntactical error is found.
* @see #getSignature()
* @since 3.5
*/
public static ObjectType toFieldSignature(String sig) throws BadBytecode {

+ 38
- 0
src/test/javassist/JvstTest4.java View File

@@ -724,4 +724,42 @@ public class JvstTest4 extends JvstTestRoot {
Object obj = make(cc.getName());
assertEquals(1, invoke(obj, "run"));
}

public void testGenericSignature() throws Exception {
CtClass cc = sloader.makeClass("test4.GenSig");
CtClass objClass = sloader.get(CtClass.javaLangObject);
SignatureAttribute.ClassSignature cs
= new SignatureAttribute.ClassSignature(
new SignatureAttribute.TypeParameter[] {
new SignatureAttribute.TypeParameter("T") });
cc.setGenericSignature(cs.encode()); // <T:Ljava/lang/Object;>Ljava/lang/Object;

CtField f = new CtField(objClass, "value", cc);
SignatureAttribute.TypeVariable tvar = new SignatureAttribute.TypeVariable("T");
f.setGenericSignature(tvar.encode()); // TT;
cc.addField(f);

CtMethod m = CtNewMethod.make("public Object get(){return value;}", cc);
SignatureAttribute.MethodSignature ms
= new SignatureAttribute.MethodSignature(null, null, tvar, null);
m.setGenericSignature(ms.encode()); // ()TT;
cc.addMethod(m);

CtMethod m2 = CtNewMethod.make("public void set(Object v){value = v;}", cc);
SignatureAttribute.MethodSignature ms2
= new SignatureAttribute.MethodSignature(null, new SignatureAttribute.Type[] { tvar },
new SignatureAttribute.BaseType("void"), null);
m2.setGenericSignature(ms2.encode()); // (TT;)V;
cc.addMethod(m2);

cc.writeFile();
Object obj = make(cc.getName());
Class clazz = obj.getClass();
assertEquals("T", clazz.getTypeParameters()[0].getName());
assertEquals("T", ((java.lang.reflect.TypeVariable)clazz.getDeclaredField("value").getGenericType()).getName());
java.lang.reflect.Method rm = clazz.getDeclaredMethod("get", new Class[0]);
assertEquals("T", ((java.lang.reflect.TypeVariable)rm.getGenericReturnType()).getName());
java.lang.reflect.Method rm2 = clazz.getDeclaredMethod("set", new Class[] { Object.class });
assertEquals("T", ((java.lang.reflect.TypeVariable)rm2.getGenericParameterTypes()[0]).getName());
}
}

+ 2
- 1
tutorial/tutorial.html View File

@@ -26,7 +26,8 @@ Shigeru Chiba
<br>6. <a href="tutorial3.html#generics">Generics</a>
<br>7. <a href="tutorial3.html#varargs">Varargs</a>
<br>8. <a href="tutorial3.html#j2me">J2ME</a>
<br>9. <a href="tutorial3.html#debug">Debug</a>
<br>9. <a href="tutorial3.html#boxing">Boxing/Unboxing</a>
<br>10. <a href="tutorial3.html#debug">Debug</a>
</ul>

<p><br>

+ 28
- 2
tutorial/tutorial3.html View File

@@ -28,7 +28,9 @@

<p><a href="#j2me">8. J2ME</a>

<p><a href="#debug">9. Debug</a>
<p><a href="#boxing">9. Boxing/Unboxing

<p><a href="#debug">10. Debug</a>

<p><br>

@@ -296,6 +298,11 @@ public Object get() { return value; }

<p>Note that no type parameters are necessary.

<p>However, if you need to make type parameters accessible through reflection
during runtime, you have to add generic signatures to the class file.
For more details, see the API documentation (javadoc) of the
<code>setGenericSignature</code> method in the <code>CtClass</code>.

<p><br>

<h2><a name="varargs">7. Varargs</a></h2>
@@ -359,7 +366,26 @@ objects, call the <code>getDeclaredMethods</code> method on a <code>CtClass</cod

<p><br>

<h2><a name="debug">9. Debug</h2>
<h2><a name="boxing">9. Boxing/Unboxing</h2>

<p>Boxing and unboxing in Java are syntactic sugar. There is no bytecode for
boxing or unboxing. So the compiler of Javassist does not support them.
For example, the following statement is valid in Java:

<ul><pre>
Integer i = 3;
</pre></ul>

<p>since boxing is implicitly performed. For Javassist, however, you must explicitly
convert a value type from <code>int</code> to <code>Integer</code>:

<ul><pre>
Integer i = new Integer(3);
</pre></ul>

<p><br>

<h2><a name="debug">10. Debug</h2>

<p>Set <code>CtClass.debugDump</code> to a directory name.
Then all class files modified and generated by Javassist are saved in that

Loading…
Cancel
Save