2013-09-03

Understanding Java from a C++ Background

A short note of thanks before I begin. Some friends showed me a lot of shortcomings in the way I was thinking about this problem. That led to a huge, sweeping revision of this article. Hopefully it is more correct, coherrent and usable now.



I was born and raised in a world of C++, which treats class objects and primitives the same way. You can pass any variable around between functions either by value, or by reference. My dependency on this paradigm never became more apparent to me than when I finally made the switch to another language: Java.

C++

In C++, you can instantiate a class object, let's call it MrObject. You can then also create a pointer to it. Let's call that MrPointer. If you then decide you want access to MrObject's data in another function, there are a lot of ways you can do this. You can:
Pass a reference to MrObject into the function using the '&' operator, giving you direct access to the original instance of MrObject himself.

void MrFunction(MrObjectClass &MrObjectRef) {...}

Within MrFunction, you can use MrObjectRef just the same as if it were MrObject himself, because this is literally just creating another alias for the same exact object in memory.
You can also:
Pass by value, creating a new instance of a MrObjectClass inside MrFunction that is a duplicate of MrObject.

void MrFunction(MrObjectClass MrObjectDupe) {...}

When you pass MrObject into this function by value like this, a new class object called MrObjectDupe is created within the function. The original MrObject stays where he is, and is isolated from anything that is going on within MrFunction.
Things get a little more tricky when you create pointers to MrObject and try passing those into functions. For example, let's say you make a pointer to MrObject, like so:
MrObjectClass * MrPointer = &MrObject;

If you're not fluent in C++, what we are doing here is not creating a new MrObject. The asterisk (*) tells us that we are creating a pointer to an object of type MrObjectClass. The name of the pointer is MrPointer. The assignment here (=), combined with the ampersand (&), tells us that the specific object in memory that MrPointer points to is the one named MrObject (which must be declared elsewhere, but can, if you wanna be fancy, be defined through MrPointer via the new keyword, for example).
Now, if you want to pass MrPointer into a function, C++ also allows you to pass that either by value, or by reference. In other words, you can:
Pass a pointer by value; create a new pointer with the same value as the pointer you passed into the function. In other words, a new pointer, but one that points to the same address as the pointer that was passed into the function.

void MrFunction(MrObjectClass * MrPointerDupe) {...}

The asterisk must still be included so that C++ knows MrPointerDupe is a pointer. The side effect of this is that we can access MrObject through this duplicated pointer, but if we point MrPointerDupe at a new address (to a different object of MrObjectClass, or a new one, or to null), then the original MrPointer will remain unaffected, still pointing at (and modifying, if dereferenced) our original MrObject.
Alternatively, you can:
Pass a pointer by reference; in other words, we are not creating a new pointer to MrObject, we are using the same original MrPointer; we are just creating a new alias for MrPointer to be used within MrFunction.

void MrFunction(MrObjectClass * &MrPointerAlias) {...}

The asterisk in this case tells us that we are declaring a pointer to an object of type MrObjectClass, and the ampersand tells us that the pointer we are creating is not a new pointer, but just an alias (another name) for the existing pointer that is getting passed in to MrFunction.

Java

The nature of Java variables may not seem clear at first, coming from a C or C++ background. In Java, every variable you declare is a reference (except for primitives like int or boolean). Even primitive types such as int have Java class equivalents that give you reference type variables for handling primitive types (such as Java's Integer class).

Why is this so important? Just taking one important example, in C++, you might be used to creating a new instance of a class object, then being able to copy it into another second class object, like so:
// C++ code to create a new instance of MrObjectClass called MrObject.
MrObjectClass MrObject();

// C++ code to create a second, separate instance of MrObjectClass called
// MrDuplicate, by copying MrObject. Note that this results in two
// distinct class objects in memory.
MrObjectClass MrDuplicate = MrObject;
By contrast, in Java, when you instantiate a class object like so:
MrObjectClass MrObject = new MrObjectClass();
you are not creating a class object called MrObject. You are implicitly creating a reference to an object of type MrObjectClass, and that reference is called MrObject. In the following Java snippet, the two declarations result in only one distinct class object instance, which has two reference variables referring or "pointing" to it. (Though these variables are not pointers, I found it useful to think about them as such in the beginning, as a sort of "training wheels" approach to getting going in Java. However, of course you should try to build an understanding of Java's implicit referential nature as early as possible.)
// Java instantiation of a reference called MrObject to a nameless object
// of type MrObjectClass
MrObjectClass MrObject = new MrObjectClass();

// Java instantiation of a second reference called MrDuplicate, which
// actually refers or "points to" the same nameless object as MrObject
// refers to, resulting in only a single nameless MrObjectClass object
MrObjectClass MrDuplicate = MrObject;
It's very important to understand this so that you will understand what happens the first time you attempt to duplicate a class object, then modify your new variable only to see the changes reflected in your first variable as well! In other words, in Java, you cannot create a MrObject that you have "direct" C-style access to. Also, perhaps most importantly, it's critical to remember that reassigning MrObject or MrDuplicate does not overwrite any data! MrObject and MrDuplicate are references, and reassigning them simply points them to new memory locations. This can, in turn, potentially leave data unreferenced, in which case Java automatically cleans it up (but this unpredictable, sometimes seemingly sporadic process, often called garbage collection is another topic for another day).

Another reason this concept is so important to grasp early on in a programmer's exposure to Java, is because Java does not support pass-by-reference! In other words, even if you get used to the fact that everything in Java is a reference, you then have to accept that all functions in Java are pass-by-value! In other words, if I pass my MrObject reference from the example above into a function, the result is that within that function I cannot directly manipulate the original MrObject, ever!

What's happening within the function is we are creating a new reference variable whose value (referred or "pointed" address) is the same as MrObject's, because that is what's passed by value. Using the new reference inside the function, we can access our referred, nameless class object's public members. But if I try to reassign my reference variable from within my function, only the duplicated reference variable within the function will refer to the new destination address (nameless class object instance) I designate (including, possibly, null); the original MrObject reference outside the function will still point to (and protect from garbage collection) the original address (nameless class object) it originally referred to in the first place.

Are there ways to simulate pass-by-reference for those instances where you really want that behavior? Sort of (storing reference variables in an array or container class and passing the array or container itself into functions by value to preserve the original pointer-like variables within is the closest I can come up with so far, though these can feel like clumsy substitutes for true pass-by-reference). But when possible, it's better to just be aware of Java's idiosyncrasies and think in a Java-like way; its lack of pass-by-reference, and its requirement that all non-primitive class object variables are references; and to design around these features to the extent possible.

Thanks for reading!
-- Steven Kitzes

2013-07-15

'const' vs 'final' - A Discussion

(For the tl;dr, click here.)

My latest forays into the realm of software development have taken me into Java country. I'm going to be taking my first classes toward my Master's in Computer Science in the coming months, and the bulk of the courses taught at my university are in Java. It will be my first time working with Java, so I thought it'd be a good idea to test the waters and get up to speed.

When I started writing my first entry level Java programs, one of the first features I instinctively tried to carry over from my C++ background was the const concept. After some research, I discovered that there is no const keyword in Java. Or, more accurately, const is a reserved word, that Java prohibits you from using in your code. It has no function in Java, but you may not use it as a variable or function name, either.

Instead, Java has a keyword called final, which seems on the surface to have a similar function to C++'s const. I wondered what the difference was between the two, and why Java's creators decided to block the const keyword from their language, I went on a quest to find out!

I came across a variety of myths along my search that I quickly busted via simple testing. For example, some folks believe that Java's final keyword can't be applied to primitive data types such as int, double, or char; but it can. Others believe that const C++ references are special, in that while they are immutable, the data they point to is mutable; however, this is also the case with a Java final.

As a side note, I found some information indicating that you do have the option in C++ of differentiating between a constant pointer to data, a pointer to constant data, and a pointer that is declared as constant to protect the otherwise non-constant data that can be dereferenced through it. If that sounds a bit confusing, it's much easier to understand when you see the code:


Cases 1 and 3 are simple enough, as far as syntax, though case 3 may be a little more confusing because of how we are protecting our data. Case 2, on the other hand, is a bit more confusing in terms of syntax; the const keyword appears after the pointer operator, even though the pointer itself is where we are applying the const functionality.

It would make more sense to me if the const keyword immediately preceded the item that it modified, in this case, the pointer operator. But sometimes you just have to accept that things are the way they are, and forge ahead!

So what is the difference between const and final? It turns out the primary difference is in initialization. In C++, a const must be defined in the same statement in which it is declared. In other words, you can't declare a C++ const and define it later in a separate statement.


On the other hand, a final in Java can be initialized in the same statement that it is declared; but you can also choose to declare it and then define it later in the program. This allows for each instance of a final to be defined by one of a variety of values (as you can see in the below example), but still ensures that once it is defined, it is constant forevermore.


As you can see in the above example, depending on whether 'someBool' is true, x might end up being defined as 10 or 20, but once it is set to one or the other, it can never be changed from there on out because it is final. Another important thing to note: when you are using a Java final without defining and declaring it in the same statement, you must be careful to define it before it is used, or you will have an error.

Hopefully this will help clear up some of the idiosyncrasies of and differences between C++'s const and Java's final!

Thanks for reading!
-- Steven Kitzes

2013-07-08

Updating Environment Variables in Windows

This weekend I installed the Java Runtime Environment and the Java Development Kit onto my desktop and my laptop, both running identical Windows 7 environments. The installation onto the desktop went without a hitch. I ran both the JRE and JDK installers, got the JetBrains IntelliJ IDEA Java IDE up and running, and tried executing my first Java 'Hello World' program from the console. Shockingly, this worked on the very first try with no errors, and from the Git Bash, no less! This was such a pleasant surprise and unexpected result that it even prompted me to rename my dev blog to 'Unexpected Result'!

But for whatever reason, after going through all the same steps on my laptop, I couldn't seem to get Java to run from Git Bash. Upon checking my environment variable (typing env | grep PATH in Git Bash), I discovered that the JDK directory somehow didn't seem to have been added!

It turns out the solution was a simple matter of closing the Git Bash and reopening it! When a PATH variable change is registered, that change won't be visible to any running instances of Git Bash. It seems that Git Bash reads the PATH variable from Windows one time only, when the CLI is launched, and doesn't refresh it until the CLI is closed and launched again. This is true of other command line interfaces in Windows, as well (such as the Windows command prompt).

So if you've just added something new to a Windows environment variable, and it doesn't seem to be working from your CLI, make sure you have restarted your CLI after the environment variable was modified and it should be smooth sailing from there!

Thanks for reading!
-- Steven Kitzes

2013-07-01

Parsing XML in ActionScript 3

I recently had a task handed down at work requiring me to parse XML data in ActionScript 3. It sounded simple, because AS3 includes documented libraries to handle XML content. But on my first pass trying to use them, I got unexpected results. After some investigation, I was able to understand what was happening. I was surprised the AS3 documentation didn't explain the behavior of the XML and XMLList classes in better detail, so I hope to fill some of the gaps with a quick write-up of my misadventure.

It was little trouble getting the XML file loaded into AS3, and I verified that the file was loading correctly by tracing the resultant XML object's contents in output. But when I tried to filter XML elements out of the XML object by tag name or attribute content, I would sporadically get unexpected results, or get no results returned at all (an empty set).

Just for some background, the XML files I was working with contained various lists of buttons for a video game UI. Each button had a button type denoted by its tag title, for example Slider, Toggle, or just plain Button. Each then had attributes, such as Name, ID, and DisplayText. So the XML would look something like this:


Note that none of the elements in the above example have any text content! My attributes have values, but the tags have no content between them. (This is legal in XML, but may have been unwise in retrospect, at least for debugging purposes.)

When I tried to filter based on button type (in other words, by tag name, e.g. Slider, Toggle, or Button) I would get strange results. When filtering MainMenu, I'd get a list of XML objects for Slider tagged elements and Button tagged elements, as desired; but would receive an empty string when filtering on Toggle tagged objects. Conversely, when filtering GfxMenu, I'd get the opposite; XML objects for Toggle tagged elements but empty strings for the others. What?!

At first, I didn't see why this would be happening, and I scoured the AS3 documentation to no avail. But after some experimentation I realized that when filtering, if only one element within the search range meets the requirements of a given search, AS3's XML class will return the text content of the element's tag automatically! And if multiple elements meet the search criteria, a list of XML elements will be returned.

I don't know if this was done to satisfy some language specifications or what, but that's what I was able to figure out!

Mystery solved.


Thanks for reading!
-- Steven Kitzes

2013-06-24

Bitmask Basics

Working directly with bits is one of my favorite things to do as a programmer. I just find it fun! I haven't used these techniques recently in any of my projects, but I wanted to take some time to explain how bitmasks work, and some of their uses and advantages. Hopefully you'll agree they're very useful, and you'll see why I like them so much!

Higher level bitwise operations (also known as bit masking, bit flagging, etc) are great for a number of reasons. I find them quite fun, in addition to being useful and more efficient than other methods of Boolean comparisons and assignments. But before going into the methods and uses of bitmasking I should give a little bit of background on the topic. I'll be giving my examples in C++ because that's the language I'm most comfortable and familiar with, but bitmasking is possible in many languages.

First of all, what is a bitmask (or, what do I mean when I say bitmask)? In C++ (or any typed language), there are many data types that you are probably familiar with. These data types represent collections of bits, organized into bytes, stored in memory. We normally think about our variables and constants in terms of a given type (for example, int, double, or maybe even float), but behind the scenes an int or double still represents a contiguous set of bits.

Let's take the char data type in C++ as an easy example (it only represents a single byte, 8 bits). We can manipulate and compare data types such as chars in terms of their constituent bits. One way of terming such a collection of bits in this context is as a bitmask. This is often the case when using a char or int not to represent an actual character or integer, but rather to represent a condensed set of Boolean values.

At this point, you may be wondering: why is this useful? Isn't it simpler to just make a bunch of bool variables and compare those? Well, yes; that would be simpler, and easier for a human to read in the code. But it would necessitate long, convoluted argument lists if those bools ever needed to be passed around; not to mention that the bool type is very wasteful in languages like C++. Remember, the smallest size for a data type is one byte, 8 bits. So for C++ to store a bool in memory, it must allocate a full byte - 8 bits - even though only one bit is really needed to represent a Boolean value. Then, when making comparisons, an entire operation is wasted on each individual check against each individual bool. Holy smokes!

Alternatively, if we have a large number of Boolean variables that we need to track, instead of wasting an entire byte on a bool for each Boolean variable we want to track, we can track up to 8 Boolean values using a char's 8 individual bits, in the form of a bitmask! (Or, to expound on that idea, up to 16 values in a short int, 32 in a standard int, etc.) In addition to the efficiency achieved by storing several Boolean values' worth of information under a single primitive data type, this also means we can save a lot of time by comparing or manipulating several Boolean values in one go, as well! And of course, we can pass a bitmask as a single arg, which communicates a lot of Boolean data in a single variable, as opposed to needing to go through the hassle of passing multiple bools or encapsulating them in a container of some kind. So how does all this work...?

Example Time

Let's start by visualizing a C++ char's bits.

As an empty bitmask, with no bits turned on, our char would look like this:
00000000

If all the bits were flipped / turned on, it would look like this:
11111111

And with some bits on and some off, the bitmask would look like this:
00101101


Comparing two bitmasks against each other, or checking if a bitmask is either zero or non-zero works more or less as you would probably expect. Keep in mind, the following bitmasks are contained in char type variables. That's why they have 8 bits each.


C++ doesn't know or care that we're using our char as a bitmask. It just so happens that we are able to use bitwise operations and comparisons on our char. This means that while we may choose to perform bitwise operations and comparisons on our char, typical C++ comparisons like those on line 10 (comparing identical bitmasks) and line 14 (comparing differing bitmasks) return true and false results just as we would expect. Of course, zero / non-zero checks (such as on line 20) work as we are used to. And finally, assignment works as you would expect as well (such as on line 25).

The real value in bitmasks starts to become clear when we look at some of the special operators we can use to compare bitmasks against each other. These are the ampersand, the bar, and the carrot (& | ^). Let's take a look at what each of these operators does.

When using these operators with two bitmasks, the bit in each position of the first operand will be compared to the corresponding bit of the second operand. I call this vertical comparison, because it looks like this:
00101101
vvvvvvvv
10110110
vvvvvvvv
????????
The return value (the question marks) will be a new bitmask, whose bits will be flipped off or on (to 0 or 1 respectively) depending on the rules associated with the operator you are using. The ampersand (and, '&') checks to see if the corresponding bits in both bitmasks are both switched on, and flips the resultant bit on if so. The bar (or, '|') checks to see if the corresponding bits in either (or both) of the compared bitmasks are switched on, and flips the resultant bit on if so. Finally, the carrot (exclusive or, '^') checks specifically to see if one of the compared bitmasks has the bit in a given position switched on, while the corresponding bit in the other bitmask is switched off, and sets the resultant bit on if so.

This is a bit tricky to explain concisely, and a bit awkward to digest if you're not used to these concepts, so check out this Gist snippet for examples and visual representations. Here I show how each of these very useful operators works, and can be combined with a variety of comparisons and checks:

Real-World Example


Now that we have some idea of the mechanics of bitmask assignment and comparison, let's look at some real-world application. One challenge that lends itself particularly well to handling via bitmask is control input checking in video games. Video games, especially action-intensive games, must run at high frame rates, so performance is key and wasting a full bool data type's worth of data on each individual check is a monumental waste of space. As you'll see below, we can efficiently contain and check all the control input Boolean values we need in a single bitmask.

In this simple example, imagine a simple game with a perspective looking down onto the top of the player, who can move up, down, left or right, who can perform a regular attack and a special attack. Let's check out how we can manage the input for this control scheme using a bitmask! Note the use of constants here; having these constants available for use in assignment and checks is what makes bitmasks usable as arrays of Boolean values. Without the constants to check against, we wouldn't know what the individual bits in a bitmask represent! Also note the use of hexadecimal expressions to define the constants. I'll talk about this more in the example, but for now, just bear in mind that this is the easiest way (that I know of) to define a bitmask with a single bit flipped on in the position you want. (If you want to understand why I'm using hexadecimal the way I am, you need an understanding of how integers are represented in binary, which I won't explore in this post. An understanding of hexadecimal isn't required to understand this bitmask example, though!)
There is a lot of omitted error checking and pseudocode in this example, but it should give you an idea of how bitmasks can be useful in a real-world application.

Thanks for reading!
-- Steven Kitzes