Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / November 2006

Tip: Looking for answers? Try searching our database.

mutate an object or create a new one?

Thread view: 
toton - 24 Oct 2006 09:08 GMT
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
Chris Uppal - 24 Oct 2006 11:50 GMT
> 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
[quoted text clipped - 4 lines]
> 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
toton - 24 Oct 2006 14:27 GMT
> > 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
[quoted text clipped - 15 lines]
> 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.
>     -- chris
Ingo R. Homann - 24 Oct 2006 15:18 GMT
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
Oliver Wong - 24 Oct 2006 19:26 GMT
> Hi,
>
[quoted text clipped - 25 lines]
>   }
> }

   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
Ingo R. Homann - 25 Oct 2006 08:01 GMT
Hi,

>     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
Chris Uppal - 25 Oct 2006 12:09 GMT
> 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
Niklas Matthies - 25 Oct 2006 14:26 GMT
>> Why should it be impossible to assign the returned value to a
>> variable of type UnmodifiableInt to document that the variable will
[quoted text clipped - 8 lines]
> 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
Ingo R. Homann - 25 Oct 2006 15:29 GMT
Hi,

>>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 ?

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
Oliver Wong - 25 Oct 2006 15:33 GMT
> Hi,
>
[quoted text clipped - 11 lines]
>
> 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
Ingo R. Homann - 25 Oct 2006 15:37 GMT
Hi,

>>void foo(UnmodifiableInt i) {...}
>>
[quoted text clipped - 4 lines]
> 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
Lasse Reichstein Nielsen - 25 Oct 2006 16:06 GMT
>> void foo(UnmodifiableInt i) {...}
>>
[quoted text clipped - 4 lines]
> 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
Signature

Lasse Reichstein Nielsen  -  lrn@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
 'Faith without judgement merely degrades the spirit divine.'

Niklas Matthies - 25 Oct 2006 16:21 GMT
> Nevermind the problems, just the name is enough to disqualify this
> approach. After all, one would have to say:
[quoted text clipped - 3 lines]
> 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
Oliver Wong - 25 Oct 2006 17:10 GMT
> I would suggest:
>
[quoted text clipped - 16 lines]
>      public void setValue(int value) { this.value = value; }
>   }

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

   - Oliver
Niklas Matthies - 25 Oct 2006 18:04 GMT
>> I would suggest:
>>
[quoted text clipped - 18 lines]
>
>     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
Chris Uppal - 25 Oct 2006 13:30 GMT
> 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
[quoted text clipped - 4 lines]
> 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
Rogan Dawes - 25 Oct 2006 17:53 GMT
>> 2) Only thing I like immutable object, [...]
>> I try to  have immutable object as
[quoted text clipped - 22 lines]
> 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
Chris Uppal - 26 Oct 2006 11:35 GMT
> 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
toton - 26 Oct 2006 15:56 GMT
> > As a counterpoint to Chris's comments, note that Swing reuses objects in
> > many cases, most notably renderers, for performance reasons.
[quoted text clipped - 18 lines]
> 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
>     -- chris
toton - 26 Oct 2006 15:44 GMT
> > 2) Only thing I like immutable object, [...]
> > I try to  have immutable object as
[quoted text clipped - 9 lines]
> 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),
[quoted text clipped - 8 lines]
> 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
[quoted text clipped - 6 lines]
> 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!

> > 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
[quoted text clipped - 19 lines]
>
> 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:
[quoted text clipped - 47 lines]
> 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!.
>     -- chris
Chris Uppal - 29 Oct 2006 11:34 GMT
> 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!

Who knows, indeed ;-)

> Heard sun is opening up its C++ sourcecode for JIT , eager to look at
> the "bleeding edge" techniques.

You already can download the source for the whole 1.6 platform from the same
page as the JDK itself.  Note that the licence may not be acceptable, so do
read it first.

   http://java.sun.com/javase/downloads/ea.jsp

>  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!

It requires a certain mental agility.  Essentially its a matter of
reclassifying a task (such as memory management) from "it's challenging and
tricky and takes a good programmer to do it properly" to "this stuff is tedious
and too boring to bother with -- let the computer do it!".  The trick is to be
able to change your stance quickly and seamlessly according to the system
you're working with at the time ;-)

> 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 "feel" there must be a better way.

The only ways I know of are:

1) Pass a huge list of parameters to the constructor -- not nice.
2) Pass an object /containing/ all the data to the constructor.  That object
(which might be a generic object such as a Map in some cases) is mutable
itself, but the object which populates itself from that data is not.
3) The downside of (2) is that you replicate the field list; it might be
simpler to keep the "seed" object in your real object as a single field, and
use that to hold the data at runtime.  It doesn't save an awful lot of code,
though.
4) Play games (simple or sophisticated) with access control.  For instance all
the initialisation could be via package-private methods, or even via private
methods (in which case you'd have a static factory method for creating the
things).

I think that all the "tricks" you can play with inner or nested classes amount
to some variation/combination of the above (albeit, perhaps, packaged more
nicely).

In the particular case you describe, I would be tempted to approach this at an
OO design level, rather than as a how-to-make-the-code-say-what-I-want level.
That's to say, I would be tempted to give the objects the responsibility for
populating themselves (taking that job away from the parser).  So the object
would have ultimate responsibility for parsing; and it would /delegate/ some or
all of that responsibility to parser objects which it used internally.  The
protocol for communication between the parser and the object which used it
would be designed so that the parser yielded up information about the various
aspects of the input rather than attempting to use that data to construct a
Document object itself.  That's just a thought, of course, it might make no
sense at all for your actual application.

> 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.

Fair enough.  I hope you enjoy the project !

It wouldn't suit me -- but then I find Java's syntax over-complicated and
wouldn't want to spend more time working with it than I had to.  My impulse
would be to try to do something at the bytecode level (much cleaner than Java
for many things), such as adding an annotation to methods which meant "should
only be called (directly or indirectly) from the constructor", and then to scan
the class files to look for potential violations of the rule.  Not really very
practical, but it could be fun ;-)

Each to his own...

   -- chris
toton - 02 Nov 2006 08:42 GMT
> > Maybe someday Java will have an @valueType attribute to "help" memory
> > allocation for non-polymorphic objects (final objects), and the
[quoted text clipped - 10 lines]
>
>     http://java.sun.com/javase/downloads/ea.jsp
Thanks for pointing out the link. Will check it for sure!

> >  To put it another way, its a fair bet that the JVM can
> > > manage memory faster than you can do it yourself ;-)
[quoted text clipped - 7 lines]
> able to change your stance quickly and seamlessly according to the system
> you're working with at the time ;-)
There is a fare chance that a "Good programmer" (not me! ) "sometimes"
do better job that a "machine". That is what C++ world claims (I am not
too sure about it though).

> > 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.
[quoted text clipped - 19 lines]
> to some variation/combination of the above (albeit, perhaps, packaged more
> nicely).
I like 4th Point, and playing with it. But "package" was meant to be
something different, rather than access control technique (a name
resolution technique).
> In the particular case you describe, I would be tempted to approach this at an
> OO design level, rather than as a how-to-make-the-code-say-what-I-want level.
[quoted text clipped - 7 lines]
> Document object itself.  That's just a thought, of course, it might make no
> sense at all for your actual application.
If Document needs to parse it's data by own, it need to be like a
parser. And it need to parse all of the supported data. Document is the
"model" ,file is the "view", and parser is the "controller". "I feel"
they need to be decoupled.

> > In the meantime writting a Java "preprocessor" which recognizes const
> > keyword and do check! However no runtime check. In progress ! Will add
[quoted text clipped - 10 lines]
> the class files to look for potential violations of the rule.  Not really very
> practical, but it could be fun ;-)
Change in byte-code level  needs a new JVM to run my code! I need to
modify Jikes RVM then (which I don't think support annotation yet). And
surely requires much more knowledge than I have. That is not just
feasible form "me" ! But like the solution, if someone do it. Java
annotation opened a lots of opportunity, which otherwise was only
possible through language extension.
> Each to his own...
>
>     -- chris
Chris Uppal - 02 Nov 2006 14:37 GMT
> I like 4th Point, and playing with it. But "package" was meant to be
> something different, rather than access control technique (a name
> resolution technique).

I don't know how much the package mechanism was originally intended as a
namespace separation feature, and how much as a code grouping feature, but it
has certainly proved to be mostly useful (and used) for the latter.   The
namespace separation is of little use unless there are actual name clashes, but
if there are name clashes then the code is in trouble even /if/ the compiler is
able to disambiguate perfectly.  So it's good practise to avoid name clashes
(within reason) -- e.g. not calling a class List or Map.   And, as a result,
namespace separation is rarely needed.  But the package-level access control is
used /a lot/.

> If Document needs to parse it's data by own, it need to be like a
> parser. And it need to parse all of the supported data.

That's not what I meant.  I said that it had /responsibility/ for parsing the
data -- that isn't at all the same thing as it containing any parsing code (the
responsibility could be, and would be, delegated).  The point (in this
particular design option) is that the users of Documents don't know about
Parser objects -- only the Documents themselves do.

> Document is the
> "model" ,file is the "view", and parser is the "controller". "I feel"
> they need to be decoupled.

I'm sorry, but I don't understand that.  I always get confused when people
start talking about MVC outside its original application domain (constructing
GUIs).  Even if I can see some sort of resemblance between the components'
roles and those of their "equivalents" in classic MVC, I can very rarely see
any point in making the comparison (I don't usually see how the metaphor makes
the concepts any clearer).

> Change in byte-code level  needs a new JVM to run my code! I need to
> modify Jikes RVM then (which I don't think support annotation yet). And
> surely requires much more knowledge than I have.

As a matter of fact Java bytecode has remained very stable over the years --
much more so than Java the language.  And of course, you don't need a whole JVM
just to analyse the bytecode -- there are several libraries available which
will do that for you.  ASM seems to be the most popular these days.  I'm not at
all urging you to become a bytecode expert (you seem to be having enough fun
with compilers for now ;-), but bytecode analysis is easier (and more
interesting[*]) than I think most Java programmers realise.

   -- chris

([*] if you have the right kind of mind ;-)
Arne Vajhøj - 31 Oct 2006 01:41 GMT
> 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!

Probably never.

That kind of things should be left to the compiler.

Arne


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.