Wrapper Classes
Look for your class's particulars in the folders on the left.
Uh oh.
jshell> ArrayList<int> al = new ArrayList<>();
| Error:
| unexpected type
| required: reference
| found: int
| ArrayList<int> al = new ArrayList<>();
| ^-^
Only Object types can be used as a type parameter in a generic class. Ouch. What do we do? The answer lies in wrapper types.
Every primitive type has a wrapper type.
Java Wrapper Types | |
---|---|
Primitive | Wrapper |
byte | Byte |
short | Short |
int | Integer |
long | Long |
boolean | Boolean |
float | Float |
double | Double |
char | Character |
The wrapper types have these elements in common.
- All live in package
java.lang
so no imports are needed. - Objects of these types are immutable
- All has a parseType static method
- All have useful toString methods.
- These are eligible types for collections such as ArrayList.
Let's see Integer
in action. We can make an
array list of Integer
s.
jshell> ArrayList<Integer> al = new ArrayList<>();
al ==> []
jshell> for(int k = 0; k < 20; k++){al.add(k*k*k);}
jshell> al
al ==> [0, 1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331,
1728, 2197, 2744, 3375, 4096, 4913, 5832, 6859]
You will notice that the constructors in Integer
are deprecated. Here is why. Notice when we use the String class
we don't use the new
keyword.
jshell> String s = "foo";
s ==> "foo"
Watch this. It's called autoboxing.
jshell> Integer i = 5;
i ==> 5
The primitive literal 5 is "boxed" automatically into an Integer
object. This is how we usually make Integer
s.
When we added the integers into the array list in the example above, autoboxing also occurred.
Also notice this. The variable i
knows it's pointing
at an Integer.
jshell> x.getClass()
| Error:
| int cannot be dereferenced
| x.getClass()
| ^--------^
Contrast that to this.
jshell> int x = 42;
x ==> 42
jshell> x.getClass()
| Error:
| int cannot be dereferenced
| x.getClass()
| ^--------^
You cannot call methods on primitives. Now observe this.
jshell> x = i;
x ==> 5
The contents of i
were autounboxed. So, we have
autoboxing and autounboxing.
All wrapper classes have this feature.
Hammer Time Here is something not to do.
jshell> int out = 17;
out ==> 17
jshell> for(Integer i = 0; i < 5000; i++){out += i;}
jshell> out
out ==> 12497517
Here 5000 boxings and 5000 unboxings occurred. That will deliver a performance hit. Use primitives for loop variables. Autoboxing and autounboxing are useful tools, not universal solutions. Like all tools, they have their place.
jshell> String quack = "531";
quack ==> "531"
jshell> //can you figure out how to get 531 out of this?
Some clever person thought of this. All of the wrappers have a feature just like this.
jshell> Integer.parseInt(quack)
$13 ==> 531
What happens if we try something dumb like using this on "duck egg."
jshell> Integer.parseInt("duck egg")
| Exception java.lang.NumberFormatException: For input string: "duck egg"
| at NumberFormatException.forInputString (NumberFormatException.java:68)
| at Integer.parseInt (Integer.java:652)
| at Integer.parseInt (Integer.java:770)
| at (#14:1)
An exception is a .45 calibre bullet heading straight for the beating heart of your program. Consider this code.
public class Exceptional
{
private static ArrayList al;
public static void main(String[] args)
{
System.out.println("I am now alive and on");
System.out.println("the correct side of the weeds");
int x = Integer.parseInt("445");
System.out.println(x);
int y = Integer.parseInt("duck egg");
System.out.println("I am dead now");
}
}
This code compiles without remark.
If you run this code, it will keep running until the line where
y
is defined as you see here. Then immediate program death
ensues.
unix> java Exceptional I am now alive and on the correct side of the weeds 445 Exception in thread "main" java.lang.NumberFormatException: For input string: "duck egg" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Integer.parseInt(Integer.java:580) at java.lang.Integer.parseInt(Integer.java:615) at Exceptional.main(Exceptional.java:11)
Now modify this program as follows.
import java.util.ArrayList;
public class Exceptional
{
private static ArrayList<String> al;
public static void main(String[] args)
{
System.out.println("I am now alive and on");
System.out.println("the correct side of the weeds");
int x = Integer.parseInt("445");
System.out.println(x);
int y = Integer.parseInt("duck egg");
//al.add("foo");
System.out.println("I am dead now");
}
}
unix> java Exceptional I am now alive and on the correct side of the weeds 445 Exception in thread "main" java.lang.NullPointerException at Exceptional.main(Exceptional.java:12)
Since you never used new
on the array list, it
pointed at null
. Calling a method on null
triggers a NullPointerException
.
Treasure Hunt What is 1000 in base 8? Some clever wag found this.
jshell> Integer.toOctalString(1000)
$1 ==> "1750"
There's this too.
jshell> Integer.toHexString(1000)
$2 ==> "3e8"
What is 1000 in base 3?
Integer.parseInt
goes in the wrong direction.
jshell> Integer.parseInt("1010111", 2)
$3 ==> 87
Look for the word "radix" on the page. We found this.
jshell> Integer.toString(1000, 3)
$4 ==> "1101001"
jshell> Integer.toString(1001, 3)
$5 ==> "1101002"
Check this out.
jshell> String s = "true"
s ==> "true"
Nope.
jshell> Boolean.parseBool(s)
| Error:
| cannot find symbol
| symbol: method parseBool(java.lang.String)
| Boolean.parseBool(s)
| ^---------------^
This works.
jshell> Boolean.parseBoolean(s)
$7 ==> true
jshell> Boolean.toString(true)
$8 ==> "true"
This works too.
jshell> "" + true
$9 ==> "true"
Let's be doubly sure.
jshell> String guac = "6.02e23"
guac ==> "6.02e23"
jshell> double avocado = Double.parseDouble(guac)
avocado ==> 6.02E23
Character os loade with useful stuff. Here are some items
isDigit
isLetter
isUpperCase
isLowerCase
isSpace
isLetterOrDigit
jshell> Character.isDigit('7')
$12 ==> true
jshell> Character.isDigit('q')
$13 ==> false
Characters are two bytes wide. It's unicode. All wrappers have a BYTES constant.
jshell> Character.BYTES
$14 ==> 2
jshell> Integer.BYTES
$15 ==> 4
jshell> Long.BYTES
$16 ==> 8
Inbox me for a cast!
jshell> Character c = 'q'
c ==> 'q'
jshell> (int) c
$18 ==> 113
More useful stuff:
jshell> Character.isAlphabetic('5')
$19 ==> false
jshell> Character.isAlphabetic('a')
$20 ==> true
jshell> Character.isAlphabetic('A')
$21 ==> true
jshell> Character.isUpper('A')
| Error:
| cannot find symbol
| symbol: method isUpper(char)
| Character.isUpper('A')
| ^---------------^
jshell> Character.isUpperCase('A')
$22 ==> true
jshell> Character.isSpace(' ')
$24 ==> true
jshell> Character.isSpace('\n')
$25 ==> true
jshell> Character.isSpace('\t')
$26 ==> true
Here is what isLetter does.
jshell> for(char c = 'A'; c <= 'z'; c++)
{
System.out.printf("%s: isLetter: %s\n", c, Character.isLetter(c));
}
A: isLetter: true
B: isLetter: true
C: isLetter: true
D: isLetter: true
E: isLetter: true
F: isLetter: true
G: isLetter: true
H: isLetter: true
I: isLetter: true
J: isLetter: true
K: isLetter: true
L: isLetter: true
M: isLetter: true
N: isLetter: true
O: isLetter: true
P: isLetter: true
Q: isLetter: true
R: isLetter: true
S: isLetter: true
T: isLetter: true
U: isLetter: true
V: isLetter: true
W: isLetter: true
X: isLetter: true
Y: isLetter: true
Z: isLetter: true
[: isLetter: false
\: isLetter: false
]: isLetter: false
^: isLetter: false
_: isLetter: false
`: isLetter: false
a: isLetter: true
b: isLetter: true
c: isLetter: true
d: isLetter: true
e: isLetter: true
f: isLetter: true
g: isLetter: true
h: isLetter: true
i: isLetter: true
j: isLetter: true
k: isLetter: true
l: isLetter: true
m: isLetter: true
n: isLetter: true
o: isLetter: true
p: isLetter: true
q: isLetter: true
r: isLetter: true
s: isLetter: true
t: isLetter: true
u: isLetter: true
v: isLetter: true
w: isLetter: true
x: isLetter: true
y: isLetter: true
z: isLetter: true
Grinch Dog Time
jshell> Integer.MAX_VALUE
$27 ==> 2147483647
jshell> Integer.MIN_VALUE
$28 ==> -2147483648
jshell> Double.MAX_VALUE
$29 ==> 1.7976931348623157E308
Here are a few features of Double.
jshell> Double.isFinite(5)
$30 ==> true
jshell> Double.isFinite(1.0/0)
$31 ==> false
jshell> Double.isNaN(1.0/0)
$32 ==> false
jshell> 1.0/0
$33 ==> Infinity
jshell> Double.SIZE
$34 ==> 64
jshell> Double.BYTES
$35 ==> 8