[英]Java: Why does this method have side effects?
我有一個產生副作用的方法,即使某些變量標記為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在決賽中有正確的答案。 你所追求的更像是C ++中的const,Java沒有。 您可以通過執行以下操作來模擬它:
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 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.