Java basics - the Java environment, object references and primitives, class structure, garbage collector | Preparing for Java Oracle Associate Certification (OCA) / Java basic technical tests

What are JVM, JRE and JDK? What’s the basic structure of a Java class? What are the characteristics of primitive and reference types? What’s the garbage collector and how does it work?

This post goes through some basics of Java, even though not directly related. I believe they compose the first chapter of the reference book OCA: Oracle Certified Associate Java SE 8 Programmer I Study Guide: Exam 1Z0-808, which I used for preparing my certification.

This series of articles are meant for people who already know the basics of Java, that is grammar and vocabulary, and knowledge of OOP. The topics covered correspond to OCA Programmer I level and relate to Java 8 version. If you need to learn the basics, I can recommend the JetBrains Academy Java developer track.

This article was mentioned in JetBrains’ Java Annotated Monthly (February 2021)

How did I study for the certification?

I already had had classes on OOP in Java through my computer science bachelor, but still a lot of subtleties where unknown to me, because my cursus was generalist (not only focused on dev) and there weren’t enough hours to learn everything. Anyway, the goal when you’re at school is not to teach you a language but a know-how, IT culture, strategies, good practices… Important is that I already knew the grammar and vocabulary of Java and I had quite good bases. From that point, I studied with the above mentioned reference book (not official from Oracle but recognized as the number one recommendation amongst developers…) which contains pretty tough exercises, that are harder than those of the certification, but also full theory. I took a notepad and made my own notes, in my own words, to summarize the important ideas, gotcha’s and difficulties. That way, I had something way shorter to refer to. Those are the notes I will share with you. It means it contains what I thought was really important or particularly difficult and might not be complete enough for you, please be aware. Also, after passing mock tests of the book (which are not the same as the exam format), I took closer mock tests with the Enthuware solution, which I highly recommend because the questions are similar, there is a timer, and very good reports, for about $10!

The Java environment

I’m going through this point quite quickly because there is much to say if you’d like to deep dive. I encourage you to search about Java, reading basic articles, and to search for terms and differences between compiled, run, transpiled, scripted, interpreted… because those are questions you could be asked during interviews (and because it’s always nice to know stuff).

Java has the great advantage to run everywhere (“write once, run everywhere”) because it runs on a Java Virtual machine, the JVM. The JVM speaks Java, it executes bytecode on any physical machine. Machines only know bytecode, that’s why a “translation” is needed.

The JRE is the Java Runtime Environment, it consists of the JVM and a few support files.

The JDK for Java Development Kit (a dedicated SDK) contains the JRE, the java language itself and the libraries (SE).

To develop in Java (compile), you need the JDK. To run your application, you need the JVM (thus the JRE).

The JRE can run a Jar file, but to create a Jar you’d need the JDK.

Some Java command lines to know

If those don’t work within a Windows environment, add the path variable to the environment variables. (Also be sure that Java JDK and JRE are installed.) If everything is well configured, you must be able to execute first two command lines and to get your version.

javac --version
java --version
java MyApp

Third line compiles a .java file into a .class file (bytecode file). The .java file is the raw file you’re writing and compiling with the JDK.

Fourth line executes/runs the .class file with the JVM. You might add arguments separated by blank spaces after “MyApp”, those will be stocked in the String [] args parameter of the main method.

That said, also please note that there must be a method with that exact signature in order to run your application :

public static void main(String [] args) {}

It does not have to be in a class whose name is “Main” but it has to be exactly like that. If the signature is different, you will encounter a runtime exception. However, it can be made finale, and it can be overloaded.

Class structure, Packages and Imports

The class structure has to be package declaration first (except if the unnamed package, which is a pretty bad practice for real projects), imports if there are any, then class definition. The class definition is the only necessary thing in any case, because without it it won’t run. A class can be public, in which case the file has to be named after it, and 0 or 1 class per file is public.

Imports can use * (wildcard), it replaces a class name in a non-static context, or a variable or method name in a static context. There will of course be a post about static so make sure to sub!

It can happen that conflicts appear in the imports. For example, java.util.Date (which you’re not supposed to use from Java 8, but you could still encounter it) and java.sql.Date. If you import both, then use “Date” in your class, the JDK will not be able to define which one you’re wanting to use. In such a case, one of the two imports has to be explicit (no *), and it will prevail, except if the whole path is used. Imports aren’t mandatory, you might use the full path of the class in your code each time, even though it’s less clearer and more time consuming.

Object references and primitives

Here’s the list of primitive types in Java :

booleantrue || false
byte (8 bits)-128 to 127
short (16 bits)-32 768 to 32 767
int (32 bits)-2 147 483 648 to 2 147 483 647
long (64 bits)well, much longer…
float (32 bits)
double (64 bits)
char (16 bits)0 to 65 535, that is alphanumeric values

GOTCHA – If you’re doing a certification, you might encounter questions on char. That’s because their behavior is kinda unnatural from a human perspective. You should play with chars in Java and test everything you can imagine not to be surprised at an inconvenient time. All upper and lower English letters plus numbers from 0 to 9 can be assigned to the char type. char is an integer! Some conversions will occur if assigning an integer to a char, that’s outside the range 0 to 65 535. The integer value has to be casted to be assigned to a char, except if it’s a compile-time constant.

Number literals are interpreted as an int. long values require a “L” right after it to mark it as a long for the compiler, otherwise it won’t compile.

A floating point number literal will be interpreted as double by default, so you have to add a “f” right after it if you want it to be a float. However, if the values is an integer, the f can be omitted.

You should also know those formats:

octal0## where # are numbers 0-7
binary0[b/B]## where # are 0 || 1
hexadecimal0[x/X]## where # are 0-9A-F

The “_” delimiter can be used to make numbers more readable. It has no impact on the compilation and running, it’s only visual. That’s why you can place it anywhere (except first/last and right before/after the point in floating point numbers).

For example 1000000 can also be written 1_000000 or 1_000_000 or 10_00000 or 100_0000 and so on.

Primitives vs References

Primitives and Reference types (“Object”, even though that is not exactly a synonym, as seen in a coming post) have very different behaviors.

The stack can only hold local primitives and object references. Objects instantiated inside an object and primitives inside an object (members of the type) are not referenced in the stack! Parameters are local and thus stored in the stack.

pass-by-valuereference (in the stack) points
to an object (instance of a class)
located in the heap
hold their value in the memory
(stack) where they are located
work as a “label” to an instance
and hold the address of it
no address/pointer/referencenullable
can call a method
can be garbage collected

Identifiers for variables, methods and classes have to follow those rules in order to compile:

  • Start with a letter or _ or $
  • Can contain above mentioned and figures
  • Note that “$” alone is a valid identifier, and “_” was until Java 9
  • Case sensitive
  • Cannot be a reserved word, in the same case. Also note that native class names are not reserved words. See Oracle list of Reserved Words.

Garbage collector

Please note that the Java language is constantly improving and that the garbage collector system is evolving with the versions. One thing that’s always been true so far is that, unlikely some low levels languages like C, Java doesn’t allow to totally take control of garbage collecting and pointers.

You should still be able to recognize in which cases an instance can be garbage collected, that is when an object in the heap is not referenced by a reference in the stack or all references pointing to it have gone out of scope.

Remember that implicit calls to System.gc(), finalize()… are NEVER guaranteed to work, because the collector is handled by the JVM. Finalize is a static method that runs 0 or 1 time per execution, so you’re not ensured that it will at the time you call it.

Well, that was a lot to take, I encourage you to play with Java in your favorite IDE and test the limits, go crazy and try things. Hope to see you in the next posts!

6 thoughts on “Java basics – the Java environment, object references and primitives, class structure, garbage collector | Preparing for Java Oracle Associate Certification (OCA) / Java basic technical tests

  1. Greetings! This is my 1st comment here so I just wanted to give a quick shout out and say I genuinely enjoy reading your blog posts. Can you suggest any other blogs/websites/forums that go over the same topics? Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *

Don’t miss out!

Receive every new article in your mailbox automatically.

Skip to content