问题
I'm writing a custom API using Reflection
to save Objects to file. I have the following class structure:
@Constructor
public XYZPOJO(@Key(key = "word") String word, @Key(key = "variations") ArrayList<String> varList) {
this.word = word;
this.varList = varList;
}
String word;
ArrayList<String> varList = new ArrayList<String>();
@Key(key = "word")
public String getWord() {
return word;
}
@Key(key = "variations")
public ArrayList<String> getVarList() {
return varList;
}
When saving Object to file, my program retrieves each method annotated with @Key
, invokes method and saves invoked value to file using the value of @Key
as the property name. Later, when I want to construct instance of Object it will search for constructor annotated with @Constructor
and then retrieve value of @Key
of each parameter in constructor and retrieve value of key (property) from file.
My main issue is that for every field I want to persist I need to duplicate the @Key
annotation (and value) before each method and before the corresponding parameter in constructor. Moreover, if both the constructor/method annotation do not match exactly it will fail to instantiate Object. It is very easy to accidentally copy the wrong values.
Is there a way to define each @Key
just once?
I was thinking of adding @Key
just once before each field I wish to persist however I believe (please correct me if I'm wrong) that I would no longer be able to instantiate class via constructor (I believe I would need to instantiate class by directly setting value of each field via reflection, thereby circumventing constructor, correct?). However, this is not ideal since the constructor performs certain necessary functions before the class is instantiated.
What other solution(s) are there?
Thanks!
回答1:
You could do that like every other library for serialization (or just switch to one of these libraries, as they all support everything you do), so possible solutions:
Skip annotation by default and just use name of getter (like
getMoney
->money
) and use annotation only in constructor. And on getter if you want to use other name in serialized form. Additionally you can look for field with same name to check annotations on it too, but it's optional and not needed.Annotate only parameters in constructor but allow to set both name and property name (by default you can assume that name == property unless someone provided both values) And later you can change it to getter method name, like that
money
->getMoney
(just addget
and make first letter upper case)Apply 1st idea but also use parameter names from constructor that are available in runtime if someone compiles code with
-parameters
flag. And then you don't need any annotation, unless you want to use different name in serialized form, then just add annotation to only field/getter.
Note:
Typical libraries just scan for public methods to find properties. So they look for methods that starts with get
or is
followed by upper case letter, that have no arguments and some return type. As typical data class will look like that.
来源:https://stackoverflow.com/questions/60501091/force-uniform-constructor-and-method-annotation-values