Perhaps now is a good time to show off this little snippet just to
highlight how nigh-impossible it is to track immutability:
public class SeeminglyImmutablePointer {
private static final Map<SeeminglyImmutablePointer, Object> map =
new MapMaker().weakKeys().makeMap();
public void set(Object val) {
map.put(this, val);
}
public Object get() {
return map.get(this);
}
}
Note that @SEF and @Unchanging have no problem with this snippet; a
compiler can clearly determine that set is not SEF, and that get() is,
and it can also determine that set() is unchanging (trivially - any
method with return type void will have that property), and that get
isn't.
A real problem here is that java lacks immutable collection types.
i.e. map.get(this) *WOULD* be unchanging if youre querying an
immutable map (Collections.unmodifiable isn't good enough, that's a
read-only view of a possibly mutating map), but there's no way to
reflect this in the type system, and thus the compiler could never
tell you, you'd have to make an assertion.
Guava / com.google.collect does have such types, though the complete
API picture if you add these is a bit ugly - preferably List does not
imply immutability, but nevertheless does not have set, clear, and
insert, then a new interface named MutableList subtypes it that adds
these and implies mutability, and a new interface named ImmutableList
subtypes List without adding new methods, but implying immutability.
On Oct 12, 4:20 pm, Ben Schulz <[email protected]> wrote:
> On 12 Okt., 11:19, Kevin Wright <[email protected]> wrote:
>
> > Where are the uninitialised values being exposed?
>
> Let me quote my first response:
>
> > No[t] a big deal because nobody can observe this state, however, once one
> > gets into initializing immutable object graphs things get very hairy very
> > quickly:
>
> It's not so much about what is exposed to library consumers, but
> rather what the library developer can observe. Obviously an immutable
> object should /appear/ to never change, but my whole point is that it
> does anyway. And it's extremely difficult to prove that complex object
> graphs (potentially containing multiple cycles) end up with all fields
> correctly initialized.
>
> A classic example is phased initialization. First you create the
> object graph, a set of objects V with arbitrary relationships between
> elements of V. Then you establish invariant I_1 for all elements of V,
> then invariant I_2, and so on and so forth until you reach I_n. At
> that point all elements in V are in fully initialized. An example of
> such object graphs is the Java type system: Only after you created all
> types and their parameters can you initialize theirs supertypes (and
> bounds respectively).
>
> interface I<T extends I<T>> {}
> class A implements I<B> {}
> class B extends A {}
>
> With kind regards
> Ben
--
You received this message because you are subscribed to the Google Groups "The
Java Posse" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/javaposse?hl=en.