Chapter:Classes - Introduction

From Juneday education
Jump to: navigation, search

Meta information about this chapter

Expand using link to the right to see the full content.

Purpose

The purpose of including this chapter is to give the students the basic knowledge needed to construct classes of their own. This is so essential to Java programming, that without this knowledge, very little can be done. After learning how to use someone else's classes to construct objects and put those objects to work, it is now time to provide the tools for knowing how to create classes from scratch (for use by the student's own programs or for use by other people).

Goal

The student shall after completing this chapter be able to:

  • Understand the basic building blocks of classes:
    • variables (instance and static)
    • constructors
    • methods (instance and static)
  • Construct basic classes containing the basic building blocks
  • Recognize the most basic Java keywords and understand the contexts where they can occur
  • Understand the concept of access modifiers (at least private and public)
  • Declare and use:
    • Variables (instance and static) and constants
    • Constructors
    • Methods (instance and class)
  • Understand the next chapters about inheritance and interfaces

Instructions to the teacher

Common problems

It's important that the student understands the difference between classes and objects. Compiled java source code files are called class files, which can be confusing unless this is addressed. Talking about the source code for a class and the class as seen by the JVM in runtime can be very confusing, since it is the class code the students are used to reading and writing, while a runtime class acts both as a type and API towards objects. Also, it is important to remind the student that a reference variable may refer to an object of some class or null. We want to stress once again that what we say has a great impact on what the students understand. Even if it becomes tedious and bureaucratic to say stuf like "toString() returns a reference to a new String with a String representation of the ojbect", this is in our experience something which the students (and sometimes even more experienced programmers) need to hear over an over again. It doesn't hurt to remind the students of this relation from time to time.

Another thing to think about is that an object is the same as an instance of a class. When alternating by calling the object "an object" and "an instance", it is not wrong to remind the students that objects and instances are synonyms in Java.

One big issue when learning programming and Java is to mentally switch between what happens in compile time and what happens in runtime. A problem for us teachers, is that we often show source code and ask questions like: "What happens when this line of code executes?". Even though we know that the Java source code resides in a class in a source code file which will be compiled to byte code in a class file, and only at runtime will that class eventually be loaded by the JVM, which in turn at some time will execute the code we were talking about, this is something we sometimes forget to point out to the students. The danger with this, of course, is that the students may subconsciously get the idea that the source code will be interpreted as it is. This, in turn, may lead to confusion about the difference between compile time (which is where we are when we look at source code) and runtime, because the code looks the same when the teacher is talking about it!

An additional potential problem with understanding all this, is polymorphism in the sense that a reference variable has the compile time type "Reference to some class" when the actual type of the object referred to at some point during runtime may have the type of a subclass to the reference type. This will be addressed in the chapters about inheritance and interfaces, but it is worth thinking about even in earlier chapters, because it is in early chapters we have the chance to lay the foundation for understanding compile time, runtime, compile time type, runtime type. The point here is that if you don't understand the difference between compile time and runtime (or maybe even also design time), it will be very hard to grasp the concept of polymorphism when it's time for that.

Understanding the difference between static members and instance members is often hard for students. First it is hard to understand what the semantic difference is, and the difference in runtime. Second, once the students understand the implication of a variable or method being static, they are faced with knowing when to choose "instance or static". It isn't obvious for new students (or sometimes even experienced programmers) to motivate when in particular a method should be static and when it shouldn't. It doesn't help that many books (for more or less natural reasons) start with the main method as a self-contained program, only to move on to refactoring the program by factoring out parts of the code to static methods in the same (and only) class as the main method.

One way of explaining how to choose between static or instance context for a method is to focus on the data which the method operates on. Methods that only operate on data provided as arguments (and that have no side effects) are good candidates for being static methods. Methods whose operations depend on the state of some object are more likely to be instance methods. Now, the latter depends of course on an understanding on grouping data and behavior together as objects. So we could rephrase the second rule about instance method candidates to, "Methods that constitute the operation you can perform on an object, the messages you can send to an object, are candidates for being instance methods, because they often need access to the state of the object in order to do their work". Another possible rephrasing could be "Methods declared in the same class as the type of the object, and whose operations depend on the state of that object, must be instance methods".

Another, perhaps more simplistic, way of explaining when to use a static method is to say "when you don't need to have access to any specific object in order to run a method, this method must be static". But this is just a rephrasing of the previous statement. The central part to understand is that method which change or use the data of a specific object, as part of this objects behavior, must be an instance method. Instance methods are tied to instances, as implied by the name. They offer a way to use or change an instance's state.

Note, though, that passing a reference to an object as a parameter to a static method, which in turn uses the state of the object, could also be described as the method "depending on the state of an object". This was of course not the intent of the rule. The rule only applies to methods "declared in the same class as the type of the object".

Once the students understand that you can have many objects of the same class, and that those objects can have different state, it is easier to explain that instance methods are applied to the instances even if they are declared in the class. Static methods, on the other hand, can be called regardless of even the existence of instances, so they can't depend on instance variables or references to instances.

A particular surprising but telling example is the classic quiz question What will be the result of compiling and running the following program:

 1 public class Example {
 2   public static void main(String[] args) {
 3     Example ex = null;
 4     System.out.println( aMethod(ex) );
 5   }
 6   static String aMethod(Example e) {
 7     return e.aNotherMethod();
 8   }
 9   static String aNotherMethod() {
10     return "Awooga";
11   }
12 }

Many would jump to the conclusion that there will be a NullPointerException on line 7, because the parameter e is null. But static methods can be called even via Null references, since the static method doesn't need or care about dereferencing the reference variable e - it needs only to know the type of e.

We have tried to sneak in a style in previous chapters and examples which lets the main method create objects of some class, and let the objects do the work. We actually believe that merely avoiding a lot of calls to static methods from the main method helps giving the students a better preparation for understanding the difference between static methods and instance methods. It is our belief that instance methods are more common than static methods(this certainly seems to be the case, looking at the Java API) and perhaps should be merited more attention for this reason alone.

When showing calls to static methods, such as mathematical functions in java.lang.Math, it is good to make a point about those methods being static and elaborate on that. For instance one can mention that it would be tedious to have to create a Math object just to get access to the mathematical functions (which are pure functions and don't depend on any state and don't have any side effects). One can also elaborate on what it would mean if it were possible to create Math objects - could there be more than one instance of "Math"? What would that mean? This is also a good time to show that it is not possible to create Math instances. Ask the students if they can guess how the class is defined in order to prevent instantiation (the answer is that it has a private constructor of course). Later, when talking about inheritance, one could ask the students if one may extend Math. If not, how is this achieved? Repeat the meaning of finalwhen used in a class declaration.

Introduction to classes

Classes are of course a very central topic in a book on Java and Java programming. It is, in fact, one of the larger topics and very heavy on syntax and semantics. We want to cover the topic on classes in its entirety but will will focus on the basics and just touch upon the heavier and more advanced stuff like nested and inner classes.

The focus of this chapter is to teach how to write your own classes and we start off by talking about the syntactic layout of class source code files. After this, we zoom in on stuff like variables (instance variables and class variables), constructors and methods (instance and class methods).

The idea is to give the students an understanding of how to declare a class, what are the different parts of a class, i.e. what declarations can exist in the class block, and an introduction to the declaration and function of those parts.

Now, head on to the next chapter!

Chapters about classes

Programming with classes

Here are the five chapters about classes in this book, so that you can keep a check on your progress:

It's important that you watch all lectures and do all the exercises. Good luck and happy reading/watching/coding!

Lecture slides and Videos

Java - Classes - Introduction (Full playlist) | Java - Classes - Introduction 1/1 | Java - Introduction to classes (Presentation PDF)

Links

Further reading

Where to go next

Next page has the exercises (if any) of this chapter: Classes_-_Introduction_-_Exercises

« PreviousBook TOCNext »