Data types
Why care about types?
Let’s talk about why we should care about types at all: what are they even for? At the lowest level, a computer is concerned with bytes, with barely any additional structure. What a type system gives us is abstraction. A type adds meaning to plain bytes: it lets us say “these bytes are text”, “those bytes are an airline reservation”, and so on. Usually, a type system goes beyond this to prevent us from accidentally mixing types up: for example, a type system usually won’t let us treat a hotel reservation as a car rental receipt.
The benefit of introducing abstraction is that it lets us forget or ignore low-level details. If I know that a value in my program is a string, I don’t have to know the intimate details of how strings are implemented: I can just assume that my string is going to behave like all the other strings I’ve worked with.
What makes type systems interesting is that they’re not all equal. In fact, different type systems are often not even concerned with the same kinds of problems. A programming language’s type system deeply colours the way we think, and write code, in that language.
… From Real World Haskell
What is it?
A data type or simply type is a classification identifying one of various types of data.
A data type is an interpretation of data (bits).
- Primitive types (int, double): hardware-based
- Objects (such as java.math.BigInteger): require software interpretation
- Composite types (int[]): software + hardware
Types of variables in Java
In Java, two basic types of variables exist:
- Primitive types
- Primitive types are hardware-based.
- Primitive types are the standard built-in types we would expect to find in any modern programming language:
size in bytes size in bits byte 1 boolean char int short long float double void
- Reference types
- Reference types are any variables that refer to an object.
This is an important distinction, because the two variable types are treated differently in various situations. All reference type objects are of a specific class, for example.
(Void is a valid return type, even though it technically is not a data type. Variables cannot be declared as type void. Void is used to denote that a method returns nothing.)
Reference Objects and Value Types
All classes in Java are derived from the root class Object
. So, given the rules of inheritance and polymorphism, an Object
class variable can refer to any reference object of any class. In other words, a widening conversion can take place from any class to Object
. Take a look at the following code, for example:
String s = new String("Hello World");
Object o = s;
MyClass m = new MyClass();
Object o = m;
One of Java’s strengths is the fact that it uses a polymorphic model wherein all classes are derived from a common root. All objects share a common base Application Programming Interface (API). This does not apply to the primitive types, however. For example, the following code doesnot work:
double d = 3.8;
Object o = d;
The Java Development Kit (JDK) comes complete with a set of classes defined by Sun as the core API. All these classes are the Java equivalent of a standard library. The Java core classes include wrapper classes for all the primitive types: Integer for int, Double for double, Float for float, and so on. Of course, all these wrapper classes are derived from the root class Object as well.
One unique case is that of the array. An array can be an array of primitives or an array of reference types. For the most part, the array itself is treated as a reference type of the Object class. The individual members, of course, are not treated in any special way. The rule of thumb is that anything created by the operator new is assignable to Object. So, again, the following code would work:
long l[10] = new long[10];
Object o = l;
Object a[] = new Object[10];
Object o = a;
What does all this mean in terms of ADTs? Well, if we create a construct that works with objects of class Object, we can use the construct with any reference type in place of Object.
Haskell
Java | Haskell | Example values in Haskell |
---|---|---|
int | Int | 1, 2, -1, -2, etc |
float | Float | 1.0, -1.23, -2.5, etc |
bool | Bool | True, False. Nothing else (see notes below) |
char | Char | ‘a’, ‘b’, ‘c’, ‘\n’, ‘\r’, ‘\t’, etc. |
String | String | “hello world”, “abc”, “a”, “b” (notice the single quotes - ’ vs double quotes - " difference between Char and String) |
double | Double | 1.0, -1.23, -2.5, etc (basically larger values than Float) |
void | () | () - see notes below |
int[], bool[], double[], String[] | [Int], [Bool], [Double], [String] | [1, 2, 3, 4] or [True, False, False], or [1.0, 5.6, 12.34] or [“hello”, “world”, “haskell”, “rocks”] |
int[][], bool[][], int[][][], float[][][] | [[Int]] , [[Bool]] , [[[Int]]] , [[[Float]]] |
[[1, 2], [3, 4, 5], [6, 7, 8]] or [[“Multi”, “dim”], [“list”, “in”, “haskell”]] |