Skip to content

Commit 4ebd82e

Browse files
committed
Numerics
1 parent be430e4 commit 4ebd82e

File tree

11 files changed

+368
-6
lines changed

11 files changed

+368
-6
lines changed

src/SUMMARY.md

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,7 @@ Make them do one. -->
532532
- [ZonedDateTime](./time/zoned_date_time.md)
533533
- [OffsetDateTime](./time/offset_date_time.md)
534534
- [Date](./time/date.md)
535+
- [Challenges](./time/challenges.md)
535536
- [ArrayList](./array_list.md)
536537
- [Ubiquity](./array_list/ubiquity.md)
537538
- [Add an item](./array_list/add_an_item.md)
@@ -593,7 +594,7 @@ Make them do one. -->
593594
- [Encapsulation](./encapsulation.md)
594595
- [Implementation Details](./encapsulation/implementation_details.md)
595596
- [Methods](./encapsulation/methods.md)
596-
- [Classes]()(./encapsulation/classes.md)
597+
- [Classes](./encapsulation/classes.md)
597598
- [Implicit Interfaces](./encapsulation/implicit_interfaces.md)
598599
- [Abstractions](./encapsulation/abstractions.md)
599600
- [Leaky Abstractions](./encapsulation/leaky_abstractions.md)
@@ -663,15 +664,24 @@ Make them do one. -->
663664
- [Static Methods]()
664665
- [Private Static Methods]()
665666
- [Class Extension](./class_extension.md)
667+
- [Extend a Class]()
668+
- [Protected Fields]()
669+
- [Protected Methods]()
670+
- [Relation to Interfaces]()
671+
- [Relation to Encapsulation]()
672+
- [Final Classes](./class_extension/final_classes.md)
666673
- [Abstract Classes](./abstract_classes.md)
674+
- [Relation to Interfaces]()
675+
667676

668677
# Data Types IV
669678

670-
- [Niche Numerics]()
671-
- [byte]()
672-
- [short]()
673-
- [long]()
674-
- [Unsigned Operations]()
679+
- [Niche Numerics](./niche_numerics.md)
680+
- [byte](./niche_numerics/byte.md)
681+
- [short](./niche_numerics/short.md)
682+
- [long](./niche_numerics/long.md)
683+
- [Unsigned Operations](./niche_numerics/unsigned_operations.md)
684+
- [float](./niche_numerics/float.md)
675685

676686
# Code Structure VIII
677687

src/class_extension.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
# Class Extension
2+

src/class_extension/final_classes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Final Classes
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Final Classes

src/niche_numerics.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Niche Numerics
2+
3+
For a surprisingly wide range of programs `int` and `double`
4+
(along with their boxed counterparts `Integer` and `Double`)
5+
are the only numeric types you will need.
6+
7+
Every now and then, however, you will want something more exotic[^wording].
8+
9+
```java
10+
~void main() {
11+
byte b = 123;
12+
13+
System.out.println(b);
14+
~}
15+
```
16+
17+
[^wording]: The reason I am calling these "exotic" and "niche" has nothing to do with how
18+
useful they are. If you want a `byte` then a `byte` is what you want. Its just that most
19+
of the time (in my experience) you can get by with a little help from your `int`s.

src/niche_numerics/byte.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# byte
2+
3+
A `byte` represents a signed value between `-128`
4+
and `127`.
5+
6+
```java
7+
~void main() {
8+
byte a = 127;
9+
System.out.println(a);
10+
byte b = -128;
11+
System.out.println(b);
12+
~}
13+
```
14+
15+
Operations like `+` and `*` on a `byte` will "promote" the result an `int`
16+
and you will need to cast the result. Going from an `int` to a `byte`
17+
is a narrowing conversion.
18+
19+
```java
20+
~void main() {
21+
byte a = 5;
22+
byte b = 6;
23+
// Need to cast the result to a (byte) again
24+
byte c = (byte) (a * b);
25+
System.out.println(c);
26+
~}
27+
```
28+
29+
Conversely, going from a `byte` to an `int` is a widening conversion and you won't
30+
need a cast.
31+
32+
```java
33+
~void main() {
34+
byte a = 5;
35+
int a2 = a; // Widening conversion
36+
System.out.println(a2);
37+
~}
38+
```
39+
40+
41+
And if you have need of a potentially nullable `byte`, `Byte` with a capital `B` is the boxed version.
42+
43+
```java
44+
~void main() {
45+
// Can't have a null "byte"
46+
// byte b = null;
47+
48+
// But you can have a null "Byte"
49+
Byte b = null;
50+
System.out.println(b);
51+
~}
52+
```
53+
54+
You will most often want a `byte` when you are trying to save space in memory.
55+
56+
```java,no_run
57+
// This array of 4 bytes
58+
byte[] bytes = { 1, 2, 3, 4 };
59+
// Will take up as much space as this
60+
// array with 1 int
61+
int[] oneInt = { 1 };
62+
```
63+
64+

src/niche_numerics/float.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# float
2+
3+
What `int` is to `long`, `float` is to `double`. Even the type name `double` implicitly means "double the size of a float." So if you want something half the size of a `double` you can use a `float`.
4+
5+
To write a float in a program you need to write `f` at the end of the floating
6+
point literal.
7+
8+
```java
9+
~void main() {
10+
float f = 3.5f;
11+
System.out.println(f);
12+
~}
13+
```
14+
15+
This is because Java sees floating point literals without a trailing `f` as representing a `double`.
16+
17+
```java,does_not_compile
18+
~void main() {
19+
float f = 3.5;
20+
System.out.println(f);
21+
~}
22+
```
23+
24+
Conversions from a `double` to a `float` are narrowing and require an explicit cast.
25+
Conversions from a `float` to a `double` are widening and do not require a cast.
26+
27+
```java
28+
~void main() {
29+
double a = 6.5;
30+
// Need a cast
31+
float b = (float) a;
32+
System.out.println(b);
33+
34+
float c = 9.5f;
35+
// Do not need a cast
36+
double d = c;
37+
System.out.println(d);
38+
~}
39+
```
40+
41+
And if you have need of a potentially nullable `float`, `Float` with a capital `F` is the boxed version.
42+
43+
```java
44+
~void main() {
45+
// Can't have a null "float"
46+
// float f = null;
47+
48+
// But you can have a null "Float"
49+
Float f = null;
50+
System.out.println(f);
51+
~}
52+
```
53+
54+
You will really only want a `float` when you are trying to save space in memory.
55+
Otherwise its best to just use a `double`.
56+
57+
```java,no_run
58+
// This array of 2 floats
59+
float[] floats = { 1.0f, 2.0f };
60+
// Will take up as much space as this
61+
// array with 1 double
62+
double[] oneDouble = { 1.0 };
63+
```

src/niche_numerics/long.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# long
2+
3+
If an `int` is not big enough for your needs, a `long` is twice as big as an `int`
4+
and can represent numbers from `-2^63` to `2^63 - 1`.
5+
6+
You can make a `long` from an integer literal, but integer literals do not
7+
normally allow for numbers that an `int` cannot store.
8+
9+
```java,does_not_compile
10+
~void main() {
11+
// Smaller numbers work without issue
12+
long smallNumber = 5;
13+
System.out.println(smallNumber);
14+
// This is too big for an int
15+
long bigNumber = 55555555555;
16+
System.out.println(bigNumber);
17+
~}
18+
```
19+
20+
For those cases you need to add an `L` to the end of the literal.[^lforlong]
21+
22+
```java
23+
~void main() {
24+
long smallNumber = 5;
25+
System.out.println(smallNumber);
26+
// But with an L at the end, its not too big for a long
27+
long bigNumber = 55555555555L;
28+
System.out.println(bigNumber);
29+
~}
30+
```
31+
32+
All operations with a `long` will result in a `long`. Conversions to `int` and
33+
other "smaller" integer types will be narrowing and require a cast.
34+
35+
```java
36+
~void main() {
37+
long a = 5;
38+
int b = 3;
39+
// a long times an int will result in a long
40+
long c = a * b;
41+
System.out.println(c);
42+
~}
43+
```
44+
45+
And if you have need of a potentially nullable `long`, `Long` with a capital `L` is the boxed version.
46+
47+
```java
48+
~void main() {
49+
// Can't have a null "long"
50+
// long l = null;
51+
52+
// But you can have a null "Long"
53+
Long l = null;
54+
System.out.println(l);
55+
~}
56+
```
57+
58+
The reason you will likely end up using `int` more than `long` is that `int`
59+
works more with other parts of Java. Like array indexing - you can't
60+
get an item in an array with a `long`, you need an `int` for that.
61+
62+
```java,does_not_compile
63+
~void main() {
64+
String[] sadRobots = { "2B", "9S", "A2" };
65+
long index = 2;
66+
// Longs can't be used as indexes
67+
String sadRobot = sadRobots[index];
68+
~}
69+
```
70+
71+
But there is nothing wrong with a `long`. If you need to represent a number that is potentially bigger than an `int` then it is useful.
72+
73+
74+
[^lforlong]: "L is for long" would be a total cop-out in a children's picture book.

src/niche_numerics/short.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# short
2+
3+
A `short` represents a signed value between `-32768`
4+
and `32767`. Representing a `short` takes twice as much memory as representing
5+
a `byte` and half as much memory as representing an `int`.
6+
7+
```java
8+
~void main() {
9+
short a = 32767;
10+
System.out.println(a);
11+
byte b = -32768;
12+
System.out.println(b);
13+
~}
14+
```
15+
16+
Operations like `+` and `*` on a `short` will "promote" the result an `int`
17+
and you will need to cast the result. Going from an `int` to a `short`
18+
is a narrowing conversion.
19+
20+
```java
21+
~void main() {
22+
short a = 5;
23+
short b = 6;
24+
// Need to cast the result to a (byte) again
25+
short c = (short) (a * b);
26+
System.out.println(c);
27+
~}
28+
```
29+
30+
Conversely, going from a `short` to an `int` is a widening conversion and you won't
31+
need a cast.
32+
33+
```java
34+
~void main() {
35+
short a = 5;
36+
int a2 = a; // Widening conversion
37+
System.out.println(a2);
38+
~}
39+
```
40+
41+
42+
And if you have need of a potentially nullable `short`, `Short` with a capital `S` is the boxed version.
43+
44+
```java
45+
~void main() {
46+
// Can't have a null "short"
47+
// short b = null;
48+
49+
// But you can have a null "Short"
50+
Short b = null;
51+
System.out.println(b);
52+
~}
53+
```
54+
55+
56+
A `short` also takes up exactly as much space as a `char` and converting between the two
57+
is allowed, but will still require an explicit cast in both directions.[^neither]
58+
59+
```java
60+
~void main() {
61+
short s = 50;
62+
char c = (char) s;
63+
s = (short) c;
64+
System.out.println(c);
65+
~}
66+
```
67+
68+
You will most often want a `short` when you are trying to save space in memory but
69+
need to represent numbers beyond what a `byte` can represent.[^rare]
70+
71+
```java,no_run
72+
// This array of 2 shorts
73+
short[] shorts = { 1, 2 };
74+
75+
// Will take up as much space as this
76+
// array with 1 int
77+
int[] oneInt = { 1 };
78+
79+
// And as much space as this array with 4 bytes
80+
byte[] bytes = { 1, 2, 3, 4 };
81+
```
82+
83+
84+
[^neither]: These are neither narrowing or widening conversions. Java just makes you put
85+
the cast. One way to view this is that when you go from a `short` to a `char` you've transformed a "number" into a "character." So while no information is lost, what the information "represents" has changed.
86+
87+
[^rare]: As you might suspect, this is more rare than the situations where you would want a `byte`.

0 commit comments

Comments
 (0)