实现接口的枚举被验证者拒绝(java.lang.VerifyError)

时间:2017-07-18 13:27:16

标签: java android enums

我使用枚举作为不同物理量的单位,例如metermiles DISTANCE。要以通用方式使用它们,有一个接口Unit,其方法为convert(double)

要加载首选单位,请使用单身人士:

public class UnitPreferences {

    private static UnitPreferences sInstance;

    private HashMap<PhysicalQuantity, Unit> mUnits;

    /**
     * Returns the instance of the preferred units collection.
     *
     * @param context the context
     * @return Instance of the preferred units collection.
     */
    public static UnitPreferences from(Context context) {
        if (sInstance == null) {
            sInstance = new UnitPreferences(context);
        }
        return sInstance;
    }

    /**
     * Creates a new set of preferred units by fetching them from the Shared Preferences.
     *
     * @param context the resources
     */
    private UnitPreferences(Context context) {
        // Load the preferred units from SharedPreferences and put them in the mUnits HashMap
    }

    /**
     * Returns all units of a specific physical quantity.
     *
     * @param physicalQuantity the physical quantity
     * @return All units available to this physical quantity.
     */
    private Unit[] getAllUnits(PhysicalQuantity physicalQuantity) {
        switch (physicalQuantity) {
            case DISTANCE:
                return DistanceUnit.values();

            // others...

            default:
                throw new RuntimeException("No units defined for " + physicalQuantity);
        }
    }

    /**
     * Returns the preferred unit of a physical quantity.
     *
     * @param phQuantity the physical quantity
     * @return The preferred unit.
     */
    public Unit getPreferredUnit(PhysicalQuantity phQuantity) {
        return mUnits.get(phQuantity);
    }
}

PhysicalQuantity枚举:

public enum PhysicalQuantity {

    DISTANCE,
    // others...

}

Unit界面:

public interface Unit {

    double convert(double value);

}

实施DistanceUnit界面的Unit

public enum DistanceUnit implements Unit {

    KILOMETER(R.string.unit_km, "km"),
    MILES(R.string.unit_mi, "mi");

    public static final double KM_PER_MI = 1.609344d;

    private int label;
    private String id;

    DistanceUnit(int label, String id) {
        this.label = label;
        this.id = id;
    }

    @Override
    public double convert(double meters) {
        double km = meters / 1000d;
        if (this == MILES) return km / KM_PER_MI;
        return km;
    }
}

问题:

我第一次使用单位时会抛出异常:

Unit distanceUnit = UnitPreferences.from(context).getPreferredUnit(DISTANCE);

当我实施它时一切正常,现在它被合并到主人之后我得到了VerifyError

java.lang.VerifyError: Verifier rejected class com.example.app.UnitPreferences: com.example.app.Unit[]
  com.example.app.UnitPreferences.getAllUnits(com.example.app.PhysicalQuantity) failed to verify:
  com.example.app.units.Unit[] com.example.app.UnitPreferences.getAllUnits(com.example.app.PhysicalQuantity):
  [0x28] returning 'Reference: java.lang.Enum[]', but expected from declaration 'Reference: com.example.app.Unit[]'
  (declaration of 'com.example.app.UnitPreferences' in /data/app/com.example.app-2/base.apk:classes32.dex)

我已经多次清理和重建并关闭了Instant Run。任何人都可以给我一个如何解决这个错误的提示吗?

2 个答案:

答案 0 :(得分:2)

这部分似乎很关键:

returning 'Reference: java.lang.Enum[]', but expected from declaration 'Reference: com.example.app.Unit[]

所以当你应该返回一个单元数组时,你将返回一个枚举数组。更改方法的返回类型,或者只是将DistanceUnit值打包到列表中以解决问题。

我建议您使用List<Unit>作为返回类型,而不是Unit[]。请参阅this以供参考。为此,请在实例化列表时调用Arrays.asList(DistanceUnit.values())

答案 1 :(得分:1)

稍微调查一下堆栈跟踪,它说:

returning 'Reference: Enum[]', but expected from declaration 'Reference: Unit[]'
getAllUnits()

中的

getAllUnits()的返回枚举手动修改为Unit[],虽然有提示,但手动修复了问题:

Casting 'DistanceUnit.values()' to 'Unit[]' is redundant

Casting Unit[] manually