从匿名 Java 类改变原始变量的合理方法是什么?

发布于 2024-08-31 08:36:07 字数 677 浏览 1 评论 0原文

我想编写以下代码:

boolean found = false;
search(new SearchCallback() {
  @Override void onFound(Object o) { found = true; }
});

显然这是不允许的,因为 found 需要是 final。出于线程安全原因,我无法将 found 设置为成员字段。最好的选择是什么?一种解决方法是定义,

final class MutableReference<T> {
  private T value;
  MutableReference(T value) { this.value = value; }
  T get() { return value; }
  void set(T value) { this.value = value; }
}

但如果格式正确,这最终会占用大量空间,如果可能的话,我宁愿不重新发明轮子。我可以将 List 与单个元素一起使用(要么改变该元素,要么清空列表),甚至可以使用 Boolean[1]。但一切似乎都很奇怪,因为没有一个选项按照预期使用。

这样做的合理方法是什么?

I would like to write the following code:

boolean found = false;
search(new SearchCallback() {
  @Override void onFound(Object o) { found = true; }
});

Obviously this is not allowed, since found needs to be final. I can't make found a member field for thread-safety reasons. What is the best alternative? One workaround is to define

final class MutableReference<T> {
  private T value;
  MutableReference(T value) { this.value = value; }
  T get() { return value; }
  void set(T value) { this.value = value; }
}

but this ends up taking a lot of space when formatted properly, and I'd rather not reinvent the wheel if at all possible. I could use a List<Boolean> with a single element (either mutating that element, or else emptying the list) or even a Boolean[1]. But everything seems to smell funny, since none of the options are being used as they were intended.

What is a reasonable way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

時窥 2024-09-07 08:36:07

我倾向于使用您提到的 boolean[1] 方法:

final boolean[] found = {false};
search(new SearchCallback() {
  @Override void onFound(Object o) { found[0] = true; }
});

这有点黑客,但它往往是最接近您实际想要的东西

I tend to do the boolean[1] method you mentioned:

final boolean[] found = {false};
search(new SearchCallback() {
  @Override void onFound(Object o) { found[0] = true; }
});

It's a bit hackish, but it tends to be the closest thing to what you actually want

灼痛 2024-09-07 08:36:07

你可以使用所有功能:

Boolean found = search(new SearchCallback<Boolean>() {
    @Override Boolean onFound(Object o) { return true; }
});

通常,如果你想改变一个封闭变量,你可以通过不这样做来更清楚地表达解决方案。

You could go all functional:

Boolean found = search(new SearchCallback<Boolean>() {
    @Override Boolean onFound(Object o) { return true; }
});

Usually if you want to mutate an enclosing variable, you can express a solution more clearly by not doing so.

人间不值得 2024-09-07 08:36:07

所有解决方案确实都是 hackish,但数组是处理它的“标准”教科书方式,因为即使在泛型之前它也是类型安全的。

在这种情况下的另一个选择是像这样创建一个私有类:

   private class Searcher implements SearchCallback {
        private boolean found;
        @Override public void onFound(Object o) { found = true; }
        public boolean search() {
              OuterClass.this.search(this);
              return found;
        }
   }

然后像这样使用它:

  boolean found = new Searcher().search();

编辑:如果我正确理解汤姆的评论,他建议将此作为替代方案

 public void foo() { //This is the method that enclosed the code in your question
     new SearchCallBack() {
         private boolean found;
         @Override public void onFound(Object o) { found = true; }
         {
            //The code that was before this in your method
            search(this);
            //The code that was after this in your method
         }
     };
 }

我认为这更黑客,我真的会找到这样的代码不寻常,但绝对值得知道它是一种选择。

All solutions are indeed hackish, but the array is the "standard" textbook way of handling it, as even pre-generics it was typesafe.

Another option in this situation is to make a private class like so:

   private class Searcher implements SearchCallback {
        private boolean found;
        @Override public void onFound(Object o) { found = true; }
        public boolean search() {
              OuterClass.this.search(this);
              return found;
        }
   }

And then use it like so:

  boolean found = new Searcher().search();

Edit: If I understand Tom's comment correctly, he is suggesting this as an alternative

 public void foo() { //This is the method that enclosed the code in your question
     new SearchCallBack() {
         private boolean found;
         @Override public void onFound(Object o) { found = true; }
         {
            //The code that was before this in your method
            search(this);
            //The code that was after this in your method
         }
     };
 }

I think that is more hackish and I would really find such code unusual, but it is definitely worth knowing that it is an option.

人生百味 2024-09-07 08:36:07

如果你真的不能使用字段,迈克尔的回答似乎是正确的。

反正。我不知道您可以触摸哪些签名,但在我看来,该回调旨在对找到的对象执行某些操作(当搜索成功时)。相反,您打算通知搜索方法的调用者它发现了某些内容。如果您的 seach() 方法返回一个布尔值,那么看起来会更自然(如果搜索成功,该方法肯定会在某个地方调用 s.onFound() ,然后设置一个内部 found 在那里标记并返回)。

If you really cant use a field, Michael answers seems right.

Anyway. I dont know what signatures you can touch, but it seems to me that that callback is intented to do something (when the search succeeds) with/to the found object. You, instead, are intending to notify the caller of the search method that it found something. It would seems much more natural if your seach() method were made to return a boolean (the method will surely call s.onFound() somewhere if the search succeeds, then set an internal found flag there and return it).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文