Универсальный метод Java для примитивов - PullRequest
2 голосов
/ 26 августа 2011

У меня есть очень креативное решение, позволяющее моему неподписанному коду получать доступ через мою подписанную библиотеку. Хотя это плохая практика, я боюсь, что у меня нет другого решения (кроме переписывания большого количества кода, который затем необходимо переписать обратно).

У меня есть следующий класс:

public abstract class full {
    public static <T,S,P> S access(final T object, final String function, final P parameter) {
        AccessController.doPrivileged(new PrivilegedAction<S>() {
            @Override
            public S run() {
                try {
                    if (parameter == null) {
                        Class[] argTypes = { };
                        Object passedArgv[] = { };
                        return (S)object.getClass().getMethod(function, argTypes).invoke(object, passedArgv);
                    } else {
                        Class[] argTypes = { parameter.getClass() };
                        Object passedArgv[] = { parameter };
                        return (S)object.getClass().getMethod(function, argTypes).invoke(object, passedArgv);
                    }
                } catch (NoSuchMethodException ex) {
                    Logger.getLogger(full.class.getName()).log(Level.SEVERE, null, ex);
                } catch (SecurityException ex) {
                    Logger.getLogger(full.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IllegalAccessException ex) {
                    Logger.getLogger(full.class.getName()).log(Level.SEVERE, null, ex);
                } catch (InvocationTargetException ex) {
                    Logger.getLogger(full.class.getName()).log(Level.SEVERE, null, ex);
                }
                return null;
            }
        });
        return null;
    }
}

Отлично работает для функций, которые возвращают объекты, но не для примитивов. Boolean bool = full.access (..); приведет к нулевому указателю, потому что универсальные методы не могут обрабатывать примитивы.

Есть идеи о том, как выбрать правильный подход?

Для проверки:

public static Boolean test() {
    return true;
}

public Main() {
    System.out.println(((Boolean)redirect.full.access(this, "test", null)));
}

Ответы [ 2 ]

1 голос
/ 26 августа 2011

Причина, по которой вы получаете NullPointerException, заключается в том, что вы всегда возвращаете null.Вы звоните doPrivileged(...), но null все еще возвращается.Попробуйте вернуть результат doPrivileged(...).Судя по всему, Auto (un) boxing работает здесь как на входах, так и на возвращаемых выходах.

Это сработало для меня (я передал примитив int и ожидал примитивного логического значения):

public class ATest
{
    public static void main(String[] args) throws UnsupportedEncodingException
    {
        int i = 5;
        Object equals = new Object();

        boolean b = full.access(i, "equals", equals);

        System.out.println(b);
    }

    public static class full
    {
        public static <T, S, P> S access(final T object, final String function, final P parameter)
        {
            return AccessController.doPrivileged(new PrivilegedAction<S>()
            {
                @Override
                public S run()
                {
                    try
                    {
                        if (parameter == null)
                        {
                            Class[] argTypes = {};
                            Object passedArgv[] = {};
                            return (S) object.getClass().getMethod(function, argTypes)
                                    .invoke(object, passedArgv);
                        }
                        else
                        {
                            Class[] argTypes = { parameter.getClass() };
                            Object passedArgv[] = { parameter };
                            return (S) object.getClass().getMethod(function, argTypes)
                                    .invoke(object, passedArgv);
                        }
                    }
                    catch (NoSuchMethodException ex)
                    {
                        Logger.getLogger(full.class.getName()).log(Level.ALL, null, ex);
                    }
                    catch (SecurityException ex)
                    {
                        Logger.getLogger(full.class.getName()).log(Level.ALL, null, ex);
                    }
                    catch (IllegalAccessException ex)
                    {
                        Logger.getLogger(full.class.getName()).log(Level.ALL, null, ex);
                    }
                    catch (InvocationTargetException ex)
                    {
                        Logger.getLogger(full.class.getName()).log(Level.ALL, null, ex);
                    }
                    return null;
                }
            });
        }
    }
}

С другой стороны, вы можете сделать это более надежным.Когда я передал Integer вместо Object, метод equals не был найден, хотя это был бы допустимый вызов метода.Если вы не нашли метод с указанным Class, вам следует снова проверить с родительскими классами классов.

1 голос
/ 26 августа 2011

Не для этого ли примитивные классы?(Boolean, Integer ...) Я не уверен, что они это сделают, я не проверял.

Длинный ответ: сделайте клон всех этих методов для возврата примитивов.1004 * или намного короче;Вы можете просто обернуть примитивный тип, который вы хотите, в объект, то есть сделать что-то вроде:

public class MyInt {
    public int intValue;
}
...