Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Well done!
You have completed Java Data Structures!
You have completed Java Data Structures!
Preview
Have you ever wanted to save an object for later after the program is done running? Well, this is called serialization. Let's explore one of the oldest methods of serialization available to Java.
Resources
Workspace Editor Shortcuts
- Highlight lines: [Shift + ↑] or [Shift + ↓]
- Comment selected lines: [⌘ + /] or on Windows [Ctrl + /]
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up
Serialization, in this context,
is the process of translating objects
0:01
into a format
0:05
that can be stored and recreated later
in the same or different environment.
0:06
You can sort of imagine this concept
as pushing a save button on an object,
0:11
and you can view deserialization
as the process of opening that object
0:15
again at a later time, or even giving it
to someone else for them to open up.
0:19
Now there's lots of ways to serialize
data.
0:24
These days, JSON, or JavaScript
Object Notation, is all the rage.
0:27
And there's XML, which we'll be very
familiar with here in the near future.
0:31
You can store this in a database
using an ORM, or Object Relational Mapper.
0:36
And there's just the straight byte rate
serialization.
0:40
We'll look at this
0:44
basic version as it's pretty easy to use,
and you might run into it in the wild.
0:44
So remember, what serialization,
also known as marshalling, is doing,
0:49
is taking an object
and storing its representation in a state
0:53
that can be loaded or deserialized
or unmarshalled at a later time.
0:57
Now the
1:03
ability to be serialized
doesn't come out of the box.
1:03
It requires that the object implements
the serializable interface,
1:07
which doesn't have any required methods.
1:11
It's just used to mark
the class as being able to be serialized.
1:13
This type of interface
is known as a marker interface.
1:17
Now let's go mark our movie class.
1:20
Okay, so I'd to be able to press
1:23
the save button on that array of movies
that we've been working with.
1:25
So in order to do that,
let's explore how to serialize movies.
1:28
So first things first,
we need to implement the marker interface,
1:32
serializable.
1:35
To make a class implement
multiple interfaces,
1:37
just simply separate them with commas.
1:40
In order to do so,
we need to import the interface.
1:44
It lives in the
IO package for input output.
1:47
And that's all you
need to do to make a class serializable.
1:52
So now, let's make a new helper class
that will allow us to save
1:54
and load these movies.
1:58
Let's call it movies.java, plural.
2:00
We'll put it in the same package.
2:03
Okay, so let's put it in the package.
2:09
So again, that's package,
and you do com.teamTreehouse.
2:10
And we're going to use a bunch of imports
from the java.io package here,
2:16
so we can simply put a star,
or asterisk, here
2:19
and it will import everything
that we need.
2:23
Now this is usually frowned upon
2:32
as being lazy and indeed it is.
2:34
And in most IDEs it will do the imports
for you, so yes, that's lazy too.
2:37
Okay so let's create the class.
2:42
Public class movies.
2:44
So let's make a static method.
2:49
And what static means is we will not need
to have an instance of this class
2:51
to use the method.
2:55
It won't return anything,
so let's say void, and we'll call it save.
2:57
And it will take an array of movies.
3:01
And let's just name it movies.
3:04
Cool.
3:06
In version 7 of Java, a new feature
3:08
called try with resources was introduced.
3:10
It'll clean up
any resources used in the try block.
3:13
Let's use it, and I'll explain afterwards
what it's doing.
3:16
So we type try and it uses parentheses.
3:20
One way in Java to create
a file is to open a file output stream.
3:23
So you say file output stream.
3:27
Typically their variable names
are the uppercase letters so
3:31
it's FOS.
3:40
It takes a parameter and that parameter
is the file name and it's relative to
3:40
for the code that's being executed.
So let's just call that movies and we do
3:44
SER for serialized. Cool. Now object output
stream
3:49
is what we use to serialize
our array Its parameter is a stream.
3:53
So object output stream follows the same
3:57
naming convention, OOS.
4:00
Equals new object output stream
4:03
and it's going to take FOS.
4:06
Typically,
4:11
you'll see this new file
output stream pushed into here,
4:11
but I just wanted to put it separate
so that we could see what's going on.
4:14
So we'll end the try with resources
block there,
4:19
and then we're going to open up the code
that we're going to call.
4:21
So it's really simple, actually.
4:24
The object output stream provides
a way to take representation in memory
4:26
and write out its binary representation
using a method called write object.
4:30
So that looks like this.
4:35
OOS, which is our object
output stream, write object.
4:37
And we're going to pass it
what was passed in, those movies there.
4:41
And that's all you need to do.
4:45
Now, it does throw an exception,
so let's catch it.
4:46
It throws an IO exception,
which was imported
4:50
along with that star import we did.
4:53
Let's name it IOE.
4:55
And let's just
4:58
go ahead and say that we had a problem
saving the movies.
4:59
And we should probably provide
a detailed error message to someone
5:03
trying to debug this.
5:06
So every one of these exceptions has this
great method called print stack trace.
5:08
Using this gives a nice looking error
that gets presented
5:13
if we have a compilation error. Great.
5:15
So when this try block is finished,
the streams are closed for us.
5:19
Prior to this being implemented,
it was always the cause
5:22
of huge problems in a thing
called resource leaks.
5:25
It required to close streams up,
5:28
and this is usually done
at the end of the try block.
5:29
So you might see something this.
5:32
No need to follow me here.
5:33
Try blocks have a keyword called finally,
and no matter what happens up
5:35
here, this block of code will run.
5:39
And you might, in the past,
5:41
have seen something this.
5:43
OOS.close.
5:46
But there's a bit of a problem, right?
5:48
Because OOS might not have been defined
properly.
5:50
So you'd have to say something if OOS is
not equal to null, then close it.
5:53
Anyways,
that doesn't need to happen anymore
5:59
because of the try with resources block.
6:01
So again, what's going to happen
is it's going to come in here,
6:04
we're going to create a new file,
6:07
and we're going to pass that file
into this object output stream.
6:09
It has a write object method,
which will write out the movies.
6:12
So let's go use it. Let's save this file.
6:16
Okay, so we need to import the new class
that we just created.
6:18
And it looks very similar to this line.
6:22
Okay, and because we made the
method static, we can just use the class,
6:26
we don't need to create
an instance of this movies class.
6:29
So let's go down here where this array is.
6:33
Let's just save this.
6:36
So we'll say movies.save.
6:37
So that's the static method
and we'll save all movies,
6:40
which is our array up here.
6:43
Cool, let's compile and save it.
6:50
Oh boy, what did I do now?
7:01
Looks I misspelled print line there.
7:04
What's all this though?
7:06
Oh wow.
7:08
In the midst of my rambling
about the star import being lazy,
7:10
I completely forgot to write the import
keyword.
7:14
This just goes to show
that we all make silly mistakes sometimes.
7:17
Or most times, if you're me.
7:21
Let's add in import here.
7:24
That'll fix all those cannot find
symbol errors we had.
7:26
and I'll spell print line correctly.
7:30
Man I bet you have all just been waiting
for me to run this one, huh?
7:32
I hope that you're learning a bit
by seeing me deal with these errors.
7:36
That why I to leave them in. Or I hope
you're at least getting a laugh out of it
7:39
Okay, let's try that again.
7:43
There we go.
7:51
If we right-click over here and choose
Refresh, we'll see that there's a new file
7:52
called Movies.ser right here.
7:56
and if we click it we'll see that
8:00
there's no preview available
and that's because this is a binary file.
8:02
Let's use the cat command
to check that out. So it's cat movies
8:06
dot ser. Cool so that's the machine
8:09
trying to suss out what those bytes
we wrote mean.
8:13
Well now I suppose we should have a way
to load a saved version of these movies up
8:16
right? So let's go back to the movies class.
8:20
So this is basically just the same code,
just the other way around.
8:26
Let's make another static method
8:30
that returns an array of movies
and takes no parameters.
8:31
So we'll say public static returns
8:36
an array of movies,
and it will be called load.
8:39
Let's initialize
8:45
movies into an empty array,
and we'll just return movies.
8:46
Just in case things go horribly wrong,
we're going to be at least meeting
8:50
our requirement
of returning a movie array.
8:53
So now, in between here,
9:00
let's do our try with resources
block again.
9:01
So we'll say try,
9:07
and in here, it's a file input stream
9:09
instead of the output stream.
9:12
so new file input stream
9:16
and you put the name of the file
9:18
that's going to open up the stream to that.
9:24
And we'll say object input stream,
ois, new object input stream.
9:26
Basically exactly the same in reverse.
And we'll pass in fis.
9:32
Now there's a method on the object
input stream called
9:37
read object and it returns an
object just we talked about.
9:40
So let's cast it to our movie array.
9:44
So let's say movies,
9:49
which we defined above already,
9:51
is equal to ois.readObject.
9:56
Okay, great.
9:59
And this also throws an exception,
an IO exception,
10:01
so let's catch that.
10:05
And let's do the system.out.println error
10:11
reading file.
10:15
Let's use
10:21
our handy-dandy stack trace method
that we learned, IOE.printstacktrace.
10:21
Okay, now read object
actually throws two possible errors.
10:26
There's another one called class
10:31
not found exception,
so let's put that in there too.
10:32
It's also covered by our import star.
10:37
Let's just go ahead and say that
10:49
there's an error loading the movies.
10:51
And we'll do cnfe.print stack trace.
10:55
then finally we'll return the movies.
11:01
So there can be multiple exceptions
that go in order as you go down
11:04
and it'll catch them for us. So again,
we're just reading this
11:07
and we're returning the movies array
11:11
and it will always return
something, we'll never return null.
11:13
So now if we come back to our example
file, let's use the new load method.
11:16
and we say movie,
11:22
loaded movies, equals movies.
11:26
Let's print them out
so we know it's working.
11:33
We'll say movie, loaded, in loaded movies.
11:35
And we'll just print loaded.
11:43
Cool.
11:51
So now I'm going to highlight
all of this code.
11:53
I'm going to comment out all those lines
except for our new lines there.
11:55
So that way we know it's loading that
and not just printing this stuff up here.
11:58
So let's go ahead and run our code again,
and this is going to read from that file
12:03
this time.
12:06
Awesome.
12:12
There it is. They came back.
12:13
So now we have a way to serialize
and un-serialize movies.
12:15
Now for one final best practice
for object serialization of this type.
12:19
So we have saved
an instance of this class.
12:24
But what happens if the class changes
and we try to load it up?
12:26
Well, we can test that right?
12:30
So let's go over back to movie.
12:32
And let's just add a new variable here.
12:34
Let's do it above genre here.
12:36
Let's say private string m director.
12:38
So we've changed
the class from how it was serialized.
12:42
So let's see what happens.
12:44
Here we go.
12:54
It says invalid class exception.
12:54
com.teamtreehouse.movie
local class incompatible.
12:57
And wow, it's
got a bunch of serial version UID numbers.
13:01
Well, this is a common enough problem
that there's a workaround.
13:06
So once you have your class in a more
or less finished and stable state,
13:09
you can run a special Java tool
on your file to generate a version number.
13:13
If you serialize your code
with this version number, as long as on
13:18
deserialization they match, it'll work
no matter how much the class has changed.
13:21
So let's do that real quick.
13:26
Let's return our class
to its normal state.
13:27
And just go ahead and run this.
13:35
Okay, great.
13:42
Now let's run the program.
13:43
The program's called SerialVer,
and you give it the name of the class,
13:45
not the name of the file,
the name of the class.
13:48
So we'll do that.
13:51
And what this will do is
13:53
it'll generate a code
that you need to put into your Java class.
13:54
So let's put this SerialVersionUID
into our class.
13:58
So I'm going to highlight
that and Command or Control-C to copy,
14:02
and I'm going to paste it right up top
here.
14:06
This is of type
14:13
long, see the L at the end there?
14:14
And now we should run the code.
14:17
I'm going to come back to example
and I'm going to make it
14:20
so that we save the code again,
so that we save it with that serial
14:22
version.
14:25
Great.
14:35
Now I'm going to come back here and we can
now break it again with director,
14:36
now that it's been serialized properly.
14:40
And so the file has been saved
14:47
with that version number in it,
but we've made a change since.
14:48
Okay, so that director variable's back.
14:51
Let's run it one more time.
14:53
And it works.
15:00
So, by
default, that code is generated for you,
15:01
but the best practice
is to define it yourself once your dust
15:04
settles,
and your code has been stabilized.
15:07
So there you go.
15:10
Welcome to the very fragile
world of serialization.
15:11
You need to sign up for Treehouse in order to download course files.
Sign upYou need to sign up for Treehouse in order to set up Workspace
Sign up