HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Using Reflection to Initialize Instance Variables

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
reflectioninstanceusingvariablesinitialize

Problem

I'm facing the issue of how to reconstruct data across a network in Java. As part of my Component based game engine (read about it here, I have to encode components as XML on the server, send it to the client, and then reconstruct the appropriate component with all the data included in the XML. For example:

package.TextureComponent
id 1 /id
width 100 /width
height 100 /height
/package.TextureComponent


Right now, I use reflection on the client to construct a new TextureComponent (but this will work for any component with primitive data types) using the complete name of the class. I then sequentially read all the String parameters from the XML into the component using reflection in this BasicDecoder:

```
public class BasicDecoder implements DataDecoder {

@Override
public void decode(DataComponent component, String[] data) {
Class compClass = component.getClass();

// fills in all public fields with data in order
Field[] fields = compClass.getFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
Class fieldType = field.getType();
String typeName = fieldType.getName().toUpperCase().replace(".", "");
FieldType type;
try {
type = FieldType.valueOf(typeName);
} catch (Exception ex) {
throw new RuntimeException("BasicDecoder cannot handle field: " + typeName);
}
try {
switch (type) {
case INT:
field.setInt(component, Integer.parseInt(data[i]));
break;
case DOUBLE:
field.setDouble(component, Double.parseDouble(data[i]));
break;
case BYTE:
field.setByte(component, Byte.parseByte(data[i]));
break;
case SHORT:
field.setShort(component, Short.parseShort(data[i]

Solution

Reflection is not the correct way to do this. You will need Serialization for this. Another option is to use XML marshalling and unmarshalling, but I am not so familiar with that.

For serialization I suggest you to pick up a copy of Effective Java, and read the last couple of items of the book, which are all about Serialization.

You really need to take care of the following, since you are dealing with a game and network:

  • Check your class invariants, constructors may not violate them.



  • Make sure that your seriliazation is all safe as attackers can exploit a lot of things to do some quite surprising things.



  • Take care of the evolvability of your classes, serialization does pose some issues on that.



I would recommend all your classes to implement a static inner classes called ProxyHelper and implement the Proxy Serialization Pattern on the classes.

Some other ad-hoc review points of your current code:

  • Do not catch Exception, catch the subclass(es) that you actually see happening, currently it will also catch RuntimeExceptions.



  • Do preferably not throw RuntimeException, but add somewhat more detail, IllegalStateException may be a candidate here.



  • Follow the coding conventions, you do it quite well in general, but in the switch (type) { } every case (and inherited code lines) need to be indented one more factor.



In general I would never let Reflection do such a task, I would add with the following code, either a public constructor taking all arguments of the object (which you can get from the String[] data), or if there are too many arguments (more than five usually), you can also emply the Builder Pattern.

Context

StackExchange Code Review Q#49518, answer score: 5

Revisions (0)

No revisions yet.