Java Forum / General / August 2006
How to give selective access to the methods in a class?
toton - 09 Aug 2006 10:48 GMT Hi, I have a class Document, which represents the data repository (a singleton class), from where the whole application gets the nessery Objects they need. Which prevents me from passing the Data from method to method. Now I only want to give access some of the class to modify some of the data. Thus like, Document object can return CC object, or Segment object or Header object. Now only SegmentCalculator can create (may be modify sometimes, otherwise they are immutable) a segment, the other can get Segment object, which has no setters. Similarly HeaderCalculator can create a header and store in the Document. others can use it.
remaining organization and class relationships are flexible. Only my concern is a good OO design for this (in Java) . I have thought a package level modifier for setters in Document, but doesn't seems a good solution, ans SegmentCalculator & Headercalculator may be in different package.
Thus the basic idea is to operate on a set of data objects, where all can use them, but only some can modify. How to organize this kind of situation into class representation? Any pattern exists for this? I have searched GOF book & Java Patterns, but unable to locate a good solution for this kind of senario.
any kind of help is appriciated.
Chris Uppal - 09 Aug 2006 11:16 GMT > I have a class Document, which represents the data repository (a > singleton class), from where the whole application gets the nessery > Objects they need. "Document" seems a strange name for what you describe as a "repository".
> Which prevents me from passing the Data from method > to method. [quoted text clipped - 7 lines] > Similarly HeaderCalculator can create a header and store in the > Document. others can use it. Maybe you could use an extra level of indirection. If you have (in the same package as Document) a collection of other classes like HeaderWriter, SegmentWriter, and so on. These have public methods which can write the relevant data to the repository, but only the repository can create them. Then the SegmentCalculator (and similar) would /use/ a SegmentWriter (which they would get from the repository in some controlled way) to perform their limited updates. Of course the issue here is what kind of control you want to apply to passing out SegmentWriter instances -- but that depends on what you want to achieve with this level of extra "security", and you haven't told us that.
Another, rather similar, approach would be to make SegmentWriter, etc, into base classes which SegmentCalculator would extend. SegmentWriter's methods for changing the data would be protected (and probably their constructors too). Thus an XxxxCalculator class would gain the "right" to update parts of the repository only by inheriting from one of the XxxxWriter classes.
You may consider both of the above ideas to be over-complicated for what they achieve, and -- truth be told -- I'm inclined to agree. It doesn't sound (to me, from over here) as if the extra level of control is actually buying you very much.
-- chris
Eric Sosman - 09 Aug 2006 12:46 GMT > Hi, > I have a class Document, which represents the data repository (a [quoted text clipped - 22 lines] > pattern exists for this? I have searched GOF book & Java Patterns, but > unable to locate a good solution for this kind of senario. "Only SegmentCalculator can [modify] a Segment ..." Okay, make Segment an inner class of SegmentCalculator, and make Segment's constructors and modifiers private. Since Segment is inside SegmentCalculator, its private methods and fields are accessible to SegmentCalculator but not to any "outside" classes.
Same strategy for HeaderCalculator and Header.
Document can contain as many Headers and Segments as you choose, but cannot modify them (it does not have access to their setters). In this way Document resembles ArrayList or HashSet: its job is to hold things, evict things, dole out references to things, and tell you whether certain things are or aren't there, but not to make changes to those things.
 Signature Eric Sosman esosman@acm-dot-org.invalid
toton - 09 Aug 2006 12:58 GMT > > Hi, > > I have a class Document, which represents the data repository (a [quoted text clipped - 29 lines] > are accessible to SegmentCalculator but not to any "outside" > classes. yes that will help, as only SegmentCalculator can modify a segment ...
> Same strategy for HeaderCalculator and Header. true.
> Document can contain as many Headers and Segments as you > choose, but cannot modify them (it does not have access to > their setters). In this way Document resembles ArrayList or > HashSet: its job is to hold things, evict things, dole out > references to things, and tell you whether certain things are > or aren't there, but not to make changes to those things. Can Document hold reference to an inner class? No, Document is not an ArrayList. It holds exactly one Header, and an ArrayList of Segment's , and can return Document or an element from Segment ArrayList ( dont allow to add an element to the ArrayList or remove, just returns the Iterator) .
Patricia Shanahan - 09 Aug 2006 13:11 GMT >>> Hi, >>> I have a class Document, which represents the data repository (a [quoted text clipped - 44 lines] > Segment ArrayList ( dont allow to add an element to the ArrayList or > remove, just returns the Iterator) . Why can't Document hold a reference to an inner class? Remember the inner class itself does not need to be private, just the methods and constructors that only SegmentCalculator should call.
If you prefer, you can have the inner class implement an interface, and have Document refer to it through the interface.
Patricia
Eric Sosman - 09 Aug 2006 13:54 GMT >> [...] >> Document can contain as many Headers and Segments as you [quoted text clipped - 5 lines] >> > Can Document hold reference to an inner class? Yes. Inner classes are classes.
> No, Document is not an ArrayList. It holds exactly one Header, and an > ArrayList of Segment's , and can return Document or an element from > Segment ArrayList ( dont allow to add an element to the ArrayList or > remove, just returns the Iterator) . I didn't mean that Document *is* an ArrayList or HashSet, I meant that it is *similar* to those. The similarity I wanted to point out is that Document's role is to hold on to a bunch of references to Segments and Headers and Whatnots, but not to make changes to those things. The methods of Document cannot call the setters of Segment, because they are private. Document can change the contents of its ArrayList of Segment references, adding new ones and evicting old ones, but it cannot make changes to the Segment instances themselves.
By the way, Iterator has a remove() method. If you want to make sure nobody except Document can change the "membership" of the ArrayList, be sure to derive the Iterator from an unmodifiable view of the ArrayList and not from the ArrayList itself. See Collections.unmodifiableList().
 Signature Eric Sosman esosman@acm-dot-org.invalid
toton - 09 Aug 2006 15:24 GMT > >> [...] > >> Document can contain as many Headers and Segments as you [quoted text clipped - 22 lines] > ones and evicting old ones, but it cannot make changes to the > Segment instances themselves. Thats fine... yes it is similar, but implements ArrayList by composition rather than inheritance.
> By the way, Iterator has a remove() method. If you want to > make sure nobody except Document can change the "membership" of > the ArrayList, be sure to derive the Iterator from an unmodifiable > view of the ArrayList and not from the ArrayList itself. See > Collections.unmodifiableList(). Oh! I have already done that. Thanks for the suggestion. One more question, slightly out of topic. ArrayList can reserve memory for certain size. I expect that memory is to reserve only the reference, not the object itself (unlike C++ containers where u can reserve for the cobect itself). How much effective is this in long run? i.e will JIT make the object contains side by side? or they will be scattered? (boils down to the question, array holds the object itself or just the reference ? ) I have a circular buffer which adds several objects from one end and removes from other end through out the program. It is preferable if the ArrayList holds the object itself. thanks again...
Eric Sosman - 09 Aug 2006 16:23 GMT toton wrote On 08/09/06 10:24,:
> [...] > One more question, slightly out of topic. > ArrayList can reserve memory for certain size. I expect that memory is > to reserve only the reference, not the object itself (unlike C++ > containers where u can reserve for the cobect itself). Correct. Object instances in Java exist "somewhere else," and the only things the program manipulates directly are references and primitives.
> How much > effective is this in long run? i.e will JIT make the object contains > side by side? or they will be scattered? (boils down to the question, > array holds the object itself or just the reference ? ) The instances exist "somewhere else," and the ArrayList holds references to them. The instances might be scattered or might be grouped together; they might even move around to different memory locations at different times. That's the JVM's worry, not yours: The reference still leads to the instance, no matter where it happens to be located.
> I have a > circular buffer which adds several objects from one end and removes > from other end through out the program. It is preferable if the > ArrayList holds the object itself. As you know by now, the ArrayList holds references and not instances. I don't see why you would prefer things to be otherwise -- but in any event, they aren't.
 Signature Eric.Sosman@sun.com
toton - 10 Aug 2006 06:00 GMT > toton wrote On 08/09/06 10:24,: > > [...] [quoted text clipped - 18 lines] > JVM's worry, not yours: The reference still leads to the > instance, no matter where it happens to be located. Yes, its JVM's worry. I know that. My worry is that, do JVM really worry to keep frequently accessed objects in nearby places? The second thing what I wanted to know, for Vector or ArrayList type of random access container, how much effective the load factor or initial capacity, as the container doesn't hold the object itself. One need to choose them judicially for STL containers, whent they contains the objects itself, otherwise frequent memory copy occures. One can see a visable performance difference there. Is that kind of fine tuning is necessary for JCF Vector or ArrayList, (or default value of 10 works fine irrespective of ArrayList size? ) )as it stores the reference only, the increase in size out of capicity will cause only copy of reference, not the object itself.
> > I have a > > circular buffer which adds several objects from one end and removes > > from other end through out the program. It is preferable if the > > ArrayList holds the object itself. The strategy is little different for the program, as you can see. The program pushes certain objects into the circular buffer, perform some operation on them and removes the older one. Thus lots of object created pushed on buffer, and older one removed. So there I see two problems, 1) No obvious hotspot, as the program doesn't run with the same object on the loop (unlike most of the applications, or GUI's). Rather it looks like a factory conveyor belt, where things are put in, operated and finished. 2) Little overhead for then gc, as lots of new objects created and processed need to be garbage collected.
Any tuning for gc can be done? any particular gc suitable for this kink of oerations?
> As you know by now, the ArrayList holds references and > not instances. I don't see why you would prefer things to > be otherwise -- but in any event, they aren't. If the contaner class objects resides nearby in memory (may not be adjascent unlike array with premitives), it is good for most programming, as most of the time program iterates over the container classes and do operation.
Eric Sosman - 10 Aug 2006 12:53 GMT >>toton wrote On 08/09/06 10:24,: >> [quoted text clipped - 13 lines] > Yes, its JVM's worry. I know that. My worry is that, do JVM really > worry to keep frequently accessed objects in nearby places? Not that I know of -- but then, I've never bothered to look. Also, there is more than one JVM, and different JVMs have different strategies for managing memory.
> The second thing what I wanted to know, for Vector or ArrayList type of > random access container, how much effective the load factor or initial [quoted text clipped - 6 lines] > only, the increase in size out of capicity will cause only copy of > reference, not the object itself. If you happen to know roughly how many objects the list will eventually contain, you can save some time by making the list that large to begin with rather than just letting it grow on its own. How much time? Probably not a lot unless the list grows quite large indeed.
>>>I have a >>>circular buffer which adds several objects from one end and removes [quoted text clipped - 6 lines] > created pushed on buffer, and older one removed. So there I see two > problems, One thing that stands out is the oddity of using an ArrayList or Vector for a "circular buffer." An ordinary array would seem more natural. (However, there's a bit of a language barrier here, and it's quite possibly you use "circular buffer" to mean something different than I do.)
> 1) No obvious hotspot, as the program doesn't run with the same object > on the loop (unlike most of the applications, or GUI's). Rather it [quoted text clipped - 5 lines] > Any tuning for gc can be done? any particular gc suitable for this kink > of oerations? Toton, have you *measured* a performance problem? Or are you merely imagining one?
 Signature Eric Sosman esosman@acm-dot-org.invalid
toton - 11 Aug 2006 14:55 GMT > >>toton wrote On 08/09/06 10:24,: > >> [quoted text clipped - 34 lines] > How much time? Probably not a lot unless the list grows quite > large indeed. Yes. I know roughly how many objects it will contain. So array resizing is not at all a problem (I know the resize operation is very few). But even I don't think resize is time consuming , as it holds only the reference, not the objects itself. And thus the array size may be very less ( I have an approx 5000 size buffer). so, for reference it may need 5000*ref_size memory which is much smaller than 5000*object_size That's why my question, as the array doesn't hold the object itself, how important is to set the array size, or increment?
> >>>I have a > >>>circular buffer which adds several objects from one end and removes [quoted text clipped - 12 lines] > and it's quite possibly you use "circular buffer" to mean something > different than I do.) Circular buffer is a static buffer over which references rotate to denote start & end. It is very much possible to implement it with array (not difficult at all, in my openion). I had uses ArrayList just to get immediate benifit of Iterator etc. I will implement it using simple array.
> > 1) No obvious hotspot, as the program doesn't run with the same object > > on the loop (unlike most of the applications, or GUI's). Rather it [quoted text clipped - 8 lines] > Toton, have you *measured* a performance problem? Or are > you merely imagining one? No. I can't measure a performance for Java, as Java doesn't support by value symantics for containers. However I had compared my C++ implementation with Java one. There is a difference. But I am not sure, whether the difference is due to memory allocation or something else. Maybe I will check in Java profiler about detail, with several run of different size. also I had a huge difference in C++, when I had transfered the program from vector<Point*> to vector<Point> symantics. as in the second case, allocator pre-allocates the memory for the objects with reserve, while for the second case it pre-allocates only for pointers. setting an object null, when it is no more in use anyway helps gc? may be I will post some representative version of the program for clear understanding.
thanks
Chris Smith - 11 Aug 2006 15:55 GMT > setting an object null, when it is no more in use anyway helps gc? I'll just respond to this. No, except in specific circumstances or unless you've done something else wrong, setting a reference to null doesn't help garbage collection.
(Incidentally, there is no such thing as setting an object to null. Null is a value for a reference, and it doesn't have anything to do with objects.)
 Signature Chris Smith - Lead Software Developer / Technical Trainer MindIQ Corporation
Patricia Shanahan - 11 Aug 2006 16:16 GMT >> setting an object null, when it is no more in use anyway helps gc? > > I'll just respond to this. No, except in specific circumstances or > unless you've done something else wrong, setting a reference to null > doesn't help garbage collection. I'm surprised, and curious about this statement. On the face of it, Java garbage collection is prevented by an object being reachable, and assigning null to a reference may transition an object from reachable to unreachable.
For example, one of my Java programs was a simulation of a computer processor-memory interconnect. The main objects were representations of transactions and of hardware components, such as processors and memory modules, and queues connecting components. There are relatively few components and queues, but they exist for the whole duration of the simulation. There are many transactions, but each should exist for only a relatively short time.
At times, a simulated component can go idle for an extended period. In an attempt to aid garbage collection, I made sure that as soon as a component had finished its work on a transaction, it set its current transaction reference to null.
Similarly, the queue implementation did some null reference assignments to ensure that each queue only had references to transactions that were actually on the queue, not to transactions that had been on it.
The invariant I was aiming for was that a long lived object should have a reference to a Transaction if, and only if, it still had work to do on the Transaction.
Was I wasting my time? It seemed to reduce memory use.
Patricia
Chris Smith - 11 Aug 2006 18:05 GMT > I'm surprised, and curious about this statement. On the face of it, Java > garbage collection is prevented by an object being reachable, and > assigning null to a reference may transition an object from reachable to > unreachable. Assigning null to a reference is certainly an effective way of preventing an object from being reachable from that reference. However, in almost all situations, it should be unnecessary to assign null to a reference just for the sake of garbage collection. It's generally better to either allow a reference to go out of scope or rely on a larger object (perhaps a Collections API container class) to manage reachability in a more logical way.
Your simulation example may be a pseudo-exception. If each component can only have one transaction at a time and spends a lot of time without one, then setting that field to null to indicate that the component is not working in a transaction is a sensible thing to do. Even so, the real issue there is that the field being null is *right*, not that it helps garbage collection. Even without the concern for garbage collection, setting that field to null to indicate the lack of a transaction would be a good thing to do.
There are other circumstances (which I only mentioned in passing in my original response) where it's indeed a good idea to set a variable to null merely for the sake of garbage collection. For example, the implementation of ArrayList allocates a block of references, and keeps the ones that are beyond the end of the current list null to avoid accidentally retaining objects. However, these are the exception rather than the rule.
Maybe your experience differs, but I have rarely if ever needed to explicitly set variables to null just to please the garbage collector. As such, I acknowledge that this can theoretically occur, but I remain skeptical when the idea of nulling references is brought up, until there's evidence that it's needed.
 Signature Chris Smith - Lead Software Developer / Technical Trainer MindIQ Corporation
Chris Smith - 11 Aug 2006 18:10 GMT > I remain > skeptical when the idea of nulling references is brought up, until > there's evidence that it's needed. And I should read threads closer. I didn't previously realize that the comment about nulling references came after the OP decided against using ArrayList and decided to write a circular buffer class. So yes, the extra array elements should be nulled when not in use.
Sorry!
 Signature Chris Smith - Lead Software Developer / Technical Trainer MindIQ Corporation
toton - 14 Aug 2006 06:19 GMT > > I remain > > skeptical when the idea of nulling references is brought up, until [quoted text clipped - 4 lines] > ArrayList and decided to write a circular buffer class. So yes, the > extra array elements should be nulled when not in use. Thus, when I remove an object from circular buffer, I need to assign it to a null reference.Is that you mean? Any special thing needed (special to Java) for writing a new collections container like circular buffer, related to memory etc? or just the standard way works? Thanks.
> Sorry! > > -- > Chris Smith - Lead Software Developer / Technical Trainer > MindIQ Corporation IchBin - 14 Aug 2006 08:26 GMT >>> I remain >>> skeptical when the idea of nulling references is brought up, until [quoted text clipped - 15 lines] >> Chris Smith - Lead Software Developer / Technical Trainer >> MindIQ Corporation You need to post o a Javascript newsgroup. This is a Java newsgroup. The are close in name but worlds apart!
Thanks in Advance... IchBin, Pocono Lake, Pa, USA http://weconsultants.phpnet.us __________________________________________________________________________
'If there is one, Knowledge is the "Fountain of Youth"' -William E. Taylor, Regular Guy (1952-)
toton - 14 Aug 2006 11:08 GMT > >>> I remain > >>> skeptical when the idea of nulling references is brought up, until [quoted text clipped - 18 lines] > You need to post o a Javascript newsgroup. This is a Java newsgroup. The > are close in name but worlds apart! Why? All the discussions are for Java only! There is nothing related to JavaScript discussed here. I think you are confused. Go through the posts. abir
> Thanks in Advance... > IchBin, Pocono Lake, Pa, USA http://weconsultants.phpnet.us > __________________________________________________________________________ > > 'If there is one, Knowledge is the "Fountain of Youth"' > -William E. Taylor, Regular Guy (1952-) Chris Smith - 14 Aug 2006 20:26 GMT > > And I should read threads closer. I didn't previously realize that the > > comment about nulling references came after the OP decided against using [quoted text clipped - 3 lines] > Thus, when I remove an object from circular buffer, I need to assign it > to a null reference.Is that you mean? I don't understand your sentence. What I mean is that when an object is removed from the circular buffer (meaning that you change an index so that the slot of the buffer is outside the occupied range) you should assign a value of null to that slot in the array.
> Any special thing needed (special to Java) for writing a new > collections container like circular buffer, related to memory etc? or > just the standard way works? The standard way of doing it works fine. Just clean up unused references by assigning them a value of null. The garbage collector is not quite smart enough to examine your algorithms and decide that you won't use a reference just because it's not between the current values of your indices.
 Signature Chris Smith - Lead Software Developer / Technical Trainer MindIQ Corporation
Free MagazinesGet 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 ...
|
|
|