public boolean isAssignmentCompatibleWith()

in src/main/java/org/apache/bcel/generic/ReferenceType.java [154:243]


    public boolean isAssignmentCompatibleWith(final Type t) throws ClassNotFoundException {
        if (!(t instanceof ReferenceType)) {
            return false;
        }
        final ReferenceType T = (ReferenceType) t;
        if (equals(NULL)) {
            return true; // This is not explicitly stated, but clear. Isn't it?
        }
        /*
         * If this is a class type then
         */
        if (this instanceof ObjectType && ((ObjectType) this).referencesClassExact()) {
            /*
             * If T is a class type, then this must be the same class as T, or this must be a subclass of T;
             */
            if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact()
                && (equals(T) || Repository.instanceOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName()))) {
                return true;
            }
            /*
             * If T is an interface type, this must implement interface T.
             */
            if (T instanceof ObjectType && ((ObjectType) T).referencesInterfaceExact()
                && Repository.implementationOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName())) {
                return true;
            }
        }
        /*
         * If this is an interface type, then:
         */
        if (this instanceof ObjectType && ((ObjectType) this).referencesInterfaceExact()) {
            /*
             * If T is a class type, then T must be Object (�2.4.7).
             */
            if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() && T.equals(OBJECT)) {
                return true;
            }
            /*
             * If T is an interface type, then T must be the same interface as this or a superinterface of this (�2.13.2).
             */
            if (T instanceof ObjectType && ((ObjectType) T).referencesInterfaceExact()
                && (equals(T) || Repository.implementationOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName()))) {
                return true;
            }
        }
        /*
         * If this is an array type, namely, the type SC[], that is, an array of components of type SC, then:
         */
        if (this instanceof ArrayType) {
            /*
             * If T is a class type, then T must be Object (�2.4.7).
             */
            if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() && T.equals(OBJECT)) {
                return true;
            }
            /*
             * If T is an array type TC[], that is, an array of components of type TC, then one of the following must be true:
             */
            if (T instanceof ArrayType) {
                /*
                 * TC and SC are the same primitive type (�2.4.1).
                 */
                final Type sc = ((ArrayType) this).getElementType();
                final Type tc = ((ArrayType) T).getElementType();
                if (sc instanceof BasicType && tc instanceof BasicType && sc.equals(tc)) {
                    return true;
                }
                /*
                 * TC and SC are reference types (�2.4.6), and type SC is assignable to TC by these runtime rules.
                 */
                if (tc instanceof ReferenceType && sc instanceof ReferenceType && ((ReferenceType) sc).isAssignmentCompatibleWith(tc)) {
                    return true;
                }
            }
            /* If T is an interface type, T must be one of the interfaces implemented by arrays (�2.15). */
            // TODO: Check if this is still valid or find a way to dynamically find out which
            // interfaces arrays implement. However, as of the JVM specification edition 2, there
            // are at least two different pages where assignment compatibility is defined and
            // on one of them "interfaces implemented by arrays" is exchanged with "'Cloneable' or
            // 'java.io.Serializable'"
            if (T instanceof ObjectType && ((ObjectType) T).referencesInterfaceExact()) {
                for (final String element : Const.getInterfacesImplementedByArrays()) {
                    if (T.equals(ObjectType.getInstance(element))) {
                        return true;
                    }
                }
            }
        }
        return false; // default.
    }