Classworking 工具箱: 分析泛型数据结构
2010-03-18 00:00:00 来源:WEB开发网TypeDescription 类只是个抽象基类,其中定义了处理三种类型的方法:原生类型、数组和类实例。这个基类以类型描述符的形式包含了一个值。我用于这个类的类型描述符大致符合 JVM 规范定义的类型描述符的形式,但是有些扩展,添加了泛型具体 “版本” 的实际参数类型列表。这个扩展允许把 Ljava/util/Map<Ljava/lang/String;Ljava/lang/String;>; 这种形式的描述符作为类型系统的一部分。
组织数据结构
组织数据结构信息的问题比表示信息的问题略微复杂一些。组织信息的基本问题在于数据结构经常是递归的:一个类中可能有一个字段,这个字段引用这个类的一个实例,或者它引用的一个类可能直接或间接地引用回到原来的类。所以,只想直接展开结构,可能会形成无限的递归循环。
我使用目录技术来处理这种递归引用。在找到类引用时,检查目标,查看这个类以前是否已经看到过。如果是,那么目录就返回现有的描述。如果没有,则目录创建新的描述实例,并立即把描述添加到目录(甚至在描述的完整细节可用之前就添加)。清单 2 显示了这个 TypeDirectory 类的基本代码,现在暂时不管它,以后会添加处理泛型的一些细节:
清单 2. TypeDirectory 类
public class TypeDirectory
{
/** Source for binary class representations. */
private final BinaryClassLoader m_loader;
/** Field list for all arrays. */
private final FieldDescription[] m_arrayFields;
/** Map from descriptor or signature to type for all non-generic types,
* including generics with substitutions. */
private HashMap<String,TypeDescription> m_typeMap =
new HashMap<String,TypeDescription>();
...
/**
* Constructor. Initializes the type directory with descriptions of
* primitive types.
*
* @param loader binary class loader
*/
public TypeDirectory(BinaryClassLoader loader) {
m_loader = loader;
addType(new PrimitiveTypeDescription("B", "byte"));
addType(new PrimitiveTypeDescription("C", "char"));
addType(new PrimitiveTypeDescription("D", "double"));
addType(new PrimitiveTypeDescription("F", "float"));
TypeDescription inttype = new PrimitiveTypeDescription("I", "int");
addType(inttype);
addType(new PrimitiveTypeDescription("J", "long"));
addType(new PrimitiveTypeDescription("S", "short"));
addType(new PrimitiveTypeDescription("V", "void"));
addType(new PrimitiveTypeDescription("Z", "boolean"));
m_arrayFields = new FieldDescription[] {
new FieldDescription("int", null, inttype)
};
}
/**
* Add type description to type directory.
*
* @param desc type description to add
*/
public void addType(TypeDescription desc) {
m_typeMap.put(desc.getDescriptor(), desc);
}
/**
* Add generic class to template directory.
*
* @param tmpl generic template to add
*/
public void addTemplate(GenericTemplate tmpl) {
m_templateMap.put(tmpl.getDescriptor(), tmpl);
}
/**
* Get description for the type. The type may be a primitive, an array, or a
* class. If the type is a generic class, it will be treated as though all
* type variables used their lower bounds.
*
* @param dtor type descriptor
* @return type description
*/
public TypeDescription getTypeInstance(String dtor) {
// check for an existing description
TypeDescription desc = m_typeMap.get(dtor);
if (desc == null) {
// new description needed - must be array or class
if (dtor.charAt(0) == '[') {
desc = new ArrayClassDescriptor(dtor,
getTypeInstance(dtor.substring(1)));
} else {
// parse binary class to build description
byte[] byts = m_loader.getBytes(dtor);
desc = new SimpleClassDescription(dtor, byts, this);
}
}
return desc;
}
/**
* Get description for generic class with specific type substitutions.
*
* @param sig field signature with type substitutions
* @param types actual types used for instance (values may be
* <code>null</code> if no substitution defined)
* @return type description
*/
public TypeDescription getSignatureInstance(String sig,
TypeDescription[] types) {
// first check for direct match on substituted signature
TypeDescription desc = (TypeDescription)m_typeMap.get(sig);
if (desc == null) {
// no direct match, first handle array
if (sig.charAt(0) == '[') {
desc = new ArrayClassDescriptor(sig,
getSignatureInstance(sig.substring(1), types));
} else {
...
}
}
return desc;
}
/**
* Get description for signature with type mapping.
*
* @param sig field signature for type variables
* @param tmap type mapping for variables
* @return type description
*/
public TypeDescription getMappedSignatureInstance(String sig,
HashMap<String,TypeDescription> tmap) {
...
}
...
/**
* Descriptor for primitive "class." There's really nothing to record for a
* primitive type except the name, so that's all this does. Because instances
* only need to be created and added to the directory at initialization, this
* is an inner class.
*/
private static class PrimitiveTypeDescription extends TypeDescription
{
private final String m_externalName;
private PrimitiveTypeDescription(String iname, String xname) {
super(iname);
m_externalName = xname;
}
public boolean isPrimitive() {
return true;
}
public String toString() {
return m_externalName;
}
}
/**
* Descriptor for array class. This is just a wrapper around the descriptor
* for the item type, with the same field list used for all arrays.
*/
private class ArrayClassDescriptor extends TypeDescription
{
private final TypeDescription m_itemType;
protected ArrayClassDescriptor(String name, TypeDescription item) {
super(name);
m_itemType = item;
}
public boolean isArray() {
return true;
}
public TypeDescription getArrayItemType() {
return m_itemType;
}
public FieldDescription[] getFields() {
return m_arrayFields;
}
public String toString() {
return m_itemType + "[]";
}
}
}
Tags:Classworking 工具箱 分析
编辑录入:爽爽 [复制链接] [打 印]更多精彩
赞助商链接