【问题标题】:Java: Using a local class in a parameterized type for a local variable referenced inside the local classJava:使用参数化类型中的局部类作为局部类内部引用的局部变量
【发布时间】:2012-06-13 17:18:29
【问题描述】:

我正在用 Java 中的单个方法实现某种算法。该算法需要一个不会在其他任何地方使用的数据结构,因此对我来说使用本地类似乎很合适。算法的最后一步需要遍历方法中之前创建的所有对象,所以我想我会让本地类的构造函数将新创建的对象添加到列表中。在 Java 中,本地类可以访问声明为 final 的本地变量。所以我尝试了这样的事情:

public void doThing() {

    class Foo {
        public Foo() {
            fooList.add(this);  // FAILS: "cannot find symbol: variable fooList"
        }
    }

    final ArrayList<Foo> fooList = new ArrayList<Foo>();

    // algorithm goes here, instantiating some Foo objects:
    Foo foo = new Foo();
    // etc.

    // now iterate through all the Foo objects that were created
    for (Foo f : fooList)
        System.out.println(f);
}

这失败了,因为显然我必须先声明fooList,然后才能在本地类中引用它。好吧,好吧,我想,我就在方法的开头声明fooList

public void doThing() {

    final ArrayList<Foo> fooList;  // FAILS: "cannot find symbol: class Foo"

    class Foo {
        public Foo() {
            fooList.add(this);
        }
    }

    fooList = new ArrayList<Foo>();

    Foo foo = new Foo();
    for (Foo f : fooList)
        System.out.println(f);
}

但这也失败了,因为显然我需要在引用它之前定义类Foo。那么如何打破这种循环依赖呢?

【问题讨论】:

  • 如果您在方法内部创建类并使用该类的列表,那么您的设计是错误的。也许您应该添加一个外部类来执行此操作。对我来说,这听起来像是 1000 行方法的开始......

标签: java generics inner-classes circular-dependency local-class


【解决方案1】:

那么我该如何打破这种循环依赖呢?

我强烈建议将本地类分解为私有静态嵌套类。我不能说我曾经看到过在方法中声明的命名类的令人愉快的用法。虽然我通常对“它仅用于一种方法”部分表示赞赏,但当您声明该类时,该方法已经达到中等长度。

当然,您总是可以使用原始类型进行声明,然后再进行转换......这可能会起作用,但显然会很糟糕。

【讨论】:

  • 我认为使用局部类会很有用的一个原因是Foo 中的方法需要在doThing() 方法中使用四个局部变量(其中一个是@987654323 @,但还有其他三个)。我可以将所有这四个作为参数传递给每个需要它们的方法,但我认为我可以通过使用本地类来避免这种迂回。但也许不是?
  • @BrianKell:听起来你的方法做的太多了。你能不把它们传递给类的构造函数,并给类一个方法来处理它们吗?
【解决方案2】:

另一种选择:

class Foo {
    public Foo(ArrayList<Foo> fooList) {
        fooList.add(this);
    }
    public Foo() {
    }
}

public void doThing() {
    final ArrayList<Foo> fooList = new ArrayList<Foo>();

    Foo foo = new Foo(fooList);

    // or simply fooList.add(new Foo());


    for (Foo f : fooList)
        System.out.println(f);
}

我认为以这种方式添加对列表的引用是个坏主意。 在这种情况下,您可以简单地编写 new Foo(fooList); 并且引用将在列表中,但您没有在方法中保存引用。这取决于您要做什么,因此请使用最舒适的变体

【讨论】:

  • 你可以给构造函数列表。或在doThing()中致电fooList.add(foo);
  • 没有必要将class设为本地,没有意义。但是 ArrayList 必须是唯一的。我编辑了我的答案
  • 你说得对,我也可以将fooList作为参数传递给构造函数;这是个好主意。感觉本地类能够访问局部变量的目的是让您不必这样做,但是哦。
  • 我也可以在每次实例化Foo 时显式调用fooList.add(foo);。但这似乎是很多复制粘贴,我想我可能会忘记在某个地方这样做,这会导致 Foo 被实例化而不被添加到列表中。
  • 您可以在一行中编写初始化和添加到列表(我更喜欢这种变体)。您还可以提供将其传递给构造函数的列表(不是好的变体,但可以)。查看编辑的构造函数
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-04
  • 2021-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多