你缺少的讀取值分配給您的配置實例。Java可以不支持任何類似this = gson.fromJson(...)
和GSON只能返回新值,並不能修補現有的。該下面是一種Gson破解版,如果它真的是必須爲,那麼請僅使用它。同樣,我強烈建議您重新設計代碼並將您的配置對象和配置讀者/作者分開 - 這些只是兩個不同的事情從技術角度來看是相互衝突的,作爲重構的結果,你可以說,一旦你得到了你的配置實例,就把它委託給一個編寫者來保存它,如果你需要的話b ACK,那麼就得到了讀者的一個實例,讀取配置值,並將其分配給您的配置(配置是單身,我記不清了),如:
final ConfigurationWriter writer = getConfigurationWriter();
writer.write(ExampleConfig.get());
...
final ConfigurationReader reader = getConfigurationReader();
ExampleConfig.set(reader.read(ExampleConfig.class));
至少這個代碼不混合兩種不同的東西,並使reader.read
的結果爲明確讀取並分配給您的配置單例。
如果你沒事打開罪惡的大門,使因爲黑客的代碼的工作,那麼你可以是爲了騙取GSON和修補當前的配置實例使用GSON TypeAdapterFactory
。
abstract class Configuration {
private static final Gson saveGson = new Gson();
public final void load()
throws IOException {
try (final FileReader reader = new FileReader(getTargetName())) {
// You have to instantiate Gson every time (unless you use caching strategies) in order to let it be *specifically* be aware of the current
// Configuration instance class. Thus you cannot make it a static field.
final Gson loadGson = new GsonBuilder()
.registerTypeAdapterFactory(new TypeAdapterFactory() {
// A Gson way to denote a type since Configuration.class may not be enough and it also works with generics
private final TypeToken<Configuration> configurationTypeToken = new TypeToken<Configuration>() {
};
@Override
@SuppressWarnings("deprecation") // isAssignableFrom is deprecated
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
// Checking if the type token represents a parent class for the given configuration
// If yes, then we cheat...
if (configurationTypeToken.isAssignableFrom(typeToken)) {
// The map that's artificially bound as great cheating to a current configuration instance
final Map<Type, InstanceCreator<?>> instanceCreators = bindInstance(typeToken.getType(), Configuration.this);
// A factory used by Gson internally, we're intruding into its heart
final ConstructorConstructor constructorConstructor = new ConstructorConstructor(instanceCreators);
final TypeAdapterFactory delegatedTypeAdapterFactory = new ReflectiveTypeAdapterFactory(
constructorConstructor,
gson.fieldNamingStrategy(),
gson.excluder(),
new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor)
);
// Since the only thing necessary here is to define how to instantiate an object
// (and we just give it an already-existing instance)
// ... just delegate the job to Gson -- it would think as if it's creating a new instance.
// Actually it won't create one, but would "patch" the current instance
return delegatedTypeAdapterFactory.create(gson, typeToken);
}
// Otherwise returning a null means looking up for an existing type adapter from how Gson is configured
return null;
}
})
.create();
// The value is still loaded to nowhere, however.
// The type adapter factory is tightly bound to an existing configuration instance via ConstructorConstructor
// This is actually another code smell...
loadGson.fromJson(reader, getClass());
}
}
public final void save()
throws IOException {
try (final FileWriter writer = new FileWriter(getTargetName())) {
saveGson.toJson(this, writer);
}
}
private String getTargetName() {
return getClass().getSimpleName() + ".json";
}
private static Map<Type, InstanceCreator<?>> bindInstance(final Type type, final Configuration existingConfiguration) {
return singletonMap(type, new InstanceCreator<Object>() {
@Override
public Object createInstance(final Type t) {
return t.equals(type) ? existingConfiguration : null; // don't know if null is allowed here though
}
});
}
}
我希望上面的代碼中的註釋是詳盡的。正如我上面所說,我懷疑你是否需要它只是因爲有意識有一些更好的代碼。你可以爭辯說,java.util.Properties
可以加載和保存自己。是的,的確如此,但java.util.Properties
可以通過設計對其屬性進行迭代,並且始終可以從其他位置讀取和寫入屬性。 Gson使用反射,一種窺視引擎蓋下方領域的方法,這對於精心設計的對象來說非常棒。您需要重構並分離兩個概念:數據和數據寫入器/讀取器。
'gson.fromJson(reader,this.getClass());' - 這是你的值丟失的地方。 'fromJson'方法返回一個_new_值,你必須在某處指定。 –
有道理,我將如何用我目前的例子來做到這一點? –