无法实例化抽象 class 'base.CreditCard'

Can't instantiate abstract class 'base.CreditCard'

我在这里遇到了一个棘手的问题,我试图让层次结构可打包 classes 但我遇到了这个奇怪的错误:

java.lang.InstantiationException: Can't instantiate abstract class br.com.dinda.models.credit_cards.base.CreditCard
    at java.lang.reflect.Constructor.newInstance()(Constructor.java:-2)
    at com.google.gson.internal.ConstructorConstructor.construct()(ConstructorConstructor.java:104)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read()(ReflectiveTypeAdapterFactory.java:186)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.read()(ReflectiveTypeAdapterFactory.java:103)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read()(ReflectiveTypeAdapterFactory.java:196)
    at com.google.gson.Gson.fromJson()(Gson.java:810)
    at com.google.gson.Gson.fromJson()(Gson.java:775)
    at com.google.gson.Gson.fromJson()(Gson.java:724)
    at com.google.gson.Gson.fromJson()(Gson.java:696)
    at com.newrelic.agent.android.instrumentation.GsonInstrumentation.fromJson()(GsonInstrumentation.java:90)
    at br.com.dinda.models.CheckoutData.fromJson()(CheckoutData.java:38)
    at br.com.dinda.repositories.CheckoutRepository.getPersistedCheckout()(CheckoutRepository.java:46)
    at br.com.dinda.repositories.CheckoutRepository.getCheckout()(CheckoutRepository.java:28)
    at br.com.dinda.presenters.CheckoutStep2Presenter.onCreate()(CheckoutStep2Presenter.java:43)
    at br.com.dinda.views.fragments.CheckoutStep2Fragment.onCreateView()(CheckoutStep2Fragment.java:183)
    at android.support.v4.app.Fragment.performCreateView()(Fragment.java:1789)
    at android.support.v4.app.FragmentManagerImpl.moveToState()(FragmentManager.java:955)
    at android.support.v4.app.FragmentManagerImpl.moveToState()(FragmentManager.java:1138)
    at android.support.v4.app.FragmentManagerImpl.moveToState()(FragmentManager.java:1120)
    at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated()(FragmentManager.java:1929)
    at android.support.v4.app.FragmentActivity.onStart()(FragmentActivity.java:547)
    at android.support.v7.app.AppCompatActivity.onStart()(AppCompatActivity.java:-1)
    at br.com.dinda.views.activities.BaseActivity.onStart()(BaseActivity.java:49)
    at android.app.Instrumentation.callActivityOnStart()(Instrumentation.java:1238)
    at android.app.Activity.performStart()(Activity.java:6288)
    at android.app.ActivityThread.performLaunchActivity()(ActivityThread.java:2397)
    at android.app.ActivityThread.handleLaunchActivity()(ActivityThread.java:2494)
    at android.app.ActivityThread.access0()(ActivityThread.java:157)
    at android.app.ActivityThread$H.handleMessage()(ActivityThread.java:1356)
    at android.os.Handler.dispatchMessage()(Handler.java:102)
    at android.os.Looper.loop()(Looper.java:148)
    at android.app.ActivityThread.main()(ActivityThread.java:5530)
    at java.lang.reflect.Method.invoke()(Method.java:-2)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run()(ZygoteInit.java:733)
    at com.android.internal.os.ZygoteInit.main()(ZygoteInit.java:623)

我的代码是:

@Parcel(converter = CreditCard.CreditCardConverter.class)
public abstract class CreditCard {

    public static final String CREDIT_CARD_MASK = "**** **** **** ####";
    public static ImmutableList<CreditCard> CREDIT_CARD_OPERATORS;

    static {
        CREDIT_CARD_OPERATORS = ImmutableList.of(
                new EloCreditCard(),
                new VisaCreditCard(),
                new MastercardCreditCard(),
                new HipercardCreditCard()
        );
    }

    @SerializedName("credit_card_id")
    Integer id;

    @SerializedName("credit_card_name")
    String name;

    @SerializedName("credit_card_number")
    String number;

    @SerializedName("credit_card_month")
    Integer month;

    @SerializedName("credit_card_year")
    Integer year;

    @SerializedName("credit_card_operator")
    String operator;

    String securityCode;

    boolean saveCreditCard;

    /**
     * Funcao para retornar o nome da operadora do cartao
     * eg. visa ou mastercard
     * @return nome da operadora
     */
    @NonNull
    public abstract String getCreditCardOperatorName();

    /**
     * Funcao que retorna o regex para verificar a validade da operadora do cartao (nums sao validos para a bandeira especificada)
     * eg. visa = Pattern.compile("^4[0-9]{15}$"),
     * @return @Pattern para a operadora especificada
     */
    public abstract Pattern creditCardRegex();

    /**
     * Funcao que retorna o Regex parcial para identificar a operadora do cartao
     * * eg. visa = Pattern.compile("^4[0-9]*$")
     * @return @Pattern para a verificacao parcial da operadora do cartao
     */
    public abstract Pattern partialCreditCardRegex();

    /**
     * Funcao que retorna o logo da bandeira da operadaora do cartao quando o msm esta selecionado
     * @return Drawable do logo
     */
    @DrawableRes
    public abstract int operatorLogoRes();

    /**
     * Funcao que retorna o logo da bandeira da operadaora do cartao quando o msm <b>nao</b> esta selecionado
     * @return Drawable do logo desmarcado (cinza)
     */
    @DrawableRes
    public abstract int operatorLogoDisabledRes();

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof CreditCard)) return false;

        CreditCard card = (CreditCard) o;

        return getCreditCardOperatorName().equals(card.getCreditCardOperatorName());

    }

    @Override
    public int hashCode() {
        return getCreditCardOperatorName().hashCode();
    }

    public static class CreditCardConverter implements ParcelConverter<CreditCard> {

        @Override
        public void toParcel(CreditCard input, android.os.Parcel parcel) {
            parcel.writeParcelable(Parcels.wrap(input), 0);
        }

        @Override
        public CreditCard fromParcel(android.os.Parcel parcel) {
            return Parcels.unwrap(parcel.readParcelable(CreditCard.class.getClassLoader()));
        }
    }
}

还有一个child class:

@Parcel
public class HipercardCreditCard extends CreditCard {

    @Override
    public String getCreditCardOperatorName() {
        return "hipercard";
    }

    @Override
    public Pattern creditCardRegex() {
        return Pattern.compile("^606282[0-9]{10}$");
    }

    @Override
    public Pattern partialCreditCardRegex() {
        return Pattern.compile("^(?:6|60|606|6062|60628|606282[0-9]{0,10})$");
    }

    @Override
    public int operatorLogoRes() {
        return R.drawable.ic_credit_card_hipercard_on;
    }

    @Override
    public int operatorLogoDisabledRes() {
        return R.drawable.ic_credit_card_hipercard_off;
    }
}

我注意将它们注​​释为@Parcel,但我似乎无法弄清楚发生了什么。

Parceler 1.1.5 版本出现此问题。

谢谢。

我相信您 运行 遇到了这个问题:

Polymorphism

Note that Parceler does not unwrap inheritance hierarchies, so any polymorphic fields will be unwrapped as instances of the base class. This is because Parceler opts for performance rather than checking .getClass() for every piece of data.

 @Parcel public class Example {
     public Parent p;
     @ParcelConstructor Example(Parent p) { this.p = p; } }

 @Parcel public class Parent {} @Parcel public class Child extends
 Parent {} Example example = new Example(new Child());
 System.out.println("%b", example.p instanceof Child); // true example
 = Parcels.unwrap(Parcels.wrap(example)); System.out.println("%b", example.p instanceof Child); // false 

Refer to the Custom Serialization section for an example of working with polymorphic fields.

所以您应该能够使用自定义序列化来解决这个问题。

https://github.com/johncarl81/parceler#custom-serialization

实际上我忘记在我的序列化程序中添加 CustomTypeAdapter,

if (json != null) {
            Gson gson = new Gson();
            return gson.fromJson(json, CheckoutData.class);

应该是:

if (json != null) {
            Gson gson = new GsonBuilder().registerTypeAdapter(CreditCard.class, new CreditCardTypeAdapter()).create();
            return gson.fromJson(json, CheckoutData.class);

抱歉打扰了,希望对别人有帮助!