Data Types _______________⇓_______________ ↓ ↓ Primitive Types Reference Types _________________________⇓_________________________ ↓ ↓ ↓ Interface Class Array
boolean
char
byte
, short
, int
, long
float
, double
byte
→ short
→ int
→ long
char
→ int
int
→ long
→ float
→ double
int
→ float
long
→ float
long
→ double
long value = intValue;Otherwise, you need to manually cast the value from one type to another:
int value = (int) longValue;Note that the value might be truncated if it exceeds the numeric range supported by the target type:
byte value = (byte) 128; // "value" will be equal to -128When applying a binary operator to operands of different types, the following rules apply:
double
, the other will be converted to double
float
, the other will be converted to float
long
, the other will be converted to long
int
(byte
, short
, and char
operands are always promoted to int
)boolean
can hold the values true
or false
.char
can hold characters.char c1 = 'a';A variable of type
char
can also hold positive integers.char
can hold values in the range: [0, 65535]cast
is required to assign an integer value to a variable of type char
.char c2 = (char) 65535;A character can be expressed as a hexadecimal value using the prefix \u
char c3 = '\u005B';Escape Characters:
escape character | unicode value | name
\" | \u0022 | Double quote \' | \u0027 | Single quote \\ | \u005c | Backslash \t | \u0009 | Tab \n | \u000a | Line feed \r | \u000d | Carriage return \b | \u0008 | BackspaceUnicode escape characters are interpreted before the code is parsed.
System.out.println("\u0022 + \u0022"); System.out.println("" + "");
char c\u0061 = 'x'; System.out.println(ca); // \u0061 in the identifier becomes the letter 'a'
System.out.println("" "");
:System.out.println("\u0022 \u0022");
// the line feed \u000a will cause multiple compiler errors
// invalid unicode: missing the 4 hex digits after \u: \unicode
char
can hold any 16-bit (basic) Unicode character.
For supplementary Unicode characters, each character has a code value (code point) that is represented as a pair of 16-bit code units.
When working with strings that may include supplementary Unicode characters,
you should be aware that a char
value might hold just one of the code units representing such a character.
For example, the smiley symbol "🙂" is represented using 2 code units:
String smiley = "🙂"; System.out.println(smiley.length()); // code units count: 2 System.out.println(smiley.codePointCount(0, smiley.length())); // code points count: 1 System.out.println(String.format("%X", (int) smiley.charAt(0))); // first code unit D83D of the smiley character System.out.println(String.format("%X", (int) smiley.charAt(1))); // second code unit DE42 of the smiley character System.out.println(String.format("%X", smiley.codePointAt(0))); // code point 1F642 of the smiley characterIf you need to print all characters in a string, use the
codePoints
method of the String
class:
"mti🙂tek".codePoints().forEach(cp -> System.out.println(new String(Character.toChars(cp))));
m t i 🙂 t e kSee the Java API documentation for how to use the
Character.toChars
method:
public static char[] toChars(int codePoint) //Converts the specified character (Unicode code point) to its UTF-16 representation stored in a char array. //If the specified code point is a BMP (Basic Multilingual Plane or Plane 0) value, the resulting char array has the same value as codePoint. //If the specified code point is a supplementary code point, the resulting char array has the corresponding surrogate pair. //Parameters: //codePoint - a Unicode code point //Returns: //a char array containing the UTF-16 representation of the code point.
byte
can hold both positive and negative values.byte
can hold values in the range [-128, 127].byte
, short
, int
, long
).byte
type with 8 bits, the bit weights are:Bit Position | 7 (MSB) | 6 | 5 | 4 | 3 | 2 | 1 | 0 (LSB) |
---|---|---|---|---|---|---|---|---|
Weight | -128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
(-128 × bit7) + (64 × bit6) + (32 × bit5) + (16 × bit4) + (8 × bit3) + (4 × bit2) + (2 × bit1) + (1 × bit0)
00000001 = (-128×0) + (64×0) + (32×0) + (16×0) + (8×0) + (4×0) + (2×0) + (1×1) = 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 = 1 10000001 = (-128×1) + (64×0) + (32×0) + (16×0) + (8×0) + (4×0) + (2×0) + (1×1) = -128 + 0 + 0 + 0 + 0 + 0 + 0 + 1 = -127 11111111 = (-128×1) + (64×1) + (32×1) + (16×1) + (8×1) + (4×1) + (2×1) + (1×1) = -128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = -1 1000 0000 = (-128×1) + (64×0) + (32×0) + (16×0) + (8×0) + (4×0) + (2×0) + (1×0) = -128 + 0 + 0 + 0 + 0 + 0 + 0 + 0 = -128
short
can hold both positive and negative values.short
can hold values in the range [-32,768, 32,767].byte
, two's complement representation is used to represent short
values.int
can hold both positive and negative values.int
can hold values in the range [-2,147,483,648 to 2,147,483,647].byte
, two's complement representation is used to represent int
values.long
can hold both positive and negative values.long
can hold values in the range [-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807].byte
, two's complement representation is used to represent long
values.long l1 = 1l; long l2 = 1L;
float
can hold real numbers.// 1.0 is a double literal by default, which is why the explicit cast or f suffix is needed. float f1 = 1.0; // compiler error: "Type mismatch: cannot convert from double to float" float f2 = (float) 1.0; // OK float f3 = 1.0f; // OK float f4 = 1.0F; // OKConstant holding the positive infinity of type float:
/** * A constant holding the positive infinity of type float. * It is equal to the value returned by Float.intBitsToFloat(0x7f800000). */ float POSITIVE_INFINITY = 1.0f / 0.0f;Constant holding the negative infinity of type float:
/** * A constant holding the negative infinity of type float. * It is equal to the value returned by Float.intBitsToFloat(0xff800000). */ float NEGATIVE_INFINITY = -1.0f / 0.0f;Constant holding a Not-a-Number (NaN) value of type float:
/** * A constant holding a Not-a-Number (NaN) value of type float. * It is equivalent to the value returned by Float.intBitsToFloat(0x7fc00000). */ float NaN = 0.0f / 0.0f;Check if a variable is not a number:
if (Float.isNaN(f3))The following is always false (use Float.isNaN instead):
if (f3 == Float.NaN)Check if a variable is positive infinity:
if (f3 == Float.POSITIVE_INFINITY)Check if a variable is negative infinity:
if (f3 == Float.NEGATIVE_INFINITY)Check if a variable is a finite floating-point value:
if (Float.isFinite(f3))Check if a variable is either positive infinity or negative infinity:
if (Float.isInfinite(f3))
double
can hold real numbers.double d1 = 1.0; // OK double d2 = 1.0d; // OK double d3 = 1.0D; // OKConstant holding the positive infinity of type double:
/** * A constant holding the positive infinity of type double. * It is equal to the value returned by Double.longBitsToDouble(0x7ff0000000000000L). */ double POSITIVE_INFINITY = 1.0 / 0.0;Constant holding the negative infinity of type double:
/** * A constant holding the negative infinity of type double. * It is equal to the value returned by Double.longBitsToDouble(0xfff0000000000000L). */ double NEGATIVE_INFINITY = -1.0 / 0.0;Constant holding a Not-a-Number (NaN) value of type double:
/** * A constant holding a Not-a-Number (NaN) value of type double. * It is equivalent to the value returned by Double.longBitsToDouble(0x7ff8000000000000L). */ double NaN = 0.0d / 0.0;Check if a variable is not a number:
if (Double.isNaN(d1))The following is always false (use Double.isNaN instead):
if (d1 == Double.NaN)Check if a variable is positive infinity:
if (d1 == Double.POSITIVE_INFINITY)Check if a variable is negative infinity:
if (d1 == Double.NEGATIVE_INFINITY)Check if a variable is a finite floating-point value:
if (Double.isFinite(d1))Check if a variable is either positive infinity or negative infinity:
if (Double.isInfinite(d1))
final
keyword.public class MyClass { void foo() { Integer var1; // The variable var1 will always be of type Integer!!! } }
final
keyword, then once it is initialized, its value cannot be changed (in other words, the variable cannot reference another object).public class MyClass { void foo() { Integer var1 = Integer.valueOf(0); final Integer var2 = Integer.valueOf(0); var1 = Integer.valueOf(10); // OK var2 = Integer.valueOf(20); // Compiler error: The final local variable var2 cannot be assigned. It must be blank and not using a compound assignment } }
public class MyClass { void foo() { Integer var1 = Integer.valueOf(0); // OK: referenced object is the same type (Integer) as variable var1 Object var2 = Integer.valueOf(0); // OK: referenced object type (Integer) is a subtype of variable var2’s type (Object) String var3 = var1; // Compiler error: Type mismatch: cannot convert from Integer to String String var4 = var2; // Compiler error: Type mismatch: cannot convert from Object to String } }
public class MyClass { void foo() { Integer var1 = Integer.valueOf(0); Object var2 = Integer.valueOf(0); var1.intValue(); var2.intValue(); // Compiler error: The method intValue() is undefined for the type Object } }
public abstract interface MyInterfaceType {}
public
and abstract
modifiers.public
access modifier (in this case it will have default access).abstract
modifier; an interface can contain method declarations as well as methods with the default modifier.protected
or private
.static
or final
.public abstract interface MyInterfaceType { public final static Integer ADD_OPERATION_ID = 0; Integer MULTIPLY_OPERATION_ID = 1; }
public
, final
, and static
.public
, final
, and static
;
the compiler adds them by default.protected
or private
.public abstract interface MyInterfaceType { public abstract Integer addOperation(Integer value1, Integer value2); Integer multiplyOperation(Integer value1, Integer value2); default Integer identity(Integer i) { return i;} }
public
and abstract
.public
and abstract
; the compiler adds them by default.protected
or private
.final
(because of the abstract
keyword), native
, or strictfp
.abstract
keyword) unless they are marked as default
.static
modifier and must provide an implementation.public
access modifier (which is implicit if omitted).extends
) only other interfaces (it cannot extend classes).package com.mtitek.inheritance; interface MyInterface1 { public void doAction1(); } interface MyInterface2 { public void doAction2(); } interface MyInterface3 extends MyInterface1, MyInterface2 { public void doAction3(); }
implements
) multiple interfaces.package com.mtitek.inheritance; interface MyInterface1 { public void doAction1(); } interface MyInterface2 { public void doAction2(); } interface MyInterface3 { public void doAction3(); }
/* The class "SuperClass1" is abstract, so it is not required to implement any of the methods from the interfaces "MyInterface1" and "MyInterface2". */ abstract class SuperClass1 implements MyInterface1, MyInterface2 { @Override public void doAction1() { } }
/* The class "SuperClass2" is not required to implement the method "doAction1" because it is already implemented by the class "SuperClass1". */ class SuperClass2 extends SuperClass1 implements MyInterface3 { @Override public void doAction2() { } @Override public void doAction3() { } }
/* The class "SubClass1" is not required to implement any methods because they are already implemented by its superclasses. */ class SubClass1 extends SuperClass2 implements MyInterface2 { }
default
modifier and must provide an implementation.public
access modifier (which is implicit if omitted).abstract
, static
, final
, native
, strictfp
, or synchronized
.protected
or private
.interface MyInterface4 { // Abstract method public abstract void doAction1(); // Default method default void doAction2() { doAction3(); // OK: can call private methods doAction4(); // OK: can call static methods } // Static method static void doAction3() { System.out.println("This is a static method"); } // Private method private void doAction4() { System.out.println("This is a private method"); } }
public class MyClass4 { public static void main(String[] args) { MyInterface4 myInterface4 = new MyInterface4() { @Override public void doAction1() { System.out.println("This is the implementation of the abstract method"); } }; myInterface4.doAction1(); myInterface4.doAction2(); MyInterface4.doAction3(); } }
InterfaceName.super.methodName()
interface MyInterface5 { default void doAction1() { System.out.println("Default from MyInterface5"); } } interface MyInterface6 { default void doAction1() { System.out.println("Default from MyInterface6"); } } // Case 1: implements interface with default method class MyClass5 implements MyInterface5 { public void doAction2() { doAction1(); // uses default implementation } } // Case 2: implements interface + overrides default method class MyClass6 implements MyInterface5 { @Override public void doAction1() { System.out.println("Overridden in MyClass6"); MyInterface5.super.doAction1(); // Can call default implementation } public void doAction3() { doAction1(); // uses overridden method } } // Case 3: Diamond problem - must resolve conflict class MyClass7 implements MyInterface5, MyInterface6 { @Override public void doAction1() { System.out.println("Overridden in MyClass7"); MyInterface5.super.doAction1(); // Must choose implementation to resolve conflict } public void doAction4() { doAction1(); // uses overridden method } }
public class MyClass8 { public static void main(String[] args) { new MyClass5().doAction1(); // call MyInterface5 new MyClass5().doAction2(); // call MyClass5 new MyClass6().doAction1(); // call MyClass6 new MyClass6().doAction3(); // call MyClass6 new MyClass7().doAction1(); // call MyClass7 new MyClass7().doAction4(); // call MyClass7 } }
extends
) only one class.implements
) multiple interfaces.new
).this
.final
, static
, or abstract
.class MyClassType implements MyInterfaceType { MyClassType() { // constructor code } @Override public Integer addOperation(Integer value1, Integer value2) { return value1 + value2; } @Override public Integer multiplyOperation(Integer value1, Integer value2) { return value1 * value2; } }
Object
type structure that can hold a fixed number of elements of the same type (primitive or reference).int myIntsArray[] = new int[10]; myIntsArray[0] = 3; System.out.println(myIntsArray.length); // 10 System.out.println(myIntsArray[0]); // 3Declare an array that can hold objects:
Object[] myObjectsArray = new Object[5]; myObjectsArray[0] = Integer.valueOf(7); System.out.println(myObjectsArray.length); // 5 System.out.println(myObjectsArray[0]); // 7Declare a String array and initialize it with initial values:
String[] myStringsArray = {"value1", "value2"}; // explicit syntax: String[] myStringsArray = new String[] {"value1", "value2"};Declare an Object array and initialize it with initial values:
Object[] myComplexObjectsArray = { myStringsArray, myObjectsArray, myIntsArray }; // explicit syntax: Object[] myComplexObjectsArray = new Object[] { myStringsArray, myObjectsArray, myIntsArray };Declare a 2-dimensional array and initialize it with initial values:
String[][] myStringsArray2D = {{"value11", "value12"}, {"value21", "value22"}, {"value31", "value32"}, {"value41", "value42"}}; // explicit syntax: String[][] myStringsArray2D = new String[][] {{"value11", "value12"}, {"value21", "value22"}, {"value31", "value32"}, {"value41", "value42"}}; System.out.println(myStringsArray2D.length); // 4 System.out.println(myStringsArray2D[0].length); // 2Declare an empty array:
String[] emptyArray1 = new String[0]; String[] emptyArray2 = {}; String[] emptyArray3 = new String[] {}; System.out.println(emptyArray1.length); // 0 System.out.println(emptyArray2.length); // 0 System.out.println(emptyArray3.length); // 0To iterate over an array, use a "
for-each
" loop: for (type element : array) statement
copyOf
" method of the "Arrays
" class: Arrays.copyOf(array, array.length)
sort
" method of the "Arrays
" class: Arrays.sort(array)