The topic of Java Serialization is an interesting one, and can almost be thought of as a stepping stone for learning the concepts of a database.
What is Java Serialization
Well, it's really as simple as storing an Object (either in memory or in some sort of file or database) in a ‘simple to read' fashion. Now when I say that it's easy to read, I mean that it's easy for a computer to read the Object, not you or me. What actually happens is that Java will look at your Object, which could have a complicated structure, and turn it into a big ordered stream of bytes.
Okay okay, I know, it's boring and complicated talk, so let's see what I can do to make it easy to understand. First, let's say we want to serialize a User
Object. You've seen examples of a User
Object before, they generally have a username and a password right? So, let's say we have a User
declared and populated with a username and password. Now we want to store that in a file so we can turn off our Java application, and then boot it up again later and retrieve that User
. This is how serialization is helpful.
Picture this…
Without Serialization
- You start your Java application in your IDE (via right-click -> Run As ->Java Application)
- You create a
User
Object - You populate that
User
with a username and password - Your Java application ends
What happens to that User
Object you so tediously created and populated with values? Well, it's GONE! Once your Java application ends, it frees up all the memory that was in use and POOF that includes your User
. Well that sucks. You probably wanted to keep that User
information
With Serialization
- You start your Java application in your IDE (via right-click -> Run As ->Java Application)
- You create a
User
Object - You populate that
User
with a username and password - You write your
User
Object to a file using Serialization - Your Java application ends
What happens to that User
Object now? Well, it's not in memory, because Java has cleaned that up when the application ended. BUT! It now exists inside of a file that is stored on your actual computer's hard drive! Holy crap! That's neat! Now if you write a little more code, you can actually read that file and re-create that User
Object when you fire up your Java application again.
Powerful stuff people
The implications of this topic means that you can now magically store all of the information that you previously had in your Java application while it was running. This is exactly the same kind of basic functionality that you would get from a database, which opens up a lot of doors with what kinds of applications you can create with Java. Now, I will say that using an actual database makes a lot more sense when you start getting into applications that you would create and sell to people, but if you just feel like creating an application that will only be used by yourself or a select few people, then this may be just the ticket :)
Let's see some code. We want to make our User
Object serializable, and in order to do that, we just need our User
Object to implement the Serializable interface. Do you still remember what that means? An interface deals with inheritance, which I talked about in this post. So that would look something like so:
import java.io.Serializable;
public class User implements Serializable
{
private static final long serialVersionUID = 4415605180317327265L;
private String username;
private String password;
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
}
Okay, so we've seen this kind of code before, except for two things. We've implemented Serializable
(which is an import from java.io.Serializable
), okay that seems pretty straight forward. But you may also see that there's a line that says:
private static final long serialVersionUID = 4415605180317327265L;
What's that all about!? Well, this is used for version control purposes. First of all, if you're using an IDE, then you will most likely be able to have the IDE generate this line of code for you. Seriously, you won't even have to do anything more than hover over the name of the class (in this case User
) and click on the “Add Generated serial version ID” or something to that effect. Okay great, but what does it mean!?
Well like I said it's used for version control. Here's an example that will help shed some light. Consider this:
- Create
User
Object - Populate it with a username/password
- Serialize the Object and store it in a file
- Stop your Java application
- Change the
User
Object code, and remove the password property and instead add a first and last name - When you make a change to the contents of an Object, you need to re-generate your serialVersionUID, so delete the existing one, and re-generate the code using your IDE
- Start up your Java application
- Try to read your stored
User
Object from the file from step 3 - You'll get an error stating
InvalidClassException
You get this error because the serialVersionUID of the Object that was stored in the file is now different from the one you're trying to read it into. Remember, you removed the password and added first/last name to your new User
Object. So the Object stored in the file had a password, this new Object doesn't. So since this is the case, Java will automatically throw the InvalidClassException
exception, and you'll need to decide what to do to handle the situation.
This topic of version control/safety is a fairly complex one that has to do with databases and storage mechanisms, so I won't go into any more detail.
Full Example
Alright, now that you know how to enable the User
Object to be stored (serialized), let's see how we actually store this thing!
package com.howtoprogramwithjava.runnable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import com.howtoprogramwithjava.business.User;
public class MyProgram
{
public static void main(String[] args) throws IOException
{
User user = new User();
user.setUsername("tpage");
user.setPassword("password123");
File file = new File("C:\testFile.txt");
OutputStream fileOutputStream = new FileOutputStream(file);
ObjectOutput outputStream = new ObjectOutputStream(fileOutputStream);
outputStream.writeObject(user);
System.out.println("I've stored the User object into the file: " + file.getName());
}
}
And voila, now I can look on my hard drive and see that a file has been created at C:testFile.txt!
Note: I had to use two backslashes (\) when listing my file location, because the backslash () is used as something called an escape character. It's most commonly used when you want to put an actual quote (“) symbol in a
String
. For more info on the backslash escape character see this explanation.
Now it's your turn
I have a challenge for you! I want you to now write some code that will take the file on your hard drive, read the file, and re-create the User
Object you previously serialized. Here's a hint, you'll need to use an ObjectInputStream
.
Alright folks, I hope this Java tutorial made the topic of serialization crystal clear. If not, feel free to ask me questions in the comments section of this post. I would also like to give thanks to DavidLeedy on twitter for requesting that I cover the topic of serialization, and I hope that I've successfully answered all the question he had about the topic! If you've already requested that I cover certain topics, give me some time and I'll write something up as soon as possible, I promise!
PS. I've written a book about Java, and I think you'll love it! If you're interested, please go check it out now!