alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (Type.java)

This example Java source code file (Type.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

compilererror, identifier, string, tc_array, tc_boolean, tc_byte, tc_char, tc_double, tc_error, tc_float, tc_int, tc_long, tc_short, type, util

The Type.java Java example source code

/*
 * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.tools.java;

import java.util.Hashtable;

/**
 * This class represents an Java Type.<p>
 *
 * It encapsulates an Java type signature and it provides
 * quick access to the components of the type. Note that
 * all types are hashed into a hashtable (typeHash), that
 * means that each distinct type is only allocated once,
 * saving space and making equality checks cheap.<p>
 *
 * For simple types use the constants defined in this class.
 * (Type.tInt, Type.tShort, ...). To create complex types use
 * the static methods Type.tArray, Type.tMethod or Type.tClass.
 *
 * For classes, arrays and method types a sub class of class
 * type is created which defines the extra type components.
 *
 * WARNING: The contents of this source file are not part of any
 * supported API.  Code that depends on them does so at its own risk:
 * they are subject to change or removal without notice.
 *
 * @see         ArrayType
 * @see         ClassType
 * @see         MethodType
 * @author      Arthur van Hoff
 */
public
class Type implements Constants {
    /**
     * This hashtable is used to cache types
     */
    private static final Hashtable typeHash = new Hashtable(231);

    /**
     * The TypeCode of this type. The value of this field is one
     * of the TC_* contant values defined in Constants.
     * @see Constants
     */
    protected int typeCode;

    /**
     * The TypeSignature of this type. This type signature is
     * equivalent to the runtime type signatures used by the
     * interpreter.
     */
    protected String typeSig;

    /*
     * Predefined types.
     */
    public static final Type noArgs[]   = new Type[0];
    public static final Type tError     = new Type(TC_ERROR,    "?");
    public static final Type tPackage   = new Type(TC_ERROR,    ".");
    public static final Type tNull      = new Type(TC_NULL,     "*");
    public static final Type tVoid      = new Type(TC_VOID,     SIG_VOID);
    public static final Type tBoolean   = new Type(TC_BOOLEAN,  SIG_BOOLEAN);
    public static final Type tByte      = new Type(TC_BYTE,     SIG_BYTE);
    public static final Type tChar      = new Type(TC_CHAR,     SIG_CHAR);
    public static final Type tShort     = new Type(TC_SHORT,    SIG_SHORT);
    public static final Type tInt       = new Type(TC_INT,      SIG_INT);
    public static final Type tFloat     = new Type(TC_FLOAT,    SIG_FLOAT);
    public static final Type tLong      = new Type(TC_LONG,     SIG_LONG);
    public static final Type tDouble    = new Type(TC_DOUBLE,   SIG_DOUBLE);
    public static final Type tObject    = Type.tClass(idJavaLangObject);
    public static final Type tClassDesc = Type.tClass(idJavaLangClass);
    public static final Type tString    = Type.tClass(idJavaLangString);
    public static final Type tCloneable = Type.tClass(idJavaLangCloneable);
    public static final Type tSerializable = Type.tClass(idJavaIoSerializable);

    /**
     * Create a type given a typecode and a type signature.
     */
    protected Type(int typeCode, String typeSig) {
        this.typeCode = typeCode;
        this.typeSig = typeSig;
        typeHash.put(typeSig, this);
    }

    /**
     * Return the Java type signature.
     */
    public final String getTypeSignature() {
        return typeSig;
    }

    /**
     * Return the type code.
     */
    public final int getTypeCode() {
        return typeCode;
    }

    /**
     * Return the type mask. The bits in this mask correspond
     * to the TM_* constants defined in Constants. Only one bit
     * is set at a type.
     * @see Constants
     */
    public final int getTypeMask() {
        return 1 << typeCode;
    }

    /**
     * Check for a certain type.
     */
    public final boolean isType(int tc) {
        return typeCode == tc;
    }

    /**
     * Check to see if this is the bogus type "array of void"
     *
     * Although this highly degenerate "type" is not constructable from
     * the grammar, the Parser accepts it.  Rather than monkey with the
     * Parser, we check for the bogus type at specific points and give
     * a nice error.
     */
    public boolean isVoidArray() {
        // a void type is not a void array.
        if (!isType(TC_ARRAY)) {
            return false;
        }
        // If this is an array, find out what its element type is.
        Type type = this;
        while (type.isType(TC_ARRAY))
            type = type.getElementType();

        return type.isType(TC_VOID);
    }


    /**
     * Check for a certain set of types.
     */
    public final boolean inMask(int tm) {
        return ((1 << typeCode) & tm) != 0;
    }

    /**
     * Create an array type.
     */
    public static synchronized Type tArray(Type elem) {
        String sig = new String(SIG_ARRAY + elem.getTypeSignature());
        Type t = (Type)typeHash.get(sig);
        if (t == null) {
            t = new ArrayType(sig, elem);
        }
        return t;
    }

    /**
     * Return the element type of an array type. Only works
     * for array types.
     */
    public Type getElementType() {
        throw new CompilerError("getElementType");
    }

    /**
     * Return the array dimension. Only works for
     * array types.
     */
    public int getArrayDimension() {
        return 0;
    }

    /**
     * Create a class type.
     * @arg className the fully qualified class name
     */
    public static synchronized Type tClass(Identifier className) {
        if (className.isInner()) {
            Type t = tClass(mangleInnerType(className));
            if (t.getClassName() != className)
                // Somebody got here first with a mangled name.
                // (Perhaps it came from a binary.)
                changeClassName(t.getClassName(), className);
            return t;
        }
        // see if we've cached the object in the Identifier
        if (className.typeObject != null) {
            return className.typeObject;
        }
        String sig =
            new String(SIG_CLASS +
                       className.toString().replace('.', SIGC_PACKAGE) +
                       SIG_ENDCLASS);
        Type t = (Type)typeHash.get(sig);
        if (t == null) {
            t = new ClassType(sig, className);
        }

        className.typeObject = t; // cache the Type object in the Identifier
        return t;
    }

    /**
     * Return the ClassName. Only works on class types.
     */
    public Identifier getClassName() {
        throw new CompilerError("getClassName:" + this);
    }

    /**
     * Given an inner identifier, return the non-inner, mangled
     * representation used to manage signatures.
     *
     * Note: It is changed to 'public' for Jcov file generation.
     * (see Assembler.java)
     */

    public static Identifier mangleInnerType(Identifier className) {
        // Map "pkg.Foo. Bar" to "pkg.Foo$Bar".
        if (!className.isInner())  return className;
        Identifier mname = Identifier.lookup(
                                className.getFlatName().toString().
                                replace('.', SIGC_INNERCLASS) );
        if (mname.isInner())  throw new CompilerError("mangle "+mname);
        return Identifier.lookup(className.getQualifier(), mname);
    }

    /**
     * We have learned that a signature means something other
     * that what we thought it meant.  Live with it:  Change all
     * affected data structures to reflect the new name of the old type.
     * <p>
     * (This is necessary because of an ambiguity between the
     * low-level signatures of inner types and their manglings.
     * Note that the latter are also valid class names.)
     */
    static void changeClassName(Identifier oldName, Identifier newName) {
        // Note:  If we are upgrading "pkg.Foo$Bar" to "pkg.Foo. Bar",
        // we assume someone else will come along and deal with any types
        // inner within Bar.  So, there's only one change to make.
        ((ClassType)Type.tClass(oldName)).className = newName;
    }

    /**
     * Create a method type with no arguments.
     */
    public static synchronized Type tMethod(Type ret) {
        return tMethod(ret, noArgs);
    }

    /**
     * Create a method type with arguments.
     */
    public static synchronized Type tMethod(Type returnType, Type argTypes[]) {
        StringBuffer buf = new StringBuffer();
        buf.append(SIG_METHOD);
        for (int i = 0 ; i < argTypes.length ; i++) {
            buf.append(argTypes[i].getTypeSignature());
        }
        buf.append(SIG_ENDMETHOD);
        buf.append(returnType.getTypeSignature());

        String sig = buf.toString();
        Type t = (Type)typeHash.get(sig);
        if (t == null) {
            t = new MethodType(sig, returnType, argTypes);
        }
        return t;
    }

    /**
     * Return the return type. Only works for method types.
     */
    public Type getReturnType() {
        throw new CompilerError("getReturnType");
    }

    /**
     * Return the argument types. Only works for method types.
     */
    public Type getArgumentTypes()[] {
        throw new CompilerError("getArgumentTypes");
    }

    /**
     * Create a Type from an Java type signature.
     * @exception CompilerError invalid type signature.
     */
    public static synchronized Type tType(String sig) {
        Type t = (Type)typeHash.get(sig);
        if (t != null) {
            return t;
        }

        switch (sig.charAt(0)) {
          case SIGC_ARRAY:
            return Type.tArray(tType(sig.substring(1)));

          case SIGC_CLASS:
            return Type.tClass(Identifier.lookup(sig.substring(1, sig.length() - 1).replace(SIGC_PACKAGE, '.')));

          case SIGC_METHOD: {
            Type argv[] = new Type[8];
            int argc = 0;
            int i, j;

            for (i = 1 ; sig.charAt(i) != SIGC_ENDMETHOD ; i = j) {
                for (j = i ; sig.charAt(j) == SIGC_ARRAY ; j++);
                if (sig.charAt(j++) == SIGC_CLASS) {
                    while (sig.charAt(j++) != SIGC_ENDCLASS);
                }
                if (argc == argv.length) {
                    Type newargv[] = new Type[argc * 2];
                    System.arraycopy(argv, 0, newargv, 0, argc);
                    argv = newargv;
                }
                argv[argc++] = tType(sig.substring(i, j));
            }

            Type argtypes[] = new Type[argc];
            System.arraycopy(argv, 0, argtypes, 0, argc);
            return Type.tMethod(tType(sig.substring(i + 1)), argtypes);
          }
        }

        throw new CompilerError("invalid TypeSignature:" + sig);
    }

    /**
     * Check if the type arguments are the same.
     * @return true if both types are method types and the
     * argument types are identical.
     */
    public boolean equalArguments(Type t) {
        return false;
    }

    /**
     * Return the amount of space this type takes up on the
     * Java operand stack. For a method this is equal to the
     * total space taken up by the arguments.
     */
    public int stackSize() {
        switch (typeCode) {
          case TC_ERROR:
          case TC_VOID:
            return 0;
          case TC_BOOLEAN:
          case TC_BYTE:
          case TC_SHORT:
          case TC_CHAR:
          case TC_INT:
          case TC_FLOAT:
          case TC_ARRAY:
          case TC_CLASS:
            return 1;
          case TC_LONG:
          case TC_DOUBLE:
            return 2;
        }
        throw new CompilerError("stackSize " + toString());
    }

    /**
     * Return the type code offset. This offset can be added to
     * an opcode to get the right opcode type. Most opcodes
     * are ordered: int, long, float, double, array. For
     * example: iload, lload fload, dload, aload. So the
     * appropriate opcode is iadd + type.getTypeCodeOffset().
     */
    public int getTypeCodeOffset() {
        switch (typeCode) {
          case TC_BOOLEAN:
          case TC_BYTE:
          case TC_SHORT:
          case TC_CHAR:
          case TC_INT:
            return 0;
          case TC_LONG:
            return 1;
          case TC_FLOAT:
            return 2;
          case TC_DOUBLE:
            return 3;
          case TC_NULL:
          case TC_ARRAY:
          case TC_CLASS:
            return 4;
        }
        throw new CompilerError("invalid typecode: " + typeCode);
    }

    /**
     * Convert a Type to a string, if abbrev is true class names are
     * not fully qualified, if ret is true the return type is included.
     */
    public String typeString(String id, boolean abbrev, boolean ret) {
        String s = null;

        switch (typeCode) {
          case TC_NULL:         s = "null";    break;
          case TC_VOID:         s = "void";    break;
          case TC_BOOLEAN:      s = "boolean"; break;
          case TC_BYTE:         s = "byte";    break;
          case TC_CHAR:         s = "char";    break;
          case TC_SHORT:        s = "short";   break;
          case TC_INT:          s = "int";     break;
          case TC_LONG:         s = "long";    break;
          case TC_FLOAT:        s = "float";   break;
          case TC_DOUBLE:       s = "double";  break;
          case TC_ERROR:        s = "<error>";
                                if (this==tPackage) s = "<package>";
                                break;
          default:              s = "unknown";
          }

        return (id.length() > 0) ? s + " " + id : s;
    }

    /**
     * Create a type string, given an identifier.
     */
    public String typeString(String id) {
        return typeString(id, false, true);
    }

    /**
     * Convert to a String
     */
    public String toString() {
        return typeString("", false, true);
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java Type.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.