문제

특정 변수가 표시 되더라도 부작용을 생성하는 방법이 있습니다. final. 왜 이런거야? 아마도 나는 무엇에 대해 혼란 스러울 것입니다 final 하다.

@Test
public void testSubGraph() {
    WeightedGraph<String, DefaultWeightedEdge> g = generateSimpleCaseGraph();

    Graph<String, DefaultWeightedEdge> sub = ChooseRoot.subgraphInDirection(g, "alpha", "l");

    assertEquals(g, generateSimpleCaseGraph()); //fails 
}

public static <V, E extends DefaultEdge> Graph<V, E> subgraphInDirection(final Graph<V, E> g, final V start, final V sink) {
    Graph<V, E> sub = removeEdges(g, start, sink);
    return removeUnconnectedNodes(sub, start);
}

private static <Vertex, Edge extends DefaultEdge> Graph<Vertex, Edge> removeEdges(final Graph<Vertex, Edge> g, Vertex start, Vertex sink) {
    final Set<Edge> outEdges = new HashSet<Edge>(g.edgesOf(start));
    boolean removedEdge;

    for (Edge e : outEdges) {
        if (! (g.getEdgeTarget(e).equals(sink) || g.getEdgeSource(e).equals(sink))) {
            removedEdge = g.removeEdge(e);
            assert removedEdge;
        }
    }
    return g;
}

private static <Vertex, Edge> Graph<Vertex, Edge> removeUnconnectedNodes(Graph<Vertex, Edge> g, Vertex start) {
    ConnectivityInspector<Vertex, Edge> conn = new ConnectivityInspector<Vertex, Edge>((UndirectedGraph<Vertex, Edge>) g);
    boolean removedVertex;

    final Set<Vertex> nodes = new HashSet<Vertex>(g.vertexSet());
    for (Vertex v : nodes) {
        if (! conn.pathExists(start, v)) {
            removedVertex = g.removeVertex(v);
            assert removedVertex;
        }
    }
    return g;
}
도움이 되었습니까?

해결책

그만큼 final 수정자는 참조를 재 할당 할 수 없음을 의미합니다. 물체의 상태가 수정되는 것을 막지는 않습니다.

편집하다: 톰에게만 :

public void doSomething1(Object arg)
{
    arg = new Object(); // OK.
}

public void doSomething2(final Object arg)
{
    arg = new Object(); // Compile error.
}

두 경우 모두 arg, 상태를 수정하는 방법을 포함하여.

다른 팁

Dan은 Final에 대한 정답을 가지고 있습니다. 당신이 후에있는 것은 Java가 가지고 있지 않은 C ++의 Const와 더 비슷합니다. 이 작업을 수행하여 시뮬레이션 할 수 있습니다.

public class Foo
{
    protected int x;

    public Foo(final int val)
    {
        x = val;
    }

    public int getX()
    {
        return (x);
    }
}

public class MutableFoo 
    extends Foo
{
    public MutableFoo(final int val)
    {
        super(val);
    }

    public void setX(final int val)
    {
        x = val;
    }
}

그런 다음 :

void bar(final Foo foo)
{
    foo.setX(5); // will not compile
}

void bar(final MutableFoo foo)
{
    foo.setX(5); // will compile
}

예쁘지는 않지만 작동합니다. 비결은 부모 클래스 (FOO)의 메소드가 인스턴스 변수를 변경하지 않도록하는 것입니다. MutableFoo 만 상태를 변경할 수있는 방법을 가질 수 있습니다.

물론 가능한 한 최선의 방법은 불변의 클래스를 작성하는 것입니다 (모든 변수를 최종 최종적으로 만드십시오). 부작용이있는 인스턴스/클래스 변수에서 메소드를 호출하지 않으므로 상황이 변경 될 수 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top