Refactoring methods that use the same code but different types

You can apply the Strategy pattern here.

interface TypeDependentBehavior<T> {
   void setFieldValue(PreparedStatement st, T value);
}

interface StringBehavior extends TypeDependentBehavior<String> {
   void setFieldValue(PreparedStatement st, String value) {
     st.setString(3, value);
   }
}    

interface IntBehavior extends TypeDependentBehavior<Integer> {
   void setFieldValue(PreparedStatement st, Integer value) {
     st.setInt(3, value);
   }
}

...

public static void saveArray<T>(Connection con, int playerID, String tableName, String fieldName, T[] array, T[] originalArray, TypeDependentBehavior<T> behavior) {
 try {
        for (int i = 0; i < array.length; i++) {
            // Check for change before running query
            if (array[i] != originalArray[i]) {
                if (array[i] != 0 && array[i] != -1) {
                    PreparedStatement updateQuery = con.prepareStatement("REPLACE INTO `" + tableName + "` (`player_id`, `index`, `" + fieldName + "`) VALUES(?, ?, ?)");
                    updateQuery.setInt(1, playerID);
                    updateQuery.setInt(2, i);
                    behavior.setFieldValue(updateQuery, array[i]);
                    updateQuery.execute();
                } else {
                    PreparedStatement deleteQuery = con.prepareStatement("DELETE FROM `" + tableName + "` WHERE `player_id` = ? AND `index` = ?");
                    deleteQuery.setInt(1, playerID);
                    deleteQuery.setInt(2, i);
                    deleteQuery.execute();
                }

                originalArray[i] = array[i];
            }
        }
    } catch (SQLException ex) {
        Logger.getLogger(PlayerSaveHandler.class.getName()).log(Level.SEVERE, "SQL Exception while saving an int array!", ex);
    }
}

You can use generics for that, for example

void doSomething(int[] array) {
    for (int i = 0; i < array.length; i++)
        System.out.println(array[i]);
}

void doSomething(long[] array) {
    for (int i = 0; i < array.length; i++)
        System.out.println(array[i]);
}

can be generalized into

<T> void doSomething(T[] array) {
    for (int i = 0; i < array.length; i++)
        System.out.println(array[i]);
}

Now you can call

int[] array1 = new int[] { 1, 2, 3 };
doSomething(array1);

long[] array2 = new long[] { 1L, 2L, 3L };
doSomething(array2);

String[] array3 = new String[] { "one", "two", "three" };
doSomething(array3);

But you should check your method implementation and make sure that it will still work with any array type, especially the SQL statement.


I would just use long[] instead of int[]. The memory difference is very small compared with the cost of using JDBC.

If you need to handle String you can use an object type.

public static void saveArray(Connection con, int playerID, String tableName, 
    String fieldName, Object[] array, Object[] originalArray) {

If you want one method for long[] and Object[] you can use the Array.getLength() and Array.get() method to access all array types generically. This could add more complexity than it saves.