【问题标题】:Java generic method for primitives原语的 Java 泛型方法
【发布时间】:2011-08-26 18:29:53
【问题描述】:

我有一个非常有创意的解决方案,允许我的未签名代码通过我的签名库进行所有访问。虽然不好的做法,但我担心我没有其他解决方案(除了重写很多代码,然后需要重写)。

我有以下课程:

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)));
}

【问题讨论】:

  • Boolean 类型不是原始类型(这就是它可以为 null 的原因),而是围绕 bool 的包装类。 bool 类型是一个原始类型——因此,NPE 位于别处。

标签: java generics methods primitive


【解决方案1】:

您获得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 的方法,则应再次检查类的父类。

【讨论】:

  • 谢谢!完全忽略了这一点! 掌心
  • 我还没有尝试过,但我认为它应该可以正常工作。我认为 void 函数比较麻烦。
【解决方案2】:

这不是原始类的用途吗? (布尔值,整数...)我不确定他们是否会这样做,我没有检查过。

长答案:克隆所有这些方法以返回原语。

或者更短;您可以将所需的原始类型包装在一个对象中,即执行以下操作:

public class MyInt {
    public int intValue;
}

【讨论】:

  • 这是一种方法。但是它需要传递一个类作为参数,所以我可以看到返回值是什么类型,然后适当地包装它。如果没有其他选项可用,我会试试这个。
猜你喜欢
  • 2012-08-29
  • 1970-01-01
  • 1970-01-01
  • 2016-03-02
  • 1970-01-01
  • 2014-01-12
  • 1970-01-01
  • 2010-09-16
相关资源
最近更新 更多