Java: разрешение методов во время выполнения

Я работаю над динамическим вызовом кода через интерпретатор и попадаю в неприятные области разрешения методов, обсуждаемые в разделе 15.12 JLS.

"Простой" способ выбрать метод - это когда вы знаете точные типы всех аргументов, и тогда вы можете использовать Class.getDeclaredMethod(String name, Class[] parameterTypes). Возможно, вам придется проверить доступность метода и суперклассы/суперинтерфейсы класса.

Но это не охватывает ни один из следующих случаев, так что это бесполезно:

  • боксирование/небоксирование примитивов
  • подтипы
  • varargs
  • нулевой аргумент (который может быть любого типа, если интерпретатор не знает иначе; во время компиляции любая двусмысленность будет устранена приведением null к классу/интерфейсу)
  • примитивное преобразование типов (не является частью Java, но допустимо в контексте языков - напр. например, Rhino Javascript, где все числа с плавающей точкой, поэтому код Java может принимать int, но вызывающая сторона передает число, которое является либо int, либо double)

(см. ниже быстрый пример первых трех)

Итак, теперь мне нужно написать свою собственную библиотеку разрешения методов...

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

package com.example.test.reflect;

import java.lang.reflect.Method;

public class MethodResolutionTest {
    public void compute(int i)              { /* implementation... */ }
    public void compute(Long l)             { /* implementation... */ }
    public void compute(Object obj)         { /* implementation... */ }
    public void compute(String... strings)  { /* implementation... */ }

    public static void main(String[] args) {
        Class<?> cl = MethodResolutionTest.class;

        /* these succeed */
        findAndPrintMethod(cl, "compute", int.class);
        findAndPrintMethod(cl, "compute", Long.class);
        findAndPrintMethod(cl, "compute", Object.class);
        findAndPrintMethod(cl, "compute", String[].class);

        /* these fail */
        findAndPrintMethod(cl, "compute", Integer.class);
        findAndPrintMethod(cl, "compute", long.class);
        findAndPrintMethod(cl, "compute", MethodResolutionTest.class);
        findAndPrintMethod(cl, "compute", String.class, String.class);
    }
    private static void findAndPrintMethod(Class<?> objectClass, 
            String methodName, Class<?>... parameterTypes) 
    {
        try {
            Method method = findMethod(objectClass, methodName, 
                   parameterTypes);
            System.out.println(method.toString());
        }
        catch (SecurityException e) {
            e.printStackTrace();
        }
        catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
    private static Method findMethod(Class<?> objectClass, 
            String methodName, Class<?>[] parameterTypes) 
        throws SecurityException, NoSuchMethodException 
    {
        return objectClass.getDeclaredMethod(methodName, parameterTypes);
    }
}
15
задан reevesy 16 June 2012 в 11:35
поделиться