How to Swap Java Reference Types in a Method

How to Swap Java Reference Types in a Method Featured Image

Swapping variables in Java is tricky business, but everyone has probably seen the three step process. Unfortunately, a problem arises when we try to abstract that process out into a method. If you found yourself stuck trying to make a swap method in Java, look no further!

Table of Contents

Problem Description

As you can probably guess, all of the articles in this series are inspired by student questions. Specifically, I had several students who were struggling with this idea of swapping variables with methods.

Swapping Primitive Types

Initially, we introduce the concept of swapping variables by showing students a block of code that looks as follows:

int a = 10;
int b = 13;
int temp = a;
a = b;
b = temp;

Now, we know the code above works because logically it makes a lot of sense. I have two variables, a and b, which each store integers. I then introduce a temporary variable which holds the value of one of the variables that I’m about to delete, a. Next, I overwrite a with the value of b, and update b with the old value of a.

Swapping Reference Types

Of course, a swap like this will work for any time of data, not just primitive types. We can do the same thing for reference types:

String a = "Draco"
String b = "Harry"
String temp = a;
a = b;
b = temp;

Again, the logic makes a lot of sense here. However, there are a few additional wrinkles. For instance, in the primitive type example, any time we used the equal sign, we created a copy of the value. In other words, any changes to temp would have no effect on a. That’s not necessarily true for reference types. For example, when we try to copy a in line 3 of our reference type swapping code, we actually create what is called an alias. Both a and temp are pointing at the same value, “Draco”. No copies of that string were made.

As it turns out, even though “Draco” isn’t copied, there are no issues with the swapping code above because we’re just rerouting references. The memory addresses that store both “Draco” and “Harry” are the same. It’s the variables that now point to opposite addresses.

Introducing Methods

With all that said, both examples of swapping variables above work fine. However, let’s imagine that you plan to do a lot of variable swapping. What happens if you decide to get clever and make a swapping method for your variables? Here’s an example with our primitive types:

public static void swap(int x, int y) {
  int temp = x;
  x = y;
  y = x;
}

int a = 10;
int b = 13;
swap(a, b);

While the swap code will still work, a and b will never be swapped. The reason is somewhat subtle. When we pass a and b as arguments, x and y become copies of those arguments. Therefore, any changes to x and y will have no effect on a and b.

Okay, but those are primitive types. We more or less know that there is no way to alias them. Reference types, on the other hand, are aliased any time they’re passed into a method. Let’s take a look:

public static void swap(String x, String y) {
  String temp = x;
  x = y;
  y = x;
}

String a = "Draco";
String b = "Harry";
swap(a, b);

In the code above, we create variables x and y which point to the same objects as a and b, respectively. Then, we create a temp variable which also points to the same object as a and x. After that, we tell x to stop pointing at “Draco” and instead point to “Harry”. Meanwhile, the opposite happens for y. When everything is said and done, here are the values of our variables:

VariableValue
a“Draco”
b“Harry”
temp“Draco”
x“Harry”
y“Draco”

In other words, nothing happened to a and b while x and y were actually swapped. So, what gives? How do we actually swap a and b? That’s the topic of this article.

The Tale of Two Reference Types

The answer to the question “how do I swap reference types in a method?” actually has two answers. In some scenarios, it’s impossible (or at least inadvisable). In other scenarios, it’s straightforward. Let’s start with the impossible scenario.

Swapping Immutable Reference Types

When we talk about types in Java, we often differentiate primitive from reference types, but there are actually three classifications:

  • Primitive (e.g., int, double, etc.)
  • Immutable Reference Types (e.g., String, etc.)
  • Mutable Reference Types (e.g., ArrayList, etc.)

There are several reasons why we introduce this distinction between immutable and mutable reference types, but the reason we introduce it in this article is because it is an important distinction when trying to swap variables.

Mutability is defined as the ability to modify or mutate an object’s data. The ability to mutate an object comes from public mutator methods (also sometimes referred to as procedures). Procedures give the user indirect access to the underlying data by modifying it in some way. A lack of public procedures, or at least public access to underlying data fields, is what makes a reference type immutable.

Immutability is surprisingly rare in Java, but it exists in one of the most common object types in the entire language, Strings. In other words, there are no methods of String that modify the underlying String. Even methods like toUpperCase() do nothing to the original String. Instead, these types of methods return new Strings, using a copy of the original String.

So, if there are no ways to modify a String, how do we swap them in a method. Well, we don’t! There is no way to write a method that can swap immutable reference types like Strings.

Okay, I’m lying somewhat. There are likely ways to swap immutable reference types, but they are highly unrecommended as they are likely brittle, buggy, and possibly dangerous. That said, if this warning hasn’t stopped you, I recommend looking into ReflectionOpens in a new tab., a library for inspecting hidden members of a class.

Swapping Mutable Reference Types

With mutable reference types, the story is somewhat different. Since we are able to modify the underlying object, we can use our aliases to perform a value swap. Here’s what that might look like using arrays:

public static void swap(int[] x, int[] y) {
  int[] temp = {x[0], x[1], x[2]};
  x[0] = y[0]
  x[1] = y[1]
  x[2] = y[2]
  y[0] = temp[0]
  y[1] = temp[1]
  y[2] = temp[2]
}

int[] a = {4, 1, 2};
int[] b = {2, 1, 6};
swap(a, b);

As you can imagine, this code is going to look different for every type of object. For instance, the array example only works if both arrays are the same length (and in this case, a length of 3). That said, because mutable data types let us manipulate the underlying objects, swapping variables is a matter of manipulating both objects until their values are properly swapped.

Still Confused? Let’s Draw!

One thing I find challenging about software development is that we sometimes avoid trying to conceptualize these ideas visually. So, what I want to do is reintroduce the idea of reference types through a silly example.

To help illustrate the idea of how reference types work, we need to understand what a reference is. For simplicity, a reference is a memory address. Rather than storing the value directly in a variable, the variable stores the address. Then, whenever we want to do something with our object, we go to the address on file.

If we think of a reference as a literal home address, it starts to make sense why methods work the way they do. For example, we can think of methods as services that are performed on our home like painting, landscaping, etc. All we have to do is give a copy of our address to the service, and they’ll come perform it.

Now, in Java, we can swap addresses with someone no problem. We just need the two parties (i.e., two variables) and a middle man (i.e., a temporary variable).

Where things become an issue is if we involve a swapping service (i.e., a method). To perform the swap, the two parties would give a copy of their address to the swapping service. From there, the service would be to swap the copies internally. However, at the end of the day, the two parties would still have their original addresses.

What the swapping service could do, however, is order services to be performed on the houses, so that they would look like each other. For example, if one party had a blue house and the other party had a red house, the swapping service could hire painters to paint the houses their respective colors.

Ultimately, however, the swapping service can never actually swap the home addresses because the addresses given to the swapping service are copies. This is a limitation of Java, in that we can’t pass the original references to our method. Other languages like C let us do this but things get complicated quickly (e.g., imagine giving the swapping service the deed to the land instead of just the address).

Reference Types Are Messy

When it comes to writing code in Java, life isn’t too bad until we start messing with reference types. Of course, they’re hard to avoid. After all, there are only 8 primitive types in the entire language. Every other piece of data is a reference type, so you have to get used to using them.

With that said, ages ago I wrote a short series to get folks up to speed on Java. If you’re interested, I recommend checking it out. It takes a conceptual approach to Java that begins with binary and arithmetic before moving straight into Object-Oriented Programming.

Otherwise, I’d appreciate it if you took a look at some of these related posts:

With that said, thanks for sticking around. See you next time!

Coding Tangents (22 Articles)—Series Navigation

As a lifelong learner and aspiring teacher, I find that not all subjects carry the same weight. As a result, some topics can fall through the cracks due to time constraints or other commitments. Personally, I find these lost artifacts to be quite fun to discuss. That’s why I’ve decided to launch a whole series to do just that. Welcome to Coding Tangents, a collection of articles that tackle the edge case topics of software development.

In this series, I’ll be tackling topics that I feel many of my own students have been curious about but never really got the chance to explore. In many cases, these are subjects that I think deserve more exposure in the classroom. For instance, did you ever receive a formal explanation of access modifiers? How about package management? Version control?

In some cases, students are forced to learn these subjects on their own. Naturally, this forms a breeding ground for misconceptions which are made popular in online forums like Stack Overflow and Reddit. With this series, I’m hoping to get back to the basics where these subjects can be tackled in their entirety.

Jeremy Grifski

Jeremy grew up in a small town where he enjoyed playing soccer and video games, practicing taekwondo, and trading Pokémon cards. Once out of the nest, he pursued a Bachelors in Computer Engineering with a minor in Game Design. After college, he spent about two years writing software for a major engineering company. Then, he earned a master's in Computer Science and Engineering. Today, he pursues a PhD in Engineering Education in order to ultimately land a teaching gig. In his spare time, Jeremy enjoys spending time with his wife, playing Overwatch and Phantasy Star Online 2, practicing trombone, watching Penguins hockey, and traveling the world.

Recent Posts