Related
I have a float[] and i would like to get a list with the same elements. I could do the ugly thing of adding them one by one but i wanted to use the Arrays.asList method. There is a problem though. This works:
List<Integer> list = Arrays.asList(1,2,3,4,5);
But this does not.
int[] ints = new int[] {1,2,3,4,5};
List<Integer> list = Arrays.asList(ints);
The asList method accepts a varargs parameter which to the extends of my knowledge is a "shorthand" for an array.
Questions:
Why does the second piece of code returns a List<int[]> but not List<int>.
Is there a way to correct it?
Why doesn't autoboxing work here; i.e. int[] to Integer[]?
There's no such thing as a List<int> in Java - generics don't support primitives.
Autoboxing only happens for a single element, not for arrays of primitives.
As for how to correct it - there are various libraries with oodles of methods for doing things like this. There's no way round this, and I don't think there's anything to make it easier within the JDK. Some will wrap a primitive array in a list of the wrapper type (so that boxing happens on access), others will iterate through the original array to create an independent copy, boxing as they go. Make sure you know which you're using.
(EDIT: I'd been assuming that the starting point of an int[] was non-negotiable. If you can start with an Integer[] then you're well away :)
Just for one example of a helper library, and to plug Guava a bit, there's com.google.common.primitive.Ints.asList.
How about this?
Integer[] ints = new Integer[] {1,2,3,4,5};
List<Integer> list = Arrays.asList(ints);
Because java arrays are objects and Arrays.asList() treats your int array as a single argument in the varargs list.
Enter Java 8, and you can do following to collect in a boxed Array:
Integer[] boxedInts = IntStream.of(ints).boxed().toArray(Integer[]::new);
Or this to collect in a boxed List
List<Integer> boxedInts = IntStream.of(ints).boxed().collect(Collectors.toList());
However, this only works for int[], long[], and double[]. This will not work for byte[].
Note that Arrays.stream(ints) and IntStream.of(ints) are equivalent. So earlier two examples can also be rewritten as:
Integer[] boxedIntArray = Arrays.stream(ints).boxed().toArray(Integer[]::new);
List<Integer> boxedIntList = Arrays.stream(ints).boxed().collect(Collectors.toList());
This last form could be favored as it omits a primitive specific subtype of Stream. However, internally it is still a bunch of overloaded's which in this case still create a IntStream internally.
The problem is not with Arrays.asList(). The problem is that you expect autoboxing to work on an array - and it doesn't. In the first case, the compiler autoboxes the individual ints before it looks at what they're used for. In the second case, you first put them into an int array (no autoboxing necessary) and then pass that to Arrays.asList() (not autoboxing possible).
Arrays.asList(T... a) effectively takes a T[] which will match any array of true objects (subclasses of Object) as an array. The only thing that won't match like that is an array of primitives, since primitive types do not derive from Object. So an int[] is not an Object[].
What happens then is that the varags mechanism kicks in and treats it as if you had passed a single object, and creates a single element array of that type. So you pass an int[][] (here, T is int[]) and end up with a 1-element List<int[]> which is not what you want.
You still have some pretty good options though:
Guava's Int.asList(int[]) Adapter
If your project already uses guava, it's as simple as using the adapter Guava provides: Int.asList(). There is a similar adapter for each primitive type in the associated class, e.g., Booleans for boolean, etc.
int foo[] = {1,2,3,4,5};
Iterable<Integer> fooBar = Ints.asList(foo);
for(Integer i : fooBar) {
System.out.println(i);
}
The advantage of this approach is that it creates a thin wrapper around the existing array, so the creation of the wrapper is constant time (doesn't depend on the size of the array), and the storage required is only a small constant amount (less than 100 bytes) in addition to the underlying integer array.
The downside is that accessing each element requires a boxing operation of the underlying int, and setting requires unboxing. This may result in a large amount of transient memory allocation if you access the list heavily. If you access each object many times on average, it may be better to use an implementation that boxes the objects once and stores them as Integer. The solution below does that.
Java 8 IntStream
In Java 8, you can use the Arrays.stream(int[]) method to turn an int array into a Stream. Depending on your use case, you may be able to use the stream directly, e.g., to do something with each element with forEach(IntConsumer). In that case, this solution is very fast and doesn't incur any boxing or unboxing at all, and does not create any copy of the underlying array.
Alternately, if you really need a List<Integer>, you can use stream.boxed().collect(Collectors.toList()) as suggested here. The downside of that approach is that it fully boxes every element in the list, which might increase its memory footprint by nearly an order of magnitude, it create a new Object[] to hold all the boxed elements. If you subsequently use the list heavily and need Integer objects rather than ints, this may pay off, but it's something to be aware of.
Why doesn't autoboxing work here; i.e. int[] to Integer[]?
While autoboxing will convert an int to an Integer, it will not convert an int[] to an Integer[].
Why not?
The simple (but unsatisfying) answer is because that is what the JLS says. (You can check it if you like.)
The real answer is fundamental to what autoboxing is doing and why it is safe.
When you autobox 1 anywhere in your code, you get the same Integer object. This is not true for all int values (due to the limited size of the Integer autoboxing cache), but if you use equals to compare Integer objects you get the "right" answer.
Basically N == N is always true and new Integer(N).equals(new Integer(N)) is always true. Furthermore, these two things remain true ... assuming that you stick with Pure Java code.
Now consider this:
int[] x = new int[]{1};
int[] y = new int[]{1};
Are these equal? No! x == y is false and x.equals(y) is false! But why? Because:
y[0] = 2;
In other words, two arrays with the same type, size and content are always distinguishable because Java arrays are mutable.
The "promise" of autoboxing is that it is OK to do because the results are indistinguishable1. But, because all arrays are fundamentally distinguishable because of the definition of equals for arrays AND array mutability. So, if autoboxing of arrays of primitive types was permitted, it would undermine the "promise".
1 - ..... provided that you don't use == to test if autoboxed values are equal.
If you pass an int[] to Arrays.asList(), the list created will be List<int[]>, which is not vaild in java, not the correct List<Integer>.
I think you are expecting Arrays.asList() to auto-box your ints, which as you have seen, it won't.
It's not possible to convert int[] to Integer[], you have to copy values
int[] tab = new int[]{1, 2, 3, 4, 5};
List<Integer> list = ArraysHelper.asList(tab);
public static List<Integer> asList(int[] a) {
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < a.length && list.add(a[i]); i++);
return list;
}
Alternatively, you can use IntList as the type and the IntLists factory from Eclipse Collections to create the collection directly from an array of int values. This removes the need for any boxing of int to Integer.
IntList intList1 = IntLists.mutable.with(1,2,3,4,5);
int[] ints = new int[] {1,2,3,4,5};
IntList intList2 = IntLists.mutable.with(ints);
Assert.assertEquals(intList1, intList2);
Eclipse Collections has support for mutable and immutable primitive List as well as Set, Bag, Stack and Map.
Note: I am a committer for Eclipse Collections.
int is a primitive type. Arrays.asList() accept generic type T which only works on reference types (object types), not on primitives. Since int[] as a whole is an object it can be added as a single element.
There is a better solution for this starting with Java 9:
List<Integer> list = List.of(null, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8);
I have a float[] and i would like to get a list with the same elements. I could do the ugly thing of adding them one by one but i wanted to use the Arrays.asList method. There is a problem though. This works:
List<Integer> list = Arrays.asList(1,2,3,4,5);
But this does not.
int[] ints = new int[] {1,2,3,4,5};
List<Integer> list = Arrays.asList(ints);
The asList method accepts a varargs parameter which to the extends of my knowledge is a "shorthand" for an array.
Questions:
Why does the second piece of code returns a List<int[]> but not List<int>.
Is there a way to correct it?
Why doesn't autoboxing work here; i.e. int[] to Integer[]?
There's no such thing as a List<int> in Java - generics don't support primitives.
Autoboxing only happens for a single element, not for arrays of primitives.
As for how to correct it - there are various libraries with oodles of methods for doing things like this. There's no way round this, and I don't think there's anything to make it easier within the JDK. Some will wrap a primitive array in a list of the wrapper type (so that boxing happens on access), others will iterate through the original array to create an independent copy, boxing as they go. Make sure you know which you're using.
(EDIT: I'd been assuming that the starting point of an int[] was non-negotiable. If you can start with an Integer[] then you're well away :)
Just for one example of a helper library, and to plug Guava a bit, there's com.google.common.primitive.Ints.asList.
How about this?
Integer[] ints = new Integer[] {1,2,3,4,5};
List<Integer> list = Arrays.asList(ints);
Because java arrays are objects and Arrays.asList() treats your int array as a single argument in the varargs list.
Enter Java 8, and you can do following to collect in a boxed Array:
Integer[] boxedInts = IntStream.of(ints).boxed().toArray(Integer[]::new);
Or this to collect in a boxed List
List<Integer> boxedInts = IntStream.of(ints).boxed().collect(Collectors.toList());
However, this only works for int[], long[], and double[]. This will not work for byte[].
Note that Arrays.stream(ints) and IntStream.of(ints) are equivalent. So earlier two examples can also be rewritten as:
Integer[] boxedIntArray = Arrays.stream(ints).boxed().toArray(Integer[]::new);
List<Integer> boxedIntList = Arrays.stream(ints).boxed().collect(Collectors.toList());
This last form could be favored as it omits a primitive specific subtype of Stream. However, internally it is still a bunch of overloaded's which in this case still create a IntStream internally.
The problem is not with Arrays.asList(). The problem is that you expect autoboxing to work on an array - and it doesn't. In the first case, the compiler autoboxes the individual ints before it looks at what they're used for. In the second case, you first put them into an int array (no autoboxing necessary) and then pass that to Arrays.asList() (not autoboxing possible).
Arrays.asList(T... a) effectively takes a T[] which will match any array of true objects (subclasses of Object) as an array. The only thing that won't match like that is an array of primitives, since primitive types do not derive from Object. So an int[] is not an Object[].
What happens then is that the varags mechanism kicks in and treats it as if you had passed a single object, and creates a single element array of that type. So you pass an int[][] (here, T is int[]) and end up with a 1-element List<int[]> which is not what you want.
You still have some pretty good options though:
Guava's Int.asList(int[]) Adapter
If your project already uses guava, it's as simple as using the adapter Guava provides: Int.asList(). There is a similar adapter for each primitive type in the associated class, e.g., Booleans for boolean, etc.
int foo[] = {1,2,3,4,5};
Iterable<Integer> fooBar = Ints.asList(foo);
for(Integer i : fooBar) {
System.out.println(i);
}
The advantage of this approach is that it creates a thin wrapper around the existing array, so the creation of the wrapper is constant time (doesn't depend on the size of the array), and the storage required is only a small constant amount (less than 100 bytes) in addition to the underlying integer array.
The downside is that accessing each element requires a boxing operation of the underlying int, and setting requires unboxing. This may result in a large amount of transient memory allocation if you access the list heavily. If you access each object many times on average, it may be better to use an implementation that boxes the objects once and stores them as Integer. The solution below does that.
Java 8 IntStream
In Java 8, you can use the Arrays.stream(int[]) method to turn an int array into a Stream. Depending on your use case, you may be able to use the stream directly, e.g., to do something with each element with forEach(IntConsumer). In that case, this solution is very fast and doesn't incur any boxing or unboxing at all, and does not create any copy of the underlying array.
Alternately, if you really need a List<Integer>, you can use stream.boxed().collect(Collectors.toList()) as suggested here. The downside of that approach is that it fully boxes every element in the list, which might increase its memory footprint by nearly an order of magnitude, it create a new Object[] to hold all the boxed elements. If you subsequently use the list heavily and need Integer objects rather than ints, this may pay off, but it's something to be aware of.
Why doesn't autoboxing work here; i.e. int[] to Integer[]?
While autoboxing will convert an int to an Integer, it will not convert an int[] to an Integer[].
Why not?
The simple (but unsatisfying) answer is because that is what the JLS says. (You can check it if you like.)
The real answer is fundamental to what autoboxing is doing and why it is safe.
When you autobox 1 anywhere in your code, you get the same Integer object. This is not true for all int values (due to the limited size of the Integer autoboxing cache), but if you use equals to compare Integer objects you get the "right" answer.
Basically N == N is always true and new Integer(N).equals(new Integer(N)) is always true. Furthermore, these two things remain true ... assuming that you stick with Pure Java code.
Now consider this:
int[] x = new int[]{1};
int[] y = new int[]{1};
Are these equal? No! x == y is false and x.equals(y) is false! But why? Because:
y[0] = 2;
In other words, two arrays with the same type, size and content are always distinguishable because Java arrays are mutable.
The "promise" of autoboxing is that it is OK to do because the results are indistinguishable1. But, because all arrays are fundamentally distinguishable because of the definition of equals for arrays AND array mutability. So, if autoboxing of arrays of primitive types was permitted, it would undermine the "promise".
1 - ..... provided that you don't use == to test if autoboxed values are equal.
If you pass an int[] to Arrays.asList(), the list created will be List<int[]>, which is not vaild in java, not the correct List<Integer>.
I think you are expecting Arrays.asList() to auto-box your ints, which as you have seen, it won't.
It's not possible to convert int[] to Integer[], you have to copy values
int[] tab = new int[]{1, 2, 3, 4, 5};
List<Integer> list = ArraysHelper.asList(tab);
public static List<Integer> asList(int[] a) {
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < a.length && list.add(a[i]); i++);
return list;
}
Alternatively, you can use IntList as the type and the IntLists factory from Eclipse Collections to create the collection directly from an array of int values. This removes the need for any boxing of int to Integer.
IntList intList1 = IntLists.mutable.with(1,2,3,4,5);
int[] ints = new int[] {1,2,3,4,5};
IntList intList2 = IntLists.mutable.with(ints);
Assert.assertEquals(intList1, intList2);
Eclipse Collections has support for mutable and immutable primitive List as well as Set, Bag, Stack and Map.
Note: I am a committer for Eclipse Collections.
int is a primitive type. Arrays.asList() accept generic type T which only works on reference types (object types), not on primitives. Since int[] as a whole is an object it can be added as a single element.
There is a better solution for this starting with Java 9:
List<Integer> list = List.of(null, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8);
I dont quite understand what is the problem with the second declaration.
// Compiles fine
ArrayList<ArrayList<String>> array = new ArrayList<ArrayList<String>>();
// error (Unexpected type, expected -reference ,found :int)
ArrayList<ArrayList<int>> intarray = new ArrayList<ArrayList<int>>();
ArrayList is an implementation of List<T>, your problem is that you are trying to create an arraylist of int, its impossible since int is not an object. using Integer will solve your problem.
ArrayList<ArrayList<Integer>> intarray = new ArrayList<ArrayList<Integer>>();
The way generics work is simple. The header of List looks a little like this:
public interface List<T>
Where T is some Object. However, int is not a subclass of Object. It is a primitive. So how do we get around this? We use Integer. Integer is the wrapper class for int. This allows us to use int values in a List, because when we add them, they get auto boxed into Integer.
Primitive types are actually scheduled for deprecation in Java 10. Taken from Wikipedia:
There is speculation of removing primitive data types, as well as moving towards 64-bit addressable arrays to support large data sets somewhere around 2018.
Just a Note on your Code
In Java, the convention is to have the declaration using the most generic type and the definition using the most specific concrete class. For example:
List myList;
// List is the interface type. This is as generic as we can go realistically.
myList = new ArrayList();
// This is a specific, concrete type.
This means that if you want to use another type of List, you won't need to change much of your code. You can just swap out the implementation.
Extra Reading
Read about Wrapper Classes.
Read about Auto Boxing and Unboxing.
Read about Primitive Types.
You can only make List of Objects. int is a primitive type.
Try use:
ArrayList<ArrayList<Integer>> intarray = new ArrayList<ArrayList<Integer>>();
You must create an ArrayList<Integer> not an ArrayList<int>
A class(Arraylist in your case) can be a type of a CLASS (Integer)
ArrayList does not except primitive types as an argument. It only accepts Object types you should use:
ArrayList<ArrayList<Integer>> intArray = new ArrayList<ArrayList<Integer>>();
In which case should you use primitive types(int) or reference types (Integer)?
This question sparked my curiosity.
In which case should you use primitive
types(int) or reference types
(Integer)?
As a rule of thumb, I will use a primitive (such as int) unless I have to use a class that wraps a primitive.
One of the cases were one must use a wrapper class such as Integer is in the case of using generics, as Java does not support the use of primitive types as type parameters:
List<int> intList = new ArrayList<int>(); // Not allowed.
List<Integer> integerList = new ArrayList<Integer>(); // Allowed.
And, in many cases, I will take advantage of autoboxing and unboxing, so I don't have to explicitly perform conversions from primitives to its wrapper class and vice versa:
// Autoboxing will turn "1", "2", "3" into Integers from ints.
List<Integer> numbers = Arrays.asList(1, 2, 3);
int sum = 0;
// Integers from the "numbers" List is unboxed into ints.
for (int number : numbers) {
sum += number;
}
Also, as an additional note, when converting from primitives to its wrapper class objects, and unique instances of objects are not necessary, use the valueOf method provided by the wrapper method, as it performs caching and return the same instance for a certain value, reducing the number of objects which are created:
Integer i1 = Integer.valueOf(1); // Prefer this.
Integer i2 = new Integer(1); // Avoid if not necessary.
For more information on the valueOf methods, the API specification for the Integer.valueOf method can serve as a reference for how those methods will behave in the wrapper classes for primitives.
That really depends on the context. First prefer the primitive, because it's more intuitive and has less overhead. If it is not possible for generics/autoboxing reasons, or if you want it to be nullable, then go for the wrapper type (complex type as you call it).
The general rules I follow when creating an API can be summarized as follows:
If the method must return an value, use a primitive type
If the method may not always apply (eg: getRadioId(...) on an object where such an ID may not exist), then return an Integer and specify in the JavaDocs that the method will return null in some cases.
On #2, look out for NPEs when autoboxing. If you have a method defined as:
public Integer getValue();
And then call it as follows:
int myValue = getValue();
In the case where getValue() returns null you'll get an NPE without an obvious cause.
Since Java does something called auto-boxing and auto-unboxing, you should use the primitive type int in most cases because of less overhead.
The only time you absolutely need to use Integer is in generics.
List<int> list; // won't compile
List<Integer> list; // correct
One case in which Integer might be prefered is when you are working with a database where numerical entries are allowed to be null, since you wouldn't be able to represent a null value with an int.
But of course if you're doing straight math, then int would be better as others have mentioned due to intuitiveness and less overhead.
My rule of thumb is: use boxed primitives only when it's necessary to get the code to compile. The only places in your code where the names of the primitive wrapper classes should appear is in generic type parameters and static method calls:
List<Integer> intList = new ArrayList<Integer>();
int n = Integer.parseInt("123");
That's the advice I would give to new Java programmers. As they learn more, they'll run into situations where they have to be more discerning, like when dealing with Maps or databases, but by then they should also have a better understanding of the difference between primitives and boxed primitives.
Autoboxing tempts us to believe int and Integer (for example) are interchangeable, but it's a trap. If you mix the two kinds of value indiscriminately, you can end up comparing two Integer values with == or trying to unbox a null without realizing it. The resulting bugs can be intermittent and difficult to track down.
It doesn't help that comparing boxed primitives with == sometimes works as if it were doing a value comparison. It's an illusion caused by the fact that values within a certain range are automatically cached in the process of autoboxing. It's the same problem we've always had with String values: comparing them with == sometimes "works" because you're actually comparing two references to the same, cached object.
When dealing with strings we can just tell the n00bs never to compare them with ==, as we've been doing all along. But comparing primitives with == is perfectly valid; the trick (thanks to autoboxing) is being sure the values really are primitives. The compiler will now let us declare a variable as an Integer and use it as if it were an int; that means we have to exercise a greater level of discipline and treat it as an error when someone does so without good reason.
Rather than calling them "complex types", you'd be best served thinking Integer, Double, etc. as "Classes", and int, double, etc. as "primitives".
If you're doing any type of sophisticated math, the Class-based numeric representation like Integer and Double will be cumbersome and slow you down - many math operations can only be done with primitives.
On the other hand, if you're trying to put your numbers into collections like Lists and Maps, those collections can only contain objects - and thus you must use (or convert to) classes like Integer and Double.
Personally, I use primitives whenever I can get away with it, and only convert to the Class representations like Integer when it's time to do input or output, and the transport requires those representations.
However, if you aren't doing any math at all, and instead are just passing the values straight through your code, you might save yourself some trouble by dealing with the Class-based forms (like Integer) exclusively.
I think this is a bit late but I wanted to add my opinion just in case.
in some scenarios, it's required to use the wrappers as the lack of a value is different from the default value.
example,
for one project I worked on, there was a field on screen where the user could enter a double value, the business requirement clearly mentioned that if the user enters a 0 the meaning is different from not entering a value and leaving the field blank and this difference will make an impact later on in a different module.
so in this scenario we had to use the Double object, since I cannot represent a lack of value using the primitive; since the primitive will default to 0 which was a valid input for the field.
I dont think there is any rule as such. I would choose the types over primitives (Integer over int) when I write method signatures, Maps, collections, Data Objects that get passed around. As such I would still like to use Integer instead of int even inside of methods etc. But if you think that is too much trouble (to type extra "eger") then it is okay to use ints for local variables.
If you want to setAttribute to session you have to use Object like Integer,Boolean,String in servlets. If you want to use value you can use primitive types. Objects may be null but primitives not. And if you want to compare types for primitives use == but objects use .equals because in object comparision == looks not values it looks if these are the same objects. And using primitives makes faster the code.
When we deal with Spring getRequest mapping methods, using boolean value does not work.
For instance :
#GetMapping("/goal")
public boolean isValidGoal() {
boolean isValid = true;
return isValid;
}
Always opt for Boolean in those cases.
I have heard of types being referred to as "boxed" in some languages.
In Java, I have heard of "autoboxing". What is this? Is it having wrapper classes for a type? How would my code change if I'm working with boxed or unboxed types?
Some data types are considered "primitive", meaning they are not treated like an object and don't have the properties of an object.
On most platforms, integers and characters are examples of types that are primitive but can be boxed.
Boxing means wrapping them in an object so they have the behavior of an object.
The exact meaning and behavior depends on the language you're using. Some languages (such as Smalltalk... at least waaay back when I was doing it...) don't allow any primitive types and consider everything to be an object, but there's a performance penalty associated with that because, at the end of the day, the processor needs to work with raw numbers and raw memory to do useful work. If you want to add two integers that have been boxed, for example, behind the scenes they are "unboxed" into primitive types, the numbers are added, and they are then boxed back into a new integer.
More specific information for Java:
Autoboxing allows java to automatically convert things like boolean and int to their Object versions Boolean and Integer in most cases. It also allows the reverse to happen.
For example:
int a = 3; // no boxing is happening
Integer b = 3; // newer versions of java automatically convert the int 3 to Integer 3
int c = b; // these same versions also automatically convert Integer 3 to int 3
Older versions of java that do not have autoboxing will require this code to do the same thing:
int a = 3; // works the same
Integer b = new Integer(3); //must set up a Integer object manually
int c = b.intValue(); //must change Integer object to a primitive
However, there are some scenarios where you still have to do things manually. For example, imagine you have a class with two methods like so:
assertEquals(int a, int b);
assertEquals(Object a, Object b)
Now, if you try to do this:
Integer a = 3;
int b = 3;
assertEquals(a, b); // this will not compile
The reason this doesn't work is because it cannot figure out whether it should unbox a to an int or box b to an Integer. Therefore it is ambiguous which method signature should be called. To fix this you can do one of these:
assertEquals((int) a, b);
assertEquals(a, (Integer) b);
Yes, boxing means taking a value type and wrapping it in a reference type. Since java introduced autoboxing you can do:
void foo(Object bar) {}
//...
foo(1);
And java will automatically turn the int 1 into an Integer. In previous versions you'd have to do:
foo(new Integer(1));
Autoboxing is most useful in java when working with generics, since you can't use primitives with generics, so to store ints in a list, you'd have to make a List<Integer> and put the ints into the list boxed.
A boxed type means that the values are allocated in a block on the heap and referenced through a pointer. This is good for uniformity in the implementation of the runtime (it makes it easier to have generic functions, etc), at the cost of an additional indirection.
Generally when you work with collections, you're dealing with arrays of Objects. In languages like Java, there is a difference between a primitive and an Object. When a primitive is "boxed", it's essentially just a wrapper around a primitive so it plays nice with the rest of the framework that's expecting an Object.
Autoboxing is just the act of putting a primitive into an object or pulling a primitive out of an object transparently so you don't have to worry about the extra step of doing it yourself.
Boxed means that they took a regular value type and created an object around it. Sort of like putting it in a box. This is generally to be avoided, because of the overhead of constructing the object.