Другой общий случай, когда можно получить это исключение, включает в себя насмешливые классы во время модульного тестирования. Независимо от используемой насмешливой структуры, вы должны убедиться, что все соответствующие уровни иерархии классов должным образом высмеиваются. В частности, все свойства HttpContext
, на которые ссылается тестируемый код, должны быть изделены.
См. « Исключение NullReferenceException при проверке пользовательского AuthorizationAttribute » для несколько подробного примера.
Используйте Integer.TYPE
вместо Integer.class
.
В соответствии с Javadocs это «экземпляр класса, представляющий примитивный тип int
».
Вы также можете использовать int.class
. Это ярлык для Integer.TYPE
. Не только классы, даже для примитивных типов, вы можете сказать type.class
в Java.
Поскольку примитивные типы являются автобоксами, вызов getConstructor(java.lang.Class<?>... parameterTypes)
завершится с ошибкой. Вам нужно будет вручную прокрутить доступные конструкторы. Если все типы совпадают, вы в порядке. Если некоторые типы не совпадают, но требуемый тип является примитивным И доступным типом является соответствующий класс-оболочка, тогда вы можете использовать этот конструктор. См. Ниже:
static <C> Constructor<C> getAppropriateConstructor(Class<C> c, Object[] initArgs){
if(initArgs == null)
initArgs = new Object[0];
for(Constructor con : c.getDeclaredConstructors()){
Class[] types = con.getParameterTypes();
if(types.length!=initArgs.length)
continue;
boolean match = true;
for(int i = 0; i < types.length; i++){
Class need = types[i], got = initArgs[i].getClass();
if(!need.isAssignableFrom(got)){
if(need.isPrimitive()){
match = (int.class.equals(need) && Integer.class.equals(got))
|| (long.class.equals(need) && Long.class.equals(got))
|| (char.class.equals(need) && Character.class.equals(got))
|| (short.class.equals(need) && Short.class.equals(got))
|| (boolean.class.equals(need) && Boolean.class.equals(got))
|| (byte.class.equals(need) && Byte.class.equals(got));
}else{
match = false;
}
}
if(!match)
break;
}
if(match)
return con;
}
throw new IllegalArgumentException("Cannot find an appropriate constructor for class " + c + " and arguments " + Arrays.toString(initArgs));
}
Если значение примитива int
автобоксировано в объект Integer
, оно больше не является примитивным. Вы не можете указать из экземпляра Integer
, было ли это int
в какой-то момент.
Я бы предложил передать два массива в метод test
: один с типами и другой со значениями. Он также устранит двусмысленность, если у вас есть конструктор MyClass(Object)
и значение строки передачи (getConstructor
будет искать конструктор String
). Кроме того, вы не можете определить ожидаемый тип параметра, если значение параметра равно null.
Для ссылки на примитивные типы используйте, например:
Integer.TYPE;
Вам нужно знать, какие аргументы, переданные в ваш метод, являются примитивными значениями. Вы можете сделать это с помощью:
object.getClass().isPrimitive()
вы можете написать
int[].class.getComponentType()
или
Integer.TYPE
или
int.class