Inserting In a List

S

Stefan Ram

Leif Roar Moldskred said:
As Java methods are pass-by-value, variable reassignment just
isn't a real source for problems so why guard against it?

Ok, this is a rather artificial example:

public isFalse( final boolean value )
{ if( value = false )return true; else return false; }

. The keyword ?final? will help to find the ?value = false? error.
But such errors are rare in Java.

I use ?final? for readability and documentation purposes:

{ final int seven = 7;
/* 12 lines omitted */
java.lang.System.out.println( seven ); }

Above, ?final? conveys the intend of the author that ?seven?
is the name of a value rather than the name of a variable
(although, technically, in Java, it still is a variable).

Conceptually, a name of a value is a totally different
thing than a name of a variable, and it helps to be able
to express both concepts with means of the source code.

A variable can change in time, a value does not change.

Moreover, the reader of the println line can immediately
conclude that it will print seven, without having to read the
12 lines omitted above. A variable could have been changed
in any of those 12 lines.

Names for values are easier to understand than names for
variables, because one does not have to take into account
the possibility that their value might have changed.
 
A

Arved Sandstrom

[ SNIP ]
Can you give an example?

This is more a matter of incorrect English. An *object* is mutable or
immutable, not a field. For variables or fields I'd never use the terms
mutable/immutable; I'd prefer simply "final" or "not final" or something
similar.

What Joerg meant is that if the final field is of a reference type then
it is perfectly possible that the object assigned to it is mutable.

AHS
 
P

paul.cager

For what it's worth, they're not:

public class ThisIsImmutable {
private String cantChangeMe;
public ThisIsImmutable(String value) {
this.cantChangeMe = value;
}
public String getCantChangeMe() {
return this.cantChangeMe;
}
}

Interestingly, is "ThisIsImmutable" immutable given you can do this?

public class NowItIsnt extends ThisIsImmutable {
public String getCantChangeMe() {
return Integer.toString(new Random().nextInt());
}
}

Of course you could make ThisIsImmutable final.
 
S

Stefan Ram

Arved Sandstrom said:
This is more a matter of incorrect English. An *object* is mutable or
immutable, not a field. For variables or fields I'd never use the terms
mutable/immutable; I'd prefer simply "final" or "not final" or something
similar.

JLS7 10.9 gives us:

?A String object is immutable, that is, its contents
never change, while an array of char has mutable elements.?

?That is, its contents never change? seems to be a
definition of ?immutable?, at least for objects.

?While an array of char has mutable elements? applies the
term to variables of type char (here, anonymous variables),
so it does not apply to objects only.

(Obviously, ?immutable? is ?not mutable?, so that ?mutable?
and ?immutable? are connected by a negation. Thus, a
definition of one also doubles as a definition of the other.)
 
A

Arved Sandstrom

JLS7 10.9 gives us:

?A String object is immutable, that is, its contents
never change, while an array of char has mutable elements.?

?That is, its contents never change? seems to be a
definition of ?immutable?, at least for objects.

?While an array of char has mutable elements? applies the
term to variables of type char (here, anonymous variables),
so it does not apply to objects only.

(Obviously, ?immutable? is ?not mutable?, so that ?mutable?
and ?immutable? are connected by a negation. Thus, a
definition of one also doubles as a definition of the other.)
I'd call that unfortunate terminology myself, as per the array of char,
and I wish the author(s) hadn't done it. An array element *is* the item
at a given position in the array, and that may or may not be mutable
depending on the type of array. How is a primitive char mutable?

I would say that the *array* of char is mutable.

AHS
 
S

Stefan Ram

Arved Sandstrom said:
I would say that the *array* of char is mutable.

An array of chars is not an array of char values,
but of char variables, each of which is mutable.
 
J

Joerg Meier

There's a lot that's been added to this thread since I retired to my bed
last night and I haven't read it all so please excuse me if I'm
repeating what others have said.

Same here.
//OK, the instance is not immutable
list.add("foo");

This is the case I was referring to: making the reference to list final
does not make the list object immutable.
This is what I mean by not modifiable, the variables x and list are
not modifiable after assignment however what list points to, sorry
refers to is a mutable instance of ArrayList<String>, this is quite
different.
I'm not sure I understand

I must admit that I didn't consider primitives in my wording. I was talking
mostly about mutable objects - making a final reference to them does not
prevent modifying the object. I fear the attempt to include primitives in
definitions like this is futile - I don't even know whether I would
consider primitives immutable or not. int i = 1; i++; // Does the 1 get
modified to a 2, or overwritten by a 2 ?
Can you give an example?

Yes, but I don't need to: you already did, it's the one I quoted above.
your list was a mutable final field.

Liebe Gruesse,
Joerg
 
J

Joerg Meier

On 03/04/13 20:01, Joerg Meier wrote:
On Wed, 03 Apr 2013 19:51:05 +0100, lipska the kat wrote: [ SNIP ]
What you are thinking of is immutability, something that is not
formalized in Java. In Java, having final mutable fields is perfectly
legitimate.
Can you give an example?
This is more a matter of incorrect English. An *object* is mutable or
immutable, not a field. For variables or fields I'd never use the terms
mutable/immutable; I'd prefer simply "final" or "not final" or something
similar.
What Joerg meant is that if the final field is of a reference type then
it is perfectly possible that the object assigned to it is mutable.
Something which I have never argued against.
There are no two ways about it, a final variable is not modifiable once
assigned to, the fact that the variable is a reference to a possibly
modifiable instance of something or other is irrelevant to my original
assertion.
A variable that is final is no longer variable, it is not modifiable, on
that I think we all agree.

Correct. I disagreed with your statement (emphasis added by me):

[...] When I see the
modifier final it says something to me, it says, this *value* is not
modifiable ('scuse the pun).

The variable/reference itself is not modifiable, but its VALUE certainly
is. And that, I feel, is the problem with using final to mean "this will be
the same throughout the code":

final Point p = new Point(0,0);

You can not be sure that the value of p will stay 0,0 throughout the code.

Liebe Gruesse,
Joerg
 
J

Joerg Meier

I do not have a problem with 'slightly'.

I would be willing to settle on that as well after some more consideration.
My statement was in the heat of the moment, considering the overhead of
many small sort steps compared to one big, optimized sorting loop, but in
retrospect, that is unlikely to make as large an impact as I initially
thought.

If I get bored enough, I'll write some sort of benchmark, but I can't think
of a good way to get realistic 'somewhat sorted' test data, since honestly
the IO of getting filenames would completely crush any possible sort cost
on something that numbers so small.

Liebe Gruesse,
Joerg
 
J

Joerg Meier

Fair enough - unless, of course a new coder tries to sort the ArrayList
rather than using one of the standard SortedMaps. I note that there are
only two and that, while ConcurrentSkipListMap is obviously faster than
TreeMap for insert/amend/delete operations it would seem to be much
slower at producing ordered lists.

Again: sorting an ArrayList is one single line. Collections.sort(list);, if
I recall correctly. I'm sure you could endure a new coder doing that.
For individual items that's true, but if the list is being updated, even
at a low rate, then ordered access will need to at least check for out of
order data before anything gets retrieved. Thats an overhead that any
structure that preserves order through updates doesn't have.

I will not argue with that. It's what I initially said sorted lists are for
in the first place - maintaining order on a dynamic list. But in this case
there was no dynamic list. The list was built once and then not modified
again.
Which is where I came in: the OP had said that he wanted to get a String
containing a list of filenames that he represented as

which at least suggests that the filenames should be ordered.
That is why I suggested that if that's what he wanted he should be using
a TreeMap rather than an ArrayList.

And I still don't see why he would want to, considering that a TreeMap
would at best be the same speed as an ArrayList, and usually slower.
I didn't suggest any alternative and never intended to, but you can see
somebody throwing the list of filenames into an ArrayList and then
running a bubble sort against the array. Ugly, I know, and bubble sorts
are horridly inefficient, but there's very little code in one. More to
the point, this would be a very natural approach for anybody coming from
a high level language background, e.g. Python, Perl, C, BASIC, PL/1,
COBOL,... doing exactly this.

Writing your own list algorithm instead of using one provided would be a
natural approach for someone coming from a high level language background ?
What ? Is this CS first semester homework or something ?

Liebe Gruesse,
Joerg
 
E

Eric Sosman

Well, it does. Section 17.5 has several subsections, and it's defined
in section 17.5.1. I feel one really should read all of 17.5 to
understand final fields however.

Ah, this is obviously some strange usage of the word "defined"
that I wasn't previously aware of.

Section 17.5.1 ("Semantics of final fields") contains precisely
zero occurrences of the word "immutable," zero occurrences of the
word "mutable," and zero occurrences of the sequences "immu" and
"mut." It's a pretty odd definition that doesn't point out the
term being defined.
It doesn't even say that "final"
confers immutability; on the contrary, it says "final fields must
be *used correctly* [emphasis mine] to provide a guarantee of
immutability."

OK, that might be part of the problem. final is necessary but not
sufficient. I'll concede that, no problem. I misspoke if I implied
otherwise.

Elsethread you will find demonstrations by various people
that "final" is not necessary for immutability. (Of course,
they're using their own, informal notions of "immutability,"
since the JLS doesn't define one. Perhaps the widely-held
ideas about "immutable" are not those you share.)
 
J

Joerg Meier

Section 17.5 says this in its second paragraph:
"final fields must be used correctly to provide a guarantee of
immutability."

I would argue that to mean "If you use final incorrectly, you might still
not have an immutable object" and not "You can only make immutable objects
with use of final".
??? The first thread to calculate a hash code will always see 0.
That's what triggers the hash code calculation, rather than just
returning the value stored in the hash code field.

How would that thread see 0 ? When I use String.hashCode for the first
time, I get the hashCode, not 0. The 0 is only ever used internally. Nobody
gets to see it. That's why String is considered immutable.

Liebe Gruesse,
Joerg
 
J

Joerg Meier

Yes it is! (Not immediately synchronized, at the end of the ctor.)
Read the JLS, besides the part I quoted above:

I don't read that (or anything relating to threads at all) from that part
of the JLS (other than the mention to the unrelated deref chain).
That's as clear as mud, but what it means is that objects referenced by
final fields, and all writes to those objects, are made visible at the
end of the object's ctor.

Yes, but that is not a multi-threading concern (and in fact writes are also
made visible when the ctor exits on non-final fields).
In the second example you gave where the reference to 'stooges' leaves
the enclosing class, it is definitely neither immutable nor thread-safe.
Yes it does! That was explicitly stated in the very short bit I quoted
at the beginning of this whole mess.

So then my second example, which you just admitted is not thread-safe
above, would by your logic still need no synchronization, because it uses
final. I'm sorry, but that just makes no sense.

You have to decide:

a) the mere use of final does not remove the need for synchronization
b) the mere use of final does remove the need for synchronization, and the
class that exposes the final instance of the list is still thread-safe.

You can't have it both ways.
No. 'final' is special here.

But you can still have immutable, thread safe objects without final:

public class A {
private int i = 1;

public int getI(); { return i; }
}

This class is thread safe and immutable. And completely without final.
No, you still need to, at a low level, insert a memory barrier to make
those writes visible.

That memory barrier is the ctor. It alone is enough to make the writes
visible.
You'd need to use synchronization or a volatile
variable or some other synchronization in Java, or you could see a
partially constructed object.

I would like to see an example to back up this claim that it's poissible to
see a partially constructed object merely by it having non-final fields,
without giving out a reference to the partially constructed object (like I
did in my example).
Also, go read Java Concurrency in Practice by Brian Goetz. He covers
this in some detail (complete with Stooges example).

Luckily someone else already quoted the point I'm trying to make that you
disagree with: you can have immutable objects without everything being
final just fine, as long as you don't let that lack of finality escape out
into the wild.

Liebe Gruesse,
Joerg
 
J

Joerg Meier

Interestingly, is "ThisIsImmutable" immutable given you can do this?
public class NowItIsnt extends ThisIsImmutable {
public String getCantChangeMe() {
return Integer.toString(new Random().nextInt());
}
}
Of course you could make ThisIsImmutable final.

I faced the same question (whether or not to make my example final)
elsethread, but in the end, with Reflection and such, you really aren't
protected against someone trying to intentionally make something mutable.
Between cloning, deserializing, using Reflection to outright remove final
decorations, and the good old brute force method of changing the source
(and you can even override the JCL if you put things in java* packages),
there's a lot of ways to 'break' things if you wanted to.

Writing a super defensive class to protect against all that didn't seem
worth the trouble to make the point we tried to make.

Liebe Gruesse,
Joerg
 
M

markspace

Perhaps the widely-held
ideas about "immutable" are not those you share.)

Well, if we're all using different definitions of a term, talking about
it is pretty tough. Immutability is defined correctly in the JLS, at
least for Java. I think it would be most useful to use that term.
 
M

markspace

How would that thread see 0 ? When I use String.hashCode for the first
time, I get the hashCode, not 0. The 0 is only ever used internally.

That's what I mean though. Internally, your thread sees 0, and then
calculates the value and caches it. There's nothing magic about
crossing a method boundary. It's all just a stream of machine
instructions to your thread. Visibility of fields (as section 17.4 of
the JLS uses that term) isn't affect by methods or objects unless you do
something explicitly (like use the synchronized keyword).
 
M

markspace

You have to decide:

a) the mere use of final does not remove the need for synchronization
b) the mere use of final does remove the need for synchronization, and the
class that exposes the final instance of the list is still thread-safe.

I thought it was obvious, but of course you also have to prevent writes
to the object. final is necessary but not sufficient. Mea culpa if
that's the cause of the misunderstanding here. I should have been more
precise in my language. Unfortunately I was just focusing on one aspect
of making an object immutable, just the final-ctor combo, and ignoring
others.
But you can still have immutable, thread safe objects without final:

public class A {
private int i = 1;

public int getI(); { return i; }
}

This class is thread safe and immutable. And completely without final.

No, this is very explicitly wrong, and I'm sure the rest of the list
would agree. (I think you're confusing this with an example using a
static (class) field.)

The JLS explicitly says that writes on one thread are not visible
immediately to another thread. If thread A constructs this object, then
thread B calls getI, it's liable to see the previous value of i (0)
rather than the write by thread A which is still sitting in A's CPU cache.

You have to do something to flush that write out to main memory. In a
nutshell, that's what visibility means in the JLS. Two threads on two
CPUs won't see the same values unless force those writes to flush out to
main memory.
That memory barrier is the ctor. It alone is enough to make the writes
visible.

No, memory barriers are pretty expensive and the Java compiler doesn't
force them when not needed. Regular ol' POJO objects don't have a
memory barrier at the end of their ctor. That's the whole point of
section 17 in the JLS, Threads and Locks. It tells you how to use your
normally not-thread-safe objects safely.
I would like to see an example to back up this claim that it's poissible to
see a partially constructed object merely by it having non-final fields,
without giving out a reference to the partially constructed object (like I
did in my example).

There are several good examples in the JLS, which I'm going to refer you
too, so I don't louse-up an example again. There's example 17.4-1 in
the section on the Java memory model:

<http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4>

There also another example 17.4.5-1 in the section on happens-before
consistency

<http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5>

Both of those examples involve two writes, but that doesn't matter. The
accompanying text makes it clear that any write, even one single write,
can be re-ordered by the system.

Also take a look at section 17.4.1 where it talks about shared variables
and heap memory.

<docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.1>

Instance fields are explicitly included, and your class A has an
instance field i that needs to be synchronized somehow. It's not thread
safe on its own.
Luckily someone else already quoted the point I'm trying to make that you
disagree with: you can have immutable objects without everything being
final just fine, as long as you don't let that lack of finality escape out
into the wild.

That example was really different than what you presented in your
example with the class A above. It's one reason why Arne's example from
JCIP also says "don't try this at home." ;-) It's really tough to
reason about these things and easy to get wrong; really really easy. I
urge you to study this because I'm concerned that you've missed a couple
of not-too-subtle points about concurrency in Java.
 
R

Robert Klemme

Section 17.5 says this in its second paragraph:

"final fields must be used correctly to provide a guarantee of
immutability."

That's the last sentence. To me that's ascribing special semantics to
just the word 'immutable.' If it's saying "final fields must be used"
then it's special for final fields. I realize there a qualifier on
that, but the qualifier is "correctly" and they're just pointing out
it's a little tricky. final fields must be used is the key point.
(Used incorrectly, of course, they won't guarantee immutability.)

The sentence states that you will only get immutability if you use final
fields correctly. That does not imply that final fields are necessary
to achieve immutability. For at least one definition of "immutable" you
can create classes with no setters and getters only returning immutable
objects - without ever using the keyword "final".
I see how you might read that differently, but without final fields the
number of useful immutable classes is pretty small. (I'm ignoring
stateless objects here.)

Not at all.

Kind regards

robert
 
J

Jim Janney

markspace said:
OK, that's true. The section I linked to refers to such objects as
"thread safe immutable." It's both concepts in one package. Objects
that aren't thread safe aren't immutable, and objects that aren't
immutable aren't thread safe. I guess that's why the two go together.

Immutable objects don't need to be defensively copied. This can be
useful even in situations where thread safety doesn't apply.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top