Working with Java data types
- Use primitives and wrapper classes, including, operators, parentheses, type promotion and casting
- Handle text using
String
andStringBuilder
classes- Use local variable type inference, including as lambda parameters
Java primitive types are boolean
(false
andtrue
as possible values),char
,byte
,short
(16-bit long),int
,long
(64-bit long),float
anddouble
Rule(s)
- Primitive types have equivalent wrapper types:
Boolean
,Character
…, which must be used in generics.- Non-primitive types are constructed as data structures by means of the
class
keyword. Note thatString
in Java is not a primitive type!- The
interface
keyword is also part of the Java typing system.- Differently from C++,
void
cannot be used as the type of a variable. However, as a Java construct,void
is itself the unique instance of a type. More precisely,java.lang.Void
conveys us to the type ofvoid
as shown in the following example.Example Primitive_types.Java.zip
try { assert (java.lang.Void.class == void.class); // The 'Void' type *IS NOT* itself the direct type of 'void' assert (java.lang.Void.TYPE == void.class); // Yes, it works! } catch (AssertionError ae) { // Run program with '-ea' option System.err.println(ae.getMessage()); // Error comes from first assertion! }
Rule(s)
- Differently from C++, Java primitive types have fixed sizes. For example, the size of
short
is 16-bit long. Variation intervals are accessible through wrapper types, for example: [Short.MIN_VALUE
(- 215)Short.MAX_VALUE
(215 - 1)].- Common types are:
java.lang.Object
(single root of inheritance graph),java.lang.System
,java.lang.Error
, etc. From Java 5, there is a seamless mapping (the idea of “autoboxing”) between primitive types and their counterparts as wrapper types in the Java kernel, i.e.,java.lang
.Example
float x = 1.F; Float y = new Float(1.F); // Heavy style, to be avoided… float z = x + y; // Autoboxing: 'float' and 'Float' are seamlessly compatible
Rule(s)
- The type of a variable can be tested by means of the
instanceof
operator with limitations.Example Primitive_types.Java.zip
int i; // assert(i instanceof int); // Type of a variable like 'i' having a primitive type like 'int' cannot be tested (compilation error) // assert(i instanceof Integer); // Compilation error as well... String surname = "Barbier"; assert(surname instanceof String); // This works (no assertion error at execution time)! Don't forget that 'java.lang.String' is not a primitive but a constructed type
Example
public class User_defined_type { boolean attribute0; byte attribute1; short attribute2; int attribute3; long attribute4; float attribute5; double attribute6; char attribute7; public static void main(String[] args) { User_defined_type object = new User_defined_type(); object.attribute0 = true; System.out.println(object.attribute0); // 'true' object.attribute1 = '\r'; System.out.println(object.attribute1); // '13' object.attribute2 = 0x7777; System.out.println(object.attribute2); // '30583' object.attribute3 = 0xFFFFFFFF; System.out.println(object.attribute3); // '-1' object.attribute4 = Long.MAX_VALUE; System.out.println(object.attribute4); // '9223372036854775807' object.attribute5 = 6.5E1F; System.out.println(object.attribute5); // '65.0' object.attribute6 = 7.2e-2D; System.out.println(object.attribute6); // '0.072' object.attribute7 = 66; System.out.println(object.attribute7); // 'B' } }
Rule(s)
- The necessity of converting a type to another or more generally mixing objects/variables with different types in expressions calls for type promotion and casting.
Example
short s1 = 0; int i = s1; // Type promotion... short s2 = (short) i; // Casting with possible undesired side effects (data loss)...
Rule(s)
- Strings are immutable objects in Java.
Example
StringBuilder s = new StringBuilder(""); s.append("Franck"); s.append(' '); s.append("Barbier"); String s1 = "", s2 = s1; assert (s1 == s2); s1 += "Franck"; // 's1' refers to a *NEW* memory object... s1 += ' '; // Again, 's1' refers to a *NEW* memory object... s1 += "Barbier"; // And, again, 's1' refers to a *NEW* memory object... assert(s1 != s2);
Basic (i.e., primitive) arrays in Java Rule(s)
- Java basic arrays, e.g.,
char given_name[] = {'F','r','a','n','c','k'};
are values of a primitive type (this is similar to JavaScript arrays).Example
assert (!(given_name instanceof Object)); // So, primitive type... assert (given_name.getClass() == char[].class); // More precisely...
Rule(s)
- Java primitive arrays have elements, whose type may be primitive or not.
Example
Object tab[] = new Object[1000]; String another_tab[] = new String[1000]; assert(tab instanceof Object[]); assert(another_tab instanceof Object[]); // Initialization: Object my_tab[] = new Object[]{new Object()}; // 'my_tab' is created with one object inside at position '0' assert(my_tab.length == 1);
Rule(s)
- The use of primitive arrays is questionable since generic “containers” exist in Java, e.g.,
java.util.ArrayList<E>
. Primitive arrays are useful when array size is steady in a Java program. Instead, generic arrays may grow or slim on demand without specific memory management.
java.lang.Object
class
Rule(s)
java.lang.Object
class is the root of the Java inheritance tree. By default, unless an explicit inheritance declaration, any constructed class inherits fromjava.lang.Object
. So,public User_defined_type extends java.lang.Object { …
is totally equivalent topublic User_defined_type { …
. This behavior is fairly different from C++, which has no inheritance graph root.Multithreading related method(s) in
java.lang.Object
void wait() throws InterruptedException // + variants void notify() // + variants
Object identity related method(s) in
java.lang.Object
protected Object clone() throws CloneNotSupportedException boolean equals(Object object) int hashCode()
Example Hashtable_illustration.Java.zip
String s1 = "Franck"; String s2 = "Franck"; assert (s1 != s2); // 's1' and 's2' are NOT the same memory object assert (s1.equals(s2)); // However, 's1' equals to 's2' assert (s1.hashCode() == s2.hashCode());
Utility related method(s) in
java.lang.Object
String toString()
Finalization related method(s) in
java.lang.Object
protected void finalize() throws Throwable
Example
System.finalization(); // Alternatively: Runtime.getRuntime().runFinalization();
Rule(s)
- As statically typed programming language, Java imposes the typing of objects. Usages are then checked by the compiler in conformance with “announced” types. Contrary to JavaScript or Python, anomalies as potential execution errors are eliminated at compilation time (execution time for JavaScript or Python). Nonetheless, “type announcement” may create no added-value code. In this scope, type inference is the ability of the compiler to derive the type of an object.
- From Java 10, the
var
keyword forces the compiler to establish the type an object on its own.
var
keyword (Java 10)Example (diamond-based instantiation omits effective type(s) in place of generic type(s))
java.util.Map<Integer, Double> polynomial = new java.util.HashMap<>(); polynomial.put(1, -12.D); polynomial.put(39, 8.D);
Example
// var polynomial = new java.util.HashMap<>(); // Danger => 'java.util.HashMap<Object,Object>' var polynomial = new java.util.HashMap<Integer, Double>(); // Diamond-based instantiation is avoided with 'var'... polynomial.put(1, -12.D); polynomial.put(39, 8.D);
var
keyword in conjunction with lambda expression (Java 11)Rule(s)
- From Java 11, the
var
keyword is allowed in lambda expression syntax.Example From_Java_9.Java.zip
var positives = java.util.Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); var stream = positives.stream().filter((var p) -> p > 1 && java.util.stream.IntStream.rangeClosed(2, (int) Math.sqrt(p)).noneMatch((var i) -> (p % i == 0))); var primes = stream.collect(java.util.stream.Collectors.toList()); primes.forEach((var p) -> System.out.print(" " + p)); // '2 3 5 7 11' is displayed...
Rule(s)
- The
var
keyword may seem useless since the type of lambda expression parameters is “naturally” inferred. However, special cases show the relative interest ofvar
.Example From_Java_9.Java.zip (annotation imposes
Integer
andint
as types of lambda expression parameters)@java.lang.annotation.Target(value = java.lang.annotation.ElementType.PARAMETER) @interface Must_be_positive { } … var stream = positives.stream().filter((@Must_be_positive Integer p) -> p > 1 && java.util.stream.IntStream.rangeClosed(2, (int) Math.sqrt(p)).noneMatch((@Must_be_positive int i) -> (p % i == 0))); … primes.forEach((@Must_be_positive Integer p) -> System.out.print(" " + p)); // '2 3 5 7 11' is displayed...
Example From_Java_9.Java.zip (using
var
ejectsInteger
andint
)… var stream = positives.stream().filter((@Must_be_positive var p) -> p > 1 && java.util.stream.IntStream.rangeClosed(2, (int) Math.sqrt(p)).noneMatch((@Must_be_positive var i) -> (p % i == 0))); … primes.forEach((@Must_be_positive var p) -> System.out.print(" " + p)); // '2 3 5 7 11' is displayed...
See also