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

Nic*_*ner 2 java graph priority-queue anonymous-class topological-sort

我想使用a 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;
}
Run Code Online (Sandbox Code Playgroud)

正确的代码

/**
 * 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;
}
Run Code Online (Sandbox Code Playgroud)

cle*_*tus 11

是的,最后决定:

public static Queue<String> topoSort(final DirectedGraph<String, DefaultEdge> g) {
Run Code Online (Sandbox Code Playgroud)

一锤定音在最后的关键字:

匿名本地类

涉及最终变量的第二种情况实际上是由语言语义强制实施的.在这种情况下,Java编译器不允许您使用变量,除非它被声明为final.这种情况出现在闭包中,也称为匿名本地类.本地类只能引用声明为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
    }
  };
} 
Run Code Online (Sandbox Code Playgroud)

如果我们对本地课程的实施方式有所了解,那么这种限制的原因就显而易见了.匿名本地类可以使用局部变量,因为编译器会自动为类提供一个私有实例字段来保存类使用的每个局部变量的副本.编译器还为每个构造函数添加隐藏参数,以初始化这些自动创建的私有字段.因此,本地类实际上并不访问本地变量,而只是它们自己的私有副本.这种方法可以正常工作的唯一方法是将局部变量声明为final,以确保它们不会改变.有了这种保证,本地类就可以确保其变量的内部副本能够准确地反映实际的局部变量.