Java Environment and Language syntax
Global description of the Java programming language
Global description of the Java programming language
This section performs an overview about the Java language, history and base concepts are quickly described
What was there before Java? We are in 1995, and the C and C++ languages dominate the world of programming at this date. Although these languages are very efficient in their own scopes, programmers are spending a lot of time in porting applications from one environment to another, because programs use directly the native libraries of each system, and this implies to change a part of a program when you want it to run on different environment...
C/C++ developers are aware of those platform-specific problem. Specific codes are generally separated from the rest of the logic. These developers must stay attentive, because some native APIs can be unintentionally inserted into the general code.
Also, sometimes the general logic and the specific code do not dissociate properly, for example the following code (found here )
/*here is a tiny example which lists the files in the current directory*/
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main(){
struct dirent *dp;
dir *dfd = opendir(".");
if(dfd != null) {
while((dp = readdir(dfd)) != null){
printf("%s\n", dp->d_name); /*you can't do much better without a specific API*/
}
closedir(dfd);
}
return 0;
}
In this sample, you can't do much more than reading files name staying cross-platform. If you want to do more, you must call native environment APIs, which makes your code adherent to this platform
This is pretty bad, because the cost of porting an application does not stop to the native calls area, this also affects the rest of the program, because native calls does not behave the same way. An other cost is the validation of each environment.
An other thing which is environment specific is the binary produced by the compilation : even if
you took great care about using cross-platform APIs, there you do not have the choice.
Each system has its specific format for binary executable (.exe, .dll
for Windows
.elf, .so
for Linux etc.).
It adds to the validation an other cost, because these different type of files does not behave
equally, and their generation can also bring errors during execution.
From this observation, a company named Sun produced at this date (remember, we're in 1995) a totally new and revolutionary system: the Java Virtual Machine (JVM).
This JVM *is* itself an environment, but a special one: it is Virtual. That means that by itself, a JVM can do nothing:
Those 3 remarks allow to see a bit more clearly the goal of the JVM: The JVM abstracts the code
written
in Java
from those bad native calls that cost developers so much time! In fact, the code is written in
Java,
this code
is compiled to make a .class
which is the kind of file the JVM can work with. This
code is
converted by the JVM that delegates native calls to its specific implementation and everything
that will
lead to
an environment specific treatment (filesystem access, network etc.) is handled by the JVM,
totally
transparently
for the programmer
You probably noticed the term .class
is mentioned just above. Indeed, Java is an
Object Oriented Programming language. This is not strong enough: Java is Massively Object
Oriented! In Java,
every little thing is an object
It implies that every files produced during the compilation phase is a .class
file
The main bug source in languages like C and C++, is that you manage the memory yourself. It may seem mandatory in certain case, but in most of the case, the lack of concentration of a developer can ruin the fine work of his colleagues.
The JVM proposes an automatic memory management system which allows developers to be free of that concern! You simply use what you need to use and the system automatically send to garbage what you don't need anymore. In fact a good knowledge of what is done behind the scene is required, but this avoid to consume time in a lot of cases.
This mechanism is called Garbage Collection. A garbage collector is an entity inside the jvm that handles useless objects. Its action is configurable, as it lays on interchangeable algorithms.
Java is more than a language, it is an environment, where several components are involved. Java allows developer to gain time when designing applications, and also when they deploy them across several environment.
Be ready, this part will be rough but you cannot pretend to have skills in Java without reading it
So... We said that in Java, everything was an object? This is true 99.9% of the time, so we'll start with learning what is a class structure
Java Objects representation is made through a "class" file. At the beginning, the class is a java file.
The class name is the way this object will be called in the developer code. This name must be the name
of the file containing this class definition. The extension of a non compiled class (the way human usually edit
classes) is *.java
There is an example below:
package fr.tbr.demo;
/**
* @author Thomas Broussard
* Date: 29/09/13
*/
public class MyDemoClass {
/**
* A private field that must be initialized during the instance construction phase
*/
private String mainText;
/**
* private integer field, this is a primitive type
*/
private int age;
/**
* A final field that never changes during the execution
*/
private static final String AUTHOR = "Thomas Broussard";
/**
* Static method to get a data shared by all of the instances of MyDemoClass
* @return the author of the class
*/
public static String getAuthor() {
return AUTHOR;
}
/**
* Constructor of a MyDemoClass object
* @param mainText
*/
public MyDemoClass(String mainText) {
this.mainText = mainText;
this.age=28;
}
/**
* Performs a demo on the current instance of MyDemoClass
*/
public void doTheDemo() {
String result = "This wonderful demo class has been written by "
+ AUTHOR + " and this object has been initialized with :"
+ this.mainText;
System.out.println(result); // access to the standard output
}
/**
* A method that overrides the Object (super class of all classes);
* @return a String containing the mainText field value
*/
@Override
public String toString() {
return mainText;
}
}
This is how we can define an object in Java, the following items are to be explained:
The first line defines the package in which the class is located. A package is represented
physically by a folder, and it is where the .java
files will be reachable.
A package is a necessary mean to organize the code, and generally avoid mistakes when the project grows
bigger. Indeed, the package name can be used to
It is advised to define a namespace using the package tree ; a namespace is a (normally) unique prefix, indicating that the code inside any sub tree of this namespace is yours
This is necessary to avoid class naming collision (two classes having the same name). In this example,
the namespace is fr.tbr
In java, you have powerful allies. Like in all languages you have comment at your disposal to indicate a critical part of your program
This is good, but in fact this is the true minimum. Java can help you better, thanks to the Javadoc system. The javadoc system is an improvement of the comment principle, allowing developer to generate a technical documentation directly from the code
To indicate a Javadoc comment, you'll have to dispose a simple block comment "A la C" and add a second star, examples below:
/** Javadoc */
/* Block comment */
// Line comment
The Javadoc is part of your Java program, it is standard and you'll have to provide javadoc on everything
that is public
This will help your teammates to understand and to reuse your code quickly. Indeed, the Javadoc will be
compiled (if asked) in a browseable html format, an example is here:
Apache commons Javadoc
You may have noticed a strange @author
indication, this is the way the javadoc system
indicates the author of a program part. Several keywords exist, allowing to highlight what is generally
important to in a program
Notice the class definition
public class MyDemoClass {
//...
}
There are three things to note:
public
this is the Visibility modifier
It is a classical feature of OOP languages, it allows the developer to select which method is reachable by another class code. The class which the name is the same as the compilation unit must be public (or package protected, although this is usually not what you want to do)
This modifier system is applicable to any other entities composing the class
Modifier name | Effect |
---|---|
public
|
This modifier indicates that every class can access to the entity |
protected
|
Only sub-classes (via inheritance) can have access to elements marked with this identifier |
private
|
Only the current class can have access to private properties |
(none)
|
When no modifier is specified, it means the property is only reachable by classes located in the same package |
class
indicates this is a class, there are several kinds
of entities
Several values are possible
Kind of entity | Description |
---|---|
class
|
It means the current compilation unit is a class, meaning it represents an object |
interface
|
Interfaces are the way Java defines "meta-class", you can see it as a characteristic shared by several classes. A typical real-world example is to say that a dog can howl and so does a wolf, although a dog is not a wolf and vice-versa. An interface "Howler" can be defined so the behaviour of howling can be shared by several classes, even if these classes do not inherit from one to each other. This quick definition of interfaces will be completed in a dedicated part of this course |
enum
|
Enums are specific objects. the word "enum" stands for "enumeration" and the goal of this kind of class is contained inside this word: they are to represent a constant collection of objects An enum is very useful when you want to structure your code, it is a recommended way to define property of an object when this object has to leave its Java Object shape (ie, when this object is required to be serialized) |
MyDemoClass
this is the name of the object that defines the class. The
compilation unit
(the name of the Java file) must be the same, here MyDemoClass.java
In the previous example, there are two class fields : the first is of type String
, the second is
declared as an int
what other kinds of Java built-in types could
you see in a program?
Java has two kinds of types: the primitive and the object types... Remember? we said that every thing was an object in Java, this is wrong again.
Primitive typesThe primitive types look like C native types, although they have a default value. You will find a description of these types hereafter:
Primitive type | Description | Range |
---|---|---|
Integer types | ||
byte
|
a signed byte |
-128 to 127 |
short
|
This is a two-bytes signed integer, it defaults to 0 if not initialized |
-32,768 to 32,767 |
int
|
This is a signed integer, it defaults to 0 if not initialized |
-2,147,483,648 to 2,147,483,647 (inclusive) |
long
|
The long is a signed integer with a wider range: the declaration of a
|
-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 |
Floating types | ||
float
|
The |
1.40129846432481707e-45 to 3.40282346638528860e+38 |
double
|
The |
4.94065645841246544e-324d to 1.79769313486231570e+308d |
Other | ||
boolean
|
the boolean in Java can have two values |
true or false |
char
|
2 bytes, unsigned, Unicode, |
0 to 65,535 |
The Object type allows to reference an other object inside your main object, this is a normal object what can be built-in or "custom" (meaning your own object). Among the noticeable built-in types, there are:
String
: this is the way to represent a characters string in Java
Integer
: this is one of the numerous objects representing a raw type in the
object style.
If you want to read more of that, consider reading the Autoboxing paragraph, just below.
The Autoboxing mechanism is integrated in Java. It allows to convert an object into a primitive type, as the code shows below:
/**
* Shows how primitive types can be "boxed" (automatically cast) to Objects
*/
final char character = 0;
final byte veryShortInt = 0;
final short shortInt = 0;
final int normalInt = 0;
final long longInt = 0l;
final float floatingPoint = 0;
final double bigFloatingPoint = 0;
final boolean aBooleanExample = true;
// Object style
final Byte byteSample = veryShortInt;
final Short shortSample = shortInt;
final Integer intSample = normalInt;
final Long longSample = longInt;
final Float floatSample = floatingPoint;
final Double doubleSample = bigFloatingPoint;
final Boolean booleanSample = aBooleanExample;
How to use the defined object? We should introduce a new keyword : the well named new
operator.
The new operator allows to create a new instance of the defined class reference.
In order to understand better the object concept in Java, you have to understand that one class is the "template" of an object, this is only a definition. When you use instances of that class, they all have their own fields values.
Only things shared by all theses instances are the static
fields. Static fields are common to all
instances, allowing to share data between them.
In the code, you'll have to do the instanciation like the following :
Identity thomas = new Identity("Thomas Broussard", "01", "t.b@sample.com");
Identity quentin = new Identity("Quentin", "02", "q.d@sample.com");
Identity clement = new Identity("Clément", "03", "c.s@sample.com");
We saw just before how to create new Java objects, now how to use them ?
To use an object, this object should already have a built-in behaviour to invoke in this object user's code. As an example, let's define an object representing a car:
There is the code hereafter :
package fr.tbr.demo;
/**a car representation*/
public class Car{
private String model;
private String brand;
private boolean engineStarted;
public Car(String model, String brand) {
super();
this.model = model;
this.brand = brand;
}
public void start(){
this.engineStarted = true;
}
public void stop(){
this.engineStarted = false;
}
@Override
public String toString() {
return "Car [model=" + model + ", brand=" + brand +
", engineStarted=" + engineStarted + "]";
}
}
Here the object has two behaviours, start() and stop(). Each action has an effect on the car state. In Java, the way of making a call to these behaviours is :
Car timeMachine = new Car("DeLorean-DMC12", "DMC");
timeMachine.start();
timeMachine.stop();
The inheritance mechanism is defined via the extends
keyword
To follow the previous example, the way to define an inheritance between a motor-vehicle and a car (specialization) is defined by the code after
package fr.tbr.demo;
/**a car representation*/
public class Car extends MotorVehicle{
private String model;
private String brand;
public Car(String model, String brand) {
super();
this.model = model;
this.brand = brand;
}
@Override
public String toString() {
String returned = "Car [model=" + model +
", brand=" + brand + ", engineStarted=" + engineStarted + "]";
Car timeMachine = new Car("DeLorean-DMC12", "DMC");
timeMachine.start();
timeMachine.stop();
return returned;
}
}
And the UML schema
Notice that you can use the properties of the parent object in the inherited object thanks to the
super
operator
In Java there are a lot of operators, only a little part is daily used. This part presents these operators and how to use them in a java program