Java 如何修复:无法为类X调用无参数构造函数:为此类型向Gson注册InstanceCreator可能会修复此问题
我试图列出所有抽象类的对象,但每个对象都有自己的类。这个列表需要持久化,所以我想我实现了parcelable,因为我在过去已经这么做了。只是不同的类都不是抽象类 我试着让抽象类可以打包,但那不能有我习惯的创建者,因为(当然)你不能创建它的实例(因为它是抽象的)。在四处阅读时,我注意到人们说抽象类中不需要构造函数,只需要子类中的构造函数 AbstractFocusPower类Java 如何修复:无法为类X调用无参数构造函数:为此类型向Gson注册InstanceCreator可能会修复此问题,java,android,abstract,parcelable,Java,Android,Abstract,Parcelable,我试图列出所有抽象类的对象,但每个对象都有自己的类。这个列表需要持久化,所以我想我实现了parcelable,因为我在过去已经这么做了。只是不同的类都不是抽象类 我试着让抽象类可以打包,但那不能有我习惯的创建者,因为(当然)你不能创建它的实例(因为它是抽象的)。在四处阅读时,我注意到人们说抽象类中不需要构造函数,只需要子类中的构造函数 AbstractFocusPower类 public abstract class AbstractFocusPower implements Parcelabl
public abstract class AbstractFocusPower implements Parcelable {
private transient AppExtension app;
private ImplementSchool school;
private String name;
private int duration;
private int cost;
private int altCost;
private int requiredLevel;
private boolean isSelected;
private boolean isResonant;
private int nofSpirtBonusUsed;
/**
* Constructor for Focus Power with no alternative cost
*/
public AbstractFocusPower(AppExtension app, ImplementSchool school, String name, int requiredLevel, int duration, int cost, boolean isSelected) {
this.app = app;
this.school = school;
this.name = name;
this.requiredLevel = requiredLevel;
this.duration = duration;
this.cost = cost;
this.altCost = -1;
this.isSelected = isSelected;
this.isResonant = false;
}
// I cut out the other constructors
public abstract AbstractFocusPower makeCopy();
public abstract String getDescription();
// I cut out the getters and setters
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.school == null ? -1 : this.school.ordinal());
dest.writeString(this.name);
dest.writeInt(this.duration);
dest.writeInt(this.cost);
dest.writeInt(this.altCost);
dest.writeInt(this.requiredLevel);
dest.writeByte(this.isSelected ? (byte) 1 : (byte) 0);
dest.writeByte(this.isResonant ? (byte) 1 : (byte) 0);
dest.writeInt(this.nofSpirtBonusUsed);
}
protected AbstractFocusPower(Parcel in) {
int tmpSchool = in.readInt();
this.school = tmpSchool == -1 ? null : ImplementSchool.values()[tmpSchool];
this.name = in.readString();
this.duration = in.readInt();
this.cost = in.readInt();
this.altCost = in.readInt();
this.requiredLevel = in.readInt();
this.isSelected = in.readByte() != 0;
this.isResonant = in.readByte() != 0;
this.nofSpirtBonusUsed = in.readInt();
}
样本子类
public class AegisFocusPower extends AbstractFocusPower {
public AegisFocusPower(AppExtension app) {
super(app, ImplementSchool.ABJURATION, app.getString(R.string.focus_power_name_aegis), 0, 1, 1, false);
}
@Override
public String getDescription() {
return getApp().getString(R.string.focus_power_desc_aegis, (1+((int) Math.floor(getApp().getCurrentCharacter().getOccultistLevel()/6.0))));
}
@Override
public AegisFocusPower makeCopy() {
return new AegisFocusPower(getApp());
}
public AegisFocusPower(Parcel in) {
super(in);
}
public static final Parcelable.Creator<AegisFocusPower> CREATOR = new Parcelable.Creator<AegisFocusPower>() {
public AegisFocusPower createFromParcel(Parcel in) {
return new AegisFocusPower (in);
}
public AegisFocusPower [] newArray(int size) {
return new AegisFocusPower[size];
}
};
}
编辑:不知道为什么那篇文章是重复的。首先,它没有一个公认的答案。答案需要第三方库。问题不在于一个抽象下的多个子类。您是否尝试过注册类型适配器,比如?我总是为特定格式(日期、大小数、任何通常需要非常特定格式的内容)和子分类添加适配器 但是,在这种情况下,不需要适配器,这是。。直接走
public abstract class AbstractFocusPower implements Parcelable {
// just some property needed to be pushed through a constructor
protected final String myString;
protected AbstractFocusPower(String myString) {
this.myString = myString;
}
}
然后是impl(是的,添加了toString()、hashCode()和equals(),就像我希望它们在域对象中的方式一样…):
然后我可以运行以下junit:
@Test
public void AegisFocusPowerToJsonAndBack(){
// single instance
AegisFocusPower ea = new AegisFocusPower("apa");
String json = GSON.toJson(ea);
assertEquals("{\"imParcelled\":\"false\",\"myString\":\"apa\"}", json);
AegisFocusPower backAtYa = (AegisFocusPower) GSON.fromJson(json, AegisFocusPower.class);
assertEquals(backAtYa, ea);
// A list
AegisFocusPower ea2 = new AegisFocusPower("bepa");
AegisFocusPower ea3 = new AegisFocusPower("cepa");
List<AegisFocusPower> powerList = new ArrayList<>();
powerList.add(ea2);
powerList.add(ea3);
String jsonList = GSON.toJson(powerList);
assertEquals("[{\"imParcelled\":\"false\",\"myString\":\"bepa\"},{\"imParcelled\":\"false\",\"myString\":\"cepa\"}]", jsonList);
List<AegisFocusPower> backAtYaz = Arrays.asList(GSON.fromJson(jsonList,AegisFocusPower[].class));
assertEquals(backAtYaz.get(0), ea2);
assertEquals(backAtYaz.get(1), ea3);
}
我使用的布尔型类型适配器与您的问题无关
这是。。足够简单,也适用于您?可能重复我尝试过的解决方案,但尽管toJson似乎给出了一个有效字符串,但尝试使用fromJson返回字符串会出现错误| | com.google.gson.JsonParseException:在json文件中找不到“type”成员。|Gson gsonFocusPowers=gsonBuilder.create();String jsonFocusPowers=SharedReferences.getString(FOCUS\u POWERS\u GSON,null);类型typeFocusPower=newtypetoken(){}.getType();ArrayList聚焦电源;focusPowers=gsonFocusPowers.fromJson(jsonFocusPowers,typeFocusPower);用一个简单的问题更新了我的答案;回想起来,我认为你可以采用一种更简单的方法,这里不需要适配器,也不需要TypeToken之类的东西……我会尝试一下(目前有点忙),但我担心的是,我有多个AbstractFocusPower子类,它们不是AegisFocusPower,但也需要在arraylist中。不用担心,只需将扩展类发送到您的fromJson()调用,就可以了。列表也可以,只是在这些情况下,像我的示例中那样将它们作为数组键入
public abstract class AbstractFocusPower implements Parcelable {
// just some property needed to be pushed through a constructor
protected final String myString;
protected AbstractFocusPower(String myString) {
this.myString = myString;
}
}
public class AegisFocusPower extends AbstractFocusPower {
boolean imParcelled;
public AegisFocusPower(String myString) {
super(myString);
}
@Override //yup the interface impl
public void parcelMe() {
imParcelled = true;
}
@Override
public String toString() {
return new StringBuilder("{ imParcelled : ").append(imParcelled).append(", myString : ").append(myString).append(" }").toString();
}
@Override
public int hashCode() {
return toString().hashCode();
}
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
} else if (other == null || !(other instanceof AegisFocusPower)) {
return false;
} else {
return other.hashCode() == hashCode();
}
}
}
@Test
public void AegisFocusPowerToJsonAndBack(){
// single instance
AegisFocusPower ea = new AegisFocusPower("apa");
String json = GSON.toJson(ea);
assertEquals("{\"imParcelled\":\"false\",\"myString\":\"apa\"}", json);
AegisFocusPower backAtYa = (AegisFocusPower) GSON.fromJson(json, AegisFocusPower.class);
assertEquals(backAtYa, ea);
// A list
AegisFocusPower ea2 = new AegisFocusPower("bepa");
AegisFocusPower ea3 = new AegisFocusPower("cepa");
List<AegisFocusPower> powerList = new ArrayList<>();
powerList.add(ea2);
powerList.add(ea3);
String jsonList = GSON.toJson(powerList);
assertEquals("[{\"imParcelled\":\"false\",\"myString\":\"bepa\"},{\"imParcelled\":\"false\",\"myString\":\"cepa\"}]", jsonList);
List<AegisFocusPower> backAtYaz = Arrays.asList(GSON.fromJson(jsonList,AegisFocusPower[].class));
assertEquals(backAtYaz.get(0), ea2);
assertEquals(backAtYaz.get(1), ea3);
}
private static final Gson GSON = (new GsonBuilder()).registerTypeAdapter(Boolean.class, new JsonBooleanDeAndSerializer()).create();