1z0-808 Oracle Java SE 8 Programmer – Encapsulation
- Section Overview
We’re now going to turn our focus to the concept of object-oriented programming. Now, of course, we’ve been doing object-oriented programming all along, but we’re going to really focus on the pillars of object oriented programming. In this section, we’re going to focus on Encapsulation, and we’re going to see specifically what is Encapsulation, why do we want to do Encapsulation, and how do we apply it to the Java programming language.
- Encapsulation and Data Hiding
The term encapsulation is often used a little differently depending on who you speak to. There are really two terms that are kind of that go with each other encapsulation and data hiding. And because they’re so frequently used together, people will often use them interchangeably, although they are really two different things. Encapsulation is strictly just the technique of bundling data with methods that operate on that data app. So an object is encapsulation, but data hiding is this idea of how the object should be accessed. And specifically, we prohibit the data of the object to be accessed directly. Instead, we provide these methods, the encapsulating methods, and depending on what we expose, other clients, other users can then access the data through these methods. They can either read the data or set the data, depending on what rules we’ve established.
And the way that we establish rules are through access modifiers. Now, there are four, but there are well, really, there’s only three words keywords, that we can use as access modifiers. And then there’s a fourth, which is the absence of a modifier and what that means. But the two most popular are public and private. And public simply means this piece of code can be accessed anywhere. So if we’re running a program and we try to access this piece of code, it’s available, it’s public. If we say private, then we mean this is only available to the class itself. And that is different than saying it’s available to the object that’s been built on this class. So it’s literally only available inside the class itself. And we’ll see some examples to help solidify this concept.
So the idea of encapsulation and data hiding is that the data we have in our objects are going to be hidden and we’ll hide them by using the private access modifier. And then we’ll create some public methods to expose that data in any way that we see fit. Now, let’s take a look at the My Date class that we’ve been working on and see how encapsulation can help improve the quality of our program. So when we don’t have encapsulation, which, by the way, we don’t have at this point, the class is going to look something like this. Now, we’ve cut out some of the methods, but just looking at the data, we’ve got a publicant day, publicant month, publicant year. They’re all public, which means the day, the month and the year can be seen and manipulated by any code in our program. And if you remember, when we did the lab for the packages, we felt like we had to do that.
We were trying to access these fields from another package. And so in order to make them available to that test code, we had to make these fields public. And all of a sudden, all the code worked and everything was fine. When you first start programming, this feels kind of natural. Of course I want all of my code to be available to the other parts of my program? Why wouldn’t I? Well, let’s see what can happen. So first of all, someone decides to use the My Date and they use it correctly. They create a my date object. They set the day, they set the month, they set the year, and everything works great. If we run this program and we use the date, it’s being used exactly as we intended, no problems there. But now someone else creates a date that doesn’t actually make sense. They’re creating this leap day. It’s February 29, 2017. And the problem is that the 29th doesn’t actually exist. Like, here’s another example. Here’s a February 1999 calendar. There’s no 29th there because that’s not a leap year. So what’s the problem?
Well, if we’re trying to mimic the real world with our objects, if we create some kind of a class that can be used in a way that breaks the rules that we’re trying to follow, that is in this case, valid dates, we’re not really mimicking the real world and we’re not achieving our goal. Other things that could go wrong, someone could decide, well, I’ve got a day and I want it to go to tomorrow. So what are they going to do? They’re going to increment the day. So they do a day plus plus. Now, if today’s date is February 7, that’s fine. If you do a day plus plus, then it’s going to say it’s now February 8 and everything works correctly. But what happens if we’re at, say, January 31 and you do plus plus? Well, to the JVM, a day is just an end. It’s a 32 bit number that has a range from a negative value to a positive value. And so when you say day plus plus, it doesn’t think, wait a second, that’s not a real day. It just doesn’t. And so at that point, our date would be January 32, 2008.
And imagine if it was December, then it’s completely screwed up because we really are trying to get to January 1 and whatever increment the year, in this case to 2009. So what we see is that when we expose the data that people can use and set the data in a way that really wasn’t intended. So we’ve got a validation issue when people access data directly, but we have other issues as well, namely flexibility. Imagine that we think about, well, imagine that a lot of people are using the My Date object, and we’re finding that it’s using quite a bit of memory. So the question we are asked is, do we really need an int to store that day and month? I mean, really, how big can a day and a month get? We’re talking for a month between the numbers of one and twelve.
An int is a 32 bit number that’s overkill. So what if we decide to change it and we go into our class and we say, yeah, we hear what you’re saying. Let’s change the day in the month to be a byte, an eight bit number. I mean, that’s still going to go all the way to 127 on the positive side, which is more than enough that we need. So we make that change and we put this code back into our code base. All of our teammates download the new code and they try to compile their program and it breaks. We’ve broken everyone else. And how did it break? What happened? Well, imagine that someone is creating a date and they had said previously, arm dot day equals eleven. Arm dot month equals eleven. That worked fine. That was legal.
The problem here is that we, what is the literal type of eleven? The literal type of eleven is an int. And then we’re setting this arm day to be an int. We’ve just changed day to be a byte. Same thing with month. Now, a 32 bit number cannot be stored in an eight bit variable without casting, right? And since no one had written casting code before, all of their code just broke. Now, you may remember that I said if we do something like byte B equals eleven, that that would work. So byte B equals. Eleven. Sure, that would work. Because we are declaring the variable and initializing it all on the same line. And so it does sort of this implicit cast that’s different than what we’re seeing here. We are not declaring the variable. The variable already exists. It’s already been declared day and month. And so when we try to set an integer value to the byte variable, it’s not going to let that happen.
- Getters and Setters: Part 1
We’ve seen that allowing direct access to the data from anyone using an object of the class is really not a good idea. In general, what we want to do is we want to make sure we’re not having any issues of validation, any issues in terms of our own flexibility for making internal changes. And the best way that we can do that is with encapsulation. So Encapsulation hides the deep detail of how things are getting done. And what we’ll do instead is we will expose certain methods and those methods will be referred to as the interface of the class. That’s what everyone else is going to be able to interact with. Now later we’re going to talk about a construct called an interface with a capital I, I guess. And that interface has similar functionality, but it’s different than what I’m talking about here. I’m simply saying that when we design a class, anything that we set as public is the public interface of the class. Those are the methods and the variables that we’ve exposed to anyone that wants to use an object of this type. So we can use accessors and mutators to create this interface of the class while we hide all the data details. Now, Accessors and Mutators are more commonly referred to as Getters and Setters. And that’ll be pretty obvious why once you see the code. So here is the code.
Once we’ve applied encapsulation and data hiding, first thing to note is that all of our instance variables are now private. All right? So we’ve got our day, month, year, we’ve got a bully and leap year. They are all private. And then what we do is we create our getters. Now this syntax, and I’m showing you this comes from, or at least is used by something called a Java bean. You might have heard of this term before. A Java bean is different than an enterprise Java bean. So it’s a totally different construct. A Java bean is really a simple class that has some private fields and then getters and Setters. There are a couple of other rules regarding Java beans. If you want to be very strict, you can’t extend any other class. There needs to be a default constructor. But in general, this is what a Java beam looks like. So our getters are what exposes the data. If someone wants to actually look at the day, the month year or leap year, we use the get method.
So Get day, get month, get year. Notice that none of these methods take any parameters and then they just simply return the type that the user has requested. Whenever we’re dealing with Booleans, we use a slightly different naming convention. Rather than Get leap year, we say is leap year, which just makes a little more sense. Setters are a little bit different. So this is how the user can manipulate the data. So we’ve got set methods for set day, set month, set year, and so on, set leap year. And they accept one parameter and that’s going to be the new value. Now, the reason we’re using setters, instead of just allowing them to access the data directly, is that now we can run all of this code through some sort of validation. So you notice here that what we’re doing is we’re checking, we’re saying, hey, they’ve given us a day in the Set day method.
Let’s make sure that this day is still valid with the current month and the current year. And if it is, great, then we’ll set it, and if it’s not, we won’t. One other thing about the naming convention that we’re seeing here, and again this is the naming convention of Java Beans, is that we’re using Lower Camel case. Going to jump back to where we can see the variables. So we’ve got all lower case day, month, year, and then lower camel case, leap year. Notice that our getter methods apply lower Camel case as well. They start with the word get and then they capitalize the name, the type. So we’ve got get day with a capital D, get month with a capital M and so on is leap year. We’ve got a capital L and a capital Y. Same thing for the setters. Set day, set month, set year, set leap year, they’re all lower camel case and that is the naming convention to follow. So here we’ve got our valid month method. And feel free to pause this screen and take a look and see if you can figure out what it’s doing. I’ll tell you, at this point, that’s not what is important. The important part is noting that we are able to create a method and we can then validate what people are passing into us and prevent them from giving us bad data so no one would be able to accidentally create a February 29 when it’s not actually a leap year, for example. Also notice that this method is private.
So here’s kind of a general rule that I always follow when I write code. I make everything private. I just start with a completely closed off class. And then as I start to add more functionality, I think, what do I really want to be exposing at this point? And then those methods I turn public. Now, with this valid method, I don’t really have any reason for anyone outside of the class to use this. This is private for me to determine whether or not I want to allow someone else to set the day to set the month or set the year. But maybe at some point I don’t want to use this valid method anymore. I can just get rid of it if it’s private because no one else would be using it.
And that’s one of the other rules that we want to follow when we’re coding is when we create a method, when we create something that’s public, I should say that anyone could be using. We do not want to get rid of it as much as possible because as soon as we get rid of something that’s public, we’ve probably broken a lot of code that others have written. So there’s a general rule that types should be open for extension, but really shouldn’t be open for modification. And what they’re saying is don’t remove stuff that people are using. Don’t change the signature of a method if someone’s already using it. Obviously there are times where that’s just not possible. You have to go in and make changes. But we really want to reduce that as much as possible.
- Getters and Setters: Part 2
Granted, now that we’re employing Encapsulation, our classes are going to be a little bit bigger. But it’s worth it. Trust me, it is absolutely worth it. Let’s just once again remind ourselves that of what we can and can’t do. So if we set all of our fields to be private now when someone instantiates a midday class, let’s say they called it D, that they will not be able to read or set the variables directly. They won’t be able to say D month equals twelve. That’s illegal. It’s not even going to compile. What we are doing though, is we’re forcing them to use the methods, to use the interface of the class that we are exposing them to, which in this case is the method Set month. So now they pass in the number twelve and we can employ our validation logic. We can actually check to see if it’s okay, and if it’s not, we don’t have to set it. We can’t really make that same kind of stop when they’re setting the data directly. It’s just setting the value. If we can legally say D month equals twelve, there’s no way for us to get in between there and say, well, let me check it first and then we’ll see if you can do that. But we can do that with a method.
So that’s one of the reasons we do this. We make sure that what they’re giving us is valid. And also we now have the flexibility to change the inner structure of our objects. So I can go in and I can change all my day month to be a byte. And what we do at that time is, remember I said a best practice is really to let’s leave those methods alone. That we’ve set are public, other people are using them. But we would have that problem, right? If we change the date and the month to a byte, if they try to set the day or the month with an Int, which is what they have been doing, it will break. We saw that earlier. But what we can do now is we’ve got the Set day. They give us an integer the day we run it through our validation to make sure it’s okay. And then at the very end here, we’re casting, we’re taking their Into day, casting it to be a byte and setting it. And that’s legal and good.
Same thing here. We’re taking their Into month, they passed in casting it to be a byte. And now we can set it to our new data type, which is a byte. And that makes a lot of sense, right? It makes much more sense for us to fix the code in one place than to simply break everyone else that was using this class and expect them to fix it in the hundreds or thousands of places that they were using it.
Now of course, some matador methods, some Setter methods will not fit the mold of what we’ve done here so far. Remember, we had this day plus, and we said that that could produce an invalid day. Well, what kind of method could we create to allow the user to do what they were trying to do here? And, well, we could make a method called tomorrow. And here, when they call tomorrow, we’ll double check to see if we should increment the day or if we should reset the day to one. Should we increment the month, or should we reset the month to one? And then we can increment the year, if that makes sense as well. So you can make any methods in addition to the getters and setters that we’ve shown, as long as it supports the class.
- Access Modifiers
All right, now let’s review what access modifiers we have available to us. So if we’re going to do encapsulation, we have to limit some of the parts of the objects, and we do that through access modifiers. Now, in the mydate example, what we did is we took all those instance variables and we changed them from public to private. And private means they’re only available to the class itself. We can add access modifiers, really to almost any part of the class definition. You can do it on not just instance variables, but static variables. Static or instance methods, constructors even the class itself. Although there are some rules for a top level class in your file, it can only be public or the default, which I’ll show you what that means in just a second. But really only those two access modifiers are available to the class itself. So let’s look at the different access modifiers. Here’s a table of the ones that we have available, and I’m really only going to focus on three of them right now.
In the next chapter, we’ll talk about inheritance and then we’ll talk about the fourth modifier at that time. So the three I want to focus on are public, private, and default. Whenever we have the modifier public, it means that access is not limited. Any code in our program can either read. If it’s a field, they could read it, they could set it. If it’s a method, it can be invoked. It can be invoked from anywhere. Private is the most restrictive and it just says that absolutely nothing can read, change or invoke this member unless it’s being called from the class itself. And then the final type here that I’m going to talk about is just called default. Sometimes you’ll hear it referred to as package or friendly. Basically, it means the absence of a modifier. And let’s look at some code so I can show you what I mean. So this represents the state of our My Date class as it exists right now.
And we set everything to be public so that any code could access it from anywhere. And we did that in our lab because we had some test classes which were in different packages and we wanted that code to be able to see and change these fields. But before we had that, we really didn’t have any modifier at all. It really just said int day, int month, and int year. That’s what I’m referring to when I talk about the default access modifier or the package or friendly.
So anything that doesn’t have an access modifier is assumed to be available to the class itself and any classes that are in the same package. If we change this to private now, we are only going to have access to this code in the class itself. And it seems like a simple concept, but I want to further define this. Let’s make some public methods. I’m just going to make one public int get day and we’ll return the day. So I’ve got a private int day for my field and a public method to call it. Now let’s go into another class. It happens to be in the same package and I’m just going to give us some space here. Ignore everything that’s below and let’s instantiate the day that we just create the My date. So I’m going to say My date D equals new my date. This is I think, the first part that confuses people when you’re first learning Java. There’s this feeling that my date D is actually the My date object. So I should be able to say D day equals twelve. And of course I can’t do that.
You can see that I’m getting an X. And the reason that we can’t do that is if we look at the My date day is private, I can only access this field in the class itself as I’m doing right here on line nine. I’m accessing that private field and that’s legal because I’m in the class itself. But in my course examples here, I’m not in the class itself. I am in a completely different class. So I don’t have access to day. And I think the reason that’s confusing is most people start to think of D as being the object itself. They’re saying, well why can’t the object access its own day? That seems odd, but that’s not in fact what’s happening. The value of D is a reference to the My date object and that’s why I use that analogy of a telephone. So we pick up the telephone and that dials the object that D is pointing to and then we say, listen, we want you to set your day to be twelve.
And the object says, okay, but where are you calling from? And we say, well we’re in course examples, we’re in the same package as you, but we’re in a different class. And then the object on the other end of the phone says, sorry, unless you’re in the class itself, I’m not going to allow you to change that. So that’s why I like that telephone analogy. It helps us understand access modifiers and the rules a little bit better. Of course I can call D get day because that is a public method that’s completely legal. So those are the three access modifiers that we’re working with so far public, private, and then just sort of the default package level, which means it’s available to the code itself. In fact, I’m going to just put this back one more time to D is day. And I’m going to show that if I get rid of this whole private here, now we have the access modifier of default. And in my example it’s legal because we happen to be in the same package.
Now most people are pretty much going to stick with public and private for the access modifiers, but especially if you’re taking the exam or if you’re writing some more complex hierarchies and structures of your code, you may want to use some of these other modifiers. There is one modifier we haven’t looked at yet and that’s protected. It’s going to make a lot more sense after we look at the next section because it’s tied to the concept of inheritance. But let me just tell you what it is. I’ll show you what it looks like and then we’ll revisit this modifier in the next section. So if I jump to the my date, I can change the access modifier to protect it. And so here is a protected day. And what that means is that this varies day is available to the class itself, it’s available to any code in the same package and it’s also available to any subclass that’s in any other package. And there’s a few little fine points to that last rule. So I’ll show you that a little bit later when we start talking about inheritance.
- Encapsulation Lab
Now we can start improving the quality of our code. And what we’re going to do is encapsulate our classes. So we will be working with access modifiers, we’ll be working with the idea to help us with encapsulation. We’ll generate, getters and setters and so on. And all the instructions are in the resource section for this lecture. The name of the file is lab eight, encapsulation and it’s a PDF download. That all. The solution code is at the end if you get stuck, and let me know if you have any questions.