Do final fields really prevent mutability in Java? - java

From the famous book Java Concurrency in Practice chapter 3.4.1 Final fields
Just as it is a good practice to make all fields private unless they
need greater visibility[EJ Item 12] , it is a good practice to make
all fields final unless they need to be mutable.
My understanding of final references in Java : A final reference/ field just prevents the the field from getting re initialized but if it references a mutable object , we can still change its state rendering it mutable . So I am having difficulty understanding the above quote . What do you think ?

final fields prevent you from changing the field itself (by making it "point" to some other instance), but if the field is a reference to a mutable object, nothing will stop you from doing this:
public void someFunction (final Person p) {
p = new Person("mickey","mouse"); //cant do this - its final
p.setFirstName("donald");
p.setLastName("duck");
}
the reference p above is immutable, but the actual Person pointed to by the reference is mutable.
you can, of course, make class Person an immutable class, like so:
public class Person {
private final String firstName;
private final String lastName;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
//getters and other methods here
}
such classes once created, cannot be modified in any way.

This quote says only what is says:
make all fields final unless they need to be mutable
mutable field is a field that you can later change to point to another object. If the field is final, it can still reference mutable object (e.g. java.util.Date). Thus the field is immutable (always points to the same object), but this object is mutable.

in java final is similer to this:
int *const p=&something //constant pointer.in c++. you can't use this pointer to change something but that something can be changed with its own.
in java final fields can't be changed but the object to who they refer may change by its own .
Ex. 'this' is final you can't assign anything to this but you can assign to object to whom this refer.
From your Ques:
it is a good practice to make all fields final unless they need to be mutable.
to just avoid any modification(either logically or accidently) to original it's always good to make them final.

As per Java code convention final variables are treated as constant and written in all Caps e.g.
private final int COUNT=10; // immutable -> cannot be changed
Making a collection reference variable final means only reference can not be changed but you can add, remove or change object inside collection. For example:
private final List Loans = new ArrayList();
list.add(“home loan”); //valid
list.add("personal loan"); //valid
loans = new Vector(); //not valid
Read more: http://javarevisited.blogspot.com/2011/12/final-variable-method-class-java.html#ixzz2KP5juxm0
To answer your question: Yes, if you use them correctly.

Disregard the quote. There's little to no benefit from making your code blotted with final's every now and then. Author aimed for a good practice, but in large code-bases, seeing everything made final rather obscures the intent, making reading code harder and more obscure - and may give little to no benefit.
Two approaches
Generally though, there are two schools. Choose yours:
AGAINST, unless really needed
One is NOT to use final, unless you REALLY want those reading the code you wrote to know that this field is special in some way and is not to be trifled with.
For, there's never a bad place to use final!
The other is enamored with final and wants it everywhere. It's less prevalent. Renauld Waldura makes for an excellent propagator of the idea. Read his linked entry, titled "Final word on final keyword", it's a good and in-depth read.
May depend on Java you use
On my part I'd just want you to know that final changed, and doesn't ALWAYS mean unmutable, as you can read in Heinz Kabutz' Java Specialist Newsletter. He takes you through how it worked in different Javas, feel free to take his code and check the Java you use.

Related

What is wrong in sharing Mutable State? [duplicate]

This question already has answers here:
How shall we write get method, so that private fields don't escape their intended scope? [duplicate]
(2 answers)
Closed 3 years ago.
In Java Concurrency in Practice chapter # 3 author has suggested not to share the mutable state. Further he has added that below code is not a good way to share the states.
class UnsafeStates {
private String[] states = new String[] {
"AK", "AL"
};
public String[] getStates() {
return states;
}
}
From the book:
Publishing states in this way is problematic because any caller can modify its contents. In this case, the states array has escaped its intended scope, because what was supposed to be private state has been effectively made public.
My question here is: we often use getter and setters to access the class level private mutable variables. if it is not the correct way, what is the correct way to share the state? what is the proper way to encapsulate states ?
For primitive types, int, float etc, using a simple getter like this does not allow the caller to set its value:
someObj.getSomeInt() = 10; // error!
However, with an array, you could change its contents from the outside, which might be undesirable depending on the situation:
someObj.getSomeArray()[0] = newValue; // perfectly fine
This could lead to problems where a field is unexpectedly changed by other parts of code, causing hard-to-track bugs.
What you can do instead, is to return a copy of the array:
public String[] getStates() {
return Arrays.copyOf(states, states.length);
}
This way, even the caller changes the contents of the returned array, the array held by the object won't be affected.
With what you have it is possible for someone to change the content of your private array just through the getter itself:
public static void main(String[] args) {
UnsafeStates us = new UnsafeStates();
us.getStates()[0] = "VT";
System.out.println(Arrays.toString(us.getStates());
}
Output:
[VT, AR]
If you want to encapsulate your States and make it so they cannot change then it might be better to make an enum:
public enum SafeStates {
AR,
AL
}
Creating an enum gives a couple advantages. It allows exact vales that people can use. They can't be modified, its easy to test against and can easily do a switch statement on it. The only downfall for going with an enum is that the values have to be known ahead of time. I.E you code for it. Cannot be created at run time.
This question seems to be asked with respect to concurrency in particular.
Firstly, of course, there is the possibility of modifying non-primitive objects obtained via simple-minded getters; as others have pointed out, this is a risk even with single-threaded programs. The way to avoid this is to return a copy of an array, or an unmodifiable instance of a collection: see for example Collections.unmodifiableList.
However, for programs using concurrency, there is risk of returning the actual object (i.e., not a copy) even if the caller of the getter does not attempt to modify the returned object. Because of concurrent execution, the object could change "while he is looking at it", and in general this lack of synchronization could cause the program to malfunction.
It's difficult to turn the original getStates example into a convincing illustration of my point, but imagine a getter that returns a Map instead. Inside the owning object, correct synchronization may be implemented. However, a getTheMap method that returns just a reference to the Map is an invitation for the caller to call Map methods (even if just map.get) without synchronization.
There are basically two options to avoid the problem: (1) return a deep copy; an unmodifiable wrapper will not suffice in this case, and it should be a deep copy otherwise we just have the same problem one layer down, or (2) do not return unmediated references; instead, extend the method repertoire to provide exactly what is supportable, with correct internal synchronization.

Publication/Escape and Encapsulation in Java

I'm reading the "Java Concurrency in Practice" book and there is a part that I don't quite understand. I know is an old book, and probably is the reason why there is no mention of my doubt.
In the "Sharing object" chapter there is a the section called "Publication and escape":
Publishing an object means making it available to code outside of its
current scope, such as by storing a reference to it where other code
can find it, returning it from a nonprivate method, or passing it to a
method in another class ...
An object that is published when it
should not have been is said to have escaped.
And there is an example:
class UnsafeStates
{
private String[] states = new String []
{"AK", "AL" ....};
public String [] getStates(){return states;}
}
Publishing states in this way is problematic because any caller can
modify its contents. In this case, the states array has escaped its
intend scope, because what was supposed to be private state has been
effectively made public.
And is specified to don't do never in this way.
I suddendly thought about the encapsulation concept where, basically, say to do exactly this.
I misunderstood the concepts or what?
The problem is this method:
public String [] getStates(){return states;}
Return your reference to states array.
Even though you declare states as private but if you get it via getStates() method, you still can modify the states variable:
UnsafeStates us = new UnsafeStates();
String[] copyStates = us.getStates();
copyStates[0] = "You don't know"; // Here the change to `copyStates` also affect the `states` variable since they're both reference to the same array.
Normally, for objects and array properties, you often return a deep copy of that properties to prevent modify internal properties.
Ex: For array:
String[] copied = new String[states.length];
System.arraycopy(states, 0, copied, 0, states.length);
return copied;
For List:
return Collections.unmodifiableList(internalList);
For Object:
return internalObject.clone(); // Require deep clone

private static final vs private final

This question has been asked here. As per the answer :
private final int NUMBER = 10;
If it cannot change, there is no point having one copy per instance.
My doubt is what if instance of the class is created, say once a day and it lasts around a few seconds. Is it good idea to keep the int(in some case object) in memory?
Assuming, there can be many (20-30) such objects.
How you store the information depends very much on what it is intended to be used for.
There are a few approaches you might take:
private static final
This is a good choice if the value will never be modified during the lifetime of the application. It means, when you're creating your multiple instances, you are only actually storing this particular variable ONCE.
private final
This is meant for those times when the value might take on different values for different instances of your object, but any specific instance will not have it's value modified throughout the object's life time.
If you're looking at something which might take on different values over a range of time, then this might be of interest to you.
public static int GetNumber(){...}
Another approach you might consider is to have a static method return the value you are after. This makes it easy to deal with changes in the value, but you also need to consider the effect of such a change throughout the lifetime of any given instance.
Hope that helps...
Regarding private final int number, your claim that
If it cannot change, there is no point having one copy per instance
is absolutely wrong. Consider this code, typical of an immutable class:
private final int number;
public MyClass(int number) {
this.number = number;
}
There are many instances of this pattern in the JDK, and in production code classes around the globe.
To answer your question about performance, I doubt you could measure the difference between using static vs instance constants.

The best way to initialize many object references to a default value in Java (code-style)

What is the best way if I have many object references which NEED to be initiliazed (in a method) to a default value and I don't want to mess my code with many lines like:
String name = null;
String address = null;
String type = null;
String edition = null;
String year = null;
I sometimes use:
String name, address, type, edition, year;
name = address = type = edition = year = null;
Is there a better way? Is this way OK?
EDIT: These are instance variables. The purpose of this question is (as the tag indicates) to improve my code-style. I just want to produce the cleanest code and human readable as possible in when encountering this situation. What I am excepting as answer is some best-practices suggestions from experienced coders and I am not interested in explanation of how variable initialization of variables in java works as this is irrelevant for this question.
EDIT2: These variables need to be initialized. I am aware of basic rules of variables initialization in java.
Having multiple assignments in one statement is considered bad quality and discouraged by the Java Coding Conventions (Section 10.4). I haven't seen multiple assignments in one statement in any serious commercial software development, because of the lack of readability. I strongly suggest to use separate assignments.
Please see my answer to an almost identical question for more details.
Both ways act as same way after compile. But it is better to use first way since it is more readable and easy to understand. But you should use variables according to context.
Non-primitive Objects are by default null. So, this means that:
String name = null;
is equivalent with:
String name;
Note that this is only the case for class members. Local variables behave differently.
Not only is the first easier to understand, the second one will create extra work in the case you decide once to change the initial value of one of the variables. Then you have to restructure the entire code. That’s not recommended. Further, keep in mind that this only works in the case of null and immutable objects and since you should not switch between different code styles you should use a pattern that works with all kinds of initial values. In other words: initialize the variables individually. This also will help if you want to turn one or some of the variables into a compile-time constant.
As per Datatypes, there is no need for you to assign null to object instance variables, Fields that are declared but not initialized will be set to a reasonable default by the compiler, in your case it will be set to null by default.
String name, address, type, edition, year=null;
Why dont you do like this. This makes your code cleaner as expected.
The only declaration
String name, address, type, edition, year;
is enough.
Because in Java, String is a class and every String reference variable are initialized to null if none of the object is assigned to it.
String name, address, type, edition, year;
it means
String name = null;
String address = null;
String type = null;
String edition = null;
String year = null;
So no need to declare the objects like this and to initialize them explicitly to null.

Should I keep instance variables in Java always initialized or not?

I recently started a new project and I'm trying to keep my instance variables always initialized to some value, so none of them is at any time null. Small example below:
public class ItemManager {
ItemMaster itemMaster;
List<ItemComponentManager> components;
ItemManager() {
itemMaster = new ItemMaster();
components = new ArrayList<ItemComponentManager>();
}
...
}
The point is mainly to avoid the tedious checking for null before using an instance variable somewhere in the code. So far, it's working good and you mostly don't need the null-value as you can check also for empty string or empty list, etc. I'm not using this approach for method scoped variables as their scope is very limited and so doesn't affect other parts of the code.
This all is kind of experimental, so I'd like to know if this approach could work or if there are some pitfalls which I'm not seeing yet. Is it generally a good idea to keep instance variables initialized?
I usually treat an empty collection and a null collection as two separate things:
An empty collection implies that I know there are zero items available. A null collection will tell me that I don't know the state of the collection, which is a different thing.
So I really do not think it's an either/or. And I would declare the variable final if I initialize them in the constructor. If you declare it final it becomes very clear to the reader that this collection cannot be null.
First and foremost, all non-final instance variables must be declared private if you want to retain control!
Consider lazy instantiation as well -- this also avoids "bad state" but only initializes upon use:
class Foo {
private List<X> stuff;
public void add(X x) {
if (stuff == null)
stuff = new ArrayList<X>();
stuff.add(x);
}
public List<X> getStuff() {
if (stuff == null)
return Collections.emptyList();
return Collections.unmodifiableList(stuff);
}
}
(Note the use of Collections.unmodifiableList -- unless you really want a caller to be able to add/remove from your list, you should make it immutable)
Think about how many instances of the object in question will be created. If there are many, and you always create the lists (and might end up with many empty lists), you could be creating many more objects than you need.
Other than that, it's really a matter of taste and if you can have meaningful values when you construct.
If you're working with a DI/IOC, you want the framework to do the work for you (though you could do it through constructor injection; I prefer setters)
-- Scott
I would say that is totally fine - just as long as you remember that you have "empty" placeholder values there and not real data.
Keeping them null has the advantage of forcing you to deal with them - otherwise the program crashes. If you create empty objects, but forget them you get undefined results.
And just to comment on the defencive coding - If you are the one creating the objects and are never setting them null, there is no need to check for null every time. If for some reason you get null value, then you know something has gone catastrophically wrong and the program should crash anyway.
I would make them final if possible. Then they have to be initialized in the constructor and cannot become null.
You should also make them private in any case, to prevent other classes from assigning null to them. If you can check that null is never assigned in your class then the approach will work.
I have come across some cases where this causes problems.
During deserialization, some frameworks will not call the constructor, I don't know how or why they choose to do this but it happens. This can result in your values being null. I have also come across the case where the constructor is called but for some reason member variables are not initialized.
In actual fact I'd use the following code instead of yours:
public class ItemManager {
ItemMaster itemMaster = new ItemMaster();
List<ItemComponentManager> components = new ArrayList<ItemComponentManager>();
ItemManager() {
...
}
...
}
The way I deal with any variable I declare is to decide if it will change over the lifetime of the object (or class if it is static). If the answer is "no" then I make it final.
Making it final forces you to give it a value when the object is created... personally I would do the following unless I knew that I would be changing what the point at:
private final ItemMaster itemMaster;
private final List components;
// instance initialization block - happens at construction time
{
itemMaster = new ItemMaster();
components = new ArrayList();
}
The way your code is right now you must check for null all the time because you didn't mark the variables as private (which means that any class in the same package can change the values to null).
Yes, it is very good idea to initialize all class variables in the constructor.
The point is mainly to avoid the
tedious checking for null before using
a class variable somewhere in the
code.
You still have to check for null. Third party libraries and even the Java API will sometimes return null.
Also, instantiating an object that may never be used is wasteful, but that would depend on the design of your class.
An object should be 100% ready for use after it's constructed. Users should not have to be checking for nulls. Defensive programming is the way to go - keep the checks.
In the interest of DRY, you can put the checks in the setters and simply have the constructor call them. That way you don't code the checks twice.
If it's all your code and you want to set that convention, it should be a nice thing to have. I agree with Paul's comment, though, that nothing prevents some errant code from accidentally setting one of your class variables to null. As a general rule, I always check for null. Yeah, it's a PITA, but defensive coding can be a good thing.
From the name of the class "ItemManager", ItemManager sounds like a singleton in some app. If so you should investigate and really, really, know Dependency Injection. Use something like Spring ( http://www.springsource.org/ ) to create and inject the list of ItemComponentManagers into ItemManager.
Without DI, Initialization by hand in serious apps is a nightmare to debug and connecting up various "manager" classes to make narrow tests is hell.
Use DI always (even when constructing tests). For data objects, create a get() method that creates the list if it doesn't exist. However if the object is complex, almost certainly will find your life better using the Factory or Builder pattern and have the F/B set the member variables as needed.
What happens if in one of your methods you set
itemMaster = null;
or you return a reference to the ItemManager to some other class and it sets itemMaster as null.
(You can guard against this easily return a clone of your ItemManager etc)
I would keep the checks as this is possible.

Categories