Java

Overview: 
Explore variable arrays in Java.
Objectives: 

Understand what arrays are and how to use them.

Content: 

An array is used to store a list of variables of the same data type. An array is defined like this:

This statement defines and then creates an array of 3 integer variables (or elements) which will be addressed as a list. The new keyword defines the size of the array. We can then put values in the array and access them with an index value (position) in the array. Arrays are indexed starting at zero:

Note that we can initialize array values with the new keyword:

Arrays may have more than one dimension:

For loops are especially useful in processing arrays:

This will print out:

row 0 col 0 = 5
row 0 col 1 = 10
row 1 col 0 = 15
row 1 col 1 = 20

Arrays are fixed in thier dimensions once created so the array size can't be changed. If you need dynamic array sizing, that is, you want to change the size of the array as your program proceeds, you can use a special class called an ArrayList. The ArrayList is defined in the java.util package. An ArrayList has methods that allow you to add and remove elements on the fly:

String s will contain "A different String object". Why? Because when we removed element zero, the rest of the elements shifted down.

ArrayLists have a number of methods you can use to manipulate the array. Note that the ArrayList can only contain object instance references (no primitives). Also note that when we created the ArrayList, we specified the type of object that would be contained in the ArrayList.

ArrayList is just one of many types of Lists available in the Java API.

Here is a video about Arrays. Here is a detailed discussion of Arrays.

Here is the example code on CodingGround.

 

Navigation:

Overview: 
Explore Java enum (enumerations) class.
Objectives: 

Understand Java enum class and how to use it.

Content: 

An enum or enumeration, is a special data type (an object) defined by Java. It is a list of constant values known at compile time by name. When a variable of the enum type is created it is assigned one of it's pre-defined constant value names and can only have one it's pre-defined constant names as its value. Because they are constants, the names assigned are by convention in upper case. Here is an example:

The key concept is using names instead of numeric or string constant values, so instead of having to remember what 1 or 9 or whatever some number means when looking at the day of the week, you use a name. Using names improves readability and reliability of code by making things more obvious. So how do we use enums? Here are some examples:

Here we created a variable day of enum type DayOfWeek and set it to TUESDAY. We can then use day in various ways. enums are best used to represent a fixed set of constants, like day of week, planets of the solar system, menu choices, any list of constants whose values are all known at compile time. Internally, each enum name is assigned an int value starting at zero, but in the simple enum case, we don't care as we want to use the names not numbers.
 
To make things more interesting, remember that an enum  is a special form of a class. Therefore it can have fields and methods. By default, enum variables won't tell you their underlying value, only the name. We can extend the enum in the above example to track and return the underlying value of the enum to demonstrate extending the enum with fields and methods:

Here we added an int field to the enum and defined a constructor to set the value of the field. We also added a method to get the day number and made the field public so we can access it directly. Note that when using a constructor, we are required to explicitly define the constants for each name. Note in this example the numeric values assigned to the enum names are not in sequence. They don't have to be. You can assign any value you wish to the names. You can use any data type for the values assigned to the names. You can also create more than one field so that an enum can contain more than one data item.
 
Enums are very useful in their basic form and given that they have the full capability of classes, they can be extended to be very powerful.
 
Here is a video about enums. Here is a detailed discussion of enums.
 
Here is the example code in CodingGround for you to experiment with.
 

Navigation:

Overview: 
Explore Java classes for basic numeric data types.
Objectives: 

Understand what the Number classes are and how they are used, including the concepts of boxing and unboxing.

Content: 

We explored Java's primitive data types in an earlier lesson. While we use primitive numeric data types directly most of the time, there are times when we need to treat a numeric primitive as an object. For this reason Java provides the Number Classes. There is a subclass of Number for each numeric primitive:

  • Byte (byte)
  • Integer (int)
  • Short (short)
  • Long (long)
  • Double (double)
  • Float (float)

These classes wrap the primitive data type in an object. Often the compiler wraps the primitive for you. If you use an primitive where an object is expected, the compiler "boxes" the primitive in its wrapper class for you. If you use a Number object where a primitive is expected the compile will convert or "unbox" the object into the primitive value.

There are three main reasons why you would want to use a Number object instead of the corresponding primitive type:

  • As an argument of a method that expects an object.
  • To use constants defined by the class, such as MIN_VALUE and MAX_VALUE, that provide the upper and lower bounds of the data type.
  • To use class methods for converting values to and from other primitive types, for converting to and from strings, and for converting between number systems (decimal, octal, hexadecimal, binary).

The last item is the most common reason.  The Number classes provide many methods for converting, parsing and otherwise manipulating numbers. Many of the methods are static, meaning you can use them without an actual instance of a Number class. A typical use is converting (parsing) a string of digits into a Number object or the primitive type. The various methods can be quite useful.

You can also use instances of Number classes just like you would a primitive type. Here is an example showing an Integer variable being used just like a primitive int and also showing one of the static methods of Integer to convert a String to an integer value:

Lets look at what is happening in the example. First we create an Integer object and set it's value to 3. Then we perform a math operation on that Integer object. To do this, Java unboxes the Integer object i to a primitive integer and adds 2 to it. The statement returns the primitive integer value 5 and Java sees that we want to put a primitive 5 into the Integer object i and so Java boxes the primitive integer back into an Integer object, which now contains 5 as it's value.

Next we print out the value of the Integer object i. Java sees we are using i like a primitive value and so unboxes the Integer object to a primitive value which println knows how to handle. We also see that since i is an Integer object, we can use the methods defined for the Integer object, one of which is toString() which returns a string representation of the numeric value. The println function sees a string and knows how to handle it.

Next we use a static method of the Integer class, parsetInt(n), to parse a string of digits into an int value and store that int value into a primitive int variable. You can see that the methods of the Integer object can be used to work with both primitive int values and Integer objects.

Finally we print the value of the primitive int j. Again, println knows how to handle primitive int values so the first j is no problem. However, the next display of j tries to use the toString() method. This will fail since the variable j is a primitive int, which does not have methods.

Here is this example on CodingGround. Compile to see the error generated by Java when you try to use a method on a primitive data type variable. Fix the problem and get the program to run.

Here is a detailed discussion of the Number Classes.

 

Navigation:

Overview: 
Explore advanced topics related to objects and how they are used.
Overview: 
Explore the concept of static fields and methods.
Objectives: 

Understand what static fields and methods are and how and when to use them.

Content: 

Normally, class members (variables and methods) are accessed via an instance reference. Leaving methods aside for the momemt, this is because class variables exist separately for each instance of a class (created with the new keyword). If you have a variable x in a class and create two instances of the class, each instance will have its own x variable, access to which is by the instance reference. You also access methods via the instance reference. Here is an example:

The result:

theVar=3   theVar=7

Instance1 and instance2 refer to separate object instances of the class and as such each has its own theVar variable which has its own value. The variable is said to be an instance variable.

What if we would like to have a class level or global variable? One that is not specific to any instance of the class but exists as a single copy in memory at  the class level? We can do that with the static modifier. Marking a variable as static means there is only one copy of the variable for all class instances. The static variable is created when first accessed and persists as long as the program runs. Any instance of the class can access the static variable as it is shared among all instances of the class.

Since static variables are not accessed via an instance reference, you use the class name with a dot to access the variable.

You can also mark methods as static. This means the method does not need an instance reference to be called. The method is class level or global. Note that static methods can only access the static variables in the same class. Non-static or instance methods can access static and instance variables. Here is an example:

This example would print out:

instance count=0
instance count=3

The example uses a static variable to count how many instances of MyClass are created. We increment globalCount in the class constructor. This would make globalCount = 2 but to demonstrate static variable access, we directly increment globalCount to 3. We can do this since globalCount has public access. Note that the first output is zero because we called the static method which caused the static globalCount varible to be created and initialized, but we have not yet created any instances of the class. Note that the last statement would generate a compile error since we are accessing a static variable through an instance reference.

Here is the example above on CodingGround. Fix the error and demonstrate the program.

Here is a video about static members. Here is a detailed discussion of static members.

 

Navigation:

Overview: 
Explore class access control modifier keywords.
Objectives: 

Understand access control modifiers for classes.

Content: 

You seen the access control modifier public used extensively in our Java examples. The access control modifier is applied to classes and class members (variables and methods) and determines what access other classes have to the class members.

Classes can have no access modifier before the class name and will default to package-private. This means the class is only visible to top level classes in the same package. You can also use public, which means the class is visible inside and outside of its package.

At the member level, things get a bit more complicated. You can use access modifiers of public, private, protected or the default package-private (no modifier specified).

  • public - The member is accessible to the world.
  • private - The member is accessible only in the same class it is defined.
  • protected - The member is accessible only in classes defined in the same package or any subclasses thereof.
  • package-private - The member is accessible only to other classes in the same package but not in subclasses.

In robotics, using public for everything will work fine. Access modifiers are typically important when creating libraries that will be shared with other projects. In those cases, there may be internal members that should not be exposed to users of the library.

Here is a video about access control. Here is a detailed discussion of access control.

 

Navigation:

Overview: 
Explore method overriding when extending classes.
Objectives: 

Understand how subclass methods can override methods in the superclass.

Content: 

We have seen how we can extend a class to have additional fields and methods and build a more specialized object. But what if we want to change the behavior of one of the superclass methods? we can do this with Overriding.

Overriding is simply defining a method in the new (sub) class that has the same signature (method name and parameter list) of a method in the parent (super) class. This method in the subclass is said to override the same method in the superclass. When you call this method on a subclass instance, you will execute  the code defined in the subclass. Note that if you call the method on an instance of the superclass, you will execute the code defined in the superclass.

Lets look at an example. Say we have a base class of Animal and subclasses of Dog and Cat. All three have the same method, whatIsMyName():

This code will print out:

I am an Animal named roger
I am a Dog named rover
I am a Cat and I am an Animal named kitty

So each class has the same method signature whatIsMyName() but the result of the method is different for each class. This concept is called polymorphisim. Note in the Cat version of whatIsMyName() we called the superclass method of the same name with the super keyword. So we can replace superclass functionality or modify the result of the superclass method in a subclass.

Here is a video with more about Overriding.

Here is the example above in CodingGround. Give it a try!

 

Navigation:

Overview: 
Explore the Inheritance feature of Java's object oriented design.
Objectives: 

Understand object inheritance and the concept of extending objects.

Content: 

In our first unit on objects we learned how objects can encapsulate fields and methods creating a custom data type we can use to model the actual objects in the problem we are trying to solve. These objects make it easy to describe and work with our data and facilitate reuse of code. In this unit we are going to explore some of the more powerful features of Java's object oriented design.

The first advanced object feature we will discuss is inheritance. Inheritance simply means that when we design a new object, we can inherit the fields and methods of some other existing object. We can say our new object inherits or extends the aspects of the base object.

We inherit or extend an object into a new object by using the extends keyword on the class definition:

When we do this, NewClass is said to be a subclass or child of OldClass. OldClass is said to be the superclass or parent of NewClass. OldClass may also be called the base class of NewClass. A class may extend only one other class. If a class does not explicitly extend another class, then it automatically extends the built-in Java class Object. Classes may extend classes that extend other classes creating a class hierarchy. Since NewClass is a sub type of OldClass, the NewClass object can be used anywhere an OldClass object is expected.

NewClass will have whatever fields and methods you write for it and it will also have all of the accessible fields and methods of OldClass (except for the constructors). This idea of inheritance allows us to build new objects reusing existing code by extending or specializing our classes into more specific or customized objects for modeling more specific object data and behaviors.

Lets look at an example. We will start with a class called Animal. It will have some fields and methods common to all animals. We will extend Animal with more specialized classes Dog and Cat. These classes will have fields and methods that apply only to them but will also have the fields and methods of class Animal:

The Dog and Cat class constructors show how to use the super keyword in a subclass to access constructors and members of the superclass. So you see that the Dog and Cat classes do not have a name member defined in them but the resulting classes do have a name member since it is defined in parent or super class.

Here is the example above in CodingGround.  Fix the compile error and see the code in action.

One aspect of inheritance is that you can use a subclass any place that the super class is required. In our example, you can use a Cat or a Dog object any place an Animal object is required. If you add this method to the Animal class above:

Then you can to this in the main method:

Object hierarchies are very powerful and used extensively in robotics API libraries. Extending classes allows you to build complex classes out of simpler classes and reuse code in classes rather than duplicating that code in other classes.

Here is a video about inheritance. Here is a detailed discussion of inheritance. Here is more information about the super keyword.

 

Navigation:

Overview: 
Explore objects in Java.
Overview: 
Explore the Java concept of class packages and using packages with the Imports statement.
Objectives: 

Understand the Java concept of class packages and using packages with the Imports statement.

Content: 

A real project, even robotics projects, can end up having many classes. You will likely need to use classes in libraries provided by FIRST or others. Finding the classes you need, controlling access to them and naming conflicts between your classes and library classes can be a problem. You may also want to organize a group of your classes into a library that can be reused with other projects or other robotics teams. Packages give us a way to group together related classes in a unique naming scheme and reference them from other classes.

Packages are intended to group related classes together and facilitate access control and prevent naming conflicts. Naming conflicts occur when you want to use a class from a library that has the same name as one or your own classes.

You create packages with the package statement placed at the start of your class files. The package statement has your package name (more on names later) and all classes with the same package name in your project are grouped into that package. All Java programs must have a package and If you don't use a package statement, your classes are grouped into the default "unnamed" package. It is good programming practice to at least put all of the classes in a project into the same directly named package. Here is more about packages.

The Java built-in library of classes is organized into the java package and there are many sub-packages by organized by function. A name.name.name format is used to create a hierarchy within packages. Here is a detailed discussion of package naming.

While a specific package name format is not required there is a detailed convention used in package names. For robotics, you might want to use a name format like this:   

org.usfirst.<fll/ftc/frc>.teamnumber.projectname

or a simpler but perfectly valid one:

teamnumber.projectname

Packages organize classes we want to make use of in our own classes. So how do we access these other classes? The types (another name for classes) in a package are referred to as members. To access the members of a package you can specify the fully qualified package name when using classes, fields or methods or you can use the import statement. Using fully qualified package names can get pretty tedious. The import statement makes the package name known to the compiler so that when the compiler finds a class, field or method name it does not find in your code, it uses the imported packages to look for the name. This is called resolving the reference. Here is a discussion on using the import statement. Please read this discussion as it covers important details not discussed here.

Note that you do not see any imports or package name in the CodingGround examples. CodingGround uses the default package and is doing the imports for you behind the scenes.

Finally, many Java compilers and IDEs want to organize your source files (.java) into directories based on the package name(s) you use. Typically a directory hierarchy is created that matches the package hierarchy. So the package name suggested above might have the directory hierarchy:

c:\projectname\src\org\usfirst\frc\team4450\projectname

or

c:\projectname\src\team4450\projectname

Note that project name is repeated because the projectname right after the c:\ is not part of the package, but is part of the project directory hierarchy.

 

Navigation:

Pages