Unpacking CS Jargon: Static Vs. Dynamic Types

Unpacking CS Jargon: Static Vs. Dynamic Types Featured Image

Computer science as a discipline is loaded with jargon that you’ll eventually have to learn. While I could probably write about all of the jargon forever, we’re only going to talk about a pair of terms today: static vs. dynamic types.

In short, the static type (aka the declared type or compile-time type) refers to the type of a variable at the time it was declared—often literally written out on the left side of an assignment statement. In contrast, the dynamic type (aka the object type or runtime type) refers to the type of a variable while the program is running—often the type seen on the right side of an assignment statement.

As always, keep reading for more details.

Table of Contents

Understanding Types

In programming, when we talk about types, we’re referring to the set of values a variable can hold. For example, we might say that a variable is of type integer. In that case, the variable may store any whole number, either positive or negative.

In some programming languages, the type systems are more rigid (e.g., the type of the variable is fixed). Languages with this style of type system include Java and C#. Other languages are more flexible and let you change the type of a variable whenever you want like Python and JavaScript.

Regardless, type systems in general bound variables to some expected set of values. But did you know that some languages have more rules around types? For example, in Java, a variable can have two types: a static type and a dynamic type. In this article, I’ll cover exactly what these terms mean.

Static, Declared, and Compile-Time Types

In languages like Java, we declare a variable as follows:

Object o;

When we declare a variable, we add it to our program environment. At the moment, it isn’t defined, but we already know enough about it to begin performing operations on it. For example, Java objects all come standard with a certain set of methods (e.g., toString()). As a result, regardless of what type of variable we see in the definition, we can guarantee that all of the Object methods will be available.

In programming, we call this type the declared type because it’s the type of the variable when it is declared. Personally, I prefer to call it the static type because it’s the type that the compiler uses to ensure that all the method calls are valid(i.e., when the program isn’t actually running). A third term you might use is the compile-time type for the same reason that I prefer the term static type. All three terms are fine and mean the same thing. However, if you find the word “static” confusing given all the other places it’s used, compile-time is a good substitute.

Dynamic, Object, and Runtime Types

In languages like Java, you define a variable as follows:

Object o = new Object();

Interestingly, the following are also ways to define a variable:

Object o = "Hello";
Object o = functionThatReturnsSomeObject();

In Java, just about everything is an object. As a result, it’s possible to assign just about anything to an Object variable, such as a String. In fact, you can even assign primitive types to an Object variable in Java, triggering autoboxing to the corresponding wrapper classOpens in a new tab. (e.g., Integer for int).

With that said, the static type of the variable will always be Object, so we’re restricted to using Object methods only. For instance, here’s some example code that prints the number seven:

Object o = 7;
System.out.println(o);

Now, this result might seem weird to you because I just said that the static type limits which methods we can call. Surely, the toString() method of Object can’t handle every possible type of object, and you’d be right! Instead, the dynamic type comes into play. See, when a method is called on a variable, the version of the method that is dispatched—more jargon, I know—is the method defined for the dynamic type. In this case, the dynamic type of o is Integer, which properly prints any int.

Naturally, the term dynamic type contrasts with static type in that dynamic type refers to the type of the variable at runtime. Perhaps unsurprisingly, this is why folks sometimes call this type the runtime type. And of course, there are other variations like object type or actual type. As always, you can pick the one that works for you. I recommend sticking with the term that actually has some semantic meaning (i.e., runtime type), even though I prefer the term dynamic type.

Some Caveats

In summary, the static type refers to the type of a variable at compile-time while the dynamic type refers to the type of the variable at runtime. That said, if you’re looking for a pair of terms to use, be sure you don’t mix and match. In general, these sets of terms come in pairs such as:

  • Static vs. Dynamic
  • Compile-time vs. Runtime
  • Declared vs. Object

Another thing worth mentioning is that there is definitely nuance in how you make use of your static types. Very rarely, if ever, are you going to have Object as a static type. More likely, the static and dynamic type will lineup. That said, some codebases rely on inheritance—yet more jargon for another time—which muddies the waters a bit. As a result, the static type might even be an interface or abstract class, which cannot exist as the dynamic type. If you’re interested in learning more about these topics, feel free to let me know, and I’ll keep writing about them.

Outside of that, I think that’s all you need to know. If you found this article helpful and want to support the site, check out this list of ways to grow the site. Likewise, here are some related posts:

As always, take care! See you next time.

Coding Tangents (43 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 and kid, playing Overwatch 2, Lethal Company, and Baldur's Gate 3, reading manga, watching Penguins hockey, and traveling the world.

Recent Posts