mutate an object or create a new one?

T

toton

Hi,
I have a typical situation for the main backbone of the program. In
my program, lots of new objects gets created, added in the processing
queue ,used and removed from the queue. Something like a air-traffic
control system or moving average.
The objects added to the queue, are by nature immutable, and that
"may help" in a threaded environment (but not very much as the
processing queues are seperate). However added immutability cause them
to be use-and throw objects. While mutability cause them to be reused.
I am trying to demonstrate the problem with a short example. While
the original problem is much complex, but the underlying working
principle is more or less same.
public class TestProcess{
public static void main(String[] args){
Deque<ObjectTobeProcessed> queue = new
ArrayDeque<ObjectTobeProcessed>(10);
for(int i = 0; i <10; ++i){///pre existing objects.
queue.addFirst(new ObjectTobeProcessed());
}
long time1 = System.currentTimeMillis();
for(int i = 0; i <10000000; i++){
queue.removeLast();///remove the last one.
queue.addFirst(new ObjectTobeProcessed());///add a new at the first.
process(queue);
}
long time2 = System.currentTimeMillis();
System.out.println ("time "+(time2-time1)*0.001);

Deque<MutableObjectTobeProcessed> queue1 = new
ArrayDeque<MutableObjectTobeProcessed>(10);
for(int i = 0; i <10; ++i){///pre-existing objects.
queue1.addFirst(new MutableObjectTobeProcessed());
}
time1 = System.currentTimeMillis();
for(int i = 0; i <10000000; i++){
queue1.getLast().setValue();
process(queue);
}
time2 = System.currentTimeMillis();
System.out.println ("time "+(time2-time1)*0.001);
}
public static void process(Deque<ObjectTobeProcessed> queue){
double sum = 0;
for(ObjectTobeProcessed o: queue ){
sum+= o.getValue();
}
}
}
class ObjectTobeProcessed{
private double value;
public ObjectTobeProcessed(){
value = Math.random();
}
public double getValue(){
return value;
}
}
class MutableObjectTobeProcessed{
private double value;
public MutableObjectTobeProcessed(){
value = Math.random();
}
public double getValue(){
return value;
}
public void setValue(){
value = Math.random();
}
}
Here two class creates some random number, while one allows to reset
its state , the other do not.
In the first case one number is removed from last, one created at
first, and some process is called (here a moving average! ) . Here a
large numver of objects created, used and thrown away. In the second
case, it mutates the last object (which is supposed to be thrown away)
to the new state. Here no object gets created and destroyed at all!.
Here the queue sequence is not the same (that don not affect the
moving average though), but that can be solved using a wrapped version
of deque (with a modulo wrapping).
There is a difference for first case and second case, and difference
increases considerabily when the objects becomes complex and stores
more than premitive types.
In the actual problem, the existing size is not fixed (as 10 here) but
nearly fixed within certain limit.
And the objects come & go from the processing queue are not so small.
And the system is supposed to be on for ever and process things as come
and go away.
The things I notice,
1) Both version has clear hotspot for processing.
2) only the second verson has hotspot for processing over same data.
3) For second version GC has very less job compared to first one.
In actual case, the objects are characters (handwritten, not printed ,
thus they can not be formed from same set of objects). Mutating them
means one can unknowingly or by mistake form a B from and A! Making
them immutable means an easier and cleaner code, but error prone (as
Java doesn't have a const , so I even can't constantify an mutable
object when needed)
Also I use Mysaifu JVM for PocketPC, which may not have as
sophisticated GC as sun's one .Though still I hadn't tested the code
there with a performance difference , I will do it in near future (my
friend had take my iPAQ :( , sure he will return it by this weekend.
Can anyone give a little more insight, and the best way to do such job?
(The processing is pretty computational gemetry related and also has
some signal processing aspect. in short instead of moving average, it
is some sot of complex mathematical calculation comes into process).
Any alternate / better way to do such job ? Something like I can have a
mutable object but selectively constantify it when needed?

Thanks for any kinds of suggestion / advice
 
C

Chris Uppal

toton said:
Also I use Mysaifu JVM for PocketPC, which may not have as
sophisticated GC as sun's one .Though still I hadn't tested the code
there with a performance difference , I will do it in near future (my
friend had take my iPAQ :( , sure he will return it by this weekend.
Can anyone give a little more insight, and the best way to do such job?
(The processing is pretty computational gemetry related and also has
some signal processing aspect. in short instead of moving average, it
is some sot of complex mathematical calculation comes into process).

It sounds as if you are doing a lot of computation which isn't related to the
creation/GCing of objects. As such the potential gains of avoiding GC (even in
an environment where GC is slow) are going to be small at best. I.e it doesn't
sound as if the extra complication would be worth it.

Remember, too, that recyling the objects is not free -- there are the extra
costs involved in resetting the obejct's states, adding them to free lists
(which would probably involve synchronised code), any additional runtime checks
you have to ensure that you are not changing objects when you shouldnt and so
on.

-- chris
 
T

toton

Chris said:
It sounds as if you are doing a lot of computation which isn't related to the
creation/GCing of objects. As such the potential gains of avoiding GC (even in
an environment where GC is slow) are going to be small at best. I.e it doesn't
sound as if the extra complication would be worth it.

Remember, too, that recyling the objects is not free -- there are the extra
costs involved in resetting the obejct's states, adding them to free lists
(which would probably involve synchronised code), any additional runtime checks
you have to ensure that you are not changing objects when you shouldnt and so
on.
1) Actual case, there are one such queue per user. Say a new user
starts writing, and a new deque is created, which are attached to each
one's Session. And one's computation doesn't access or modify to
other's data. So I don't do any synchronization there.
2) Only thing I like immutable object, as it protects from accidentally
modifying data. Not that much for thread safety (as that comes
relatively free to me, as I have separate Session for each user).
However as Java doesn't have a const keyword ( which I use heavily in
C++, and miss very much in Java) I try to have immutable object as
much as possible. It makes a lots of thing simpler. Only this kind of
cases I get little confused. It is a typical class of programs !
Resetting an object is not free, neither memory allocation. But what is
the cost comparison for Java (in C++ resetting an object is cheap,
memory allocation in heap is costly. Thus STL do so much copy, but
little memory allocation, and still is very fast).
3) I have a little more question. I want a few of my classes to evolve
over time (i.e they are mutable.) as all of the states are not
available initially. However if anyone wants it I need to send an
unmodifyable snapshot of it ( i.e constantify it & send). Again as Java
do not have const, I am looking for some inner class based
implementation. Anything specific known regarding that? (like a
modifier class, If someone gets access to modifier of a class he will
be able to modify its state, otherwise the class is immutable! ) .

Thanks for help and suggestion.
 
I

Ingo R. Homann

Hi,

concerning your problem of recycling objects, my opinion is clear:

Do NOT recycle objects. It *may* speed up you app in some cases (while
it may slow down your app in other cases). Write clean and readable code
and choose the right data structures and algorithms. If your platform
does not have enough resources to properly run your application,
recycling objects will not help very much. In 99% there are more
disadvantages than advantages.

To your other question ("const" (which I am missing as well) vs
"mutability"):

I have not tested it in a productive environment, but an approach would
by something like that:

class UnmodifiableInt {
protected int i;
public int getValue() {
return i;
}
}

class ModifiableInt extends UnmodifiableInt {
public void setValue(int i) {
this.i=i;
}
}

Then, you can do the following:

class Foo
{

void bar1(ModifiableInt i)
{
}

void bar2(UnmodifiableInt i)
{
}

void bar()
{
UnmodifiableInt ui = new UnmodifiableInt();
ModifiableInt i = new ModifiableInt();
bar1(ui); // compiler error
bar1(i);
bar2(ui);
bar2(i);
}

}

For "plain" objects (in contrast to "compound" objects) this should work
easily.

Of course it is not "save" because if you have a reference of type
UnmodifiableInt, it may point to an object of type ModifiableInt, so
that you could do a cast. But on the other hand, casts are always
somehow "unsafe"... (IIRC its the same with 'const' which you can "cast
away")

On the other hand, even immutable Types like java.lang.String can be
modified (using reflection).

Ciao,
Ingo
 
O

Oliver Wong

Ingo R. Homann said:
Hi,

concerning your problem of recycling objects, my opinion is clear:

Do NOT recycle objects. It *may* speed up you app in some cases (while it
may slow down your app in other cases). Write clean and readable code and
choose the right data structures and algorithms. If your platform does not
have enough resources to properly run your application, recycling objects
will not help very much. In 99% there are more disadvantages than
advantages.

To your other question ("const" (which I am missing as well) vs
"mutability"):

I have not tested it in a productive environment, but an approach would by
something like that:

class UnmodifiableInt {
protected int i;
public int getValue() {
return i;
}
}

class ModifiableInt extends UnmodifiableInt {
public void setValue(int i) {
this.i=i;
}
}

I recommend having 3 classes, instead of 2 (or 2 classes, and 1
interface):

interface Int {
public int getValue();
}

final class UnmodifiableInt implements Int {
protected int i;
public int getValue() {
return i;
}
}

final class ModifiableInt implements Int {
protected int i;
public int getValue() {
return i;
}
public void setValue(int i) {
this.i=i;
}
}

The problem with the 2-class design is that it fails the IS-A test of
inheritance: that is, it should not be the case than a ModifiableInt IS-A
UnmodifiableInt. So you should not be able to use a ModifableInt anywhere an
UnmodifiableInt is expected.

- Oliver
 
I

Ingo R. Homann

Hi,

Oliver said:
The problem with the 2-class design is that it fails the IS-A test of
inheritance: that is, it should not be the case than a ModifiableInt IS-A
UnmodifiableInt. So you should not be able to use a ModifableInt anywhere an
UnmodifiableInt is expected.

No, I think, the 2-class-design is better:

Consider you have a method that wants to indicate that it does not
change the Parameter:

void foo(UnmodifiableInt i) {...}

Now, why should it be impossible to pass a ModifiableInt to that method?

And vice versa: Consider a method is returning an ModifiableInt:

ModifiableInt foo() {...}

Why should it be impossible to assign the returned value to a variable
of type UnmodifiableInt to document that the variable will not be modified?

Ciao,
Ingo
 
C

Chris Uppal

Ingo said:
Why should it be impossible to assign the returned value to a variable
of type UnmodifiableInt to document that the variable will not be
modified?

Because the user of the Unmodifiable should be able to rely on it not, in fact,
being modified ?

To some extent this is a documentary issue rather than an OO design issue --
the question being whether and when the user of an object can assume that that
object is immutable. For instance the class name "UnmodifiableXxx" strongly
suggests immutability, the class name "ReadonlyXxxFacade" does not.

-- chris
 
C

Chris Uppal

toton said:
2) Only thing I like immutable object, [...]
I try to have immutable object as
much as possible. It makes a lots of thing simpler.

That's sensible.

Resetting an object is not free, neither memory allocation. But what is
the cost comparison for Java (in C++ resetting an object is cheap,
memory allocation in heap is costly. Thus STL do so much copy, but
little memory allocation, and still is very fast).

Ah, you are a C++ programmer. You will almost certainly find that your
intuitions about costs are wrong in the Java world.

That's for two important reasons: one is that in Java certain operations are
performed /much/ more often than in C++ (object allocation is a case in point),
and so they receive a great deal of attention from the JVM implementers. The
other reason is that Java implementations (at least on desktop machines and
bigger) tend to be extremely advanced (Sun's JVMs as about close to the
bleeding edge as you can get), and so the implementation techniques are less
than obvious, and the mapping from source code to eventual machine code may be
a lot more indirect than would normally be the case with a C++ program. The
effect of adaptive optimisation alone makes it hard both to reason about, and
to measure, performance (BTW, any micro-benchmark -- like the one in your first
post in this thread -- which does not take account of adaptive optimisation is
probably completely useless.)

Now, on desktop (and better) machines object allocation is /very/ fast (only a
very few instructions -- less than it takes to zero the memory for the newly
allocated object), and normally it would be a mistake to use object pools
(might even slow the program down, since the GC algorithms are designed and
tuned on the -- correct -- assumption that most objects don't survive for very
long at all). Whether that still applies in your target JVM (on the iPAQ) I
have no idea. But what you can be fairly sure of is that the target JVM's
memory handling has been very carefully designed around the hardware's balance
of CPU speed and memory size. To put it another way, its a fair bet that the
JVM can manage memory faster than you can do it yourself ;-)

3) I have a little more question. I want a few of my classes to evolve
over time (i.e they are mutable.) as all of the states are not
available initially. However if anyone wants it I need to send an
unmodifyable snapshot of it ( i.e constantify it & send). Again as Java
do not have const, I am looking for some inner class based
implementation. Anything specific known regarding that? (like a
modifier class, If someone gets access to modifier of a class he will
be able to modify its state, otherwise the class is immutable! ) .

I suggest that before you get stuck into complex code to try to replicate C++'s
pointer-to-const semantics, you should first get some practise with working
without it. This is (IMO) another case where intuitions trained on C++ are not
applicable in the Java world; and you may find that the cost/benefit equation
of "controlled mutability" favours a different balance in Java. Consider that
in C++ sticking "const" onto some declaration has minimally disruptive effect
on the source and/or overall design, and has zero cost at runtime. In Java
there is no equivalent of that mechanism, so controlled immutability (as
opposed to just creating completely immutable objects) would have a cost in
both design/code effort, and at runtime. The costs are higher, but the benefit
is at most the same and may actually be smaller (as a result of Java's
generally safer and less easy-to-break-accidentally semantics).

I.e. just don't bother (normally).

On the fairly rare occasions where you /do/ need to hand out data while
disallowing changes to it, you should consider at least three options:

1) Just hand out a copy (remember allocation is cheap in Java). This should
be your first choice since it is both simple and totally reliable.

2) Hand out a reference to the data, but in the form of a reference of a type
which doesn't include mutating operators. Oliver and Ingo have already
discussed this option. Note that there is not much to prevent the consumer
from misusing the reference by downcasting it back to the mutable type.

3) Hand out a helper object which itself has no mutating operations, and which
implements readonly operations by forwarding them to the "real" object. Thus
the consumer only ever has controlled access to the real object. Something
like:

public class MyStuff
{
private RealData m_realData;

public static class PublicData
{
private final RealData m_data;
PublicData(ReadData data) { m_data = data; }
public int getX() { return m_data.getX(); }
}

private static class RealData
{
....
int getX() { ... }
void setX(int x) { ... }
....
}

public PublicData
getData()
{
return new PublicData(m_realData);
}
}

There's nothing magical about the use of nested classes in the above. They
might make the code look prettier for this kind of application, but they don't
add anything semantically different from what you could do with "real"
(top-level) classes.

Do note that all these options add complexity and have a runtime cost (which
may not, in fact, be very great, but it won't be zero). Don't use these
techniques unless you have a better reason than just a habit carried over from
C++.

-- chris
 
N

Niklas Matthies

Because the user of the Unmodifiable should be able to rely on it
not, in fact, being modified ?

To some extent this is a documentary issue rather than an OO design
issue -- the question being whether and when the user of an object
can assume that that object is immutable. For instance the class
name "UnmodifiableXxx" strongly suggests immutability, the class
name "ReadonlyXxxFacade" does not.

It seems to me that, as the Collections.unmodifiable*() methods
suggest, "unmodifiable" does not mean "immutable", but rather mean
what you call "readonly". "Unmodifiable" is a property of the
interface (or proxy) type, i.e. the (observable) object state cannot
be modified via that interface/proxy (but possibly via some other one),
whereas "immutable" is a property of the class, i.e. instances of such
a class don't ever change their (observable) state throughout their
lifetime.

In any case, however they are named, these are two distinct concepts
(immutability implies unmodifiability, but not the other way round),
and their implementation will look different accordingly.

-- Niklas Matthies
 
I

Ingo R. Homann

Hi,

Chris said:
Because the user of the Unmodifiable should be able to rely on it not, in fact,
being modified ?

Well, I explained my point of view to this in a post before:

'Of course it is not "save" because if you have a reference of type
UnmodifiableInt, it may point to an object of type ModifiableInt, so
that you could do a cast. But on the other hand, casts are always
somehow "unsafe"... (IIRC its the same with 'const' which you can "cast
away")
On the other hand, even immutable Types like java.lang.String can be
modified (using reflection).'

Ciao,
Ingo
 
O

Oliver Wong

Ingo R. Homann said:
Hi,



No, I think, the 2-class-design is better:

Consider you have a method that wants to indicate that it does not change
the Parameter:

void foo(UnmodifiableInt i) {...}

Now, why should it be impossible to pass a ModifiableInt to that method?

It depends on the situation, of course, but what if foo, for example,
uses i as the key in a hashtable, on the assumption that the hashcode for i
will never change. Then passing in a ModifiableInt might cause a lot of
problems.

You could simulate your intended behaviour in the 3-class (or
2-class+1-interface) design as:

void foo(Int i) { ... }

Where Int is the interface/class which only has the getter, but makes no
guarantee about whether or not i is immutable. I.e. you could pass
ImmutableInt or MutableInt to foo, because both classes implement/extend
Int.
And vice versa: Consider a method is returning an ModifiableInt:

ModifiableInt foo() {...}

Why should it be impossible to assign the returned value to a variable of
type UnmodifiableInt to document that the variable will not be modified?

Similarly, you could assign this to a reference of type Int if you don't
care about modifiability.

However, I realize now that I had assumed "unmodifiable" was synonymous
with "immutable", but Chris' and Niklas' posts indicate that some
programmers may interpret a difference between these two terms.

- Oliver
 
I

Ingo R. Homann

Hi,

Oliver said:
It depends on the situation, of course, but what if foo, for example,
uses i as the key in a hashtable, on the assumption that the hashcode for i
will never change. Then passing in a ModifiableInt might cause a lot of
problems.

Ah, OK, perhaps that's what Chris meant as well (I interpreted his
answer diffently (that the value could be changed by casting the
reference to a ModifiableInt)... post cancelled).

Good reason!

Ciao,
Ingo
 
L

Lasse Reichstein Nielsen

Oliver Wong said:
It depends on the situation, of course, but what if foo, for example,
uses i as the key in a hashtable, on the assumption that the hashcode for i
will never change. Then passing in a ModifiableInt might cause a lot of
problems.

Nevermind the problems, just the name is enough to disqualify this
approach. After all, one would have to say:
"ModifiableInt is-a UnmodifiableInt"
That's incorrect, so either the names or the inheritance is wrong.

If anything, it should be something like ModifiableInt and ReadableInt,
because the modifiable int is a readable int.

/L
 
N

Niklas Matthies

Nevermind the problems, just the name is enough to disqualify this
approach. After all, one would have to say:
"ModifiableInt is-a UnmodifiableInt"
That's incorrect, so either the names or the inheritance is wrong.

If anything, it should be something like ModifiableInt and ReadableInt,
because the modifiable int is a readable int.

I would suggest:

interface Int { int getValue(); }

interface ModifiableInt extends Int { void setValue(int value); }

class ImmutableInt implements Int
{
private final int value;
public ImmutableInt(int value) { this.value = value; }
public int getValue() { return value; }
}

class MutableInt implements ModifiableInt
{
private int value;
public MutableInt(int value) { this.value = value; }
public int getValue() { return value; }
public void setValue(int value) { this.value = value; }
}

-- Niklas Matthies
 
O

Oliver Wong

Niklas Matthies said:
I would suggest:

interface Int { int getValue(); }

interface ModifiableInt extends Int { void setValue(int value); }

class ImmutableInt implements Int
{
private final int value;
public ImmutableInt(int value) { this.value = value; }
public int getValue() { return value; }
}

class MutableInt implements ModifiableInt
{
private int value;
public MutableInt(int value) { this.value = value; }
public int getValue() { return value; }
public void setValue(int value) { this.value = value; }
}

2 classes + 2 interfaces? Now that's just being crazy. ;)

- Oliver
 
R

Rogan Dawes

Chris said:
toton said:
2) Only thing I like immutable object, [...]
I try to have immutable object as
much as possible. It makes a lots of thing simpler.

That's sensible.

Resetting an object is not free, neither memory allocation. But what is
the cost comparison for Java (in C++ resetting an object is cheap,
memory allocation in heap is costly. Thus STL do so much copy, but
little memory allocation, and still is very fast).

Ah, you are a C++ programmer. You will almost certainly find that your
intuitions about costs are wrong in the Java world.

That's for two important reasons: one is that in Java certain operations are
performed /much/ more often than in C++ (object allocation is a case in point),
and so they receive a great deal of attention from the JVM implementers. The
other reason is that Java implementations (at least on desktop machines and
bigger) tend to be extremely advanced (Sun's JVMs as about close to the
bleeding edge as you can get), and so the implementation techniques are less
than obvious, and the mapping from source code to eventual machine code may be
a lot more indirect than would normally be the case with a C++ program. The
effect of adaptive optimisation alone makes it hard both to reason about, and
to measure, performance (BTW, any micro-benchmark -- like the one in your first
post in this thread -- which does not take account of adaptive optimisation is
probably completely useless.)

As a counterpoint to Chris's comments, note that Swing reuses objects in
many cases, most notably renderers, for performance reasons.

From the JavaDocs for DefaultTableCellRenderer:

Implementation Note: This class inherits from JLabel, a standard
component class. However JTable employs a unique mechanism for rendering
its cells and therefore requires some slightly modified behavior from
its cell renderer. The table class defines a single cell renderer and
uses it as a as a rubber-stamp for rendering all cells in the table; it
renders the first cell, changes the contents of that cell renderer,
shifts the origin to the new location, re-draws it, and so on. The
standard JLabel component was not designed to be used this way and we
want to avoid triggering a revalidate each time the cell is drawn. This
would greatly decrease performance because the revalidate message would
be passed up the hierarchy of the container to determine whether any
other components would be affected. So this class overrides the
validate, revalidate, repaint, and firePropertyChange methods to be
no-ops. If you write your own renderer, please keep this performance
consideration in mind.

Rogan
 
N

Niklas Matthies

2 classes + 2 interfaces? Now that's just being crazy. ;)

You won't have to use them all at the same time. :)
Clients will only "see" either Int, ModifiableInt or (if the guarantee
of immutability really needs to be made explicit) ImmutableInt.

You could also drop MutableInt and instead implement it directly in
ModifiableInt, but this would remove the flexibility of passing a
differently-implemented ModifiableInt to clients. With a simple int
this might not seem so probable, but think of ModifiableList or
similar.

Take the collections framework for example. A better design would have
been to make the Collection interface "unmodifiable" (i.e. with all
the mutating methods removed) and provide a ModifiableCollection
interface that extends it with the mutating methods. Same for List,
Map, Set and so on. Then ArrayList would implement ModifiableList,
but you could still simply pass it to clients as just List and be
certain that they don't modify it (unless they attempt to cast it to
ModifiableList) instead of having to wrap it into an "unmodifiable"
proxy. In addition the framework could provide one ImmutableList class
that implements List and whose constructor takes an arbitrary List
whose elements would be copied to become the contents of the
ImmutableList (which would then be really immutable instead of just
unmodifiable).

To illustrate the analogy with the interfaces/classes above:

Int ~ List
ModifiableInt ~ ModifiableList
ImmutableInt ~ ImmutableList
MutableInt ~ ArrayList, LinkedList, ...

So, yes, it's one additional interface (ModifiableList) and one
additional class (ImmutableList), but it would be much sounder than
the existing design (where you get UnsupportedOperationExceptions),
and it can be used with all List implementations, so it amortizes
pretty well.

Of course, having something like C++'s "const" (or rather its inverse:
a "modifiable" qualifier) would be even better.

-- Niklas Matthies
 
C

Chris Uppal

Rogan said:
As a counterpoint to Chris's comments, note that Swing reuses objects in
many cases, most notably renderers, for performance reasons.

Indeed, yes.

Still, I'd like to make a couple of observations (I'm not disagreeing, you
understand, just expanding on a good point):

I really should have been clearer that I was refering to the time taken to
allocate the memory -- the time taken to initalise the object that will live in
that memory is, of course, dependent on the object itself, and may take an
arbitrarily long time.

public class Ouch
{
publich Ouch() { for (;;); }
}

;-)

Also, if wouldn't advise newcomers to Java to take Swing as an example of
either good /or/ typical Java programming.

-- chris
 
T

toton

Chris said:
toton said:
2) Only thing I like immutable object, [...]
I try to have immutable object as
much as possible. It makes a lots of thing simpler.

That's sensible.

Resetting an object is not free, neither memory allocation. But what is
the cost comparison for Java (in C++ resetting an object is cheap,
memory allocation in heap is costly. Thus STL do so much copy, but
little memory allocation, and still is very fast).

Ah, you are a C++ programmer. You will almost certainly find that your
intuitions about costs are wrong in the Java world.
Yes, I "see" Java memory allocations are much faster than C++ new
allocation (dynamic one). Java dynamic allocation almost competes with
C++ stack based (static) allocation!
Maybe someday Java will have an @valueType attribute to "help" memory
allocation for non-polymorphic objects (final objects), and the
collection will "hold" the value type objects! Who knows!
That's for two important reasons: one is that in Java certain operations are
performed /much/ more often than in C++ (object allocation is a case in point),
and so they receive a great deal of attention from the JVM implementers. The
other reason is that Java implementations (at least on desktop machines and
bigger) tend to be extremely advanced (Sun's JVMs as about close to the
bleeding edge as you can get), and so the implementation techniques are less
than obvious, and the mapping from source code to eventual machine code may be
a lot more indirect than would normally be the case with a C++ program. The
effect of adaptive optimisation alone makes it hard both to reason about, and
to measure, performance (BTW, any micro-benchmark -- like the one in your first
post in this thread -- which does not take account of adaptive optimisation is
probably completely useless.)
Heard sun is opening up its C++ sourcecode for JIT , eager to look at
the "bleeding edge" techniques.
Now, on desktop (and better) machines object allocation is /very/ fast (only a
very few instructions -- less than it takes to zero the memory for the newly
allocated object), and normally it would be a mistake to use object pools
(might even slow the program down, since the GC algorithms are designed and
tuned on the -- correct -- assumption that most objects don't survive for very
long at all). Whether that still applies in your target JVM (on the iPAQ) I
have no idea. But what you can be fairly sure of is that the target JVM's
memory handling has been very carefully designed around the hardware's balance
of CPU speed and memory size. To put it another way, its a fair bet that the
JVM can manage memory faster than you can do it yourself ;-)
That always one programmer wants! But a human never wants a machine to
overperform him! what a irony!
I suggest that before you get stuck into complex code to try to replicate C++'s
pointer-to-const semantics, you should first get some practise with working
without it. This is (IMO) another case where intuitions trained on C++ are not
applicable in the Java world; and you may find that the cost/benefit equation
of "controlled mutability" favours a different balance in Java. Consider that
in C++ sticking "const" onto some declaration has minimally disruptive effect
on the source and/or overall design, and has zero cost at runtime. In Java
there is no equivalent of that mechanism, so controlled immutability (as
opposed to just creating completely immutable objects) would have a cost in
both design/code effort, and at runtime. The costs are higher, but the benefit
is at most the same and may actually be smaller (as a result of Java's
generally safer and less easy-to-break-accidentally semantics).

I.e. just don't bother (normally).
It is again like, I want an immutable class, but the class is big! How
to set all of the fields within constructor? It will be a huge list.
I have a Document class, which has name, address , and many other
fields. Now this class can load its fields from different types of
files, some are XML based, some simply name value pair. Now, the
Document need not to know the parsing logic, it is separated. A parser
for each type parses the file, and sets the field in the Document. and
when done, Document is ready, an immutable class. No more modification
is allowed. To make it immutable I need to pass all of the parameters
to the Document ctor, which is a long list (say 20 fields). Other thing
I can have is setters, which makes it mutable.
I "feel" there must be a better way. Like I make Document an inner
class for an abstract class Parser (or an interface) which all of the
specific parsers implement! Thus all of the parsers can access the
Document fields and set them. But no setters, thus no one else can do
it. Not sure about the idea ( I am not sure about the inner classes ).
On the fairly rare occasions where you /do/ need to hand out data while
disallowing changes to it, you should consider at least three options:

1) Just hand out a copy (remember allocation is cheap in Java). This should
be your first choice since it is both simple and totally reliable.

2) Hand out a reference to the data, but in the form of a reference of a type
which doesn't include mutating operators. Oliver and Ingo have already
discussed this option. Note that there is not much to prevent the consumer
from misusing the reference by downcasting it back to the mutable type.

3) Hand out a helper object which itself has no mutating operations, and which
implements readonly operations by forwarding them to the "real" object. Thus
the consumer only ever has controlled access to the real object. Something
like:

public class MyStuff
{
private RealData m_realData;

public static class PublicData
{
private final RealData m_data;
PublicData(ReadData data) { m_data = data; }
public int getX() { return m_data.getX(); }
}

private static class RealData
{
....
int getX() { ... }
void setX(int x) { ... }
....
}

public PublicData
getData()
{
return new PublicData(m_realData);
}
}

There's nothing magical about the use of nested classes in the above. They
might make the code look prettier for this kind of application, but they don't
add anything semantically different from what you could do with "real"
(top-level) classes.

Do note that all these options add complexity and have a runtime cost (which
may not, in fact, be very great, but it won't be zero). Don't use these
techniques unless you have a better reason than just a habit carried over from
C++.
In the meantime writting a Java "preprocessor" which recognizes const
keyword and do check! However no runtime check. In progress ! Will add
a good skill to my compiler knowledge! Not something serious, Just for
fun! The Java project is also my personal one only, as a hobby.

Thanks all for the long discussion and suggestions and advices!.
 
T

toton

Chris said:
Indeed, yes.

Still, I'd like to make a couple of observations (I'm not disagreeing, you
understand, just expanding on a good point):

I really should have been clearer that I was refering to the time taken to
allocate the memory -- the time taken to initalise the object that will live in
that memory is, of course, dependent on the object itself, and may take an
arbitrarily long time.

public class Ouch
{
publich Ouch() { for (;;); }
}

;-)

Also, if wouldn't advise newcomers to Java to take Swing as an example of
either good /or/ typical Java programming.
And here, the O.P. ( Myself) is not a new comer in Java World. He
professionally worked with some big company in Java (now in a small
company, with C++ , and more in research field :( ) . But all those
programs are really trivial (You know EJB , Servlet, Hibernate etc) ,
doesn't require much in-depth knowledge about the language itself. But
when it comes with his personal interses, he goes a little deep and
explores the possiblities, problems and solutions, as here no
timeframe, no rulebook no project leader! His interests are in language
construction (among others) and developed a nearly full compiler for
Java, which compiles a Java programm, and you can run it!
Thanks
 

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,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top