Java:从anon内部类访问局部变量? (PriorityQueue中)

时间:2009-11-17 02:27:48

标签: java graph priority-queue anonymous-class topological-sort

我想使用PriorityQueue对图表进行拓扑排序。为简洁起见,我想为比较器使用匿名内部类。但是,我需要访问图g才能确定我正在查看的节点的程度。这可能吗?

    /**
 * topological sort 
 * @param g must be a dag
 */
public static Queue<String> topoSort(DirectedGraph<String, DefaultEdge> g) {
    Queue<String> result = new PriorityQueue<String>(g.vertexSet().size(), 
            new Comparator<String>() {

                DirectedGraph<String, DefaultEdge> g;

                @Override
                public int compare(String arg0, String arg1) {
                    if (g.inDegreeOf(arg0) < g.inDegreeOf(arg1)) {
                        return -1;
                    }
                    if (g.inDegreeOf(arg0) > g.inDegreeOf(arg1)) {
                        return 1;
                    }
                    return 0;
                }
    });

    result.addAll(g.vertexSet());

    return result;
}

更正后的代码

/**
 * topological sort 
 * @param g must be a dag
 */
public static Queue<String> topoSort(final DirectedGraph<String, DefaultEdge> g) {
    Queue<String> result = new PriorityQueue<String>(g.vertexSet().size(), 
            new Comparator<String>() {          
                @Override
                public int compare(String arg0, String arg1) {
                    if (g.inDegreeOf(arg0) < g.inDegreeOf(arg1)) {
                        return -1;
                    }
                    if (g.inDegreeOf(arg0) > g.inDegreeOf(arg1)) {
                        return 1;
                    }
                    return 0;
                }
    });

    result.addAll(g.vertexSet());

    return result;
}

3 个答案:

答案 0 :(得分:11)

是的,最后决定:

public static Queue<String> topoSort(final DirectedGraph<String, DefaultEdge> g) {

请参阅The Final Word On the final Keyword

  

匿名本地类

     

涉及最终的第二种情况   变量实际上是由强制要求的   语言语义学。在那种情况下,   Java编译器不会让你使用   变量,除非它被声明为final。   关闭会出现这种情况,   也称为匿名本地类。   本地课程只能参考本地课程   变量和参数   宣布决赛。

public void doSomething(int i, int j)
{
  final int n = i + j; // must be declared final

  Comparator comp = new Comparator()
  {
    public int compare(Object left, Object right)
    {
      return n; // return copy of a local variable
    }
  };
} 
     

这种限制的原因   如果我们发现一些亮光就会变得明显   如何实施本地类。   匿名本地类可以使用本地   变量因为编译器   自动给出一个班级   用于保存副本的私有实例字段   该类使用的每个局部变量。   编译器还添加了隐藏   每个构造函数的参数   初始化这些自动创建   私人领域。因此,一个本地班   实际上并不访问本地   变量,但仅仅是它自己的私有   他们的副本。唯一的方法就是这样   正确的工作是如果当地的   变量被声明为final,所以   他们保证不会改变。   有了这个保证到位,   当地的班级确信它的   变量的内部副本   准确反映当地的实际情况   变量

答案 1 :(得分:2)

如果在内部类中使用局部变量,编译器将为内部类生成实例字段,并将局部变量值复制到其中。现在,如果局部变量发生变化,则instancs变量值仍将具有旧值。因此,为了使局部变量值与实例字段相同且不可变,它是最终的。

答案 2 :(得分:0)

仅供参考,google collections您也可以选择

  Ordering.natural().onResultOf(
      new Function<String, Integer>() {
        public Integer apply(String arg) {
          return g.inDegreeOf(arg);
        }
      });

除非您可以找到该功能的其他用途,否则这并不一定能为您节省大量的输入,但它确实可以防止您经常陷入手动比较器实现的错误。