This question already has answers here:
Should I instantiate instance variables on declaration or in the constructor?
(15 answers)
Closed 9 years ago.
When I use Java based on my C++ knowledge, I love to initialize variable using the following way.
public class ME {
private int i;
public ME() {
this.i = 100;
}
}
After some time, I change the habit to
public class ME {
private int i = 100;
public ME() {
}
}
I came across others source code, some are using 1st convention, others are using 2nd convention.
May I know which convention do you all recommend, and why?
I find the second style (declaration + initialization in one go) superior. Reasons:
It makes it clear at a glance how the variable is initialized. Typically, when reading a program and coming across a variable, you'll first go to its declaration (often automatic in IDEs). With style 2, you see the default value right away. With style 1, you need to look at the constructor as well.
If you have more than one constructor, you don't have to repeat the initializations (and you cannot forget them).
Of course, if the initialization value is different in different constructors (or even calculated in the constructor), you must do it in the constructor.
I have the practice (habit) of almost always initializing in the contructor for two reasons, one in my opinion it adds to readablitiy (cleaner), and two there is more logic control in the constructor than in one line. Even if initially the instance variable doesn't require logic, having it in the constructor gives more flexibility to add logic in the future if needed.
As to the concern mentioned above about multiple constructors, that's easily solved by having one no-arg constructor that initializes all the instance variables that are initilized the same for all constructors and then each constructor calls this() at the first line. That solves your reduncancy issues.
I tend to use the second one to avoid a complicated constructor (or a useless one), also I don't really consider this as an initialization (even if it is an initialization), but more like giving a default value.
For example in your second snippet, you can remove the constructor and have a clearer code.
If you initialize in the top or in constructor it doesn't make much difference .But in some case initializing in constructor makes sense.
class String
{
char[] arr/*=char [20]*/; //Here initializing char[] over here will not make sense.
String()
{
this.arr=new char[0];
}
String(char[] arr)
{
this.arr=arr;
}
}
So depending on the situation sometime you will have to initialize in the top and sometimes in a constructor.
FYI other option's for initialization without using a constructor :
class Foo
{
int i;
static int k;
//instance initializer block
{
//run's every time a new object is created
i=20;
}
//static initializer block
static{
//run's only one time when the class is loaded
k=18;
}
}
The only problem I see with the first method is if you are planning to add more constructors. Then you will be repeating code and maintainability would suffer.
I recommend initializing variables in constructors. That's why they exist: to ensure your objects are constructed (initialized) properly.
Either way will work, and it's a matter of style, but I prefer constructors for member initialization.
Both the options can be correct depending on your situation.
A very simple example would be: If you have multiple constructors all of which initialize the variable the same way(int x=2 for each one of them). It makes sense to initialize the variable at declaration to avoid redundancy.
It also makes sense to consider final variables in such a situation. If you know what value a final variable will have at declaration, it makes sense to initialize it outside the constructors. However, if you want the users of your class to initialize the final variable through a constructor, delay the initialization until the constructor.
One thing, regardless of how you initialize the field, use of the final qualifier, if possible, will ensure the visibility of the field's value in a multi-threaded environment.
I think both are correct programming wise,
But i think your first option is more correct in an object oriented way, because in the constructor is when the object is created, and it is when the variable should initialized.
I think it is the "by the book" convention, but it is open for discussion.
Wikipedia
It can depend on what your are initialising, for example you cannot just use field initialisation if a checked exception is involved. For example, the following:
public class Foo {
FileInputStream fis = new FileInputStream("/tmp"); // throws FileNotFoundException
}
Will cause a compile-time error unless you also include a constructor declaring that checked exception, or extend a superclass which does, e.g.:
public Foo() throws FileNotFoundException {}
I would say, it depends on the default. For example
public Bar
{
ArrayList<Foo> foos;
}
I would make a new ArrayList outside of the constructor, if I always assume foos can not be null. If Bar is a valid object, not caring if foos is null or not, I would put it in the constructor.
You might disagree and say that it's the constructors job to put the object in a valid state. However, if clearly all the constructors should do exactly the same thing(initialize foos), why duplicate that code?
Related
I can't understand where the final keyword is really handy when it is used on method parameters.
If we exclude the usage of anonymous classes, readability and intent declaration then it seems almost worthless to me.
Enforcing that some data remains constant is not as strong as it seems.
If the parameter is a primitive then it will have no effect since the parameter is passed to the method as a value and changing it will have no effect outside the scope.
If we are passing a parameter by reference, then the reference itself is a local variable and if the reference is changed from within the method, that would not have any effect from outside of the method scope.
Consider the simple test example below.
This test passes although the method changed the value of the reference given to it, it has no effect.
public void testNullify() {
Collection<Integer> c = new ArrayList<Integer>();
nullify(c);
assertNotNull(c);
final Collection<Integer> c1 = c;
assertTrue(c1.equals(c));
change(c);
assertTrue(c1.equals(c));
}
private void change(Collection<Integer> c) {
c = new ArrayList<Integer>();
}
public void nullify(Collection<?> t) {
t = null;
}
Stop a Variable’s Reassignment
While these answers are intellectually interesting, I've not read the short simple answer:
Use the keyword final when you want the compiler to prevent a
variable from being re-assigned to a different object.
Whether the variable is a static variable, member variable, local variable, or argument/parameter variable, the effect is entirely the same.
Example
Let’s see the effect in action.
Consider this simple method, where the two variables (arg and x) can both be re-assigned different objects.
// Example use of this method:
// this.doSomething( "tiger" );
void doSomething( String arg ) {
String x = arg; // Both variables now point to the same String object.
x = "elephant"; // This variable now points to a different String object.
arg = "giraffe"; // Ditto. Now neither variable points to the original passed String.
}
Mark the local variable as final. This results in a compiler error.
void doSomething( String arg ) {
final String x = arg; // Mark variable as 'final'.
x = "elephant"; // Compiler error: The final local variable x cannot be assigned.
arg = "giraffe";
}
Instead, let’s mark the parameter variable as final. This too results in a compiler error.
void doSomething( final String arg ) { // Mark argument as 'final'.
String x = arg;
x = "elephant";
arg = "giraffe"; // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
}
Moral of the story:
If you want to ensure a variable always points to the same object,
mark the variable final.
Never Reassign Arguments
As good programming practice (in any language), you should never re-assign a parameter/argument variable to an object other than the object passed by the calling method. In the examples above, one should never write the line arg = . Since humans make mistakes, and programmers are human, let’s ask the compiler to assist us. Mark every parameter/argument variable as 'final' so that the compiler may find and flag any such re-assignments.
In Retrospect
As noted in other answers…
Given Java's original design goal of helping programmers to avoid dumb mistakes such as reading past the end of an array, Java should have been designed to automatically enforce all parameter/argument variables as 'final'. In other words, Arguments should not be variables. But hindsight is 20/20 vision, and the Java designers had their hands full at the time.
So, always add final to all arguments?
Should we add final to each and every method parameter being declared?
In theory, yes.
In practice, no.➥ Add final only when the method’s code is long or complicated, where the argument may be mistaken for a local or member variable and possibly re-assigned.
If you buy into the practice of never re-assigning an argument, you will be inclined to add a final to each. But this is tedious and makes the declaration a bit harder to read.
For short simple code where the argument is obviously an argument, and not a local variable nor a member variable, I do not bother adding the final. If the code is quite obvious, with no chance of me nor any other programmer doing maintenance or refactoring accidentally mistaking the argument variable as something other than an argument, then don’t bother. In my own work, I add final only in longer or more involved code where an argument might mistaken for a local or member variable.
#Another case added for the completeness
public class MyClass {
private int x;
//getters and setters
}
void doSomething( final MyClass arg ) { // Mark argument as 'final'.
arg = new MyClass(); // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
arg.setX(20); // allowed
// We can re-assign properties of argument which is marked as final
}
record
Java 16 brings the new records feature. A record is a very brief way to define a class whose central purpose is to merely carry data, immutably and transparently.
You simply declare the class name along with the names and types of its member fields. The compiler implicitly provides the constructor, getters, equals & hashCode, and toString.
The fields are read-only, with no setters. So a record is one case where there is no need to mark the arguments final. They are already effectively final. Indeed, the compiler forbids using final when declaring the fields of a record.
public record Employee( String name , LocalDate whenHired ) // 🡄 Marking `final` here is *not* allowed.
{
}
If you provide an optional constructor, there you can mark final.
public record Employee(String name , LocalDate whenHired) // 🡄 Marking `final` here is *not* allowed.
{
public Employee ( final String name , final LocalDate whenHired ) // 🡄 Marking `final` here *is* allowed.
{
this.name = name;
whenHired = LocalDate.MIN; // 🡄 Compiler error, because of `final`.
this.whenHired = whenHired;
}
}
Sometimes it's nice to be explicit (for readability) that the variable doesn't change. Here's a simple example where using final can save some possible headaches:
public void setTest(String test) {
test = test;
}
If you forget the 'this' keyword on a setter, then the variable you want to set doesn't get set. However, if you used the final keyword on the parameter, then the bug would be caught at compile time.
Yes, excluding anonymous classes, readability and intent declaration it's almost worthless. Are those three things worthless though?
Personally I tend not to use final for local variables and parameters unless I'm using the variable in an anonymous inner class, but I can certainly see the point of those who want to make it clear that the parameter value itself won't change (even if the object it refers to changes its contents). For those who find that adds to readability, I think it's an entirely reasonable thing to do.
Your point would be more important if anyone were actually claiming that it did keep data constant in a way that it doesn't - but I can't remember seeing any such claims. Are you suggesting there's a significant body of developers suggesting that final has more effect than it really does?
EDIT: I should really have summed all of this up with a Monty Python reference; the question seems somewhat similar to asking "What have the Romans ever done for us?"
Let me explain a bit about the one case where you have to use final, which Jon already mentioned:
If you create an anonymous inner class in your method and use a local variable (such as a method parameter) inside that class, then the compiler forces you to make the parameter final:
public Iterator<Integer> createIntegerIterator(final int from, final int to)
{
return new Iterator<Integer>(){
int index = from;
public Integer next()
{
return index++;
}
public boolean hasNext()
{
return index <= to;
}
// remove method omitted
};
}
Here the from and to parameters need to be final so they can be used inside the anonymous class.
The reason for that requirement is this: Local variables live on the stack, therefore they exist only while the method is executed. However, the anonymous class instance is returned from the method, so it may live for much longer. You can't preserve the stack, because it is needed for subsequent method calls.
So what Java does instead is to put copies of those local variables as hidden instance variables into the anonymous class (you can see them if you examine the byte code). But if they were not final, one might expect the anonymous class and the method seeing changes the other one makes to the variable. In order to maintain the illusion that there is only one variable rather than two copies, it has to be final.
I use final all the time on parameters.
Does it add that much? Not really.
Would I turn it off? No.
The reason: I found 3 bugs where people had written sloppy code and failed to set a member variable in accessors. All bugs proved difficult to find.
I'd like to see this made the default in a future version of Java. The pass by value/reference thing trips up an awful lot of junior programmers.
One more thing.. my methods tend to have a low number of parameters so the extra text on a method declaration isn't an issue.
Using final in a method parameter has nothing to do with what happens to the argument on the caller side. It is only meant to mark it as not changing inside that method. As I try to adopt a more functional programming style, I kind of see the value in that.
Personally I don't use final on method parameters, because it adds too much clutter to parameter lists.
I prefer to enforce that method parameters are not changed through something like Checkstyle.
For local variables I use final whenever possible, I even let Eclipse do that automatically in my setup for personal projects.
I would certainly like something stronger like C/C++ const.
Since Java passes copies of arguments I feel the relevance of final is rather limited. I guess the habit comes from the C++ era where you could prohibit reference content from being changed by doing a const char const *. I feel this kind of stuff makes you believe the developer is inherently stupid as f*** and needs to be protected against truly every character he types. In all humbleness may I say, I write very few bugs even though I omit final (unless I don't want someone to override my methods and classes). Maybe I'm just an old-school dev.
Short answer: final helps a tiny bit but... use defensive programming on the client side instead.
Indeed, the problem with final is that it only enforces the reference is unchanged, gleefully allowing the referenced object members to be mutated, unbeknownst to the caller. Hence the best practice in this regard is defensive programming on the caller side, creating deeply immutable instances or deep copies of objects that are in danger of being mugged by unscrupulous APIs.
I never use final in a parameter list, it just adds clutter like previous respondents have said. Also in Eclipse you can set parameter assignment to generate an error so using final in a parameter list seems pretty redundant to me.
Interestingly when I enabled the Eclipse setting for parameter assignment generating an error on it caught this code (this is just how I remember the flow, not the actual code. ) :-
private String getString(String A, int i, String B, String C)
{
if (i > 0)
A += B;
if (i > 100)
A += C;
return A;
}
Playing devil's advocate, what exactly is wrong with doing this?
One additional reason to add final to parameter declarations is that it helps to identify variables that need to be renamed as part of a "Extract Method" refactoring. I have found that adding final to each parameter prior to starting a large method refactoring quickly tells me if there are any issues I need to address before continuing.
However, I generally remove them as superfluous at the end of the refactoring.
Follow up by Michel's post. I made myself another example to explain it. I hope it could help.
public static void main(String[] args){
MyParam myParam = thisIsWhy(new MyObj());
myParam.setArgNewName();
System.out.println(myParam.showObjName());
}
public static MyParam thisIsWhy(final MyObj obj){
MyParam myParam = new MyParam() {
#Override
public void setArgNewName() {
obj.name = "afterSet";
}
#Override
public String showObjName(){
return obj.name;
}
};
return myParam;
}
public static class MyObj{
String name = "beforeSet";
public MyObj() {
}
}
public abstract static class MyParam{
public abstract void setArgNewName();
public abstract String showObjName();
}
From the code above, in the method thisIsWhy(), we actually didn't assign the [argument MyObj obj] to a real reference in MyParam. In instead, we just use the [argument MyObj obj] in the method inside MyParam.
But after we finish the method thisIsWhy(), should the argument(object) MyObj still exist?
Seems like it should, because we can see in main we still call the method showObjName() and it needs to reach obj. MyParam will still use/reaches the method argument even the method already returned!
How Java really achieve this is to generate a copy also is a hidden reference of the argument MyObj obj inside the MyParam object ( but it's not a formal field in MyParam so that we can't see it )
As we call "showObjName", it will use that reference to get the corresponding value.
But if we didn't put the argument final, which leads a situation we can reassign a new memory(object) to the argument MyObj obj.
Technically there's no clash at all! If we are allowed to do that, below will be the situation:
We now have a hidden [MyObj obj] point to a [Memory A in heap] now live in MyParam object.
We also have another [MyObj obj] which is the argument point to a [Memory B in heap] now live in thisIsWhy method.
No clash, but "CONFUSING!!" Because they are all using the same "reference name" which is "obj".
To avoid this, set it as "final" to avoid programmer do the "mistake-prone" code.
What difference that final makes between the code below. Is there any advantage in declaring the arguments as final.
public String changeTimezone( Timestamp stamp, Timezone fTz, Timezone toTz){
return ....
}
public String changeTimezone(final Timestamp stamp, final Timezone fTz,
final Timezone toTz){
return ....
}
As a formal method parameter is a local variable, you can access them from inner anonymous classes only if they are declared as final.
This saves you from declaring another local final variable in the method body:
void m(final int param) {
new Thread(new Runnable() {
public void run() {
System.err.println(param);
}
}).start();
}
Extract from The final word on the final keyword
Final Parameters
The following sample declares final parameters:
public void doSomething(final int i, final int j)
{
// cannot change the value of i or j here...
// any change would be visible only inside the method...
}
final is used here to ensure the two
indexes i and j won't accidentally be
reset by the method. It's a handy way
to protect against an insidious bug
that erroneously changes the value of
your parameters. Generally speaking,
short methods are a better way to
protect from this class of errors, but
final parameters can be a useful
addition to your coding style.
Note that final parameters are not
considered part of the method
signature, and are ignored by the
compiler when resolving method calls.
Parameters can be declared final (or
not) with no influence on how the
method is overriden.
The final prevents you from assigning a new value to the variable, and this can be helpful in catching typos. Stylistically you might like to keep the parameters received unchanged and assign only to local variables, so final would help to enforce that style.
Must admit I rarely remember to use final for parameters, maybe I should.
public int example(final int basicRate){
int discountRate;
discountRate = basicRate - 10;
// ... lots of code here
if ( isGoldCustomer ) {
basicRate--; // typo, we intended to say discountRate--, final catches this
}
// ... more code here
return discountRate;
}
It doesn't make a lot of difference. It just means that you can't write:
stamp = null;
fTz = new ...;
but you can still write:
stamp.setXXX(...);
fTz.setXXX(...);
It's mainly a hint to the maintenance programmer that follows you that you aren't going to assign a new value to the parameter somewhere in the middle of your method where it isn't obvious and might therefore cause confusion.
The final keyword when used for parameters/variables in Java marks the reference as final. In case of passing an object to another method, the system creates a copy of the reference variable and passes it to the method. By marking the new references final, you protect them from reassignment. It's considered sometimes a good coding practice.
For the body of this method the final keyword will prevent the argument references to be accidentally reassigned giving a compile error on those cases (most IDEs will complain straight away). Some may argue that using final in general whenever possible will speed things up but that's not the case in recent JVMs.
Two advantages that I see are listed :
1 Marking the method argument as final prevents reassignment of the argument inside the method
From you example
public String changeTimezone(final Timestamp stamp, final Timezone fTz,
final Timezone toTz){
// THIS WILL CAUSE COMPILATION ERROR as fTz is marked as final argument
fTz = Calendar.getInstance().getTimeZone();
return ..
}
In a complicated method marking the arguments as final will help in accidental interpretation of these arguments as methods local variables and reassigning as compiler will flag these cases as shown in the example.
2 Passing the argument to an anonymous inner class
As a formal method parameter is a local variable, you can access them from inner anonymous classes only if they are declared as final.
- In the past (before Java 8 :-) )
Explit use of "final" keyword affected accessibility of the method variable for internal anonymous classes.
- In modern (Java 8+) lanaguage there is no need for such usage:
Java introduced "effectively final" variables. Local variables and method paramters are assummed final if the code does not imply changing of value of the variable. So if you see such keyword in Java8+ you can assume it is unecessary. Introduction of "effectively final" makes us type less code when using lambdas.
Its just a construct in Java to help you define a contract and stick to it. A similar discussion here : http://c2.com/cgi/wiki?JavaFinalConsideredEvil
BTW - (as the twiki says), marking args as final is generally redundant if you are following good programming principles and hance done reassign / redefine the incoming argument reference.
In the worst case, if you do redefine the args reference, its not going to affect the actual value passed to the function - since only a reference was passed.
I'm speaking of marking variables and fields final in general - doesn't just apply to method arguments. (Marking methods/classes final is a whole different thing).
It's a favor to the readers/future maintainers of your code. Together with a sensible name of the variable, it's helpful and reassuring to the reader of your code to see/understand what the variables in question represent - and it's reassuring to the reader that whenever you see the variable in the same scope, the meaning stays the same, so (s)he doesn't have to scratch his head to always figure out what a variable means in every context. We've seen too many abuses of "re-use" of variables, that makes even a short code snippet hard to understand.
The final keyword prevents you from assigning a new value to the parameter. I would like to explain this with a simple example
Suppose we have a method
method1(){
Date dateOfBirth =new Date("1/1/2009");
method2(dateOfBirth);
method3(dateOfBirth); }
public mehod2(Date dateOfBirth) {
....
....
....
}
public mehod2(Date dateOfBirth) {
....
....
....
}
In the above case if the "dateOfBirth" is assigned new value in method2 than this would result in the wrong output from method3. As the value that is being passed to method3 is not what it was before being passed to method2. So to avoid this final keyword is used for parameters.
And this is also one of the Java Coding Best Practices.
This question already has answers here:
Initialize class fields in constructor or at declaration?
(16 answers)
Closed 10 years ago.
What is the difference between the following two, and which is more preferable??
public class foo {
int i = 2;
}
public class foo {
int i;
foo() {
i = 2;
}
}
In your example, there is no difference in behavioural semantics. In Java, all instance field initializers (and instance blocks) are executed after superclass initialization, and before the body of the constructor; see JLS 12.5.
The difference lies in code readability and (in other examples) avoiding repetitious coding and fragility1. These need to be assessed on a case-by-case basis.
It is also worth noting that there are some cases where you have to initialize in the constructor; i.e. when the initialization depends on a constructor parameter.
1 - The repetitiousness and fragility issues are flip-sides of the same thing. If you have multiple constructors, the "initialize in constructor" approach tends to lead to repetition. And if you add extra fields, you might to add the initialization to all relevant constructors; i.e. fragility.
If you have two or more constructors and intialization value differs in each of them, then you should use constructor initialization as there is no way to do the same with member initialization...
however if you have just one constructor...you can use member initialization for better code clarity..
In particular this case there is no difference in these two variants. First variant is more preferable, because initializations of fields inside constructor, as usual, use external values from constructor arguments.
First of all I think the second example should look like this:
public class foo{
int i;
foo(){
i = 0;
}
}
Otherwise i is just a local variable in the C'tor scope.
Second, the first example shows initialization which is called before the class C'tor is invoked. this is good if you want this to happen no matter what C'tor is used.
It also enables you to declare i as readonly.
In your first example, i is an instance variable of class foo (better name would be Foo). It's initialised at class loading.
In your second example, i is also an instance varaible but in this case initialised in the foo() constructor.
There is no real difference here, and especially with primitives.
However, in a multi-threaded environment, if you do intend to initialise your ivars in your constructor, and those ivars are non-primitive, you need to avoid the risk of exposing a partially constructed object. The reason for this is that constructors aren't synchronised and can't have the synchronised keyword applied but then two threads can't be constructing the same object.
So, to avoid this, you should never expose this in your constructor. One way of doing so is to call non-final methods. Doing so, say calling an abstract method, allows some unknown code to do something with your unfinished object. Obviously, this can't be done if you initialise in your declaration.
p.s. I thought there was something on this in Effective Java but couldn't find anything.
I can't understand where the final keyword is really handy when it is used on method parameters.
If we exclude the usage of anonymous classes, readability and intent declaration then it seems almost worthless to me.
Enforcing that some data remains constant is not as strong as it seems.
If the parameter is a primitive then it will have no effect since the parameter is passed to the method as a value and changing it will have no effect outside the scope.
If we are passing a parameter by reference, then the reference itself is a local variable and if the reference is changed from within the method, that would not have any effect from outside of the method scope.
Consider the simple test example below.
This test passes although the method changed the value of the reference given to it, it has no effect.
public void testNullify() {
Collection<Integer> c = new ArrayList<Integer>();
nullify(c);
assertNotNull(c);
final Collection<Integer> c1 = c;
assertTrue(c1.equals(c));
change(c);
assertTrue(c1.equals(c));
}
private void change(Collection<Integer> c) {
c = new ArrayList<Integer>();
}
public void nullify(Collection<?> t) {
t = null;
}
Stop a Variable’s Reassignment
While these answers are intellectually interesting, I've not read the short simple answer:
Use the keyword final when you want the compiler to prevent a
variable from being re-assigned to a different object.
Whether the variable is a static variable, member variable, local variable, or argument/parameter variable, the effect is entirely the same.
Example
Let’s see the effect in action.
Consider this simple method, where the two variables (arg and x) can both be re-assigned different objects.
// Example use of this method:
// this.doSomething( "tiger" );
void doSomething( String arg ) {
String x = arg; // Both variables now point to the same String object.
x = "elephant"; // This variable now points to a different String object.
arg = "giraffe"; // Ditto. Now neither variable points to the original passed String.
}
Mark the local variable as final. This results in a compiler error.
void doSomething( String arg ) {
final String x = arg; // Mark variable as 'final'.
x = "elephant"; // Compiler error: The final local variable x cannot be assigned.
arg = "giraffe";
}
Instead, let’s mark the parameter variable as final. This too results in a compiler error.
void doSomething( final String arg ) { // Mark argument as 'final'.
String x = arg;
x = "elephant";
arg = "giraffe"; // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
}
Moral of the story:
If you want to ensure a variable always points to the same object,
mark the variable final.
Never Reassign Arguments
As good programming practice (in any language), you should never re-assign a parameter/argument variable to an object other than the object passed by the calling method. In the examples above, one should never write the line arg = . Since humans make mistakes, and programmers are human, let’s ask the compiler to assist us. Mark every parameter/argument variable as 'final' so that the compiler may find and flag any such re-assignments.
In Retrospect
As noted in other answers…
Given Java's original design goal of helping programmers to avoid dumb mistakes such as reading past the end of an array, Java should have been designed to automatically enforce all parameter/argument variables as 'final'. In other words, Arguments should not be variables. But hindsight is 20/20 vision, and the Java designers had their hands full at the time.
So, always add final to all arguments?
Should we add final to each and every method parameter being declared?
In theory, yes.
In practice, no.➥ Add final only when the method’s code is long or complicated, where the argument may be mistaken for a local or member variable and possibly re-assigned.
If you buy into the practice of never re-assigning an argument, you will be inclined to add a final to each. But this is tedious and makes the declaration a bit harder to read.
For short simple code where the argument is obviously an argument, and not a local variable nor a member variable, I do not bother adding the final. If the code is quite obvious, with no chance of me nor any other programmer doing maintenance or refactoring accidentally mistaking the argument variable as something other than an argument, then don’t bother. In my own work, I add final only in longer or more involved code where an argument might mistaken for a local or member variable.
#Another case added for the completeness
public class MyClass {
private int x;
//getters and setters
}
void doSomething( final MyClass arg ) { // Mark argument as 'final'.
arg = new MyClass(); // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
arg.setX(20); // allowed
// We can re-assign properties of argument which is marked as final
}
record
Java 16 brings the new records feature. A record is a very brief way to define a class whose central purpose is to merely carry data, immutably and transparently.
You simply declare the class name along with the names and types of its member fields. The compiler implicitly provides the constructor, getters, equals & hashCode, and toString.
The fields are read-only, with no setters. So a record is one case where there is no need to mark the arguments final. They are already effectively final. Indeed, the compiler forbids using final when declaring the fields of a record.
public record Employee( String name , LocalDate whenHired ) // 🡄 Marking `final` here is *not* allowed.
{
}
If you provide an optional constructor, there you can mark final.
public record Employee(String name , LocalDate whenHired) // 🡄 Marking `final` here is *not* allowed.
{
public Employee ( final String name , final LocalDate whenHired ) // 🡄 Marking `final` here *is* allowed.
{
this.name = name;
whenHired = LocalDate.MIN; // 🡄 Compiler error, because of `final`.
this.whenHired = whenHired;
}
}
Sometimes it's nice to be explicit (for readability) that the variable doesn't change. Here's a simple example where using final can save some possible headaches:
public void setTest(String test) {
test = test;
}
If you forget the 'this' keyword on a setter, then the variable you want to set doesn't get set. However, if you used the final keyword on the parameter, then the bug would be caught at compile time.
Yes, excluding anonymous classes, readability and intent declaration it's almost worthless. Are those three things worthless though?
Personally I tend not to use final for local variables and parameters unless I'm using the variable in an anonymous inner class, but I can certainly see the point of those who want to make it clear that the parameter value itself won't change (even if the object it refers to changes its contents). For those who find that adds to readability, I think it's an entirely reasonable thing to do.
Your point would be more important if anyone were actually claiming that it did keep data constant in a way that it doesn't - but I can't remember seeing any such claims. Are you suggesting there's a significant body of developers suggesting that final has more effect than it really does?
EDIT: I should really have summed all of this up with a Monty Python reference; the question seems somewhat similar to asking "What have the Romans ever done for us?"
Let me explain a bit about the one case where you have to use final, which Jon already mentioned:
If you create an anonymous inner class in your method and use a local variable (such as a method parameter) inside that class, then the compiler forces you to make the parameter final:
public Iterator<Integer> createIntegerIterator(final int from, final int to)
{
return new Iterator<Integer>(){
int index = from;
public Integer next()
{
return index++;
}
public boolean hasNext()
{
return index <= to;
}
// remove method omitted
};
}
Here the from and to parameters need to be final so they can be used inside the anonymous class.
The reason for that requirement is this: Local variables live on the stack, therefore they exist only while the method is executed. However, the anonymous class instance is returned from the method, so it may live for much longer. You can't preserve the stack, because it is needed for subsequent method calls.
So what Java does instead is to put copies of those local variables as hidden instance variables into the anonymous class (you can see them if you examine the byte code). But if they were not final, one might expect the anonymous class and the method seeing changes the other one makes to the variable. In order to maintain the illusion that there is only one variable rather than two copies, it has to be final.
I use final all the time on parameters.
Does it add that much? Not really.
Would I turn it off? No.
The reason: I found 3 bugs where people had written sloppy code and failed to set a member variable in accessors. All bugs proved difficult to find.
I'd like to see this made the default in a future version of Java. The pass by value/reference thing trips up an awful lot of junior programmers.
One more thing.. my methods tend to have a low number of parameters so the extra text on a method declaration isn't an issue.
Using final in a method parameter has nothing to do with what happens to the argument on the caller side. It is only meant to mark it as not changing inside that method. As I try to adopt a more functional programming style, I kind of see the value in that.
Personally I don't use final on method parameters, because it adds too much clutter to parameter lists.
I prefer to enforce that method parameters are not changed through something like Checkstyle.
For local variables I use final whenever possible, I even let Eclipse do that automatically in my setup for personal projects.
I would certainly like something stronger like C/C++ const.
Since Java passes copies of arguments I feel the relevance of final is rather limited. I guess the habit comes from the C++ era where you could prohibit reference content from being changed by doing a const char const *. I feel this kind of stuff makes you believe the developer is inherently stupid as f*** and needs to be protected against truly every character he types. In all humbleness may I say, I write very few bugs even though I omit final (unless I don't want someone to override my methods and classes). Maybe I'm just an old-school dev.
Short answer: final helps a tiny bit but... use defensive programming on the client side instead.
Indeed, the problem with final is that it only enforces the reference is unchanged, gleefully allowing the referenced object members to be mutated, unbeknownst to the caller. Hence the best practice in this regard is defensive programming on the caller side, creating deeply immutable instances or deep copies of objects that are in danger of being mugged by unscrupulous APIs.
I never use final in a parameter list, it just adds clutter like previous respondents have said. Also in Eclipse you can set parameter assignment to generate an error so using final in a parameter list seems pretty redundant to me.
Interestingly when I enabled the Eclipse setting for parameter assignment generating an error on it caught this code (this is just how I remember the flow, not the actual code. ) :-
private String getString(String A, int i, String B, String C)
{
if (i > 0)
A += B;
if (i > 100)
A += C;
return A;
}
Playing devil's advocate, what exactly is wrong with doing this?
One additional reason to add final to parameter declarations is that it helps to identify variables that need to be renamed as part of a "Extract Method" refactoring. I have found that adding final to each parameter prior to starting a large method refactoring quickly tells me if there are any issues I need to address before continuing.
However, I generally remove them as superfluous at the end of the refactoring.
Follow up by Michel's post. I made myself another example to explain it. I hope it could help.
public static void main(String[] args){
MyParam myParam = thisIsWhy(new MyObj());
myParam.setArgNewName();
System.out.println(myParam.showObjName());
}
public static MyParam thisIsWhy(final MyObj obj){
MyParam myParam = new MyParam() {
#Override
public void setArgNewName() {
obj.name = "afterSet";
}
#Override
public String showObjName(){
return obj.name;
}
};
return myParam;
}
public static class MyObj{
String name = "beforeSet";
public MyObj() {
}
}
public abstract static class MyParam{
public abstract void setArgNewName();
public abstract String showObjName();
}
From the code above, in the method thisIsWhy(), we actually didn't assign the [argument MyObj obj] to a real reference in MyParam. In instead, we just use the [argument MyObj obj] in the method inside MyParam.
But after we finish the method thisIsWhy(), should the argument(object) MyObj still exist?
Seems like it should, because we can see in main we still call the method showObjName() and it needs to reach obj. MyParam will still use/reaches the method argument even the method already returned!
How Java really achieve this is to generate a copy also is a hidden reference of the argument MyObj obj inside the MyParam object ( but it's not a formal field in MyParam so that we can't see it )
As we call "showObjName", it will use that reference to get the corresponding value.
But if we didn't put the argument final, which leads a situation we can reassign a new memory(object) to the argument MyObj obj.
Technically there's no clash at all! If we are allowed to do that, below will be the situation:
We now have a hidden [MyObj obj] point to a [Memory A in heap] now live in MyParam object.
We also have another [MyObj obj] which is the argument point to a [Memory B in heap] now live in thisIsWhy method.
No clash, but "CONFUSING!!" Because they are all using the same "reference name" which is "obj".
To avoid this, set it as "final" to avoid programmer do the "mistake-prone" code.
This question already has answers here:
Should I instantiate instance variables on declaration or in the constructor?
(15 answers)
Closed 9 years ago.
When I use Java based on my C++ knowledge, I love to initialize variable using the following way.
public class ME {
private int i;
public ME() {
this.i = 100;
}
}
After some time, I change the habit to
public class ME {
private int i = 100;
public ME() {
}
}
I came across others source code, some are using 1st convention, others are using 2nd convention.
May I know which convention do you all recommend, and why?
I find the second style (declaration + initialization in one go) superior. Reasons:
It makes it clear at a glance how the variable is initialized. Typically, when reading a program and coming across a variable, you'll first go to its declaration (often automatic in IDEs). With style 2, you see the default value right away. With style 1, you need to look at the constructor as well.
If you have more than one constructor, you don't have to repeat the initializations (and you cannot forget them).
Of course, if the initialization value is different in different constructors (or even calculated in the constructor), you must do it in the constructor.
I have the practice (habit) of almost always initializing in the contructor for two reasons, one in my opinion it adds to readablitiy (cleaner), and two there is more logic control in the constructor than in one line. Even if initially the instance variable doesn't require logic, having it in the constructor gives more flexibility to add logic in the future if needed.
As to the concern mentioned above about multiple constructors, that's easily solved by having one no-arg constructor that initializes all the instance variables that are initilized the same for all constructors and then each constructor calls this() at the first line. That solves your reduncancy issues.
I tend to use the second one to avoid a complicated constructor (or a useless one), also I don't really consider this as an initialization (even if it is an initialization), but more like giving a default value.
For example in your second snippet, you can remove the constructor and have a clearer code.
If you initialize in the top or in constructor it doesn't make much difference .But in some case initializing in constructor makes sense.
class String
{
char[] arr/*=char [20]*/; //Here initializing char[] over here will not make sense.
String()
{
this.arr=new char[0];
}
String(char[] arr)
{
this.arr=arr;
}
}
So depending on the situation sometime you will have to initialize in the top and sometimes in a constructor.
FYI other option's for initialization without using a constructor :
class Foo
{
int i;
static int k;
//instance initializer block
{
//run's every time a new object is created
i=20;
}
//static initializer block
static{
//run's only one time when the class is loaded
k=18;
}
}
The only problem I see with the first method is if you are planning to add more constructors. Then you will be repeating code and maintainability would suffer.
I recommend initializing variables in constructors. That's why they exist: to ensure your objects are constructed (initialized) properly.
Either way will work, and it's a matter of style, but I prefer constructors for member initialization.
Both the options can be correct depending on your situation.
A very simple example would be: If you have multiple constructors all of which initialize the variable the same way(int x=2 for each one of them). It makes sense to initialize the variable at declaration to avoid redundancy.
It also makes sense to consider final variables in such a situation. If you know what value a final variable will have at declaration, it makes sense to initialize it outside the constructors. However, if you want the users of your class to initialize the final variable through a constructor, delay the initialization until the constructor.
One thing, regardless of how you initialize the field, use of the final qualifier, if possible, will ensure the visibility of the field's value in a multi-threaded environment.
I think both are correct programming wise,
But i think your first option is more correct in an object oriented way, because in the constructor is when the object is created, and it is when the variable should initialized.
I think it is the "by the book" convention, but it is open for discussion.
Wikipedia
It can depend on what your are initialising, for example you cannot just use field initialisation if a checked exception is involved. For example, the following:
public class Foo {
FileInputStream fis = new FileInputStream("/tmp"); // throws FileNotFoundException
}
Will cause a compile-time error unless you also include a constructor declaring that checked exception, or extend a superclass which does, e.g.:
public Foo() throws FileNotFoundException {}
I would say, it depends on the default. For example
public Bar
{
ArrayList<Foo> foos;
}
I would make a new ArrayList outside of the constructor, if I always assume foos can not be null. If Bar is a valid object, not caring if foos is null or not, I would put it in the constructor.
You might disagree and say that it's the constructors job to put the object in a valid state. However, if clearly all the constructors should do exactly the same thing(initialize foos), why duplicate that code?