patternjavaMinor
Three methods to serialize 7-, 6-, and 3-dimensional int arrays
Viewed 0 times
threearraysserializedimensionalmethodsandint
Problem
Here's some code I wrote which sends multi-dimensional arrays to a file, is there any way I can make a generic method?
public void sendSevenToFile(int[][][][][][][] seven, String filename) throws IOException {
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(filename));
outputStream.writeObject(seven);
}
public void sendSixToFile(int[][][][][][] six, String filename) throws IOException {
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(filename));
outputStream.writeObject(six);
}
public void sendThreeToFile(int[][][] three, String filename) throws IOException {
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(filename));
outputStream.writeObject(three);
}Solution
An array in Java is an object, not a primitive, so you can accept the parameter as
And just in case you want this to be absolutely specific for only
Note that a nice side-effect of this approach is that you can now serialize arrays of arbitrary dimensions!
Note the naming convention - I use
Also, the first
Addendum
The OP asked in the comments as to how to determine the number of dimensions of an array if it has been casted to
I use Java 8
References:
I referred to this StackOverflow answer for the array type verification code.
Object, without specializing it as an array (you do not do that in your current code either, so you do not lose anything by this approach). Yes, you lose some type safety this way, but you can get it back during runtime by using .getClass().isArray(). Overall, my approach is:/**
* Serializes an array of arbitrary dimensions to a file
* @param array the array to serialize
* @param filename the name of the file to serialize array to
* @throws IllegalArgumentException if array is not an array
* @throws IOException if some error was encountered during serialization
*/
public void serializeArrayToFile(Object array, String filename) throws IOException {
if(!array.getClass().isArray()){
throw new IllegalArgumentException("Cannot serialize non-array object " + array.toString());
}
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(filename));
outputStream.writeObject(array);
}And just in case you want this to be absolutely specific for only
int arrays of arbitrary dimensions,/**
* Serializes an array of arbitrary dimensions to a file
* @param array the array to serialize
* @param filename the name of the file to serialize array to
* @throws IllegalArgumentException if array is not an int array
* @throws IOException if some error was encountered during serialization
*/
public void serializeArrayToFile(Object array, String filename) throws IOException {
Class classOfArray = array.getClass();
if(!classOfArray.isArray()){
throw new IllegalArgumentException("Cannot serialize non-array object " + array.toString());
}
Class componentType = classOfArray.getComponentType();
if(!(componentType.isPrimitive() &&
int.class.isAssignableFrom(componentType)) {
// Can also be `UnsupportedOperationException1, depending on required semantics
throw new IllegalArgumentException(String.format(
"Serialization of non-`int` array %s of component type %s is not allowed",
array.toString(), componentType.toString()));
}
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(filename));
outputStream.writeObject(array);
}Note that a nice side-effect of this approach is that you can now serialize arrays of arbitrary dimensions!
Note the naming convention - I use
serialize instead of send, as that is what you are actually doing. Although I do not do it here for purposes of compatibility with the existing project structure, you might consider making this method static as it does not depend on the implicit this.Also, the first
array.toString() isn't required, the string concatenation will do it implicitly, but in my policy for such cases, explicit is better than implicit.Addendum
The OP asked in the comments as to how to determine the number of dimensions of an array if it has been casted to
Object. This is possible via reflection, whether by descending the type hierarchy until the result of .getClass().isArray() is false (slow), or by counting the number of '[' characters in the result of .getClass().getName() (faster). I'll illustrate the second method, which has been suggested by @wizzwizz4 in the comments, as that is more practical in all respects (I do not consider it to be "hacky", as @wizzwizz4 does, as the result of getName() for the class of any array type is explicitly documented as here.public static int getDimensionsOfArray(Object array) {
return (int) array.getClass()
.getName()
.chars()
.filter(c -> c == '[')
.count();
}I use Java 8
Streams here, but you could just as well do it with a loop (I like the declarative approach of using Streams, as my primary language is Scala). The cast to int exists because Stream.count() returns a long, as Streams are lazy and can theoretically hold an infinite number of elements.References:
I referred to this StackOverflow answer for the array type verification code.
Code Snippets
/**
* Serializes an array of arbitrary dimensions to a file
* @param array the array to serialize
* @param filename the name of the file to serialize <code>array</code> to
* @throws IllegalArgumentException if <code>array</code> is not an array
* @throws IOException if some error was encountered during serialization
*/
public void serializeArrayToFile(Object array, String filename) throws IOException {
if(!array.getClass().isArray()){
throw new IllegalArgumentException("Cannot serialize non-array object " + array.toString());
}
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(filename));
outputStream.writeObject(array);
}/**
* Serializes an array of arbitrary dimensions to a file
* @param array the array to serialize
* @param filename the name of the file to serialize <code>array</code> to
* @throws IllegalArgumentException if <code>array</code> is not an <code>int</code> array
* @throws IOException if some error was encountered during serialization
*/
public void serializeArrayToFile(Object array, String filename) throws IOException {
Class<?> classOfArray = array.getClass();
if(!classOfArray.isArray()){
throw new IllegalArgumentException("Cannot serialize non-array object " + array.toString());
}
Class<?> componentType = classOfArray.getComponentType();
if(!(componentType.isPrimitive() &&
int.class.isAssignableFrom(componentType)) {
// Can also be `UnsupportedOperationException1, depending on required semantics
throw new IllegalArgumentException(String.format(
"Serialization of non-`int` array %s of component type %s is not allowed",
array.toString(), componentType.toString()));
}
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(filename));
outputStream.writeObject(array);
}public static int getDimensionsOfArray(Object array) {
return (int) array.getClass()
.getName()
.chars()
.filter(c -> c == '[')
.count();
}Context
StackExchange Code Review Q#158922, answer score: 6
Revisions (0)
No revisions yet.