Skip to content

Commit 4aefc55

Browse files
committed
Migrate casting ConversionUtils methods to Types
The following methods moved: * ConversionUtils#canAssign(Class, Class) -> Types.isAssignable(Type, Type) * ConversionUtils#canCast(Class, Class) -> Types.isAssignable(Type, Type) * ConversionUtils#canAssign(Object, Class) -> Types.isInstance(Object, Class) * ConversionUtils#canCast(Object, Class) -> Types.isInstance(Object, Class) * ConversionUtils#cast(Object, Class) -> Types.cast(Object, class) Note that Types.isAssignable(Type, Type) already existed; this migration simply deprecates the ConversionUtils method and moves the unit tests. This also changes Types.isAssignable to throw NullPointerException if a null destination type is given, since it never makes sense to cast from anything to a null type.
1 parent f8875f5 commit 4aefc55

File tree

4 files changed

+140
-117
lines changed

4 files changed

+140
-117
lines changed

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

Lines changed: 39 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -87,63 +87,6 @@ public static <T> T convertToEnum(final String src, final Class<T> dest) {
8787
}
8888
}
8989

90-
/**
91-
* Casts the given object to the specified type, or null if the types are
92-
* incompatible.
93-
*/
94-
public static <T> T cast(final Object src, final Class<T> dest) {
95-
if (!canCast(src, dest)) return null;
96-
@SuppressWarnings("unchecked")
97-
final T result = (T) src;
98-
return result;
99-
}
100-
101-
/**
102-
* Checks whether objects of the given class can be assigned to the specified
103-
* type. Unlike {@link Class#isAssignableFrom(Class)}, this method considers
104-
* auto-unboxing.
105-
*
106-
* @return true If the destination class is assignable from the source one, or
107-
* if the source class is null and destination class is non-null.
108-
*/
109-
public static boolean canAssign(final Class<?> src, final Class<?> dest) {
110-
return canCast(src, dest);
111-
}
112-
113-
/**
114-
* Checks whether the given object can be assigned to the specified type.
115-
* Unlike {@link Class#isAssignableFrom(Class)}, this method considers
116-
* auto-unboxing.
117-
*
118-
* @return true If the destination class is assignable from the source
119-
* object's class, or if the source object is null and destionation
120-
* class is non-null.
121-
*/
122-
public static boolean canAssign(final Object src, final Class<?> dest) {
123-
return canCast(src, dest);
124-
}
125-
126-
/**
127-
* @deprecated use {@link #canAssign(Class, Class)} instead
128-
*/
129-
@Deprecated
130-
public static boolean canCast(final Class<?> src, final Class<?> dest) {
131-
if (dest == null) return false;
132-
if (src == null) return true;
133-
final Class<?> saneSrc = getNonprimitiveType(src);
134-
final Class<?> saneDest = getNonprimitiveType(dest);
135-
return saneDest.isAssignableFrom(saneSrc);
136-
}
137-
138-
/**
139-
* @deprecated use {@link #canAssign(Object, Class)} instead
140-
*/
141-
@Deprecated
142-
public static boolean canCast(final Object src, final Class<?> dest) {
143-
if (dest == null) return false;
144-
return src == null || canCast(src.getClass(), dest);
145-
}
146-
14790
// -- ConvertService setter --
14891

14992
/**
@@ -152,8 +95,8 @@ public static boolean canCast(final Object src, final Class<?> dest) {
15295
public static void setDelegateService(final ConvertService convertService,
15396
final double priority)
15497
{
155-
if (ConversionUtils.convertService == null ||
156-
Double.compare(priority, servicePriority) > 0)
98+
if (ConversionUtils.convertService == null || Double.compare(priority,
99+
servicePriority) > 0)
157100
{
158101
ConversionUtils.convertService = convertService;
159102
servicePriority = priority;
@@ -228,6 +171,42 @@ public static Class<?> getClass(final Type type) {
228171
return Types.raw(type);
229172
}
230173

174+
/** @deprecated use {@link Types#cast} */
175+
@Deprecated
176+
public static <T> T cast(final Object src, final Class<T> dest) {
177+
if (!canCast(src, dest)) return null;
178+
@SuppressWarnings("unchecked")
179+
final T result = (T) src;
180+
return result;
181+
}
182+
183+
/** @deprecated use {@link Types#isAssignable} */
184+
@Deprecated
185+
public static boolean canAssign(final Class<?> src, final Class<?> dest) {
186+
return canCast(src, dest);
187+
}
188+
189+
/** @deprecated use {@link Types#isInstance} */
190+
@Deprecated
191+
public static boolean canAssign(final Object src, final Class<?> dest) {
192+
return canCast(src, dest);
193+
}
194+
195+
/** @deprecated use {@link Types#isAssignable} */
196+
@Deprecated
197+
public static boolean canCast(final Class<?> src, final Class<?> dest) {
198+
if (dest == null) return false;
199+
if (src == null) return true;
200+
return Types.isAssignable(Types.box(src), Types.box(dest));
201+
}
202+
203+
/** @deprecated use {@link Types#isInstance} */
204+
@Deprecated
205+
public static boolean canCast(final Object src, final Class<?> dest) {
206+
if (dest == null) return false;
207+
return src == null || canCast(src.getClass(), dest);
208+
}
209+
231210
/** @deprecated use {@link Types#raws} and {@link Types#component} */
232211
@Deprecated
233212
public static Class<?> getComponentClass(final Type type) {
@@ -252,7 +231,7 @@ public static <T> T getNullValue(final Class<T> type) {
252231
return Types.nullValue(type);
253232
}
254233

255-
//-- Helper methods --
234+
// -- Helper methods --
256235

257236
/**
258237
* Gets the {@link Converter} to use for the given conversion request. If the

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,30 @@ public static boolean isAssignable(final Type source, final Type target) {
546546
return TypeUtils.isAssignable(source, target);
547547
}
548548

549+
/**
550+
* Checks whether the given object can be cast to the specified type.
551+
*
552+
* @return true If the destination class is assignable from the source
553+
* object's class, or if the source object is null and destination
554+
* class is non-null.
555+
* @see #cast(Object, Class)
556+
*/
557+
public static boolean isInstance(final Object obj, final Class<?> dest) {
558+
if (dest == null) return false;
559+
return obj == null || dest.isInstance(obj);
560+
}
561+
562+
/**
563+
* Casts the given object to the specified type, or null if the types are
564+
* incompatible.
565+
*/
566+
public static <T> T cast(final Object src, final Class<T> dest) {
567+
if (!isInstance(src, dest)) return null;
568+
@SuppressWarnings("unchecked")
569+
final T result = (T) src;
570+
return result;
571+
}
572+
549573
/**
550574
* Creates a new {@link ParameterizedType} of the given class together with
551575
* the specified type arguments.
@@ -978,8 +1002,12 @@ public int hashCode() {
9781002
* @param type the subject type to be assigned to the target type
9791003
* @param toType the target type
9801004
* @return {@code true} if {@code type} is assignable to {@code toType}.
1005+
* @throws NullPointerException if {@code toType} is null.
9811006
*/
9821007
public static boolean isAssignable(final Type type, final Type toType) {
1008+
if (toType == null) {
1009+
throw new NullPointerException("Destination type is null");
1010+
}
9831011
return isAssignable(type, toType, null);
9841012
}
9851013

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

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -57,63 +57,6 @@
5757
*/
5858
public class ConversionUtilsTest {
5959

60-
/** Tests {@link ConversionUtils#canCast(Class, Class)}. */
61-
@Test
62-
public void testCanCast() {
63-
// check casting to superclass
64-
assertTrue(ConversionUtils.canCast(String.class, Object.class));
65-
66-
// check casting to interface
67-
assertTrue(ConversionUtils.canCast(ArrayList.class, Collection.class));
68-
69-
// casting numeric primitives is not supported
70-
assertFalse(ConversionUtils.canCast(double.class, float.class));
71-
assertFalse(ConversionUtils.canCast(float.class, double.class));
72-
73-
// check casting with boxing
74-
assertTrue(ConversionUtils.canCast(int.class, Number.class));
75-
76-
// casting from null always works
77-
final Class<?> nullClass = null;
78-
assertTrue(ConversionUtils.canCast(nullClass, Object.class));
79-
assertTrue(ConversionUtils.canCast(nullClass, int[].class));
80-
final Object nullObject = null;
81-
assertTrue(ConversionUtils.canCast(nullObject, Object.class));
82-
assertTrue(ConversionUtils.canCast(nullObject, int[].class));
83-
84-
// casting to null is not allowed
85-
assertFalse(ConversionUtils.canCast(nullClass, null));
86-
assertFalse(ConversionUtils.canCast(Object.class, null));
87-
assertFalse(ConversionUtils.canCast(nullObject, null));
88-
assertFalse(ConversionUtils.canCast(new Object(), null));
89-
}
90-
91-
/** Tests {@link ConversionUtils#cast(Object, Class)}. */
92-
@Test
93-
public void testCast() {
94-
// check casting to superclass
95-
final String string = "Hello";
96-
final Object stringToObject = ConversionUtils.cast(string, Object.class);
97-
assertSame(string, stringToObject);
98-
99-
// check casting to interface
100-
final ArrayList<?> arrayList = new ArrayList<>();
101-
final Collection<?> arrayListToCollection =
102-
ConversionUtils.cast(arrayList, Collection.class);
103-
assertSame(arrayList, arrayListToCollection);
104-
105-
// casting numeric primitives is not supported
106-
final Float doubleToFloat = ConversionUtils.cast(5.1, float.class);
107-
assertNull(doubleToFloat);
108-
final Double floatToDouble = ConversionUtils.cast(5.1f, double.class);
109-
assertNull(floatToDouble);
110-
111-
// boxing works though
112-
final Number intToNumber = ConversionUtils.cast(5, Number.class);
113-
assertSame(Integer.class, intToNumber.getClass());
114-
assertEquals(5, intToNumber.intValue());
115-
}
116-
11760
/** Tests {@link ConversionUtils#convertToEnum(String, Class)}. */
11861
@Test
11962
public void testConvertToEnum() {

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

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,79 @@ class Struct {
389389
assertSame(int[].class, paramClass);
390390
}
391391

392+
/** Tests {@link Types#isAssignable(Type, Type)}. */
393+
@Test
394+
public void testIsAssignable() {
395+
// check casting to superclass
396+
assertTrue(Types.isAssignable(String.class, Object.class));
397+
398+
// check casting to interface
399+
assertTrue(Types.isAssignable(ArrayList.class, Collection.class));
400+
401+
// casting numeric primitives is not supported
402+
assertFalse(Types.isAssignable(double.class, float.class));
403+
assertFalse(Types.isAssignable(float.class, double.class));
404+
405+
// boxing is not reported to work
406+
// TODO: Consider changing this behavior.
407+
assertFalse(Types.isAssignable(int.class, Number.class));
408+
409+
// casting from null always works
410+
assertTrue(Types.isAssignable(null, Object.class));
411+
assertTrue(Types.isAssignable(null, int[].class));
412+
}
413+
414+
/** Tests {@link Types#isAssignable(Type, Type)} from null to null. */
415+
@Test(expected = NullPointerException.class)
416+
public void testIsAssignableNullToNull() {
417+
Types.isAssignable(null, null);
418+
}
419+
420+
/** Tests {@link Types#isAssignable(Type, Type)} from Class to null. */
421+
@Test(expected = NullPointerException.class)
422+
public void testIsAssignableClassToNull() {
423+
Types.isAssignable(Object.class, null);
424+
}
425+
426+
/** Tests {@link Types#isInstance(Object, Class)}. */
427+
@Test
428+
public void testIsInstance() {
429+
// casting from null always works
430+
final Object nullObject = null;
431+
assertTrue(Types.isInstance(nullObject, Object.class));
432+
assertTrue(Types.isInstance(nullObject, int[].class));
433+
434+
// casting to null is not allowed
435+
assertFalse(Types.isInstance(nullObject, null));
436+
assertFalse(Types.isInstance(new Object(), null));
437+
}
438+
439+
/** Tests {@link Types#cast(Object, Class)}. */
440+
@Test
441+
public void testCast() {
442+
// check casting to superclass
443+
final String string = "Hello";
444+
final Object stringToObject = Types.cast(string, Object.class);
445+
assertSame(string, stringToObject);
446+
447+
// check casting to interface
448+
final ArrayList<?> arrayList = new ArrayList<>();
449+
final Collection<?> arrayListToCollection = //
450+
Types.cast(arrayList, Collection.class);
451+
assertSame(arrayList, arrayListToCollection);
452+
453+
// casting numeric primitives is not supported
454+
final Float doubleToFloat = Types.cast(5.1, float.class);
455+
assertNull(doubleToFloat);
456+
final Double floatToDouble = Types.cast(5.1f, double.class);
457+
assertNull(floatToDouble);
458+
459+
// boxing works though
460+
final Number intToNumber = Types.cast(5, Number.class);
461+
assertSame(Integer.class, intToNumber.getClass());
462+
assertEquals(5, intToNumber.intValue());
463+
}
464+
392465
// -- Helper classes --
393466

394467
private static class Thing<T> {

0 commit comments

Comments
 (0)