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 / August 2007

Tip: Looking for answers? Try searching our database.

Setter ignored on collection

Thread view: 
LT - 14 Aug 2007 07:14 GMT
I remember reading somthing about the behaviour exhibetet by the
program below (where a private collection is altered without going
through its accessor). But cannot seam to find the info anymore - can
someone enlightenme as to why this works:

Class for test
#################
public class TestMe {
    private Set<String> values = new HashSet<String>();
    private int called = 0;
    public Set<String> getValues() {
        return values;
    }
    public void setValues(Set<String> values) {
        for (String v : values) {
            if (v.equals("invalid"))
                throw new IllegalArgumentException("invalid value");
        }
        this.values = values;
        called++;
    }
    public int getCalled() {
        return this.called;
    }
}
#################

Test code
#################
TestMe test = new TestMe();
String valid = "valid";
String anotherValid = "anotherValid";
String invalid = "invalid";

// sets values without calling setter
test.getValues().add(valid);
if (test.getValues().contains(valid)) {
    System.out.println("setter is called: " + test.getCalled()
            + " times, values are: " + test.getValues().toString());
}

// sets values by calling setter
Set<String> values = new HashSet<String>();
values.add(anotherValid);
test.setValues(values);
if (test.getValues().contains(anotherValid)) {
    System.out.println("setter is called: " + test.getCalled()
            + " times, values are: " + test.getValues().toString());
}

// does not work as expected
test.getValues().add(invalid);
if (test.getValues().contains(invalid)) {
    System.out.println("setter is called: " + test.getCalled()
            + " times, values are: " + test.getValues().toString());
}

// works as expected
test.getValues().remove(invalid);
values.add(invalid);
boolean caughtException = false;
try {
    test.setValues(values);
} catch (IllegalArgumentException e) {
    caughtException = true;
}
System.out.println("caught exception: " + caughtException);
#################

The output becomes
#################
setter is called: 0 times, values are: [valid]
setter is called: 1 times, values are: [anotherValid]
setter is called: 1 times, values are: [invalid, anotherValid]
caught exception: true
#################

I can see why this might work given the reference to the collection
returned from the getter, but is there a way to stop this from
happening (besides declaring the collection as unmodifiable ?)
LT - 14 Aug 2007 07:54 GMT
> I remember reading somthing about the behaviour exhibetet by the
> program below (where a private collection is altered without going
[quoted text clipped - 79 lines]
> returned from the getter, but is there a way to stop this from
> happening (besides declaring the collection as unmodifiable ?)

This
http://groups.google.com/group/comp.lang.java.programmer/browse_thread/thread/d0
0bd73d438458a5/b454ab63085a4fa4?lnk=gst&q=exposing+collection&rnum=1#b454ab63085
a4fa4

discussion was enlightening, so I went with the

#################
public Set<String> getValues() {
   return Collections.unmodifiableSet(values);
}
#################

which seamed like the better solution.
Patricia Shanahan - 14 Aug 2007 14:17 GMT
> I remember reading somthing about the behaviour exhibetet by the
> program below (where a private collection is altered without going
[quoted text clipped - 9 lines]
>         return values;
>     }
...

Making values private but providing this implementation of getValues
means the caller cannot change which Set values references, but can
change the membership.

If you want the caller to be able to view, but not change, the set:

public Set<String> getValues() {
  return Collections.unmodifiableSet(values);
}

This gives the caller a view of the set that will reflect changes you
make to it, but does not give the caller any power to add or remove
elements.

Patricia
Daniel Pitts - 14 Aug 2007 21:01 GMT
> > I remember reading somthing about the behaviour exhibetet by the
> > program below (where a private collection is altered without going
[quoted text clipped - 28 lines]
>
> Patricia

Alternatively, if you want the caller to have their own version of the
set to play with

public Set<String> getValues() {
  return new HashSet<String>(values);
}


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.