I need to manage data in my program where Java-Vector suits the purpose as it is synchronized,provides dynamic size and fast random access through index.
But I want to make my Vector Read Only for other Program Classes and Read Write for my own Class.
I read about Collections.unmodifiableList() ,but if I make my Vector unmodifiable, it will become read-only to my class as well.
How can I solve this problem?
I read about Collections.unmodifiableList(), but if I make my Vector unmodifiable, it will become read-only to my class as well.
I think you misunderstand what that method does. In reality, it creates an unmodifiable wrapper for the existing list, leaving the original list modifiable.
So the way to handle your requirement is to do something like this1:
private Vector<?> myVector = new Vector<?>();
private List<?> readOnly = Collections.Collections.unmodifiableList((myVector);
public List<?> getList() { return readOnly; }
Anything that has access to myVector can still add and remove elements from it. The changes will be visible via the readonly object ... but "change" operations on that object won't work.
(The other approach is to create copies of the original Vector object, but I'm pretty sure that doesn't meet your requirements.)
1 - Note that the readOnly object is a List but not a Vector. This shouldn't be a problem unless you have made the mistake of declaring the getter as returning a Vector. If you've done that, and you can't correct the mistake, then you will need to create your own subclass of Vector along the line of Evgeniy Dorofeev's answer. Otherwise Collections.unmodifiableList(...) will do just fine.
Make it a private member of your class and only provide getters that return an immutable version of the vector as a public way to access it, using the function you mentioned (Collections.unmodifiableList()).
If you really want an unmodifiable Vector (not just List) create a method as
public static Vector unmodifiableVector(Vector v) {
return new Vector(v) {
#Override
public void add(int index, Object element) {
throw new UnsupportedOperationException();
}
#Override
public synchronized boolean addAll(Collection c) {
#Override
public synchronized void addElement(Object obj) {
// ... other mutators
}
}
try this:
Collections.unmodifiableList(myList);
Make vector a private member of your class. expose a public method to the callers which will get a reference to an unmodifiableCollection.
public Vector getVector(){
return Collections.unmodifiableList(yourVector) ;
}
For use in your internal class, you can either reference the vector directly or create a private method which will return a reference to collection.
private Vector getMyVector(){
return yourVector ;
}
I think if you make your Vector as private member attribute in your along with all write methods as private while read methods as public, you would be OK e.g.
private Vector<T> myVector = ...
private void setMyVector(Vector<T> vector){
myVector = vector;
}
private void addElement(T element){
myVector.add(element);
}
public T getElement(int indx){
return myVector.get(indx);
}
....
....
By making the vector instance as private and providing setter as private with getter as public would be the correct path in my opinion.
For the :
List<T> readOnlyList = Collections.unmodifiableList(myList);
it will readnoly instance, however, it will still allow the access to other classes to call add/set/remove methods but calling these methods results in UnsupportedException being raised.
Also, based on your requirement, you are looking for the updation of the vector / addition of new elements in it. So may by look for concurrent package to make it safer in doing so.
Its better to give copy of your Vector rather than giving original reference of your Vector Like following:
Vector vector = // your vector object in your class
public Vector<String> getMyVercorObject(){
return (Vector<String>)vector.clone() ;
}
The best way is to use Vector internally, only expose mutations (add, remove, etc) using methods, and only return an unmodifiable view using an interface (List). Such an implementation might look like this (for example sake let's say the elements are strings):
private final List<String> list = new Vector<String>();
/** Adds the specified element. */
public void addElement(String element) {
list.add(element);
}
/** Replaces all elements. */
public void setElements(List<String> newElements) {
list.clear();
list.addAll(newElements);
}
/** Returns all elements. */
public List<String> getElement() {
return Collections.unmodifiableList(list);
}
In this way your class has full access to the list, while external entities can only mutate using the public methods.
Note that Vector is pretty much not used. If you require a thread safe list then consider ArrayList in conjunction with synchronizedList:
private final List<String> list = Collections.synchronizedList(new ArrayList<String>());
Related
So, we created a simple class with some private class member and automatically generated getter for it. But getter actually returned a reference to that member, resulting in gaining full access to a private member. Is that okay?
Here's the code of a class:
public class User {
private ArrayList<String> strings = new ArrayList(){ {
add("String1");
add("String2");
} };
public User() {
}
public ArrayList<String> getStrings() {
return strings;
}
public void setStrings(ArrayList<String> strings) {
this.strings = strings;
}
}
Code of main method:
public class Main {
public static void main(String[] args){
User user = new User();
System.out.println(user.getStrings());
user.getStrings().add("String3");
System.out.println(user.getStrings());
}
}
And output:
[String1, String2]
[String1, String2, String3]
I've changed the getter to this one:
public ArrayList<String> getStrings() {
return (ArrayList<String>)strings.clone();
}
But the question remains, what getters are for if not for safety? And what is the right way to write them?
No, it isn't okay because it breaks encapsulation and thus the class can't maintain its own invariants. Same with constructors.
But the problem isn't with getters/setters, it's with the code that autogenerates them.
To cut a long story short: don't use autogenerated accessors blindly, if they're dealing with mutable structures, make defensive copies (or immutable equivalents).
As an aside, I would not have a getter with an ArrayList return type, even if it's just a copy. It's usually none of the client's business what kind of list you're returning, so my getter would look like this:
public List<String> getStrings() {
return new ArrayList<>(strings);
}
Or using an immutable view:
public List<String> getStrings() {
return Collections.unmodifiableList(strings);
}
Or using Guava's ImmutableList class:
public List<String> getStrings() {
return ImmutableList.copyOf(strings);
}
There are subtle differences between the three solutions so which one's best may vary. As a general rule I prefer returning immutable structures because that makes it clear that changes made to the structure won't be reflected, i.e. user.getStrings().add( "X" ); will fail with an exception.
Another subtle problem with the code you showed us is the double braces initialisation. Imagine a class like this:
public class Foo {
private List<String> strings = new ArrayList() {{ add("bar");}};
private Object veryLargeField; //the object stored here consumes a lot of memory
public List<String> getStrings() {
return strings;
}
}
Now imagine we're doing this:
private class Bar {
private List<String> fooStrings;
public Bar() {
this.fooStrings = new Foo().getStrings();
}
}
How much memory would Bar consume (or to use the precise term: retain)? Well, it turns out that quite a lot, because what you do with the double brace initialisation is create an anonymous inner class, which will contain a reference to its outer class (Foo), and thus while the list returned is accessible, all the other fields of Foo will be ineligible for garbage collection.
From my point of view getters usually should serve two purposes:
first they should guard the implementation details.
second they should provide a way to extend easily (e.g. validation or instrumentation)
If your example violates these principles depends on the context:
If your class should own the strings then probably everyone should interact with the container object to modify the list and not with the list itself. To expose a collection (e.g. For processing in a method that expects a collection) you can use e.g. Collections.unmodifiableList(). If on the other hand the class only owns the list of strings then it is not an implementation detail to have a list.
Using a getter instead of directly accessing the fields allows you to easily add data conversation, tracing instrumentation and other things without changing all the places where the field is used.
Consider the following class:
public class Cars extends Observable{
private ArrayList<String> carList = new ArrayList<String>();
public void addToCarList(String car){
// ...
hasChanged();
notifyObservers();
}
public void removeFromCarList(String car){
// ...
hasChanged();
notifyObservers();
}
public ArrayList<String> getCarList() {
return carList;
}
}
As you can see, every time the carList is changed, I want to notify the Observers.
If someone does getCarList().add(...);, this is circumvented.
How can I give read access to the carList (for iterating over it etc.) but prevent write access to it except for the special methods addToCarList and removeFromCarList?
I thought about this:
public ArrayList<String> getCarList() {
return (ArrayList<String>)carList.clone();
}
but someone using my class would, when adding something to the clone of carList, not be informed that that's not the way it's meant to be done.
You can return an unmodifiable view of it, changing the return type to List<String> instead of ArrayList<String>:
public List<String> getCars() {
return Collections.unmodifiableList(carList);
}
Note that as Collections.unmodifiableList does only provide a view, the caller will still see any other changes that are made via addToCarList and removeFromCarList (which I'd rename to addCar and removeCar, probably). Is that what you want?
Any mutating operations on the returned view will result in an UnsupportedOperationException.
First, always avoid using concrete class at the left side of assignment and as a return value of method. So, fix your class as
public class Cars extends Observable{
private List<String> carList = new ArrayList<String>();
........................
public List<String> getCarList() {
return carList;
}
}
Now you can use Collections.unmodifiableList() to make you list read-only:
public List<String> getCarList() {
return Collections.unmodifiableList(carList);
}
BTW, if you do not really have to return List you can probably return Collection or even Iterable. This will make increase the encapsulation level of your code and make future modifications easier.
Jon Skeet's answer is excellent (as always) but the one thing it doesn't touch on is concurrency issues.
Returning an unmodifiable collection will still leave you with issues if multiple threads are accessing this object at the same time. For example if one thread is iterating over the list of cars and then at the same time another thread adds a new card.
You will still need to synchronize access to that list somehow, and this is one reason why you might consider returning a clone() of the list as well as or instead of just wrapping it in the unmodifiableList wrapper. You would still need to synchronize around the clone() but once the clone is completed and the list returned to the querying code it no longer needs to be synchronized.
I think you could probably make your Object implement the Collection-Interface, if it is in fact an ObservableList. It is a List and it should be Observable - so it should implement both interfaces.
You could even Extend List<..> because you just want to add extra functionality (observers) to the current functionality and your List can be used everywhere where a normal List could be used...
use Collections.unmodifiableList(list) as it provides a new List object which cannot be modified , it would throw an UnsupportedOperationException while trying to update/add/delete objects list.
enter code hereI am new to Java, i have a class "RSTrule" with class variable "private ArrayList nucleusType". I want to set values to this arraylist in another class namely "RSTRules"
i use the following code:
public class RSTRule{
private ArrayList<Type> nucleusType;
}
public class RSTRules extends ArrayList<RSTRule> {
public RSTRule generateSimilarSentence()
{
RSTRule rstRule=new RSTRule();
rstRule.setNucleusType(.....)
return rstRule;
}
}
i have two or three values for nucleus array. for example I want to add "UMM" and "UMNM" to nucleus array list in a short form.
how can i do that?
Use Arrays.asList (no clue what UMM and UMNM are, but something like below)
rstRule.setNucleusType(Arrays.asList(UMM, UMNM));
There is a tricky part though, the ArrayList created by asList cannot be modified. If you need that, there are two options.
1: Wrap the new list in an ArrayList:
rstRule.setNucleusType(new ArrayList<Type>(Arrays.asList(UMM, UMNM)));
2: Change your setter like:
public void setNucleusType(List<Type> list) {
nucleusType.clear();
nucleusType.addAll(list);
}
If any existing array list with you pass it,otherwise create a new one and add elements to it and pass that.
RSTRule rstRule=new RSTRule();
List<Type> someList = new ArrayList<Type>();
someList.add(UMM); //remember the UMM is of type TYPE
someList.add(UMNM); //remember the UMNM is of type TYPE
rstRule.setNucleusType(someList)
return rstRule;
You can do this way
RSTRule rstRule=new RSTRule();
List<Type> list=new ArrayList<>();
list.add(UMM);// add some thing in your Type
rstRule.setNucleusType(list)
return rstRule;
ArrayList is the collection class useful to store the value in the array format.
RSTRule rstRule=new RSTRule();
List<Type> someList = new ArrayList<Type>();
someList.add(Value);
someList.add(value);
rstRule.setNucleusType(someList)
return rstRule;
Avoid having similar names RSTRule and RSTRules is not practical when you will read you program: call them RSTRule and RSTRuleList for example
RSTRuleList is a good idea globally since you whant to control what is in your list depending on your business case. Therefore you can hide the list in RSTRuleList
Now you use also RSTRuleList as a factory (which is not ideal: it's preferable to use a dependency injection framework, but it's ok for some needs)
class RSTRuleList {
protected ArrayList ruleList;
public RSTRule generateSimilarSentence(... params) {
...
return rstRule;
}
public addRule( ... params ) {
ruleList.add( generateSimilarSentence(params) );
}
}
Hope it helps,
Best Regards,
Zied
class RSTRuleList {
protected ArrayList ruleList;
public RSTRule generateSimilarSentence(... params) {
...
return rstRule;
}
public addRule( ... params ) {
ruleList.add( generateSimilarSentence(params) );
}
}
(The code in the above answer didn't format)
Zied
Your question is not clear enough. Please see the comments and try to clarify the missing points.
You first need to add a method for RSTRule class to allow external classes to add to its internal list. Something like:
public class RSTRule {
// You need to create the ArrayList first,
// and I suggest use interfaces as declaration when fit
private final List<Type> nucleusType = new ArrayList<Type>();
public void addType(final Type type) {
this.nucleusType.add(type);
}
}
I don't know what RSTRules is needed for...
I have a question about using getter methods in java.
Suppose I had this class:
class Test {
private ArrayList<String> array = new ArrayList<String>();
public ArrayList getArray() {
return this.array;
}
public void initArray() {
array.add("Test 1");
array.add("Test 2");
}
}
class Start {
public static void main(String args[]) {
initArray();
getArray().remove(0);
}
}
My question is:
Would the actual arraylist object be modified ("Test 1" removed from it)? I think I have seen this in places, but I thought that getters were simply providing a copy of that object. Not a reference to it. If it did work that way (as a reference), then would this work as well (Would the arraylist object of the class Test be altered by this as well)?:
class Start {
public static void main(String args[]) {
initArray();
ArrayList aVar = getArray();
aVar.remove(0);
}
}
Java returns references to the Array, so it won't be a copy and it will modify the List. In general, unless its a primitive type (int,float,etc) you will be getting a reference to the object.
You have to explicitly copy the array yourself if you want a duplicate to be returned.
The way I understand it, Object reference variables are little more than memory addresses of the objects themselves. So what is returned from getArray() is a reference variable to that ArrayList. An object may have many reference variables, but it is still the same object that gets modified.
Java does everything pass by value. So anytime you pass an object reference variable as a parameter or return it's value, you are passing or returning the value of the object reference variable.
As others said, unless it's a primitive type, you get a reference to the object. It is similar to a pointer in C++, it allows you to access the object, but unlike C++ reference (pointer to the memory address of a variable) it doesn't allow you to replace it with another object. Only setter can do that.
I see two variants in your question, test.getArray().remove(0) and aVar.remove(0). There is no difference in the results of those, it's still just some pointer-like reference and it modifies the original.
You never get a clone by just calling a getter, so unless the object is immutable, you can modify the object that the getter gave you access to. For example, String is immutable, any basic Collection (including ArrayList) is mutable. You can call Collections.unmodifiable*(...) to make a collection unmodifiable. However, if the items of collection are mutable, they can still be changed.
In some cases, getting a clone is a good idea, in most cases it's not. A getter shouldn't clone anything at all, it shouldn't even modify data unless it initializes a possibly null collection or something like that. If you want an unmodifiable collection containing immutable objects, try to do it this way. In this example we have a class FooImpl that implements interface Foo, the reasons to be explained later.
public interface Foo {
int getBar();
}
public class FooImpl Foo {
private int bar;
#Override
public int getBar() {
return bar;
}
public void setBar(int newValue) {
this.bar = newValue;
}
}
As you see, Foo has no setter. If you create some ArrayList<Foo> and pass it from some getter as Collections.unmodifiableList(myArrayList), it almost seems you did it. But the work is not done yet. If the class FooImpl is public (which it is in this case), someone might try if that foo he found in the list is an instanceof FooImpl and then cast it as (FooImpl) foo making it mutable. However, we can wrap any Foo into a wrapper called FooWrapper. It implements Foo as well:
public class FooWrapper implements Foo {
private Foo foo;
public FooWrapper(Foo foo) {
this.foo = foo;
}
public int getBar() {
return foo.getBar();
}
// No setter included.
}
Then we can put a new FooWrapper(myFoo) into a Collection<FooWrapper>. This wrapper doesn't have any public setter and the foo inside is private. You cannot modify the underlying data. Now about that Foo interface. Both FooImpl and FooWrapper implement it, if any method doesn't intend to modify the data, it can ask for Foo on input. It doesn't matter which Foo you get.
So, if you want unmodifiable collection containing unmodifiable data, make a new Collection<Foo>, feed it with FooWrapper objects and then call Collections.unmodifiable*(theCollection). Or make a custom collection that wraps the whole collection of Foo, returning FooWrappers, for example this list:
public MyUnmodifiableArrayList implements List<Foo> {
ArrayList<Foo> innerList;
public get(int index) {
Foo result = innerList.get(index);
if (!(result instanceof FooWrapper)) {
return new FooWrapper(result);
}
return result; // already wrapped
}
// ... some more List interface's methods to be implemented
}
With wrapped collection, you don't have to iterate through the original collection and make its clone with wrappers of data. This solution is much better when you don't read it whole, but it creates a new FooWrapper every time you call get() on it, unless the Foo on that index is already a FooWrapper. In a long running thread with millions of calls to get(), this could become an unnecessary benchmark for the garbage collector, making you use some inner array or map containing already existing FooWrappers.
Now you can return the new, custom List<Foo>. But again, not from a plain getter. Make it something like getUnmodifiableFooList() for your private ArrayList<FooImpl> fooList field.
As pointed out, your getter does not modify the list, it returns an modifiable reference to the list. Tools like Findbugs will warn you about that... you may either live with that and trust the users of your class to not clobber your list, or use this to return an unmodifiable reference to your list:
public static List<String> getArray() {
return Collections.unmodifiableList(array);
}
To answer your question, with a getter you get direct access to a variable.
Run this code and you can see that the String in the ArrayList is removed. But don't use a static ArraList like in this example in your code.
public class Test {
private static ArrayList<String> array = new ArrayList<String>();
public static ArrayList<String> getArray() {
return array;
}
public static void initArray() {
array.add("Test 1");
array.add("Test 2");
}
public static void main(String[] args) {
initArray();
ArrayList aVar = getArray();
aVar.remove(0);
System.out.println(aVar.size());
}
}
That a getter does not modify the object you call it upon is purely a matter of convention. It certainly does not change the target's identity, but it can change its internal state. Here's a useful example, if a bit sketchy:
public class Fibonacci {
private static ConcurrentMap<Integer, BigInteger> cache =
new ConcurrentHashMap<>();
public BigInteger fibonacci(int i) {
if (cache.containsKey(i)) {
return cache.get(i);
} else {
BigInteger fib = compute(i); // not included here.
cache.putIfAbsent(i, fib);
return fib;
}
}
So, calling Fibonacci.fibonacci(1000) may change the internal state of the target, but it's still the same target.
Now, here's a possible security violation:
public class DateRange {
private Date start;
private Date end;
public DateRange(final Date start, final Date end) {
if (start.after(end)) {
throw new IllegalArgumentException("Range out of order");
}
this.start = start;
this.end = end;
}
public Date getStart() {
return start;
}
// similar for setStart, getEnd, setEnd.
}
The problem is that java.lang.Date is mutable. Someone can write code like:
DateRange range = new DateRange(today, tomorrow);
// In another routine.
Date start = range.getStart();
start.setYear(2088); // Deprecated, I know. So?
Now range is out of order. It's like handing the cashier your wallet.
This is why it is best to do one of these, the earlier ones being preferable.
Have as many objects as possible be immutable. This is why Joda-Time was written, and why dates will chnage yet again in Java 8.
Make defensive copies of items one sets or gets.
Return an immutable wrapper of an item.
Return collections as iterables, not as themselves. Of course, someone might cast it back.
Return a proxy to access the item, that can't be cast to its type.
I know, I know. if I want C or C++, I know where to find them.
1. Return
I would like to add a collection of objects to an arrayList ,only if the particular attribute is not null.
I am thinking of extending the ArrayList and implementing the check inside the child class.
One alternate way is to check for the the attribute before putting it in a Arraylist, but that would mean , i will have to scatter the if checks every where if i need to add the objects to the arraylist based on the logic.
I would like to know your thoughts on it ... on a second thought is it a overkill ?
Decorator pattern
I would actually recommend wrapping ArrayList using well-documented Decorator pattern. You simply wrap your ArrayList with another List implementation that delegates most of the methods but adds validation logic:
public class ValidatingListDecorator extends AbstractList<MyBusinessObject>
{
private final List<MyBusinessObject> target;
public ValidatingListDecorator(List<MyBusinessObject> target) {
this.target = target;
}
#Override
public MyBusinessObject set(int index, MyBusinessObject element)
{
validate(element);
return target.set(index, element);
}
#Override
public boolean add(MyBusinessObject o)
{
validate(o);
return target.add(o);
}
//few more to implement
}
Advantages:
You can still access raw list without validation if you want (but you can restrict this)
Easier to stack different validations, turn them on and off selectively.
Promotes composition over inheritance as noted by #helios
Improves testability
Does not tie you to a specific List implementation, you can add validation to LinkedList or Hibernate-backed persistent lists. You can even think about generic Collection decorator to validate any collection.
Implementation notes
Despite the implementation remember there are quite a lot of methods you have to remember about while overriding: add(), addAll(), set(), subList() (?), etc.
Also your object must be immutable, otherwise the user can add/set valid object and modify it afterwards to violate the contract.
Good OO design
Finaly I wrote:
validate(element)
but consider:
element.validate()
which is a better design.
Stacking validations
As noted before if you want to stack validations, validating each proprty/apsect in a single, separate class, consider the following idiom:
public abstract class ValidatingListDecorator extends AbstractList<MyBusinessObject>
{
private final List<MyBusinessObject> target;
public ValidatingListDecorator(List<MyBusinessObject> target) {
this.target = target;
}
#Override
public MyBusinessObject set(int index, MyBusinessObject element)
{
validate(element);
return target.set(index, element);
}
protected abstract void validate(MyBusinessObject element);
}
...and few implementations:
class FooValidatingDecorator extends ValidatingListDecorator {
public FooValidatingDecorator(List<MyBusinessObject> target)
{
super(target);
}
#Override
protected void validate(MyBusinessObject element)
{
//throw if "foo" not met
}
}
class BarValidatingDecorator extends ValidatingListDecorator {
public BarValidatingDecorator(List<MyBusinessObject> target)
{
super(target);
}
#Override
protected void validate(MyBusinessObject element)
{
//throw if "bar" not met
}
}
Want to only validate foo?
List<MyBusinessObject> list = new FooValidatingDecorator(rawArrayList);
Want to validate both foo and bar?
List<MyBusinessObject> list =
new BarValidatingDecorator(new FooValidatingDecorator(rawArrayList));
If you would like to enforce this I don't see why not (although you should check the return value of the add method whenever you do add to make sure that it succeeded).
This is a good way to get rid of that redundant logic which may or may not stick around in later software iterations.
I don't think this is a good practice. Consider instead writing a Util-Method in a Util-Class taking two parameters: The array list and the object you would like to add. There you can check whatever you want and can reuse the logic all over your code.
Only issue would be if you go to reuse this code and you don't remember you've overriden the ArrayList class, make sure to comment thoroughly.