Spaces:
Running
Running
| Finally, this week, let's go through the meaning of the MODIFIER "final" in different contexts. | |
| As the name suggests, "final" means that we permanently fix some feature. | |
| However, it WORKS in slightly DIFFERENT WAYS IN DIFFERENT CONTEXTS. | |
| 1 | |
| In the context of a 'LOCAL VARIABLE', the modifier means that the value of the variable CANNOT CHANGE AFTER INITIALISATION. | |
| This is a way to ensure that the value of the variable does not change even by accident. | |
| public static void main(String[] args) { | |
| // The value of a is always 3 | |
| final int a = 3; | |
| // Ollie always points to the same student object | |
| final Student ollie = new Student("Oliver", "oliver@example.com", 123); | |
| // HOWEVER, the object CAN CHANGE IF it is NOT IMMUTABLE | |
| // i.e., if suitable public OPERATIONS are OFFERED TO the CLIENT | |
| oliver.setStudyCredits(159); | |
| } | |
| 2 | |
| 2A | |
| In the context of an ATTRIBUTE, the operation is similar. | |
| The difference is that the value can either be given immediately at the time of definition… | |
| class Ball { | |
| // SET VALUE AT ATTRIBUTE LEVEL | |
| private final double diameter = 10.0; | |
| } | |
| 2B | |
| … or leave the value to be given in the CONSTRUCTORS. | |
| If the value is not given at the time of definition, it must be given in each constructor. | |
| After this, the value cannot change. | |
| class Ball { | |
| private final double diameter; | |
| public Ball(double diameter) { | |
| // SET VALUE IN THE CONSTRUCTOR | |
| this.diameter = diameter; | |
| } | |
| } | |
| 3 | |
| A PARAMETER can also be defined with the 'final' modifier. | |
| In this case, the value of the parameter variable cannot change. | |
| For example, objects passed as parameters could be equipped with a final modifier, | |
| so that the original reference is not accidentally lost within the method. | |
| public static void removeNegatives(final ArrayList<Integer> list) { | |
| // Now the value of the parameter variable list cannot change, | |
| // i.e., it always points to the list that was passed | |
| // as a parameter. | |
| 4 | |
| In the context of METHODS and CLASSES, the final modifier is related to INHERITANCE. | |
| A method equipped with the modifier cannot be overridden in a derived class: | |
| class SecretAgent { | |
| private String name; | |
| private String code; | |
| public SecretAgent(String name, String code) { | |
| this.name = name; | |
| this.setCode(code); | |
| } | |
| // 'final' METHOD | |
| public final void setCode(String code) { | |
| // The class can be inherited, but this method cannot | |
| // be overridden in the derived class | |
| if (SecretAgent.codeOk(code)) { | |
| this.code = code; | |
| } | |
| else { | |
| this.code = "000"; | |
| } | |
| } | |
| public static boolean codeOk(String code) { | |
| if (code.length() != 3 || !code.startsWith("00")) { | |
| return false; | |
| } | |
| try { | |
| Integer.valueOf("" + code.charAt(2)); | |
| return true; | |
| } catch (NumberFormatException e) { | |
| return false; | |
| } | |
| } | |
| } | |
| A good example of this could be a setting method that is called in the constructor | |
| - if it is overridden in the derived class, the operation of the class can change significantly. | |
| If a class is equipped with the 'final' modifier, the 'final' CLASS CANNOT BE INHERITED at all by other classes. | |
| A typical example is the Java 'String' class, whose inheritance attempt leads to a compiler error message: | |
| eg1 | |
| // Now Ball cannot be inherited, an inheritance attempt gives an error | |
| final class Ball { | |
| private final double diameter; | |
| public Ball(double diameter) { | |
| this.diameter = diameter; | |
| } | |
| } | |
| class SoccerBall extends Ball { } // Compiler error! | |
| eg2 | |
| // String is declared as: | |
| public final class String { | |
| // ... | |
| } | |
| class MyString extends String { } // COMPILER ERROR! | |
| ======================================== | |
| The Last Piece on the Board | |
| At the end of chapter 6, let's implement a simple game. | |
| The game starts with an 'empty game board', where each player alternately places 1-3 of their own game pieces according to their own choice. | |
| The player who places the last piece on the board wins. | |
| A piece can only be placed in an empty square. | |
| There can be different amounts of pieces on the board at different rounds of the game. | |