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

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.

Related

How many objects are created in this case? [duplicate]

This question already has answers here:
String s = new String("xyz"). How many objects has been made after this line of code execute?
(21 answers)
Closed 5 years ago.
The title says it all
String a;
String b = new String("Hello");
I've seen a lot of questions like this but none of them had Strings that weren't initiated yet.
Can someone help me on this ?
Thank you.
You are creating a single object that is referenced by variable b, a is a declared variable without any data assigned to it, that is not an object in a Java sense
First row only declares a string variable, but doesn't create object. In the second row, a string object is created with a new keyword.
So there's only one object created.
Here is an explanation took from OCA Java SE 7 Programmer I Certification Guide: Prepare for the 1ZO-803 exam:
An object comes into the picture when you use the keyword operator new.
You can initialize a reference variable with this object. Note the difference between declaring a variable and initializing it. The following is an example of a class Person and another class ObjectLifeCycle:
class Person {}
class ObjectLifeCycle {
Person person;
}
In the previous code, no objects of class Person are created in the class ObjectLife-Cycle; it declares only a variable of type Person. An object is created when a reference variable is initialized:
class ObjectLifeCycle2 {
Person person = new Person();
}
Syntactically, an object comes into being by using the new operator. Because
Strings can also be initialized using the = operator, the following code is a valid example of String objects being created
class ObjectLifeCycle3 {
String obj1 = new String("eJava");
String obj2 = "Guru";
}

Why does a final collection still get updated?

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);

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 ;)

How is upcasted object stored in Heap in Java

So I wrote a simple java code here as shown below.
package com.example.aakash;
public abstract class Book {
String title;
String author;
Book(String t,String a){
title=t;
author=a;
}
abstract void display();
}
So Book is an abstract class which is to be extended by two different class called MyBook and ABook class as shown below.
package com.example.aakash;
public class MyBook extends Book {
private int price;
MyBook(String t, String a,int p) {
super(t, a);
price = p;
}
#Override
public void display(){
System.out.println("Title: "+title);
System.out.println("Author: "+author);
System.out.println("Price: "+price);
}
}
package com.example.aakash;
public class ABook extends Book {
private int price;
ABook(String t, String a,int p) {
super(t, a);
price = p;
}
#Override
public void display(){
System.out.println("Title: "+title);
System.out.println("Author: "+author);
System.out.println("Price: "+price);
}
}
package com.example.aakash;
import java.util.ArrayList;
public class Main {
public static void main(String[] args){
ArrayList<Book> myArray = new ArrayList<Book>();
String bookName = "Book";
for(int i=1;i<=10;i++){
if(i%2==0){
String tempBook = bookName + i;
String author = "Author2";
Book temp = new MyBook(tempBook,author,i*50);
myArray.add(temp);
}else{
String tempBook = bookName + i;
String author = "Author1";
Book temp = new ABook(tempBook,author,i*50);
myArray.add(temp);
}
}
for(int i=0;i<10;i++){
Book temp = myArray.get(i);
temp.display();
System.out.println("--------------------------------------------------");
}
myArray.get(5).display();
}
}
Okay so when I run this program, the display method print the right book,author and price every single time. Just the way they are stored. However at runtime, JVM doesn't know that weather a Book object on the array list is of type MyBook or ABook. So my question is how does calling the display method print the right book every single time. How does ArrayList of Book object get stored on heap? (i.e all objects get store in heap in Java) Does it store it as upcasted Book object. Or does it store it as the actual MyBook and ABook type of object so that when display method is called, JVM explicitly knows that weather the method on MyBook or ABook is to be called?
P.S. Yes example is kind of bad but suppose I don't even have similar display method on MyBook and ABook. Even then the JVM still executes the correct display method. So please explain what is going on in JVM when up-casting is done.
The concrete object is an ABook declared as Book.
Which display method select is resolved at runtime, not a compile time.
From JLS:
If the method that is to be invoked is an instance method, the actual
method to be invoked will be determined at run time, using dynamic
method lookup (§15.12.4).
Basically it means that the real instance type is taken at runtime. If the method is overwritten in that class this method is executed, if it is not overwritten the method of the super class is invoked.
You are mixing up objects and references. You never store an object in an ArrayList, you are just storing a reference to an object. A reference might have a broader type than the object it is pointing to, but that never changes the actual type of the object.
In fact, due to type erasure, an ArrayList<Book> doesn’t even contain references of the type Book, it has no knowledge about it. It only contains references of type Object, but that’s sufficient for the ArrayList to work as all it needs, is the method boolean equals(Object) that is declared in java.lang.Object. Since the type of the reference does not change the type of the actual object, invoking equals on an object via a reference typed as Object will still invoke the most specific method of the actual type, if the equals method has been overridden.
You may also store the same object multiple times in a List, whereas “store an object” is a colloquial term which you always have to translate to “store a reference to that object” for yourself. There’s still only one object if you do that and the list will just contain multiple references to it. Modifying that object through one of these references will become visible through all other references immediately.
The type of an object is fixed right when it is created and stored within the object in an implementation specific manner. That’s also the reason why a runtime type cast narrowing the type to a more specific one can verify the correctness. The cast is not changing the type of the object, it’s only creating a new reference to the same object with a more specific type out from a reference with a broader type, after the correctness has been proven. This also happens implicitly when retrieving a reference from the ArrayList<Book>; the reference of type Object stored in the list is converted to the reference of type Book you will receive.
This concept is called Polymorphism.
ABook is a Book
MyBook is a Book
You can have an ArrayList and have inside objects of ABook and MyBook.
But everytime that you get an object of this ArrayList, you can only call book's method, unless you make a downcast to one of this subclass. But you have to be sure of the subclass before the cast, because you might get an CastException.
Finally, if you call an override method, at runtime he will always call the object method. At runtime he we always call the objects method.

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