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.
}