Skip to content

Commit f25e92a

Browse files
committed
Migrate ClassUtils.getArrayClass to Types.array
This also changes the behavior of the method to throw IllegalArgumentException, rather than returning null, if something goes wrong with the creation of the array type. But the deprecated method preserves the legacy behavior, for backwards compatibility. The new behavior is more consistent with the other methods of the Types class -- and it is better in general for a reusable library to do proper exception handling. If the behavior is too bothersome, we could add "boolean quietly" flags to every method, but it would rather clutter things.
1 parent b2ac61d commit f25e92a

4 files changed

Lines changed: 69 additions & 31 deletions

File tree

src/main/java/org/scijava/util/ClassUtils.java

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
import java.io.File;
3636
import java.lang.annotation.Annotation;
3737
import java.lang.reflect.AnnotatedElement;
38-
import java.lang.reflect.Array;
3938
import java.lang.reflect.Field;
4039
import java.lang.reflect.Method;
4140
import java.lang.reflect.Type;
@@ -221,25 +220,6 @@ public static Class<?> loadClass(final String name,
221220
}
222221
}
223222

224-
/**
225-
* Gets the array class corresponding to the given element type.
226-
* <p>
227-
* For example, {@code getArrayClass(double.class)} returns
228-
* {@code double[].class}.
229-
* </p>
230-
*/
231-
public static Class<?> getArrayClass(final Class<?> elementClass) {
232-
if (elementClass == null) return null;
233-
// NB: It appears the reflection API has no built-in way to do this.
234-
// So unfortunately, we must allocate a new object and then inspect it.
235-
try {
236-
return Array.newInstance(elementClass, 0).getClass();
237-
}
238-
catch (final IllegalArgumentException exc) {
239-
return null;
240-
}
241-
}
242-
243223
/** Checks whether a class with the given name exists. */
244224
public static boolean hasClass(final String className) {
245225
return hasClass(className, null);
@@ -689,6 +669,15 @@ public static int compare(final Class<?> c1, final Class<?> c2) {
689669

690670
// -- Helper methods --
691671

672+
private static Class<?> arrayOrNull(final Class<?> componentType) {
673+
try {
674+
return Types.array(componentType);
675+
}
676+
catch (final IllegalArgumentException exc) {
677+
return null;
678+
}
679+
}
680+
692681
/**
693682
* Populates the cache of annotated elements for a particular class by looking
694683
* for all inherited and declared instances annotated with the specified
@@ -813,6 +802,12 @@ public static Field getField(final Class<?> c, final String fieldName) {
813802
return Types.field(c, fieldName);
814803
}
815804

805+
/** @deprecated Use {@link Types#array(Class)} instead. */
806+
@Deprecated
807+
public static Class<?> getArrayClass(final Class<?> elementClass) {
808+
return Types.raw(arrayOrNull(elementClass));
809+
}
810+
816811
// -- Helper classes --
817812

818813
/**

src/main/java/org/scijava/util/Types.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,43 @@ public static Field field(final Class<?> c, final String name) {
147147
return field(c.getSuperclass(), name);
148148
}
149149

150+
/**
151+
* Gets the array class corresponding to the given element type.
152+
* <p>
153+
* For example, {@code arrayType(double.class)} returns {@code double[].class}
154+
* .
155+
* </p>
156+
*
157+
* @param componentType The type of elements which the array possesses
158+
* @throws IllegalArgumentException if the type cannot be the component type
159+
* of an array (this is the case e.g. for {@code void.class}).
160+
*/
161+
public static Class<?> array(final Class<?> componentType) {
162+
if (componentType == null) return null;
163+
// NB: It appears the reflection API has no built-in way to do this.
164+
// So unfortunately, we must allocate a new object and then inspect it.
165+
return Array.newInstance(componentType, 0).getClass();
166+
}
167+
168+
/**
169+
* Gets the array type&mdash;which might be a {@link Class} or a
170+
* {@link GenericArrayType} depending on the argument&mdash;corresponding to
171+
* the given element type.
172+
* <p>
173+
* For example, {@code arrayType(double.class)} returns {@code double[].class}
174+
* .
175+
* </p>
176+
*
177+
* @param componentType The type of elements which the array possesses
178+
*/
179+
public static Type array(final Type componentType) {
180+
if (componentType == null) return null;
181+
if (componentType instanceof Class) {
182+
return array((Class<?>) componentType);
183+
}
184+
return new TypeUtils.GenericArrayTypeImpl(componentType);
185+
}
186+
150187
/**
151188
* Gets the component type of the given array type, or null if not an array.
152189
*/

src/test/java/org/scijava/util/ClassUtilsTest.java

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -127,17 +127,6 @@ public void testFailureLoud() {
127127
ClassUtils.loadClass("a.non.existent.class", false);
128128
}
129129

130-
@Test
131-
public void testGetArrayClass() {
132-
assertSame(boolean[].class, ClassUtils.getArrayClass(boolean.class));
133-
assertSame(String[].class, ClassUtils.getArrayClass(String.class));
134-
assertSame(Number[].class, ClassUtils.getArrayClass(Number.class));
135-
assertSame(boolean[][].class, ClassUtils.getArrayClass(boolean[].class));
136-
assertSame(String[][].class, ClassUtils.getArrayClass(String[].class));
137-
assertSame(Number[][].class, ClassUtils.getArrayClass(Number[].class));
138-
assertNull(ClassUtils.getArrayClass(void.class));
139-
}
140-
141130
@Test
142131
public void testUnpackedClass() throws IOException {
143132
final File tmpDir = createTemporaryDirectory("class-utils-test-");

src/test/java/org/scijava/util/TypesTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import static org.junit.Assert.assertEquals;
3636
import static org.junit.Assert.assertNull;
3737
import static org.junit.Assert.assertSame;
38+
import static org.junit.Assert.fail;
3839

3940
import java.io.Serializable;
4041
import java.lang.reflect.Field;
@@ -133,6 +134,22 @@ public void testRaws() {
133134
Serializable.class, Cloneable.class);
134135
}
135136

137+
/** Tests {@link Types#array}. */
138+
@Test
139+
public void testArray() {
140+
assertSame(boolean[].class, Types.array(boolean.class));
141+
assertSame(String[].class, Types.array(String.class));
142+
assertSame(Number[].class, Types.array(Number.class));
143+
assertSame(boolean[][].class, Types.array(boolean[].class));
144+
assertSame(String[][].class, Types.array(String[].class));
145+
assertSame(Number[][].class, Types.array(Number[].class));
146+
try {
147+
Types.array(void.class);
148+
fail("Unexpected success creating void[]");
149+
}
150+
catch (final IllegalArgumentException exc) { }
151+
}
152+
136153
/** Tests {@link Types#param}. */
137154
@Test
138155
public void testParam() {

0 commit comments

Comments
 (0)