1. 程式人生 > >Types方法之isCastable-isConvertible

Types方法之isCastable-isConvertible

ner types sig unbox byte span motion all 子類

5. Conversions and Promotions

5.1. Kinds of Conversion
5.1.1. Identity Conversion
5.1.2. Widening Primitive Conversion
5.1.3. Narrowing Primitive Conversion
5.1.4. Widening and Narrowing Primitive Conversion
5.1.5. Widening Reference Conversion
5.1.6. Narrowing Reference Conversion
5.1.7. Boxing Conversion
5.1.8. Unboxing Conversion
5.1.9. Unchecked Conversion
5.1.10. Capture Conversion
5.1.11. String Conversion
5.1.12. Forbidden Conversions
5.1.13. Value Set Conversion
5.2. Assignment Conversion
5.3. Method Invocation Conversion
5.4. String Conversion
5.5. Casting Conversion
5.5.1. Reference Type Casting
5.5.2. Checked Casts and Unchecked Casts
5.5.3. Checked Casts at Run Time
5.6. Numeric Promotions
5.6.1. Unary Numeric Promotion
5.6.2. Binary Numeric Promotion

 /**
     * Is t a subtype of or convertible via boxing/unboxing conversion to s?
     */
    public boolean isConvertible(Type t, Type s, Warner warn) {
        if (t.tag == ERROR)
            return true;
        boolean tPrimitive = t.isPrimitive();
        boolean sPrimitive = s.isPrimitive();
        if (tPrimitive == sPrimitive) {
            return isSubtypeUnchecked(t, s, warn);
        }

        if (!allowBoxing)
            return false;

        return tPrimitive
            ? isSubtype(boxedClass(t).type, s)
            : isSubtype(unboxedType(t), s);
    }  

當兩個類型相同時(同時為原始類型或引用類型)通過調用isSubtypeUnchecked()方法來進一步判斷。

 /**
     * Is t an unchecked subtype of s?
     */
    public boolean isSubtypeUnchecked(Type t, Type s, Warner warn) {
        boolean result = isSubtypeUncheckedInternal(t, s, warn);
        if (result) {
            checkUnsafeVarargsConversion(t, s, warn);
        }
        return result;
    }  

在如上方法中涉及到兩個重要的方法isSubtypeUncheckedInternal()與checkUnsafeVarargsConversion(),不過優先調用前一個方法,如果是Unchecked Subtype關系,則需要檢查是否為Unsafe Varargs Conversion。

 private boolean isSubtypeUncheckedInternal(Type t, Type s, Warner warn) {
        if (t.tag == ARRAY && s.tag == ARRAY) {
            if (((ArrayType)t).elemtype.tag <= lastBaseTag) { 
                return isSameType(elemtype(t), elemtype(s));
            } else {
                return isSubtypeUnchecked(elemtype(t), elemtype(s), warn);
            }
        } else if (isSubtype(t, s)) {
            return true;
        }
        else if (t.tag == TYPEVAR) {
            return isSubtypeUnchecked(t.getUpperBound(), s, warn);
        }
        else if (s.tag == UNDETVAR) {
            UndetVar uv = (UndetVar)s;
            if (uv.inst != null)
                return isSubtypeUnchecked(t, uv.inst, warn);
        }
        else if (!s.isRaw()) {
            Type t2 = asSuper(t, s.tsym);
            if (t2 != null && t2.isRaw()) {
                if (isReifiable(s))
                    warn.silentWarn(LintCategory.UNCHECKED);
                else
                    warn.warn(LintCategory.UNCHECKED);
                return true;
            }
        }
        return false;
}

當兩個類型是數組類型時,並且是原始數組類型時,則數組類型的元素類型必須相同,也就是byte[]與int[]沒有父子類關系,如下代碼會報錯:

byte[] x = new byte[10];
int[] y = (int[])x;

  

 

 /**
     * Is t is castable to s?
     * s is assumed to be an erased type.
     * (not defined for Method and ForAll types).
     */
    public boolean isCastable(Type t, Type s, Warner warn) {
        if (t == s)
            return true;

        if (t.isPrimitive() != s.isPrimitive())
            return allowBoxing && (
                       isConvertible(t, s, warn) ||
                       (
                                allowObjectToPrimitiveCast &&
                                s.isPrimitive() &&
                                isSubtype(boxedClass(s).type, t)
                       )
            );

        if (warn != warnStack.head) {
            try {
                warnStack = warnStack.prepend(warn);
                checkUnsafeVarargsConversion(t, s, warn);
                return isCastable.visit(t,s);
            } finally {
                warnStack = warnStack.tail;
            }
        } else {
            return isCastable.visit(t,s);
        }
    }

  

Types方法之isCastable-isConvertible