В Java, как мне узнать, имеет ли объект правильный тип для передачи в качестве параметра метода? Особенно если тип примитивный? - PullRequest
1 голос
/ 14 июля 2020

Я использую отражение для вызова метода в Java. Я хотел бы проверить, имеет ли значение, которое потенциально должно быть передано в метод, правильный тип, прежде чем я вызываю метод.

Моя первоначальная идея заключалась в том, чтобы получить класс параметра через method.getParameterTypes() а затем сравните этот тип с типом объекта, который я хотел бы передать. Если это подкласс, продолжайте.

Однако это не удается для метода, который принимает примитив. Если у меня есть метод:

private void doThing(boolean parp) {}

Возвращаемое значение getParameterTypes для этого указывает, что тип параметра - это класс с именем boolean в модуле java.base. Однако я мог бы захотеть передать значение типа java.lang.Boolean, которое, хотя и вполне законно для передачи, не входит в иерархию типов. java.lang.Boolean не является подклассом и не имеет никакого отношения к boolean.

Какой тест я могу использовать против заданного типа параметра метода и типа заданного объекта, чтобы определить, является ли он допустимым? передать этот объект в метод?

1 Ответ

2 голосов
/ 14 июля 2020

Примерно так:

private static final Map<Class<?>, Class<?>> primitiveToBoxed = new HashMap<>();
static {
  primitiveToBoxed.put(Boolean.TYPE, Boolean.class);
  primitiveToBoxed.put(Character.TYPE, Character.class);
  primitiveToBoxed.put(Byte.TYPE, Byte.class);
  primitiveToBoxed.put(Short.TYPE, Short.class);
  primitiveToBoxed.put(Integer.TYPE, Integer.class);
  primitiveToBoxed.put(Long.TYPE, Long.class);
  primitiveToBoxed.put(Float.TYPE, Float.class);
  primitiveToBoxed.put(Double.TYPE, Double.class);
  primitiveToBoxed.put(Void.TYPE, Void.class);
}

private static final Map<Class<?>, Set<Class<?>>> allowedConversions = new HashMap<>();
static {
  allowedConversions.put(Short.class, setOf(Byte.class));
  allowedConversions.put(Integer.class, setOf(Byte.class, Character.class, Short.class));
  allowedConversions.put(Long.class, setOf(Byte.class, Character.class, Short.class, Integer.class));
  allowedConversions.put(Float.class, setOf(Byte.class, Character.class, Short.class, Integer.class, Long.class));
  allowedConversions.put(Double.class, setOf(Byte.class, Character.class, Short.class, Integer.class, Long.class, Float.class));
}

static <T> Set<T> setOf(T... elements) {
  return new HashSet<>(Arrays.asList(elements));
}

static boolean isCompatible(Class<?> type, Object value) {
  if (type.isPrimitive()) {
    if (value == null) {
      return false;
    }
    type = primitiveToBoxed.get(type);
  }
  return value == null || type.isAssignableFrom(value.getClass())
      || allowedConversions.getOrDefault(type, emptySet()).contains(value.getClass());
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...