簡體   English   中英

無法實例化抽象類“ base.CreditCard”

[英]Can't instantiate abstract class 'base.CreditCard'

我在這里面臨一個尷尬的問題,我正在嘗試使用層次結構可拆分的類,但是卻遇到了這個奇怪的錯誤:

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$3.construct()(ConstructorConstructor.java:104)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read()(ReflectiveTypeAdapterFactory.java:186)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.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.access$900()(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()));
        }
    }
}

還有一個兒童班:

@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版本上已發生此問題。

謝謝。

我相信您遇到了這個問題:

多態性

請注意,Parceler不會解包繼承層次結構,因此任何多態字段都將被解包為基類的實例。 這是因為Parceler選擇性能而不是為每個數據檢查.getClass()。

 @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 

有關使用多態字段的示例,請參見“自定義序列化”部分。

因此,您應該能夠使用自定義序列化解決此問題。

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);

抱歉打擾,希望對您有所幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM