Você pode utilizar recursividade quando encontrar tipos de dado não-primitivos.
Abaixo vou postar uma classe Reflector que você pode utilizar da seguinte forma e ver o resultado gerado:
Reflector reflector = new Reflector();
String conteudo = reflector.reflect( instanciaQueVoceQuiser );
System.out.println(conteudo);
Código da classe Reflector, se entender como o código funciona, deve ficar fácil de adaptar pra sua necessidade:
import java.lang.reflect.Field;
public class Reflector {
public String reflect(Object object) {
StringBuilder text = new StringBuilder();
reflectObject(text, "", object);
return text.toString();
}
private String typeName(Class<?> type) {
String typeName = type.getName();
if (!type.isArray()) {
return typeName;
}
int dimensions = typeName.lastIndexOf('[') + 1;
final String name;
switch (typeName.charAt(dimensions)) {
case 'Z':
name = "boolean";
break;
case 'B':
name = "byte";
break;
case 'C':
name = "char";
break;
case 'D':
name = "double";
break;
case 'F':
name = "float";
break;
case 'I':
name = "int";
break;
case 'J':
name = "long";
break;
case 'S':
name = "short";
break;
case 'L':
default:
name = typeName.substring(dimensions + 1, typeName.lastIndexOf(';'));
break;
}
StringBuilder text = new StringBuilder(name);
for (int i = 0; i < dimensions; i++) {
text.append("[]");
}
return text.toString();
}
private void reflectObject(StringBuilder text, String indent, Object object) {
if (object == null) {
text.append(indent).append("null");
return;
}
Class<?> objectClass = object.getClass();
String type;
if (objectClass.isAnnotation()) {
type = "annotation";
} else if (objectClass.isEnum()) {
type = "enum";
} else if (objectClass.isInterface()) {
type = "interface";
} else {
type = "class";
}
text.append(indent).append(type).append(" ").append(typeName(objectClass)).append(" {");
Field[] attributes = objectClass.getDeclaredFields();
if (attributes.length > 0) {
text.append("\n");
for (Field attribute : attributes) {
reflectAttribute(text, indent, object, attribute);
}
}
text.append(indent).append("}");
}
private void reflectAttribute(StringBuilder text, String indent, Object object, Field attribute) {
try {
attribute.setAccessible(true);
Class<?> attributeType = attribute.getType();
Object attributeValue = attribute.get(object);
text.append("\n").append(indent).append(" ").append(attribute.getName()).append(" : ").append(typeName(attributeType));
if (attributeValue != null && !attributeType.isPrimitive()) {
text.append(" = (\n\n");
reflectObject(text, indent + " ", attributeValue);
text.append("\n");
text.append(indent).append(" ").append(");\n");
} else {
text.append(";\n");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Se você quiser algo mais bem estruturado e elaborado, poderia cogitar implementar o padrão de projeto Visitor, mas não é algo trivial de se fazer.