The “final” Keyword in Java
The Kubernetes ecosystem is huge and quite complex, so it’s easy to forget about costs when trying out all of the exciting tools.
To avoid overspending on your Kubernetes cluster, definitely have a look at the free K8s cost monitoring tool from the automation platform CAST AI. You can view your costs in real time, allocate them, calculate burn rates for projects, spot anomalies or spikes, and get insightful reports you can share with your team.
Connect your cluster and start monitoring your K8s costs right away:
We rely on other people’s code in our own work. Every day.
It might be the language you’re writing in, the framework you’re building on, or some esoteric piece of software that does one thing so well you never found the need to implement it yourself.
The problem is, of course, when things fall apart in production — debugging the implementation of a 3rd party library you have no intimate knowledge of is, to say the least, tricky.
Lightrun is a new kind of debugger.
It’s one geared specifically towards real-life production environments. Using Lightrun, you can drill down into running applications, including 3rd party dependencies, with real-time logs, snapshots, and metrics.
Learn more in this quick, 5-minute Lightrun tutorial:
Slow MySQL query performance is all too common. Of course it is. A good way to go is, naturally, a dedicated profiler that actually understands the ins and outs of MySQL.
The Jet Profiler was built for MySQL only, so it can do things like real-time query performance, focus on most used tables or most frequent queries, quickly identify performance issues and basically help you optimize your queries.
Critically, it has very minimal impact on your server’s performance, with most of the profiling work done separately — so it needs no server changes, agents or separate services.
Basically, you install the desktop application, connect to your MySQL server, hit the record button, and you’ll have results within minutes:
DbSchema is a super-flexible database designer, which can take you from designing the DB with your team all the way to safely deploying the schema.
The way it does all of that is by using a design model, a database-independent image of the schema, which can be shared in a team using GIT and compared or deployed on to any database.
And, of course, it can be heavily visual, allowing you to interact with the database using diagrams, visually compose queries, explore the data, generate random data, import data or build HTML5 database reports.
The Kubernetes ecosystem is huge and quite complex, so it’s easy to forget about costs when trying out all of the exciting tools.
To avoid overspending on your Kubernetes cluster, definitely have a look at the free K8s cost monitoring tool from the automation platform CAST AI. You can view your costs in real time, allocate them, calculate burn rates for projects, spot anomalies or spikes, and get insightful reports you can share with your team.
Connect your cluster and start monitoring your K8s costs right away:
We’re looking for a new Java technical editor to help review new articles for the site.
1. Overview
While inheritance enables us to reuse existing code, sometimes we do need to set limitations on extensibility for various reasons; the final keyword allows us to do exactly that.
In this tutorial, we’ll take a look at what the final keyword means for classes, methods, and variables.
2. Final Classes
Classes marked as final can’t be extended. If we look at the code of Java core libraries, we’ll find many final classes there. One example is the String class.
Consider the situation if we can extend the String class, override any of its methods, and substitute all the String instances with the instances of our specific String subclass.
The result of the operations over String objects will then become unpredictable. And given that the String class is used everywhere, it’s unacceptable. That’s why the String class is marked as final.
Any attempt to inherit from a final class will cause a compiler error. To demonstrate this, let’s create the final class Cat:
And let’s try to extend it:
public class BlackCat extends Cat
We’ll see the compiler error:
The type BlackCat cannot subclass the final class Cat
Note that the final keyword in a class declaration doesn’t mean that the objects of this class are immutable. We can change the fields of Cat object freely:
Cat cat = new Cat(); cat.setWeight(1); assertEquals(1, cat.getWeight());
If we follow the rules of good design strictly, we should create and document a class carefully or declare it final for safety reasons. However, we should use caution when creating final classes.
Notice that making a class final means that no other programmer can improve it. Imagine that we’re using a class and don’t have the source code for it, and there’s a problem with one method.
If the class is final, we can’t extend it to override the method and fix the problem. In other words, we lose extensibility, one of the benefits of object-oriented programming.
3. Final Methods
Methods marked as final cannot be overridden. When we design a class and feel that a method shouldn’t be overridden, we can make this method final. We can also find many final methods in Java core libraries.
Sometimes we don’t need to prohibit a class extension entirely, but only prevent overriding of some methods. A good example of this is the Thread class. It’s legal to extend it and thus create a custom thread class. But its isAlive() methods is final.
This method checks if a thread is alive. It’s impossible to override the isAlive() method correctly for many reasons. One of them is that this method is native. Native code is implemented in another programming language and is often specific to the operating system and hardware it’s running on.
Let’s create a Dog class and make its sound() method final:
Now let’s extend the Dog class and try to override its sound() method:
public class BlackDog extends Dog < public void sound() < >>
We’ll see the compiler error:
- overrides com.baeldung.finalkeyword.Dog.sound - Cannot override the final method from Dog sound() method is final and can’t be overridden
If some methods of our class are called by other methods, we should consider making the called methods final. Otherwise, overriding them can affect the work of callers and cause surprising results.
If our constructor calls other methods, we should generally declare these methods final for the above reason.
What’s the difference between making all methods of the class final and marking the class itself final? In the first case, we can extend the class and add new methods to it.
In the second case, we can’t do this.
4. Final Variables
Variables marked as final can’t be reassigned. Once a final variable is initialized, it can’t be altered.
4.1. Final Primitive Variables
Let’s declare a primitive final variable i, then assign 1 to it.
And let’s try to assign a value of 2 to it:
public void whenFinalVariableAssign_thenOnlyOnce() < final int i = 1; //. i=2; >
The final local variable i may already have been assigned
4.2. Final Reference Variables
If we have a final reference variable, we can’t reassign it either. But this doesn’t mean that the object it refers to is immutable. We can change the properties of this object freely.
To demonstrate this, let’s declare the final reference variable cat and initialize it:
If we try to reassign it we’ll see a compiler error:
The final local variable cat cannot be assigned. It must be blank and not using a compound assignment
But we can change the properties of Cat instance:
cat.setWeight(5); assertEquals(5, cat.getWeight());
4.3. Final Fields
Final fields can be either constants or write-once fields. To distinguish them, we should ask a question — would we include this field if we were to serialize the object? If no, then it’s not part of the object, but a constant.
Note that according to naming conventions, class constants should be uppercase, with components separated by underscore (“_”) characters:
static final int MAX_WIDTH = 999;
Note that any final field must be initialized before the constructor completes.
For static final fields, this means that we can initialize them:
For instance final fields, this means that we can initialize them:
Otherwise, the compiler will give us an error.
4.4. Final Arguments
The final keyword is also legal to put before method arguments. A final argument can’t be changed inside a method:
public void methodWithFinalArguments(final int x)
The above assignment causes the compiler error:
The final local variable x cannot be assigned. It must be blank and not using a compound assignment
5. Conclusion
In this article, we learned what the final keyword means for classes, methods, and variables. Although we may not use the final keyword often in our internal code, it may be a good design solution.
As always, the complete code for this article can be found in the GitHub project.
Slow MySQL query performance is all too common. Of course it is. A good way to go is, naturally, a dedicated profiler that actually understands the ins and outs of MySQL.
The Jet Profiler was built for MySQL only, so it can do things like real-time query performance, focus on most used tables or most frequent queries, quickly identify performance issues and basically help you optimize your queries.
Critically, it has very minimal impact on your server’s performance, with most of the profiling work done separately — so it needs no server changes, agents or separate services.
Basically, you install the desktop application, connect to your MySQL server, hit the record button, and you’ll have results within minutes:
Вот так final…
В java есть ключевое слово – final . Оно может применяться к классам, методам, переменным (в том числе аргументам методов). Для класса это означает, что класс не сможет иметь подклассов, т.е. запрещено наследование. Это полезно при создании immutable (неизменяемых) объектов, например, класс String объявлен, как final .
public final class String < >class SubString extends String < //Ошибка компиляции >
Следует также отметить, что к абстрактным классам (с ключевым словом abstract ), нельзя применить модификатор final , т.к. это взаимоисключающие понятия. Для метода final означает, что он не может быть переопределен в подклассах. Это полезно, когда мы хотим, чтобы исходную реализацию нельзя было переопределить.
public class SuperClass < public final void printReport()< System.out.println("Report"); >> class SubClass extends SuperClass < public void printReport()< //Ошибка компиляции System.out.println("MyReport"); >>
Для переменных примитивного типа это означает, что однажды присвоенное значение не может быть изменено. Для ссылочных переменных это означает, что после присвоения объекта, нельзя изменить ссылку на данный объект. Это важно! Ссылку изменить нельзя, но состояние объекта изменять можно. С java 8 появилось понятие — effectively final . Применяется оно только к переменным (в том числе аргументам методов). Суть в том, что не смотря на явное отсутствие ключевого слова final , значение переменной не изменяется после инициализации. Другими словами, к такой переменной можно подставить слово final без ошибки компиляции. effectively final переменные могут быть использованы внутри локальных классов ( Local Inner Classes ), анонимных классов ( Anonymous Inner Classes ), стримах (Stream API).
public void someMethod() < // В примере ниже и a и b - effectively final, тк значения устанавливаютcя однажды: int a = 1; int b; if (a == 2) b = 3; else b = 4; // с НЕ является effectively final, т.к. значение изменяется int c = 10; c++; Stream.of(1, 2).forEach(s->System.out.println(s + a)); //Ок Stream.of(1, 2).forEach(s-> System.out.println(s + c)); //Ошибка компиляции >
- Что можно сказать про массив, когда он объявлен final ?
- Известно, что класс String — immutable , класс объявлен final , значение строки хранится в массиве char , который отмечен ключевым словом final .
public final class String implements java.io.Serializable, Comparable, CharSequence < /** The value is used for character storage. */ private final char value[];
- Т.к. массив – это объект, то final означает, что после присвоения ссылки на объект, уже нельзя ее изменить, но можно изменять состояние объекта.
final int[] array = ; array[0] = 9; //ок, т.к. изменяем содержимое массива – array = new int[5]; //ошибка компиляции
import java.lang.reflect.Field; class B < public static void main(String[] args) throws Exception < String value = "Old value"; System.out.println(value); //Получаем поле value в классе String Field field = value.getClass().getDeclaredField("value"); //Разрешаем изменять его field.setAccessible(true); //Устанавливаем новое значение field.set(value, "JavaRush".toCharArray()); System.out.println(value); /* Вывод: * Old value * JavaRush */ >>
Обратите внимание, что если бы мы попытались изменить подобным образом финальную переменную примитивного типа, то ничего бы не вышло. Предлагаю вам самостоятельно в этом убедить: создать Java класс, например, с final int полем и попробовать изменить его значение через Reflection API. Всем удачи!