Final (Java): Difference between revisions

Content deleted Content added
Typo corrected
 
(17 intermediate revisions by 8 users not shown)
Line 1:
{{Short description|Keyword in the Java programming language}}
{{lowercase title}}
In the [[Java (programming language)|Java programming language]], the <code>'''final'''</code> [[Keyword (computing)|keyword]] is used in several contexts to define an entity that can only be assigned once.
 
Line 9 ⟶ 10:
Example:
<syntaxhighlight lang="java">
public final class MyFinalClassFinalClass {...}
// ...
}
 
// Forbidden
public class ThisIsWrong extends MyFinalClass {...} // forbidden
public class DerivedClass extends FinalClass {
// ...
}
</syntaxhighlight>
 
==Final methods==
 
A final [[Method (computer science)|method]] cannot be [[Method overriding|overridden]] or hidden by subclasses.<ref>[http{{Cite web |title=Chapter 8. Classes |url=https://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls |access-8.4.3.3date=2024-04-25 JLS 8|website=docs.4oracle.3.3. final Methods]com}}</ref> This is used to prevent unexpected behavior from a subclass altering a method that may be crucial to the function or consistency of the class.<ref>[http{{Cite web |title=Writing Final Classes and Methods |url=https://javadocs.sunoracle.com/docs/booksjavase/tutorial/java/IandI/final.html Writing|access-date=2024-04-25 Final Classes and Methods]|website=docs.oracle.com}}</ref>
 
Example:
<syntaxhighlight lang="java">
public class Base {
public final void m2m1() { ... }
{
public final void m1m2() { ... }
public final void m2() {...}
 
public static void m3() { ... }
public static final void m4() { ... }
}
 
public class Derived extends Base {
public void m2m1() { ... } // forbiddenOK, overriding Base#m1()
{
public void m1m2() { ... } // OK, overriding Base#m1()forbidden
public void m2() {...} // forbidden
 
public static void m3() { ...} } // OK, hiding Base#m3()
public static void m4() { ...} } // forbidden
}
</syntaxhighlight>
 
A common misconception is that declaring a method as <code>final</code> improves efficiency by allowing the compiler to directly insert the method wherever it is called (see [[inline expansion]]). Because the method is loaded at [[run time (program lifecycle phase)|runtime]], compilers are unable to do this. Only the runtime environment and [[Just-in-time compilation|JIT]] compiler know exactly which classes have been loaded, and so only they are able to make decisions about when to inline, whether or not the method is final.<ref>[{{Cite web |title=Java theory and practice: Is that your final answer? |url=http://www.ibm.com/developerworks/java/library/j-jtp1029.html Java theory|url-status=dead and practice|archive-url=https://web.archive.org/web/20090208100217/http://www.ibm.com/developerworks/java/library/j-jtp1029.html Is|archive-date=2009-02-08 that|access-date=2024-04-25 your final answer?]|website=developer.ibm.com}}</ref>
 
Machine code compilers that generate directly executable, platform-specific [[machine code]], are an exception. When using [[static linking]], the compiler can safely assume that methods and variables computable at [[compile-time]] may be inlined.
Line 46 ⟶ 50:
A '''final [[Variable (programming)|variable]]''' can only be initialized once, either via an initializer or an assignment statement. It does not need to be initialized at the point of declaration: this is called a "blank final" variable. A blank final [[instance variable]] of a class must be definitely assigned in every constructor of the class in which it is declared; similarly, a blank final static variable must be definitely assigned in a static initializer of the class in which it is declared; otherwise, a compile-time error occurs in both cases.<ref>Java Language Specification #8.3.1.2.</ref> (Note: If the variable is a reference, this means that the variable cannot be re-bound to reference another object. But the object that it references is still [[mutable object|mutable]], if it was originally mutable.)
 
Unlike the value of a [[constant (computer science)|constant]], the value of a final variable is not necessarily known at compile time. It is considered good practice to represent final constants in all uppercase, using underscore to separate words.<ref>http{{Cite web |title=Java Programming Style Guidelines |url=https://geosoftpetroware.no/development/javastyle.html |access-date=2024-04-25 |website=petroware.no}}</ref>
 
Example:
Line 52 ⟶ 56:
public class Sphere {
 
// piPi is a universal constant, about as constant as anything can be.
public static final double PI = 3.141592653589793;
 
Line 61 ⟶ 65:
 
Sphere(double x, double y, double z, double r) {
radius = r;
xPos = x;
yPos = y;
zPos = z;
}
 
Line 155 ⟶ 159:
final boolean hasTwoDigits;
if (number >= 10 && number < 100) {
hasTwoDigits = true;
}
if (number > -100 && number <= -10) {
hasTwoDigits = true; // compile-error because the final variable might already be assigned.
}
</syntaxhighlight>
 
In addition, a blank final also has to be definitely assigned before being accessed. <ref name="define_assignment" />
<syntaxhighlight lang="java">
final boolean isEven;
 
if (number % 2 == 0) {
isEven = true;
}
 
Line 174 ⟶ 178:
</syntaxhighlight>
 
Note though that a non-final local variable also needs to be definitely assigned before being accessed. <ref name="define_assignment" />
 
<syntaxhighlight lang="java">
Line 180 ⟶ 184:
 
if (number % 2 == 0) {
isEven = true;
}
 
Line 188 ⟶ 192:
 
==C/C++ analog of final variables==
{{detailsfurther|const (computer programming)}}
In [[C (programming language)|C]] and [[C++]], the analogous construct is the <code>[[const (computer programming)|const]]</code> [[keyword (computer programming)|keyword]]. This differs substantially from <code>final</code> in Java, most basically in being a [[type qualifier]]: <code>const</code> is part of the ''[[data type|type]],'' not only part of the identifier (variable). This also means that the constancy of a value can be changed by casting (explicit type conversion), in this case known as "const casting". Nonetheless, casting away constness and then modifying the object results in [[undefined behavior]] if the object was originally declared <code>const</code>. Java's <code>final</code> is a strict rule such that it is impossible to compile code that directly breaks or bypasses the final restrictions. Using [[Reflection (computer programming)#Java|reflection]], however, it is often possible to still modify final variables. This feature is mostly made use of when [[Serialization|deserializing]] objects with final members.
 
Further, because C and C++ expose pointers and references directly, there is a distinction between whether the pointer itself is constant, and whether the data pointed to by the pointer is constant. Applying <code>const</code> to a pointer itself, as in <code>SomeClass * const ptr</code>, means that the contents being referenced can be modified, but the reference itself cannot (without casting). This usage results in behaviour which mimics the behaviour of a <code>final</code> variable reference in Java. By contrast, when applying const to the referenced data only, as in <code>const SomeClass * ptr</code>, the contents cannot be modified (without casting), but the reference itself can. Both the reference and the contents being referenced can be declared as <code>const</code>.
 
In C++, the <code>final</code> keyword is used to denote that a function cannot be further overridden. It is also used similarly to Java to declare a class as final (cannot be extended).
 
<syntaxhighlight lang="C++">
// final in a class declaration declares that a class cannot be extended
class Z final : public X, public Y {
public:
// final in a method signature declares that a method cannot be overridden further
void someOperation() override final {
// do something here
}
};
</syntaxhighlight>
 
==C# analogs for final keyword ==
[[C Sharp (programming language)|C#]] can be considered as similar to Java, in terms of its language features and basic syntax: Java has JVM, C# has .Net Framework; Java has bytecode, C# has MSIL; Java has no pointers (real memory) support, C# is the same.
 
Regarding the final keyword, C# has two related keywords:
Line 200 ⟶ 217:
# The equivalent keyword for variables is <code>readonly</code> <ref>[https://stackoverflow.com/questions/1327544/what-is-the-equivalent-of-javas-final-in-c What is the equivalent of Java's final in C#?]</ref>
 
Note that a key difference between the C/C++ derived keyword <code>const</code> and the C# keyword <code>readonly</code> is that <code>const</code> is evaluated at compile time, while <code>readonly</code> is evaluated at runtime, and thus can have aan expression that is only calculated and fixed later (at runtime).
 
== See also ==
* [[final (C++)]]
 
==References==