So another useful Java keyword is final.
You use that generally to define constant values.
So strictly speaking, final fields are not actually constants,
because they can be modified but only once, and
any modification must be performed before the class constructor finishes.
So what that means is that we can assign a final field it's value
either when we first declare it, or in the constructor.
So as an example, we'll create a test class here.
We'll just call it some class.
Some class.
So we can create a final variable here.
And we can create the final field as a private,
final int instanceNumber equals 1.
So I can do it in there.
I'll just tidy that up a bit...we could also do it in the constructor, like so,
we could put something like...instanceNumber equals 1.
Now, both of these examples obviously do the same thing.
The field instance number set to 1 and because it was marked
final its value can't be changed any where else in the class, or
if we made it public from any where outside of the class either.
But in this case it's usual to assign the value and declaring the field,
but if you prefer you can use a constructor instead.
Now one reason why you might want to and might need to initialize the variable in
the constructor Would be if its value is a result of some calculation that you know,
perhaps relies on some other code as such as a method from another class.
As an example, when reading a record from a database,
you might wanna store the class instances unique database's key which wouldn't be
available until you read the record from the database but then ready to create
the class instance from the database field So we haven't created databases yet.
So that's a mechanism to show how this would work.
What we'll do is we'll create a mechanism for
ensuring that every instance of a class has a unique instance number, or ID.
What this will require is for
us to track a variable each time a new class instance is created.
So this is an ideal candidate for using a class variable.
As we saw in the previous lecture.
So what we'll do is we'll make instance number public,
to make it easy to demonstrate that it can't be changed.
But normally, when doing this you'd make it private.
So I'm gonna change this now, this public final and instance number.
I'm gonna remove the initialization.
And as I mentioned I'm gonna change it to public.
So what we'll also do is we'll, how about,
study variable...call it class counter.
Set that equal to 0.
Then we need a string for a name, so private--final string name.
So, we're gonna have constructor.
We know we're going accept a parameter.
And this is IntelliiJ complaining that it may not be initialized but
we'll fix that in our code shortly.
So, we use a parameter for the constructor.
This.name = name and now IntelliJ's happy on line 10.
And we'll increment the class counter.
Because we're instantiating a new version of this class and
we'll say instanceNumber equal to classCounter.
Then what we'll do is, we'll output name
created, instance is + instanceNumber.
So that's our constructor.
Now we just want to put a getter there as well.
So we're going to put getter for our instance number.
Like so.
So let's go back now to main and create some instances of this class.
So we'll put SomeClass one equals new SomeClass "one".
SomeClass two equals new SomeClass "two" and
SomeClass three is new SomeClass "three"
So if we run that, We
can see unlike in the discussion of static where we had a getter for the static field and
we always got the same value, whichever class this is recorded on,
here we're actually storing the incremented static value in a class field.
And so each instance of a class will maintain its own value, For
instance number, as we can see.
So, just to demonstrate that, what I mean, is we can put
one.getInstanceNumber...two.
two.getInstanceNumber and three.getInstanceNumber.
So, if we run that, And
notice how they're all maintaining their own value for instance number.
So by making instance number final,
the value, its value can't be changed once the class instance has been created.
So, attempting to do so will give an error, and the code won't even compile.
As an example.
For instance, we set instance number to a public.
one.InstanceNumber InstanceNumber equal four,
we actually get an error immediately.
Cannot assign a value to final variable instanceNumber.
So it's actually a good idea to mark variables as final whenever you
know that the value shouldn't be changed once the initial value's been set.
And a constant value Would be an ideal candidate for that.
That said though, you may be used to seeing constant values in Java you have
done some coding before declared using static final and that is more normal for
constant, our instance number here going back to the code
was not being treated as a constant because we didn't want to assign its value but
we only wanted to assign it once and we didn't want it to change after that point.
And that is also why we didn't use uppercase for the variable name
If you remember from the discussion on naming conventions,
constant variable names should be in upper case.
So why are constants declared a static final?
Well the reason is that if the value really is a constant and won't change,
then it doesn't make sense to store a copy of that in every single class instance.
They all hold the same value so
it makes sense to store it only once at the class level.
So hence, values that are constant are usually declared using static final.
We can see examples of this right throughout the Java framework.
One example is in the Math package.
So if we go back to our main method.
And I'll just out that error.
We could do something like print out math
using the Java Math library.pi.
And that's pi in uppercase there.
And if we just hover over that and have a look, public, static,
final, double pi you can see there and it's obviously got the value of pi.
So it's declared as a public static final double.
So it's usual to assign the value of static field variables at
the time they're declared but again they can be done after in a similar manner
to non-static final fields and we'll see that shortly.
First, though, we'll stay with the Math class,
because we want to have a look at another use of final, so
what we're going to do is we'll just make a little bit of a change here,
to create an instance of Math so we can do some sums.
So, we're gonna type after that line, Math m equals new Math.
Oh dear.
Unfortunately that doesn't work, and we get the error.
Math has private access in Java.Lang.Math.
So, we just hover over that.
So, if we right click on that now to go to the class declaration Declaration.
You can see there, there's actually a comment above the code.
And it says, don't let anyone instantiate this class.
And so the reason we're getting that error is the constructor has been
marked private.
And that's to prevent, as you saw in our code
instances of it being created and the reason I did that in the next class
is all the next Math class' methods are static as well and they are all
available without requiring instance. So to make that clear and to actually enforce it,
the creators of this class, the math class, made the constructor private and
that prevents any instances from being created. Now, ah! you might think,
I can get around that by creating a subclass of math Which I can instantiate.
Unfortunately or actually fortunately, creators have thought of this as well and
have stopped you from wasting your time by declaring the Math class up here as final.
So, by marking a class as final,
applying that to a class, it prevents the class from being sub-classed so
any attempt to extend Math will fail because it's been marked final.
So just to confirm that.
Try extends math and you are going to get an error.
There is no default constructor available and that also has to do with the fact that it
is only when you have got a private instructor.
So I'm just gonna undo that.
The bottom line is that anyway by marking a class as final,
you can prevent your class from being subclassed.
Now its possible that you might wish that a class you're creating to be extended or
subclassed, but you might have one or more methods that are crucial to the correct
operation of your class But you don't want just those to be overridden.
So, in that case, marking the methods as final will prevent them
from being overridden, even if you do allow the class itself to be subclassed.
So, just to demonstrate that, I'll close down this Math.java now, and
we'll create a new class.
We'll call it public, we'll call it password.
And I'll just close down the wrong window.
So, let's firstly create a static final int key.
Key equals 748576362, could be any number.
Private final int encrypted password.
We'll create a constructor, and we'll pass the password in.
What we'll do is we'll also have an encrypt function so,
the password would come in just as a password and encrypted and
move our function to encrypt the password so
So I'm writing a function that will encrypt or decrypt and
then save it into the encrypted password, which is encrypted at that point.
And let's do something really simple there with the encryptDecrypt.
This is just an example.
Private int encryptDecrypt setting a parameter of the password
And, which return password.
key.set.
And, that's using an XOR to XOR the values there.
And, then we'll store the passwords so we need another one, more public.
public void
storePassword
Saving password as
This dot encrypted password.
Sorry, encrypted password.
And we would test it to confirm, or to check whether the password's valid.
So I'm gonna type public.
public boolean letMeIn which accepts a password as a parameter.
Then we will put if encrypted-- encryptDecrypt
password is equal to password on file.
Then we will print some sort of welcome message, welcome return true,
else "Nope you cannot come in" return false
And that should have up there, that shouldn't change,
that should be just password.
We're passing the unencrypted password to the encryptDecrypt method.
So, the encryption, as I mentioned,
is a very basic XOR Which just checks the bits in the two values and
returns a 1 in any position where there is a 1 in only one of the values.
So if you apply the XOR operation to the result you get back your original value.
It does have applications in the field of cryptography.
Although used in a much, much more complex manner than what I've done there.
So in main, go back to main now.
Get rid of the other error
I am going to create a new password instance, called storePassword so
we are going to put password equals 674312 equal
Password password= new Password (pw).
Then we'll put password.storePassword.
So if you run that Saving password as 747902050,
and of course that's completely different to the number that we passed to it.
Now this is an example of why you'd want to prevent one of your methods
from being overwritten, not as an example of how to encrypt storing in a database.
So cryptography is a very complex subject.
And I would strongly advise you to use an existing cryptography library, if you ever
really needed to encrypt passwords or anything else for that matter.
By all means, write your own cryptography library once you've completed [LAUGH]
a PhD in the subject, but until then don't be tempted.
Trust me on this one.
So anyway, getting back to our example,
the constructor getting back to our code So the constructor takes the password and
encrypts it as you can see and encrypts it setting a field storing the encryptability
so that can be checked when the user attempts to log in.
So lets call the letMeIn method, with a few passwords to check to see if it is working.
So I came back down here Now, main, so, we stored the passwords,
we'll now see if we can, get in the password.letMein 1.
password.letMeIn 523266
And this makes this a bit easier for copying.
We'll try another one, 9773.
Try another one, maybe 0.
-1.
Then we'll do our correct currently 674312.
So if we run that, we should get an error on all of them other than the last one.
Nope, you cannot come into the first five, and then the last one Welcome,
we're able to get in because we specific the right password.
So you can see that work and the last example correctly logged us in.
The first five entries, the first five passwords we tried all failed.
But the problem actually comes if someone overrides the stored
password method in the sub class.
So I'm gonna end the video here, but in the next video we'll extend on from that.
And talk about the problems, and want to actually create a new class that extends
from this one, and show you how to get around the issues that will come up.
So, see you in the next video.