Getting started with Java LanguageInheritanceStreamsExceptions and exception handlingCollectionsLambda ExpressionsGenericsFile I/OArraysInterfacesMapsStringsInputStreams and OutputStreamsDefault MethodsClasses and ObjectsBasic Control StructuresConcurrent Programming (Threads)Console I/OSingletonsVisibility (controlling access to members of a class)Regular ExpressionsAutoboxingDocumenting Java CodeExecutor, ExecutorService and Thread poolsObject Class Methods and ConstructorJAXBPrimitive Data TypesNetworkingOptionalEnumsHttpURLConnectionAnnotationsAudioDate ClassCalendar and its SubclassesNashorn JavaScript engineJava Native InterfaceRemote Method Invocation (RMI)Iterator and IterableOperatorsAssertingScannerProperties ClassPreferencesReflection APIConstructorsByteBufferSerializationJSON in JavaRandom Number GenerationRecursionPolymorphismStringBuilderReference Data TypesBit ManipulationJava AgentsEncapsulationType ConversionBigIntegerBigDecimalRSA EncryptionVarargs (Variable Argument)ThreadLocalLogging (java.util.logging)Using the static keywordDisassembling and DecompilingResources (on classpath)log4j / log4j2JVM FlagsOracle Official Code StandardCharacter encodingJava Memory ManagementImmutable ObjectsObject CloningAlternative CollectionsListsBufferedWriterLocalTimeSetsComparable and ComparatorJVM Tool InterfaceNested and Inner ClassesApache Commons LangGetters and SettersThe ClasspathBytecode ModificationXML Parsing using the JAXP APIsReference TypesLocalization and InternationalizationJAX-WSXML XPath EvaluationJava Performance TuningParallel programming with Fork/Join frameworkCommon Java PitfallsNon-Access ModifiersJava Compiler - 'javac'XJCProcessInstalling Java (Standard Edition)Command line Argument ProcessingDates and Time (java.time.*)Fluent InterfaceXOM - XML Object ModelJust in Time (JIT) compilerFTP (File Transfer Protocol)Java Native AccessModulesJava Pitfalls - Exception usageJava Pitfalls - Language syntaxServiceLoaderClassloadersObject ReferencesJava Pitfalls - Performance IssuesCreating Images ProgrammaticallyAppletsNIO - NetworkingNew File I/OSecure objectsJava Pitfalls - Threads and ConcurrencySplitting a string into fixed length partsJava Pitfalls - Nulls and NullPointerExceptionSecurityManagerJNDIsuper keywordThe java.util.Objects ClassThe Java Command - 'java' and 'javaw'Atomic TypesJava Floating Point OperationsConverting to and from Stringssun.misc.UnsafeJava Memory ModelJava deploymentJava plugin system implementationsQueues and DequesRuntime CommandsNumberFormatSecurity & CryptographyJava Virtual Machine (JVM)Unit TestingJavaBeanExpressionsLiteralsJava SE 8 FeaturesJava SE 7 FeaturesPackagesCurrency and MoneyConcurrent CollectionsUsing ThreadPoolExecutor in MultiThreaded applications.Java Editions, Versions, Releases and DistributionsDynamic Method DispatchJMXSecurity & CryptographyGenerating Java CodeJShellBenchmarksCollection Factory MethodsMulti-Release JAR FilesStack-Walking APITreeMap and TreeSetSocketsJava SocketsUsing Other Scripting Languages in JavaFunctional InterfacesList vs SET2D Graphics in JavaClass - Java ReflectionDequeue InterfaceEnum MapEnumSet classLocal Inner ClassJava Print ServiceImmutable ClassString TokenizerFileUpload to AWSAppDynamics and TIBCO BusinessWorks Instrumentation for Easy IntegrationReaders and WritersHashtableEnum starting with numberSortedMapWeakHashMapLinkedHashMapStringBufferChoosing CollectionsC++ ComparisonCompletableFuture

Autoboxing

Other topics

Using int and Integer interchangeably

As you use generic types with utility classes, you may often find that number types aren't very helpful when specified as the object types, as they aren't equal to their primitive counterparts.

List<Integer> ints = new ArrayList<Integer>();
Java SE 7
List<Integer> ints = new ArrayList<>();

Fortunately, expressions that evaluate to int can be used in place of an Integer when it is needed.

for (int i = 0; i < 10; i++)
    ints.add(i);

The ints.add(i); statement is equivalent to:

ints.add(Integer.valueOf(i));

And retains properties from Integer#valueOf such as having the same Integer objects cached by the JVM when it is within the number caching range.

This also applies to:

  • byte and Byte
  • short and Short
  • float and Float
  • double and Double
  • long and Long
  • char and Character
  • boolean and Boolean

Care must be taken, however, in ambiguous situations. Consider the following code:

List<Integer> ints = new ArrayList<Integer>();
ints.add(1);
ints.add(2);
ints.add(3);
ints.remove(1); // ints is now [1, 3]

The java.util.List interface contains both a remove(int index) (List interface method) and a remove(Object o) (method inherited from java.util.Collection). In this case no boxing takes place and remove(int index) is called.

One more example of strange Java code behavior caused by autoboxing Integers with values in range from -128 to 127:

Integer a = 127;
Integer b = 127;
Integer c = 128;
Integer d = 128;
System.out.println(a == b); // true
System.out.println(c <= d); // true
System.out.println(c >= d); // true
System.out.println(c == d); // false

This happens because >= operator implicitly calls intValue() which returns int while == compares references, not the int values.

By default, Java caches values in range [-128, 127], so the operator == works because the Integers in this range reference to the same objects if their values are same. Maximal value of the cacheable range can be defined with -XX:AutoBoxCacheMax JVM option. So, if you run the program with -XX:AutoBoxCacheMax=1000, the following code will print true:

Integer a = 1000;
Integer b = 1000;
System.out.println(a == b); // true

Using Boolean in if statement

Due to auto unboxing, one can use a Boolean in an if statement:

Boolean a = Boolean.TRUE;
if (a) { // a gets converted to boolean
    System.out.println("It works!");
}

That works for while, do while and the condition in the for statements as well.

Note that, if the Boolean is null, a NullPointerException will be thrown in the conversion.

Auto-unboxing may lead to NullPointerException

This code compiles:

Integer arg = null;
int x = arg;

But it will crash at runtime with a java.lang.NullPointerException on the second line.

The problem is that a primitive int cannot have a null value.

This is a minimalistic example, but in practice it often manifests in more sophisticated forms. The NullPointerException is not very intuitive and is often little help in locating such bugs.

Rely on autoboxing and auto-unboxing with care, make sure that unboxed values will not have null values at runtime.

Memory and Computational Overhead of Autoboxing

Autoboxing can come at a substantial memory overhead. For example:

Map<Integer, Integer> square = new HashMap<Integer, Integer>();
for(int i = 256; i < 1024; i++) {
    square.put(i, i * i); // Autoboxing of large integers
}

will typically consume substantial amount of memory (about 60kb for 6k of actual data).

Furthermore, boxed integers usually require additional round-trips in the memory, and thus make CPU caches less effective. In above example, the memory accessed is spread out to five different locations that may be in entirely different regions of the memory: 1. the HashMap object, 2. the map's Entry[] table object, 3. the Entry object, 4. the entrys key object (boxing the primitive key), 5. the entrys value object (boxing the primitive value).

class Example {
  int primitive; // Stored directly in the class `Example`
  Integer boxed; // Reference to another memory location
}

Reading boxed requires two memory accesses, accessing primitive only one.

When getting data from this map, the seemingly innocent code

int sumOfSquares = 0;
for(int i = 256; i < 1024; i++) {
    sumOfSquares += square.get(i);
}

is equivalent to:

int sumOfSquares = 0;
for(int i = 256; i < 1024; i++) {
    sumOfSquares += square.get(Integer.valueOf(i)).intValue();
}

Typically, the above code causes the creation and garbage collection of an Integer object for every Map#get(Integer) operation. (See Note below for more details.)

To reduce this overhead, several libraries offer optimized collections for primitive types that do not require boxing. In addition to avoiding the boxing overhead, these collection will require about 4x less memory per entry. While Java Hotspot may be able to optimize the autoboxing by working with objects on the stack instead of the heap, it is not possible to optimize the memory overhead and resulting memory indirection.

Java 8 streams also have optimized interfaces for primitive data types, such as IntStream that do not require boxing.

Note: a typical Java runtime maintains a simple cache of Integer and other primitive wrapper object that is used by the valueOf factory methods, and by autoboxing. For Integer, the default range of this cache is -128 to +127. Some JVMs provide a JVM command-line option for changing the cache size / range.

Different Cases When Integer and int can be used interchangeably

Case 1: While using in the place of method arguments.

If a method requires an object of wrapper class as argument.Then interchangeably the argument can be passed a variable of the respective primitive type and vice versa.

Example:

int i;
Integer j;
void ex_method(Integer i)//Is a valid statement
void ex_method1(int j)//Is a valid statement

Case 2: While passing return values:

When a method returns a primitive type variable then an object of corresponding wrapper class can be passed as the return value interchangeably and vice versa.

Example:

int i;
Integer j;
int ex_method()
{...
return j;}//Is a valid statement
Integer ex_method1()
{...
return i;//Is a valid statement
}

Case 3: While performing operations.

Whenever performing operations on numbers the primitive type variable and object of respective wrapper class can be used interchangeably.

int i=5;
Integer j=new Integer(7);
int k=i+j;//Is a valid statement
Integer m=i+j;//Is also a valid statement

Pitfall:Remember to initialize or assign a value to an object of the wrapper class.

While using wrapper class object and primitive variable interchangeably never forget or miss to initialize or assign a value to the wrapper class object else it may lead to null pointer exception at runtime.

Example:

public class Test{
    Integer i;
    int j;
    public void met()
    {j=i;//Null pointer exception
    SOP(j);
    SOP(i);}   
    public static void main(String[] args)
    {Test t=new Test();
    t.go();//Null pointer exception
    }

In the above example, the value of the object is unassigned and uninitialized and thus at runtime the program will run into null pointer exception.So as clear from the above example the value of object should never be left uninitialized and unassigned.

Contributors

Topic Id: 138

Example Ids: 538,2045,10510,10864,23629

This site is not affiliated with any of the contributors.