【问题标题】:Chaining a method on dynamic call链接动态调用的方法
【发布时间】:2019-12-06 08:25:28
【问题描述】:

假设我在Post entity 上有一个用户列表

private List<User> users = new ArrayList<>();

我可以使用清除它

post.getUsers().clear();

并且可以添加到它

post.getUsers().addAll(Something);

如果使用动态调用函数getUsers,我该怎么做?我试过了

post.getClass().getMethod("getUsers").invoke(post).getClass().getMethod("clear").invoke(new ArrayList<>());

我也试过了

ArrayList.class.getMethod("clear").invoke(post);

但我得到了一个

WARN  o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Resolved [java.lang.IllegalArgumentException: object is not an instance of declaring class]

知道我该怎么做吗?

请注意这是有效的

post.getClass().getMethod("getUsers").invoke(post); //get the users

我只是不知道如何在其上链接 clear 方法或 addAll。

【问题讨论】:

  • 你能告诉我怎么做吗?
  • 应该传递从get users函数返回返回的数组列表对象,用于clear函数的调用

标签: java spring-boot


【解决方案1】:

Method.invoke 返回一个Object,而Object 类没有clear() 方法,因此您需要将返回的对象强制转换为List

Post post = new Post();
Method m = post.getClass().getMethod("getUsers");
List<User> users = (List<User>)m.invoke(post);
users.clear();

而且如果你想要它在一行,它是丑陋的,但可以做到:

((List<User>)(post.getClass().getMethod("getUsers").invoke(post))).clear();

这也有效:

List.class.cast(post.getClass().getMethod("getUsers").invoke(post)).clear();

【讨论】:

  • 抱歉,请假的地方回复晚了。如何在 addAll 上使用它?我试过这个 List.class.cast(getMethodEntity).addAll((Collection>) Objects.requireNonNull(fieldValue));这是有效的,但我有一个警告说未经检查的调用 'addAll(Collection extends E>)' 作为原始类型'java.util.List'的成员
  • @Beginner 这是因为您从invoke 获得的列表没有类型。当您尝试添加User 时,您会收到一条警告,它基本上是在告诉您:“小心,您正在尝试将User 添加到List,我不知道该列表是否是List&lt;User&gt;"。您知道它是 List&lt;User&gt;,因此您可以忽略该警告,或使用注释抑制它。我认为没有办法解决这个问题。没关系。
【解决方案2】:

只需查看ArrayList 的 JavaDocs。

ArrayList.clear() 不返回任何内容,因为它是 void 方法,ArrayList.addAll() 返回 boolean

因此,为了允许方法链接,您必须将调用包装在您的 Post 实体中以返回 post 实体本身。然后你可以得到方法链。

因此,在您的 Post 实体中,您需要添加:

public Post clearUsers() {
    users.clear();
    return this;
}

public Post addAllUsers(List<User> usersToAdd) {
    users.addAll(usersToAdd);
    return this;
}

并调用这些方法而不是getUsers().xyz()(无论如何这是一种非常糟糕的风格。posobject 拥有这些用户。它应该是唯一操纵这些用户的人)。

【讨论】:

  • 换行是什么意思。抱歉,我刚接触 java
【解决方案3】:

您需要在post 包含的数组列表对象上调用这些方法。

例如,您可以在post.getUsers()上调用clear作为

ArrayList.class.getMethod("clear").invoke(
                // this will give you reference to array list contained by post
                post.getClass().getMethod("getUsers").invoke(post)
        );

上面的代码测试如下

public class DynamicInvocation {
    public static void main(String[] args) throws Exception {
        Post post = new Post();
        post.getUsers().add(new User());
        System.out.println(post.getUsers());
        ArrayList.class.getMethod("clear").invoke(
                post.getClass().getMethod("getUsers").invoke(post)
        );
        System.out.println(post.getUsers());
    }
}

class Post {
    private List<User> users = new ArrayList<>();

    public List<User> getUsers() {
        return users;
    }
}

class User {
}

【讨论】:

  • 还是一样我得到错误对象不是声明类的实例
  • @Beginner 添加了运行良好的调用示例。你能再检查一下你的代码吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-06-26
  • 2011-07-09
  • 2017-06-23
  • 1970-01-01
  • 2017-01-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多