Java Buzzwords

You will hear and see quite a few Java buzzwords in the Java world. It’s important to know the Java buzzwords because they represent the factors that have played important roles in shaping the Java language. These words are summarized in Table 1-3.

Buzzword

Description

Architecture neutral The Java compiler compiles the source code into bytecode, whichdoes not depend upon any machine architecture, but can be easilytranslated into a specific machine by a JVM for that machine.
Distributed Java offers extensive support for the distributed environment of theInternet.
Dynamic New code can be added to the libraries without affecting theapplications that are using the libraries, runtime type informationcan be found easily, and so on.
High performance The Just-In-Time (JIT) compilers improve the performance ofinterpreting the bytecode by caching the interpretations.
Interpreted The Java compiler compiles the source code into bytecode, whichcan be executed on any machine by the Java interpreter of anappropriate JVM.
Multithreaded Java provides support for multithreaded programming.
Object oriented Java supports the features and philosophy of object-orientedprogramming.
Portable There are no implementation-dependent aspects of the languagespecifications. For example, the sizes of primitive data types and thebehavior of the arithmetic on them are specified. This contributes tomaking programs portable among different platforms such asWindows, Mac, and Unix.
Robust Java provides support for error checking at various stages: earlychecking at compile time, and dynamic checking at runtime. Thiseliminates some situations that are error prone such as pointers inthe C language.
Secure Because Java supports the distributed environment of the Internet,it also offers multiple security features.
Simple Java omits many clumsy and confusing features of otherprogramming languages such as C++. Also, Java is designed to beable to run stand-alone on small machines. The size of the basicinterpreter and class support is 40 KB.

The most popular buzzwords are architecture neutral (or platform independent), object oriented, and portable.

The three most important takeaways from this chapter are the following:

  • You write a computer program in a high-level language and use the compiler to convert it into an executable program that will actually be executed by the computer.
  • Following the underlying philosophy of object-oriented programming, Java allows you to adapt computing to the problem that you are trying to solve by directly representing the objects in the problem with objects in the Java program. The objects are created from classes that you write.
  • The Java compiler creates bytecode that can be translated by a Java virtual machine (JVM) for a specific platform, such as Windows, Solaris, or Mac, into executable instructions. So, a Java program written once can be run on different platforms by using different JVMs.

The Memory Usage by a Java Program

The instructions of a running program and the related data are temporarily stored in the computer memory. Java has good news for you here: you don’t need to worry about memory management because the JVM and garbage collector will take care of it. However, you can help by being aware of where different things are stored in the memory. This will also help you to understand how objects are created. As shown in Figure 1-4, a program’s data is placed in two different areas in memory: the stack and the heap. Stack and heap refers to the different ways (or places) to store the elements of a running program in memory.

Java Memory Stack Heap

Living on the Stack

The following elements of a Java program live on the stack:

  • Local variables: The variables of primitive types defined inside a method or as method parameters.
  • Local reference variables: The variables that refer to an object and are defined inside a method or as a method parameter. Remember that an object that a local variable refers to lives on the heap and not on the stack.
  • Method invocations: When you invoke (call) a method, the method is pushed onto the stack (that is, placed on top of the stack).

Local variables live inside a method, and the scope of a local variable is the execution of the method. When the method execution is complete, the local variables inside the method are gone. But the objects, to which some of these local variables may be referring, are still alive and well on the heap.

Living on the Heap

The following elements of a Java program live on the heap:

  • Instance variables: The variables of primitive types defined inside a class but outside of all its methods.
  • Instance reference variables: The variables that refer to an object and are defined inside a class but outside of all its methods.
  • Objects: Represent the entities in the real-world problem that the Java program is trying to solve. All the objects live on the heap, always.

Remembering whether a particular element lives on the stack or on the heap is easy: a local variable (primitive or reference) belongs to a method and lives with it on the stack, while an instance variable belongs to an object and lives with it on a heap. However, also note that a local reference variable on a stack points to an object on the heap, and the object will not die with the local reference variable.

The objects on the heap that are no longer in use are eventually collected by a program called a garbage collector to free up the memory used by them. For this reason, the heaps are also called garbage-collectible heaps.

The instanceof Operator in Java

The instanceof operator determines if a given object is of the type of a specific class. To be more specific, the instanceof operator tests whether its first operand is an instance of its second operand. The test is made at runtime. The first operand is supposed to be the name of an object or an array element, and the second operand is supposed to be the name of a class, interface, or array type. The syntax is

<op1> instanceof <op2>

The result of this operation is a boolean: true or false. If an object specified by <op1> is an instance of a class specified by <op2>, the outcome of the operation is true, and otherwise is false. The outcome of the operation will also be true if <op2> specifies an interface that is implemented either by the class of the object specified by <op1> or by one of its superclasses. For example, consider the following code fragment:

interface X{}
class A implements X {}
class B extends A {}
A a = new A();
B b = new B();

Note that class B does not implement the interface X directly, but class A does, and class B extends class A. Given this code, all of the following statements are true:

if( b instanceof X)
if (b instanceof B)
if(b instance of A)
if(a instance of A)
if(a instanceof X)

Knowing the type of an object at runtime is useful for the following reasons:

  • Some invalid casts (explicit type conversions) involving class hierarchies cannot be caught at compile time. Therefore, they must be checked at runtime (using the instanceof operator), to avoid a runtime error.
  • You might have a situation where one process is generating various kinds of objects, and the other process is processing them. The other process may need to know the object type before it can properly process it. In this situation the instanceof operator would be helpful, too.
|