Why does a final collection still get updated? - java

I've this code where I store two collections and then add an event listener (no lambda here - I need to stick to Java 7 ;) ).
// rri is a ReturnRequestInterface
final Collection<BigDecimal> selectedItems = rri.getSelected();
final Collection<BigDecimal> unselectedItems = rri.getUnSelected();
rri.addInformationChangeEventListener(new ComponentInformationChangeListener() {
#Override
public void informationChange(RequestChangeEvent event) {
ReturnRequestInterface source = (ReturnRequestInterface) event.getSource();
boolean debug1 = source.getSelected().containsAll(selectedItems);
boolean debug2 = source.getUnSelected().containsAll(unselectedItems);
}
});
I've debugged this initially and the collection was correctly setup. It contained no objects, since the code was just initialized.
Debugging the listener (the event was fired because an item selection was made) left me confused. The booleans debug1 and debug2 are both true because the collection selectedItems and unselectedItems were updated according to the item selection. So, the event source collection contained the same items as the declared final collections (selectedItems, unselectedItems).
Don't the two declared final collections have to stay as they are?

final simply means that a variable that has been declared final cannot be changed, and a class which is final cannot be inherited from.
all variables that aren't primitive are references in Java, which means that they 'point' or refer to an instance of an object, but are not objects themselves.
What you are referring to is called an immutable object, which is an instance of a final class that all of its fields are final and private and has no setters.
hope this helps clarify.

Using final only means that the reference cannot be changed to point at another object not whether its contents can be updated or not.
If you want an unmodifiable set use something like Collections.unmodifiableSet(yourSet);

Related

Is it possible to do a final class immutable in Java?

Recently on the interview I had an interesting question.
We have mutable class:
final class Example {
private int i;
private String s;
private Object o;
// get, set
}
And instance of this class Example e = new Example();
Can we somehow make this instance immutable? Without changing original class.
My thoughts:
Deep cloning of this instance? But not sure if it's possible.
Maybe something like serialization/deserialization?
If you are unable to make modifications to the Example class and you cannot subclass it (in your snippet, it is marked as final) the closest solution I can think of is to create a wrapper class, which is immutable. This is not a perfect solution, and has it's drawbacks.
First, how to do it:
final class ImmutableExample {
// Redeclare every field as in the Example class
// but make sure they can't be reassigned
// (in this case I'll declare them as final)
private final int i;
private final String s;
private final Object o;
ImmutableExample(Example mutableExample) {
// copy fields from original
this.i = mutableExample.getI();
this.s = mutableExample.getS();
this.o = mutableExample.getO();
}
// add getters but definitely no setters
}
Then everywhere you have code like this:
Example e = new Example();
e.setI(42); // etc
Change to:
Example e = new Example();
e.setI(42); // etc
ImmutableExample immutableE = new ImmutableExample(e);
And pass around references to immutableE, and make sure that the e reference does not escape.
Now, for the drawbacks:
ImmutableExample is not an instance of Example, so you cannot pass the immutable type to a method which expects the mutable type, and operations like if (immutableE instanceof Example) or (Example)immutableE will not work as before
You have to be very careful that every field of Example is also immutable, or ImmutableExample will also be mutable. Consider, for example, that the field of type Object could be something mutable, like a HashMap or a Date.
When the Example class changes, you have to repeat the change in ImmutableExample.
If it was possible to subclass Example, or if it was an interface, this approach might be more useful, but I can't see any other way when Example cannot be subclassed.
If each of those fields have getters/setters, then to make it immutable, you will have to
Make each field private and final
Make a copy of each field when it's getter is called
Remove all setters
Any methods within the class that changes it's state must either be removed or use the new getters to access any internals
Immutability is a property of a class not an instance. So besides bytecode twiddling or other means to change the class; not possible.
With a none final class i would create an immutable decorator. That would not make the instance immutable, but provide an immutable wrapper to that instance.
You could not assign the instance to any variable/field, making it impossible to change it ;)

Why can I change private final ArrayList<Book>? [duplicate]

This question already has answers here:
Java final modifier
(2 answers)
Closed 9 years ago.
I have class that looks like this :
public class InformationSystem {
private final ArrayList<Book> books;
private final ArrayList<Reader> readers;
public InformationSystem() {
books = new ArrayList<Book>();
readers = new ArrayList<Reader>();
}
public void addBook(final String author, final String title) {
Book book = new Book(author, title);
books.add(book);
}
}
Why can I add/remove values from arraylist that is final?
I can't change the Car, Still I'm able to change the parts inside it :)
From Language specification # chapter 14.12.4
Once a final variable has been assigned, it always contains the same value. If a final variable holds a reference to an object, then the state of the object may be changed by operations on the object, but the variable will always refer to the same object.
You cannot re assign, still you can change the state.
In short
books =newBooksList; // huh! I'm final, No
books.add(book); //ok
What you want is to make your List immutable. See this post: java-immutable-collections
Or directly look at the java.util.Collections.unmodifiableList() method.
http://docs.oracle.com/javase/6/docs/api/java/util/Collections.html?is-external=true#unmodifiableList%28java.util.List%29
Reference to an ArrayList object is final - you can't change that reference, you can't reassign.
But, you can call object's methods. In particular, even these methods, which change the state of the object.
So, ArrayList objects are mutable. On the other hand, for example, String objects are immutable. You can't change their internal state.
You have Created books object of type ArrayList as final.
so, books object refers ArrayList Object on the Heap, and as it is declared as final its reference will never change but you can change content of the object.
So, you can add/remove the items from ArrayList defined as final.
Keeping a Reference to an object final keeps the link pointing to the object as final, which cannot be changed. But the state of the actual object can change.
Link to which the reference variable points is final, the state of object to which it points is not final
If the object to which you are referring to is Immutable then you will achieve what you thought would happen.
final means that your reference is immutable - it cannot change.
However ArrayList is a mutable (can change) data structure.
You cannot change what books points to, but you can the data structure to which it points. In sum, you have an immutable reference to a mutable data structure.
Because you have declare the ArrayList variable book as a final variable so you can not reassign book with another object while you can do any thing with the current object.
ArrayList<Book> book = new ArrayList<Book>();
You can not reassign book variable like following.
ArrayList<Book> book2 = new ArrayList<Book>();
book = book2;
While you can do anything with the current book object because you are not changing the content of final variable you are changing content of object to which final variable is referencing.

Having trouble with adding an ArrayList to an ArrayList of ArrayLists

public class Tabel {
private static int dimension;
private ArrayList<ArrayList<Character>> tabel;
public Tabel(int dimension) {
Tabel.dimension = dimension;
for (int i=0;i<Tabel.dimension*Tabel.dimension;i++) {
tabel.add(new ArrayList<Character>());
}
}
}
When I try to debug (eclipse ide) I get a lot of weird "errors" or at the very least I encounter something I consider unexpected.
The private static int does not appear in the "variables" section of debug.
I get a NullPointerException on tabel.add(...) but when I watch the debug, it enters the for once, does not add anything in the table because when I hit "next" instead of jumping to the closing braces it jumps out of the function.
If I comment the .add it works so that's the problem (I think). Is my syntax wrong ? or should I post more code ?
tabel is not initialized, so it is null.
Change
private ArrayList<ArrayList<Character>> tabel;
to
private ArrayList<ArrayList<Character>> tabel = new ArrayList<ArrayList<Character>>();
Or better:
private List<ArrayList<Character>> tabel = new ArrayList<ArrayList<Character>>();
since this does not tie tabel to ArrayList.
You have not initialized the private List. Do the following:
private List<ArrayList<Character>> tabel = new ArrayList<ArrayList<Character>>();
I'd have trouble understanding that level of nesting too.
It's better to refer to List rather than ArrayList. Unless you need a method in the concrete class, it makes your program more flexible to refer to the interface and the methods in the interface.
Create a class (1) that has a field defined as a List of Character. Set the field to a new ArrayList in the constructor.
Create another class (2) that has a field defined as a List of class (1). Set the field to a new ArrayList in the constructor.
Create another class (3) that has a field defined as a List of class (2). Set the field to a new ArrayList in the constructor.
Since you understand what you're doing, you can give these 3 classes more meaningful names.

Java: List listener for passed reference needed?

I want to pass a reference of a dynamic list basically. in Class2 the getTheList method should keep getting the new list even when the orginal list changes. Should I add a listener or I have to change my design in a better way to do this?
class1{
public class1(){
List orginalList=getOrginalList();
Class2 c2=new Class2(orginalList);
}
public List getOrginalList(){
//here read and return the updated orginal
//List from a web service
}
}
class2{
List myList;
public class2(List realList){
myList=realList;
}
private int getTheList(){
//when I call this method I want to get the updated list
return myList.size();
}
}
From your comment...
//something here later changes the orginal list but In class2
//I still keep getting the old list!
... it looks like you expect there to be two list objects. There aren't. There's just one list, which you have two references to. If you want to make a copy of the list, you'll need to do that explicitly. The assignment operator never creates a copy of an object. It just copies the value of one expression to a variable. The value of that expression is always either a reference or a primitive value - never an object.

Java Final arraylist

My question is regarding declaring an arraylist as final. I know that once I write final ArrayList list = new ArrayList(); I can add, delete objects from this list, but I can not list = new ArrayList() or list = list1. But what will be the use of declaring arraylist as
Private static final ArrayList list = new ArrayList();. And apart from the difference I have mentioned above what will be the difference between following two declaration:
1. ArrayList list = new ArrayList()
2. private static final ArrayList list = new ArrayList();
Just to "bring a little water to your Mill" you will understand the interest of final when you'll want to make your list publically availiable but unmodifiable.
In java one can make a list unmodifiable with Collections.unmodifiableList(modifiableList).
Now have a look to the following code :
public class MyClass{
public static List<String> MY_PUBLIC_LIST;
static{
ArrayList<String> tmp = new ArrayList<String>();
tmp.add("a");
tmp.add("b");
tmp.add("c");
MY_PUBLIC_LIST = tmp;
}
}
Well, in anyclass, anywhere in your code you can do something like this
MyClass.MY_PUBLIC_LIST = null;
MyClass.MY_PUBLIC_LIST = new ArrayList<String>();
MyClass.MY_PUBLIC_LIST.clear();
MyClass.MY_PUBLIC_LIST.add("1");
When you add the final keyword to your variable, the first two won't be allowed
public static final List<String> MY_PUBLIC_LIST;
But you'll still be able to modify the content of the list :
MyClass.MY_PUBLIC_LIST.clear();
MyClass.MY_PUBLIC_LIST.add("1");
By adding a Collections.unmodifiableList(modifiableList) at the end of the static block you'll prevent this too :
MY_PUBLIC_LIST = Collections.unmodifiableList(tmp);
Ok we are almost there. Just to be sure you get the whole picture lets keep the Collections.unmodifiableList(modifiableList) but let me remove the final modifier
public class MyClass{
public static List<String> MY_PUBLIC_LIST;
static{
ArrayList<String> tmp = new ArrayList<String>();
tmp.add("a");
tmp.add("b");
tmp.add("c");
MY_PUBLIC_LIST = Collections.unmodifiableList(tmp);
}
}
What can you do in that case ?
...
...
Well you can do whatever you want like in the first case (given that you assign the new list first) :
MyClass.MY_PUBLIC_LIST = null;
MyClass.MY_PUBLIC_LIST = new ArrayList<String>();
MyClass.MY_PUBLIC_LIST.clear();
MyClass.MY_PUBLIC_LIST.add("1");
You're right that declaring the list final means that you cannot reassign the list variable to another object.
The other question (I think) was
public class SomeClass {
private static final ArrayList list = new ArrayList();
}
vs
public class SomeClass {
ArrayList list = new ArrayList();
}
let's take each modifier in turn.
private Means only this class (SomeClass) can access list
static Means that there is only one instance of the list variable for all instances of SomeClass to share. The list instance is associated with the SomeClass class rather than each new SomeClass instance. If a variable is non-static it's said to be an instance variable
final as you know means that you cannot reassign the list variable another value.
In the second declaration there are no modifiers, so the variable is an instance variable and it also gets package-private access protection (Sometimes called default access protection). This means that this class (SomeClass) and other classes in the same package can access the variable.
You can find out more about public, private, and package-private here: Access control
You can find out more about final and static here: Class variables
When you say
final ArrayList list = new ArrayList();
this means that the variable list will always point to the same ArrayList object. There are two situations in which this can be useful.
You want to make sure that no-one reassigns your list variable once it has received its value. This can reduce complexity and helps in understanding the semantics of your class/method. In this case you are usually better off by using good naming conventions and reducing method length (the class/method is already too complex to be easily understood).
When using inner classes you need to declare variables as final in an enclosing scope so that you can access them in the inner class. This way, Java can copy your final variable into the inner class object (it will never change its value) and the inner class object does not need to worry what happens to the outer class object while the inner class object is alive and needs to access the value of that variable.
The second part of your question is about the difference between
ArrayList list = new ArrayList();
and
private static final ArrayList list = new ArrayList();
The difference of course are the modifiers. private means not visible outside the class, static means that it is defined on the class level and doesn't need an instance to exist, and final is discussed above. No modifiers means package-private or default access.
You say "I can add, delete (and find) objects", but who is I?
The different between your two cases concerns from which code those list operations can be called.
In general you need to consider the scope of the declaration, you greatly increase the maintainability of code if you reduce the visibility of your variables. If you have a class:
Public Class MyThing {
public int importantValue;
// more code
}
That important value can be changed by any other code, anywhere else in an application. If instead you make it private and provide a read accessor:
Public Class MyThing {
private int importantValue;
public int getImportantValue(){
return importantValue;
}
// more code
}
you now know only the class itself can change the value - for large applications this massively increases maintainability. So declaring the list private limits what code can see, and change the contents of the list.
The use of static makes the list shared by all instances of the class, rather than each instance getting its ovn copy.

Categories

Resources