Frage

Ich habe eine Methode, die Nebenwirkungen erzeugt, obwohl bestimmte Variablen final gekennzeichnet sind. Warum ist das? Vielleicht bin ich verwirrt, was final der Fall ist.

@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;
}
War es hilfreich?

Lösung

Die final Modifikator bedeutet nur, dass der Verweis nicht neu zugewiesen werden kann. Es muss nicht den Zustand des Objekts verhindern, geändert werden.

EDIT: Nur für Tom:

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

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

In beiden Fällen können Sie Methoden für das Objekt aufrufen, auf den arg, einschließlich Methoden, die ihren Zustand ändern.

Andere Tipps

Dan hat die richtige Antwort auf endgültig. Was sind Sie nach ist mehr wie const in C ++, Java, die nicht verfügt. Sie können es simulieren, indem dies zu tun:

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;
    }
}

dann tun:

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

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

Nicht schön, aber es funktioniert. Der Trick ist, um sicherzustellen, dass keine der Methoden in der Elternklasse (Foo) auf den Instanzvariablen Änderungen vornehmen -. Nur MutableFoo Methoden haben kann, dass der Staat zu ändern erlauben

Natürlich ist das beste, was, so viel wie möglich zu tun, ist unveränderliche Klassen zu schreiben (macht alle Variablen final) und rufen Sie diese Methoden nicht auf Instanz / Klassenvariablen, die Nebenwirkungen haben, so dass die Dinge nicht <ändern / p>

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top