2016-09-15 3 views
1

내가 여기에 어려운 문제에 직면하고있어, 내가 계층 구조 parcelable 수업을하기 위해 노력하고있어하지만이 이상한 오류 받고 있어요 :추상 클래스를 인스턴스화 할 수 없습니다 '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로 주석 처리를했다,하지만 난 Fi에없는 것 무슨 일이 일어나고 있는지 찾아라.

이 문제는 Parceler 1.1.5 버전에서 발생했습니다.

감사합니다.

+0

일반적으로 추상 클래스는 인스턴스화 할 수 없으며 인터페이스를 인스턴스화 할 수 없습니다. abstact 클래스를 확장해야합니다. – baudo2048

+0

그 요점은, 내가 추상 클래스를 인스턴스화하지 않고, Parceler가 기본 클래스를 호출하는 이유를 이해할 수 없다는 것입니다. – Leonardo

+0

제공되는 스택 추적은 Gson이 추상 클래스를 인스턴스화하는 데 문제가 있음을 나타냅니다. Github에 대해서도 다음과 같이 대답합니다. https://github.com/johncarl81/parceler/issues/237 –

답변

1

는 사실은 내가해야 내 시리얼 CustomTypeAdapter에 추가

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

를 잊었다!

0

나는이 문제에 실행중인 믿는다

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

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.

그래서 당신이이 문제를 얻기 위해 사용자 정의 직렬화를 사용할 수 있어야합니다.

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

죄송합니다 귀찮게하고 다른 사람을 도움이되기를 바랍니다 : https://github.com/johncarl81/parceler#custom-serialization