Generics type as a parameter - java

The following code is the one I was using for updating some field's value in the database
public void updatesomeField(String registrationID) {
ContentValues objValues;
try {
objDatabase=this.getWritableDatabase();
objValues = new ContentValues();
objValues.put(COLUMN_REGISTRATION_ID,registrationID);
objDatabase.update(CUSTOMER_USERS_TABLE_NAME, objValues,null,null);
objDatabase.close();
} catch(Exception errorException) {
Log.d("error",""+ errorException);
}
}
Then I decided to use a generic approach and hence written the above code like
public <T> void update(String tableName, String columnName, T value) {
ContentValues objValues;
try {
objDatabase=this.getWritableDatabase();
objValues = new ContentValues();
objValues.put(columnName,value); ///here comes the error BECAUSE THE 'value'
objDatabase.update(tableName, objValues,null,null);
objDatabase.close();
} catch(Exception errorException) {
Log.d("error",""+ errorException);
}
}
Error is because ContentValues is final and I cannot extend it to create my new own class to store my generic variable type. What optimization should be performed so that I can get rid of the error by having the same code?
ANOTHER VERSION OF THE SAME QUESTION (IF THE ABOVE ASKED THING IS DIFFICULT TO UNDERSTAND)
I have a final predefined class ContentValues having method put which take parameters in the form of key and values.
However I want to implement a generic functionality and want to decide it on run time that what should be the type of the value

You could write an Adapter which does the dispatching for you:
class ContentValuesAdapter {
private ContentValues values;
public ContentValuesAdapter(ContentValues values) {
this.values = values;
}
public void put(String columnName, Object value) {
if(value instanceof String) {
values.put(columnName, (String) value);
} else if ( ... ) {
...
}
}
public ContentValues getContentValues() {
return this.values;
}
/* Delegate all other methods to the ContentValue instance. */
}
Now you can use this class instead of the original class, and keep your using code clean.

I use generic types throughout my applications, and have to say that one of the simplest (possibly not the best, or most efficient) ways of determining object type is instanceof - For e.g:
if(obj instanceof SiteContact){
buildContactDropdownList((SiteContact)obj);
}else if(obj instanceof Delivery){
buildDeliveryList((Delivery)obj);
}
You could quite easily wrap this up inside a helper class too.

If the ContentValues class belong to a third-party library and you have no access to its source code, then I'm afraid you're stuck with it.
Apparently, ContentValues contains a put(String,String) method. What you could do, is call the toString() method of value:
objValues.put(columnName, value.toString());
Since the toString() method is defined already in the class Object, you don't need to use generics for this. So you can just call your method:
public void update(String tableName, String columnName, Object value)
{
...
}

Related

Best pattern to create a wrapper Constructor

The problem is the following. Given a class GenericConfig which encapsulates a Map<String, Object> to contain several configurations, a class SpecificConfig is desired to have getters to retrieve specific map values.
For example, I want to avoid testing that GenericConfig.getProperties().get(KEY_OF_PROPERTY); is null and getting the value, with the burden of memorizing the key value in the calling method. I want to create a SpecificConfig that is created only if the key is present and that has a getProperty() method.
Example of what I want to avoid:
private final static String KEY_OF_PROPERTY = "key.for.my.value";
public void process(List<GenericConfig> configs) {
for(GenericConfig config: configs) {
String value = config.getProperties().get(KEY_OF_PROPERTY);
if (value != null) {
// do something
}
}
}
This is my attempt:
public final class SpecificConfig extends GenericConfig {
public SpecificConfig(GenericConfig from) {
if(from.getProperties().get(KEY_OF_PROPERTY) != null) {
this.properties = from.getProperties();
} else {
throw new ThisIsNotTheConfigIWant();
}
}
public String getProperty() {
return (String) this.properties.get(KEY_OF_PROPERTY);
}
}
So I can do the following:
public void process(List<GenericConfig> configs) {
for(GenericConfig config: configs) {
try {
SpecificConfig c = new SpecificConfig(config);
// now i can be sure that c is of the required type
// do stuff related to that type
} catch (ThisIsNotTheConfigIWant) { /* ignore this config */ }
}
}
Is throwing a checked exception in the constructor a bad thing in OOP? Does a pattern to solve this problem exist? Is it viable to instantiate null in the constructor instead of throwing an exception.
When calling the constructor it must return an instance of the class, never null. But if you want it to be possible to be null, use a static factory method instead:
public SpecificConfig maybeCreateFrom(GenericConfig c) {
if (<matches>) {
return SpecificConfig(c);
} else {
return null;
}
}
Then on the for-loop you can check for not-null. I think that is generally better than using clunky exceptions for control-flow handling. Though I suspect this is still not the best architecture for you.
Does the class GenericConfig holds a single config or a Map of configs? I would consider just creating methods to fetch configs with the existing keys + doing any null checks. Then you can just call getConfigX() or something.

Java SQLData - Cast to user object with a list/array?

I'm learning on how to use SQLData and having an issue with casting back to my object.
My Oracle Types looks something like this:
CREATE OR REPLACE TYPE activities_t AS OBJECT
(
list activity_list_t;
);
CREATE OR REPLACE TYPE activity_list_t AS TABLE OF activity_t;
CREATE OR REPLACE TYPE activity_t AS OBJECT
(
startDate DATE;
endDate DATE;
);
And my Java looks like this:
public class Activities implements SQLData {
private String sqlType = "ACTIVITIES_T";
List<Activity> list;
// must have default ctor!
public Activities() {
}
public String getSQLTypeName() throws SQLException
{
return sqlType;
}
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public void readSQL(SQLInput stream, String typeName) throws SQLException
{
Array a = stream.readArray();
// :(
}
public void writeSQL(SQLOutput stream) throws SQLException
{
// stream.writeArray(this.list);
}
}
I've tried a few things in readSQL but I am not having much success - what am I missing?
I am calling a PLSQL stored procedure which has an OUT parameter of "activities_t" using JDBC:
Map map = connection.getTypeMap();
map.put("ACTIVITIES_T", Class.forName("Activities"));
connection.setTypeMap(map);
callableStatement = connection.prepareCall("{call GET_ACTIVITIES(?)}");
callableStatement.execute();
Thanks!
Steve
(most of the above is from memory as the code is at work...)
You'll need to add a type mapping for the type ACTIVITY_T as well as the one for ACTIVITIES_T. It's not clear from your question whether you've already done this.
Let's assume you've done this and created a class called Activity which implements SQLData as well. Once you've done that, the following should suffice to read the activity list within Activities:
public void readSQL(SQLInput stream, String typeName) throws SQLException {
Array array = stream.readArray();
this.list = new ArrayList<Activity>();
for (Object obj : (Object[])array.getArray()) {
list.add((Activity)obj);
}
}
Tips:
JDBC APIs are case-sensitive with regard to type names; you will see a Unable to resolve type error if your type name does not exactly match. Oracle will uppercase your type name unless you double-quoted the name in its create statement.
You may need to specify SCHEMA.TYPE_NAME if the type isn't in your default schema.
Remember to grant execute on types if the user you are connecting with is not the owner.
If you have execute on the package, but not the type, getArray() will throw an exception when it tries to look for type metadata.
getArray()
My solution is essentially the same as Luke's. However, I needed to provide a type mapping when getting the array: array.getArray(typeMap)
You can also set a default type map on the Connection, but this didn't work for me.
When calling getArray() you get an array of the object type, i.e. the SQLData implementation you created that represents activity_t
Here is a generic function you might find useful:
public static <T> List<T> listFromArray(Array array, Class<T> typeClass) throws SQLException {
if (array == null) {
return Collections.emptyList();
}
// Java does not allow casting Object[] to T[]
final Object[] objectArray = (Object[]) array.getArray(getTypeMap());
List<T> list = new ArrayList<>(objectArray.length);
for (Object o : objectArray) {
list.add(typeClass.cast(o));
}
return list;
}
writeArray()
Figuring out how to write an array was frustrating, Oracle APIs require a Connection to create an Array, but you don't have an obvious Connection in the context of writeSQL(SQLOutput sqlOutput). Fortunately, this blog has a trick/hack to get the OracleConnection, which I've used here.
When you create an array with createOracleArray() you specify the list type for the type name, NOT the object type. i.e. activity_list_t
Here's a generic function for writing arrays. In your case, listType would be "activity_list_t" and you would pass in a List<Activity>
public static <T> void writeArrayFromList(SQLOutput sqlOutput, String listType, #Nullable List<T> list) throws SQLException {
final OracleSQLOutput out = (OracleSQLOutput) sqlOutput;
OracleConnection conn = (OracleConnection) out.getSTRUCT().getJavaSqlConnection();
conn.setTypeMap(getTypeMap()); // not needed?
if (list == null) {
list = Collections.emptyList();
}
final Array array = conn.createOracleArray(listType, list.toArray());
out.writeArray(array);
}
Note: at one point I thought setTypeMap was required, but now when I remove that line my code still works, so I'm not sure if it's necessary.

Need help refactoring some duplicated Java code. Interface or Generics or some other solution?

I have some Data Objects e.g. Task, Resource etc.
These Objects hold domain data e.g.
public class Task{
private int Id;
private String taskName;
.......
//getters and setters here
//in addition they have a special method dynamically to get values i.e. There is a reason for this
public static String runGetter(Task task, String getter) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
for (Method method : task.getClass().getMethods()) {
if (method.getName().toLowerCase().equalsIgnoreCase(getter.toLowerCase())) {
if (method.getReturnType().isPrimitive()) {
StringBuilder sb = new StringBuilder();
sb.append(method.invoke(task));
return sb.toString();
}
if (method.invoke(task) != null) {
return method.invoke(task).toString();
}
}
}
return null;
}
}
}
Now I have some methods that take these objects and write them out to streams
e.g.
public class WriterUtil{
public void write(Task task, File outputFile){
//write the task object out.
}
public void write(Resource resource, File outputFile){
//write the resource object out
}
....
}
The write methods call another method to get data out of the object as follows. (Yes, it can be made more efficient but it is not the core of my problem)
public class WriterUtil {
.....
public static String extractLine(Task task, LinkedHashMap<String, String> columns, String delimiter) throws IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
StringBuilder sb = new StringBuilder();
Iterator<String> itr = columns.keySet().iterator();
while (itr.hasNext()) {
String getter = "get" + itr.next();
String value = Task.runGetter(task, getter);
if (value == null)
value = "";
sb.append(value + delimiter + " ");
}
return sb.toString().substring(0, sb.lastIndexOf(delimiter)).trim();
}
......
}
My Main problem is this given the described scenario above, I find myself writing the same identical code for each domain object e.g.
public void write(Task task, File outputFile)
public void write(Resource resource, File outputFile)
//etc ....
I repeat the same for extractLine.
As you can see I am duplicating the same code for each domain object. Where the only thing varying is the actual domain object. These methods do the exact same thing with each domain object.
My Question is; if I am to refactor these methods and write one method each to apply to every domain object, what are my best options.
Should I have the domain objects implement an interface? This seems rather cumbersome and I am not sure it is the right course of action.
Can I use generics? I expect it is probably the best practice but I have very limited experience with how to go about generifying (Is that a word?) my Domain Objects and these common methods. Can someone offer a re-write of my above code on how they would modify them for generic?
Do I have a third option?
Move the reflection code into a utility type and change the signature to:
public static String runGetter(Object bean, String getter)
The Task type isn't used at all inside the method.
Likewise, the only reason you need a Task type here is because the other call requires it:
public static String extractLine(Object bean, Map<String, String> columns,
String delimiter)
You'll need to use an interface; generics can't be employed here (you could do it in C++ with templates, but not in Java).
If you don't want you objects to implement the interface, you can create helper objects for each of your domain classes; those helper objects would implement an interface with the extractLine() function:
class TaskExtractLine implements IExtractLine
{
public TaskExtractLine(Task task)
{
this.task = task;
}
public String extractLine(LinkedHashMap<String, String> columns, String delimiter)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
{
return WriterUtil.extractLine(task, columns, delimiter);
}
private Task task;
}
Then you'll have the write function like this: public void write(IExtractLine extractLineHelper, File outputFile) and call it like this: write(new TaskExtractLine(task), outputFile).

Java Generics Selective Return Value

I've been struggling with this for a while and have yet to find an answer. As a result, my brain is somewhat muddled, so pardon me if I make a dumb mistake.
I'm trying to implement a typed INI parser, that will parse this kind of file:
[section1]
<int>intkey=0
<float>floatkey=0.0
<str>stringkey=test
[section2]
<float>x=1.0
<float>y=1.0
<float>z=0.0
In doing so, I have a central class named Config, which handles the basic reading and writing operations. One of the methods of Config is called get(String section, String key), which ideally would return a value appropriate for the requested section-key pair, like so:
Config cfg = new Config("test.ini");
cfg.get("section2", "x"); // 1.0, not "1.0" or some Object that technically represents the float
cfg.get("section1", "intkey"); // 0
cfg.get("section1", "strkey"); // "test"
I'm currently using an enum to handle the conversion of the String to various types, with an abstract method overridden by the different types:
enum Type
{
INTEGER ("int") {
public Object parse(String value) {
try
{
return Integer.parseInt(value);
} catch (NumberFormatException e)
{
return null;
}
}
},
FLOAT ("float") {
public Object parse(String value) {
try
{
return Float.parseFloat(value);
} catch (NumberFormatException e)
{
return null;
}
}
},
STRING ("str") {
public Object parse(String value) {
return value;
}
};
public final String name;
Type(String name)
{
this.name = name;
}
private static HashMap<String, Type> configMap = generateConfigMap();
private static HashMap<String, Type> generateConfigMap()
{
HashMap<String, Type> map = new HashMap<String, Type>();
for (Type type : Type.values())
map.put(type.name, type);
return map;
}
public static Type get(String name)
{
return configMap.get(name);
}
abstract public Object parse(String value);
}
Unfortunately, parse(String value) returns an Object, and when passed out of Config, requires a cast or similar, and ideally this would be self-contained.
If I'm going about this completely wrong and there's a more flexible or simple way to code it, please let me know. I'm open to suggestions. Though I would like to know if there's a way to do this. Maybe with generics...?
Note: I know I'm missing imports and the like. That's not why I'm posting here.
Here's the thing. If the code that calls config.get() doesn't know what type to expect, you can't possibly return anything other than Object since the calling code doesn't know what to expect. Of course you'll have to cast.
Now, if you wanted to design Config in a way that the caller did know what type it was asking for, than that becomes a bit easier. The easiest approach then is to do something like this:
public class Config {
public int getInt(String a, String b) {
return ((Integer)get(a, b)).intValue();
}
}
But until the caller knows what to expect, you really gain nothing from avoiding casts.
If you want to return a a type of object depending on what you get you can do this:
public <T extends MyObject> T myMethod(Class<T> type) {
return type.cast(myObj);
}

What is the best way to compare several javabean properties?

I need to compare dozens of fields in two objects (instances of the same class), and do some logging and updating in case there are differences. Meta code could look something like this:
if (a.getfield1 != b.getfield1)
log(a.getfield1 is different than b.getfield1)
b.field1 = a.field1
if (a.getfield2!= b.getfield2)
log(a.getfield2 is different than b.getfield2)
b.field2 = a.field2
...
if (a.getfieldn!= b.getfieldn)
log(a.getfieldn is different than b.getfieldn)
b.fieldn = a.fieldn
The code with all the comparisons is very terse, and I would like to somehow make it more compact. It would be nice if I could have a method which would take as a parameter method calls to setter and getter, and call this for all fields, but unfortunately this is not possible with java.
I have come up with three options, each which their own drawbacks.
1. Use reflection API to find out getters and setters
Ugly and could cause run time errors in case names of fields change
2. Change fields to public and manipulate them directly without using getters and setters
Ugly as well and would expose implementation of the class to external world
3. Have the containing class (entity) do the comparison, update changed fields and return log message
Entity should not take part in business logic
All fields are String type, and I can modify code of the class owning the fields if required.
EDIT: There are some fields in the class which must not be compared.
Use Annotations.
If you mark the fields that you need to compare (no matter if they are private, you still don't lose the encapsulation, and then get those fields and compare them. It could be as follows:
In the Class that need to be compared:
#ComparableField
private String field1;
#ComparableField
private String field2;
private String field_nocomparable;
And in the external class:
public <T> void compare(T t, T t2) throws IllegalArgumentException,
IllegalAccessException {
Field[] fields = t.getClass().getDeclaredFields();
if (fields != null) {
for (Field field : fields) {
if (field.isAnnotationPresent(ComparableField.class)) {
field.setAccessible(true);
if ( (field.get(t)).equals(field.get(t2)) )
System.out.println("equals");
field.setAccessible(false);
}
}
}
}
The code is not tested, but let me know if helps.
The JavaBeans API is intended to help with introspection. It has been around in one form or another since Java version 1.2 and has been pretty usable since version 1.4.
Demo code that compares a list of properties in two beans:
public static void compareBeans(PrintStream log,
Object bean1, Object bean2, String... propertyNames)
throws IntrospectionException,
IllegalAccessException, InvocationTargetException {
Set<String> names = new HashSet<String>(Arrays
.asList(propertyNames));
BeanInfo beanInfo = Introspector.getBeanInfo(bean1
.getClass());
for (PropertyDescriptor prop : beanInfo
.getPropertyDescriptors()) {
if (names.remove(prop.getName())) {
Method getter = prop.getReadMethod();
Object value1 = getter.invoke(bean1);
Object value2 = getter.invoke(bean2);
if (value1 == value2
|| (value1 != null && value1.equals(value2))) {
continue;
}
log.format("%s: %s is different than %s%n", prop
.getName(), "" + value1, "" + value2);
Method setter = prop.getWriteMethod();
setter.invoke(bean2, value2);
}
}
if (names.size() > 0) {
throw new IllegalArgumentException("" + names);
}
}
Sample invocation:
compareBeans(System.out, bean1, bean2, "foo", "bar");
If you go the annotations route, consider dumping reflection and generating the comparison code with a compile-time annotation processor or some other code generator.
I would go for option 1, but I would use getClass().getDeclaredFields() to access the fields instead of using the names.
public void compareAndUpdate(MyClass other) throws IllegalAccessException {
for (Field field : getClass().getDeclaredFields()) {
if (field.getType() == String.class) {
Object thisValue = field.get(this);
Object otherValue = field.get(other);
// if necessary check for null
if (!thisValue.equals(otherValue)) {
log(field.getName() + ": " + thisValue + " <> " + otherValue);
field.set(other, thisValue);
}
}
}
}
There are some restrictions here (if I'm right):
The compare method has to be implemented in the same class (in my opinion it should - regardless of its implementation) not in an external one.
Just the fields from this class are used, not the one's from a superclass.
Handling of IllegalAccessException necessary (I just throw it in the example above).
This is probably not too nice either, but it's far less evil (IMHO) than either of the two alternatives you've proposed.
How about providing a single getter/setter pair that takes a numeric index field and then have getter/setter dereference the index field to the relevant member variable?
i.e.:
public class MyClass {
public void setMember(int index, String value) {
switch (index) {
...
}
}
public String getMember(int index) {
...
}
static public String getMemberName(int index) {
...
}
}
And then in your external class:
public void compareAndUpdate(MyClass a, MyClass b) {
for (int i = 0; i < a.getMemberCount(); ++i) {
String sa = a.getMember();
String sb = b.getMember();
if (!sa.equals(sb)) {
Log.v("compare", a.getMemberName(i));
b.setMember(i, sa);
}
}
}
This at least allows you to keep all of the important logic in the class that's being examined.
While option 1 may be ugly, it will get the job done. Option 2 is even uglier, and opens your code to vulnerabilities you can't imagine. Even if you eventually rule out option 1, I pray you keep your existing code and not go for option 2.
Having said this, you can use reflection to get a list of the field names of the class, if you don't want to pass this as a static list to the method. Assuming you want to compare all fields, you can then dynamically create the comparisons, in a loop.
If this isn't the case, and the strings you compare are only some of the fields, you can examine the fields further and isolate only those that are of type String, and then proceed to compare.
Hope this helps,
Yuval =8-)
since
All fields are String type, and I can modify code of the class owning the fields if required.
you could try this class:
public class BigEntity {
private final Map<String, String> data;
public LongEntity() {
data = new HashMap<String, String>();
}
public String getFIELD1() {
return data.get(FIELD1);
}
public String getFIELD2() {
return data.get(FIELD2);
}
/* blah blah */
public void cloneAndLogDiffs(BigEntity other) {
for (String field : fields) {
String a = this.get(field);
String b = other.get(field);
if (!a.equals(b)) {
System.out.println("diff " + field);
other.set(field, this.get(field));
}
}
}
private String get(String field) {
String value = data.get(field);
if (value == null) {
value = "";
}
return value;
}
private void set(String field, String value) {
data.put(field, value);
}
#Override
public String toString() {
return data.toString();
}
magic code:
private static final String FIELD1 = "field1";
private static final String FIELD2 = "field2";
private static final String FIELD3 = "field3";
private static final String FIELD4 = "field4";
private static final String FIELDN = "fieldN";
private static final List<String> fields;
static {
fields = new LinkedList<String>();
for (Field field : LongEntity.class.getDeclaredFields()) {
if (field.getType() != String.class) {
continue;
}
if (!Modifier.isStatic(field.getModifiers())) {
continue;
}
fields.add(field.getName().toLowerCase());
}
}
this class has several advantages:
reflects once, at class loading
it is very simply adding new fields, just add new static field (a better solution here
is using Annotations: in the case you care using reflection works also java 1.4)
you could refactor this class in an abstract class, all derived class just get both
data and cloneAndLogDiffs()
the external interface is typesafe (you could also easily impose immutability)
no setAccessible calls: this method is problematic sometimes
A broad thought:
Create a new class whose object takes the following parameters: the first class to compare, the second class to compare, and a lists of getter & setter method names for the objects, where only methods of interest are included.
You can query with reflection the object's class, and from that its available methods. Assuming each getter method in the parameter list is included in the available methods for the class, you should be able to call the method to get the value for comparison.
Roughly sketched out something like (apologies if it isn't super-perfect... not my primary language):
public class MyComparator
{
//NOTE: Class a is the one that will get the value if different
//NOTE: getters and setters arrays must correspond exactly in this example
public static void CompareMyStuff(Object a, Object b, String[] getters, String[] setters)
{
Class a_class = a.getClass();
Class b_class = b.getClass();
//the GetNamesFrom... static methods are defined elsewhere in this class
String[] a_method_names = GetNamesFromMethods(a_class.getMethods());
String[] b_method_names = GetNamesFromMethods(b_class.getMethods());
String[] a_field_names = GetNamesFromFields(a_class.getFields());
//for relative brevity...
Class[] empty_class_arr = new Class[] {};
Object[] empty_obj_arr = new Object[] {};
for (int i = 0; i < getters.length; i++)
{
String getter_name = getter[i];
String setter_name = setter[i];
//NOTE: the ArrayContainsString static method defined elsewhere...
//ensure all matches up well...
if (ArrayContainsString(a_method_names, getter_name) &&
ArrayContainsString(b_method_names, getter_name) &&
ArrayContainsString(a_field_names, setter_name)
{
//get the values from the getter methods
String val_a = a_class.getMethod(getter_name, empty_class_arr).invoke(a, empty_obj_arr);
String val_b = b_class.getMethod(getter_name, empty_class_arr).invoke(b, empty_obj_arr);
if (val_a != val_b)
{
//LOG HERE
//set the value
a_class.getField(setter_name).set(a, val_b);
}
}
else
{
//do something here - bad names for getters and/or setters
}
}
}
}
You say you presently have getters and setters for all these fields? Okay, then change the underlying data from a bunch of individual fields to an array. Change all the getters and setters to access the array. I'd create constant tags for the indexes rather than using numbers for long-term maintainability. Also create a parallel array of flags indicating which fields should be processed. Then create a generic getter/setter pair that use an index, as well as a getter for the compare flag. Something like this:
public class SomeClass
{
final static int NUM_VALUES=3;
final static int FOO=0, BAR=1, PLUGH=2;
String[] values=new String[NUM_VALUES];
static boolean[] wantCompared={true, false, true};
public String getFoo()
{
return values[FOO];
}
public void setFoo(String foo)
{
values[FOO]=foo;
}
... etc ...
public int getValueCount()
{
return NUM_VALUES;
}
public String getValue(int x)
{
return values[x];
}
public void setValue(int x, String value)
{
values[x]=value;
}
public boolean getWantCompared(int x)
{
return wantCompared[x];
}
}
public class CompareClass
{
public void compare(SomeClass sc1, SomeClass sc2)
{
int z=sc1.getValueCount();
for (int x=0;x<z;++x)
{
if (!sc1.getWantCompared[x])
continue;
String sc1Value=sc1.getValue(x);
String sc2Value=sc2.getValue(x);
if (!sc1Value.equals(sc2Value)
{
writeLog(x, sc1Value, sc2Value);
sc2.setValue(x, sc1Value);
}
}
}
}
I just wrote this off the top of my head, I haven't tested it, so their may be bugs in the code, but I think the concept should work.
As you already have getters and setters, any other code using this class should continue to work unchanged. If there is no other code using this class, then throw away the existing getters and setters and just do everything with the array.
I would also propose a similar solution to the one by Alnitak.
If the fields need to be iterated when comparing, why not dispense with the separate fields, and put the data into an array, a HashMap or something similar that is appropriate.
Then you can access them programmatically, compare them etc. If different fields need to be treated & compared in different ways, you could create approriate helper classes for the values, which implement an interface.
Then you could just do
valueMap.get("myobject").compareAndChange(valueMap.get("myotherobject")
or something along those lines...

Categories