Skip to content

Commit 8719512

Browse files
committed
Make canCast support auto-unboxing
This behavior is especially important for conversion with constructors when the constructor accepts primitive type while a Number is given. See conversion from int to net.imglib2.type.number.integer.IntType for example.
1 parent 8a15335 commit 8719512

File tree

3 files changed

+34
-4
lines changed

3 files changed

+34
-4
lines changed

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,10 @@ public static <T> T cast(final Object src, final Class<T> dest) {
106106
*/
107107
public static boolean canCast(final Class<?> src, final Class<?> dest) {
108108
if (dest == null) return false;
109-
return src == null || dest.isAssignableFrom(src);
109+
if (src == null) return true;
110+
final Class<?> saneSrc = getNonprimitiveType(src);
111+
final Class<?> saneDest = getNonprimitiveType(dest);
112+
return saneDest.isAssignableFrom(saneSrc);
110113
}
111114

112115
/**

src/test/java/org/scijava/convert/ConvertServiceTest.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,22 @@ class Struct {
498498
setFieldValue(struct, "singleValue", new int[] { 4, 8, 2 });
499499
}
500500

501+
/**
502+
* Test behavior when setting a single element field with a constructor that
503+
* accepts a primitive type (int).
504+
*/
505+
@Test
506+
public void testLegitimateSingletonInt() {
507+
class Struct {
508+
509+
private IntWrapper intWrapper;
510+
}
511+
final Struct struct = new Struct();
512+
513+
setFieldValue(struct, "intWrapper", Integer.valueOf(12));
514+
assertNotNull(struct.intWrapper);
515+
}
516+
501517
/**
502518
* Test behavior when setting a single element field with a constructor that
503519
* accepts a primitive array.
@@ -628,6 +644,18 @@ private static interface INumberList extends List<Number> {
628644
// NB: No implementation needed.
629645
}
630646

647+
/**
648+
* Dummy class with an int constructor to ensure that when converting using
649+
* constructors, auto-unboxing should work as expected.
650+
*/
651+
public static class IntWrapper {
652+
653+
@SuppressWarnings("unused")
654+
public IntWrapper(final int gonnaWrapThisInt) {
655+
// nothing to do
656+
}
657+
}
658+
631659
/**
632660
* Dummy class with an array constructor to ensure that the logic to
633661
* recursively convert arrays doesn't consume the array improperly when it

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,8 @@ public void testCanCast() {
7373
assertFalse(ConversionUtils.canCast(double.class, float.class));
7474
assertFalse(ConversionUtils.canCast(float.class, double.class));
7575

76-
// boxing is not reported to work
77-
// TODO: Consider changing this behavior.
78-
assertFalse(ConversionUtils.canCast(int.class, Number.class));
76+
// check casting with boxing
77+
assertTrue(ConversionUtils.canCast(int.class, Number.class));
7978

8079
// casting from null always works
8180
final Class<?> nullClass = null;

0 commit comments

Comments
 (0)