In Java, what is the difference between an abstract class and an interface?

This post is about Java, and has nothing to do with Python.  I’ve posted it here so that it can be available to other folks who might find it useful. (And because I don’t have a Java blog!)

In Java, what is the difference between an abstract class and an interface?

This is a question that comes up periodically. When I Googled for answers to it, I didn’t very much like any of the answers that I found, so I wrote my own. For those who might be interested, here it is.

Q: What is the difference between an abstract class and an interface?

A: Good question.

To help explain, first let me introduce some terminology that I hope will help clarify the situation.

  • I will say that a fully abstract class is an abstract class in which all methods are abstract.
  • In contrast, a partially abstract class is an abstract class in which some of the methods are abstract, and some are concrete (i.e. have implementations).

Q: OK. So what is the difference between a fully abstract class and an interface?

A: Basically, none. They are the same.

Q: Then why does Java have the concept of an interface, as well as the concept of an abstract class?

A: Because Java doesn’t support multiple inheritance. Or rather I should say, it supports a limited form of multiple inheritance.

Q: Huh??!!!

A: Java has a rule that a class can extend only one abstract class, but can implement multiple interfaces (fully abstract classes).

There’s a reason why Java has such a rule.

Remember that a class can be an abstract class without being a fully abstract class. It can be a partially abstract class.

Now imagine that that we have two partially abstract classes A and B. Both have some abstract methods, and both contain a non-abstract method called foo().

And imagine that Java allows a class to extend more than one abstract class, so we can write a class C that extends both A and B. And imagine that C doesn’t implement foo().

So now there is a problem. Suppose we create an instance of C and invoke its foo() method. Which foo() should Java invoke? A.foo() or B.foo()?

Some languages allow multiple inheritance, and have a way to answer that question. Python for example has a “method resolution order” algorithm that determines the order in which superclasses are searched, looking for an implementation of foo().

But the designers of Java made a different choice. They choose to make it a rule that a class can inherit from as many fully abstract classes it wants, but can inherit from only one partially abstract class. That way, the question of which foo() to use will never come up.

This is a form of limited multiple inheritance. Basically, the rule says that you can inherit from (extend) as many classes as you want, but if you do, only one of those classes can contain concrete (implemented) methods.

So now we do a little terminology substitution:

abstract class = a class that contains at least one abstract method, and can also contain concrete (implemented) methods

interface =  a class that is fully abstract — it has abstract methods, but no concrete methods

With those substitutions, you get the familiar Java rule:

A class can extend at most one abstract class, but may implement many interfaces.

That is, Java supports a limited form of multiple inheritance.

Python & Java: A Side-by-Side Comparison

I wrote this little piece a long time ago — it was last updated in May 2007. In 2009 I moved it from my website to this blog. At this point I consider it an historical artifact, in the sense that I consider it frozen; I’m no longer going to update it when, for example, Java acquires a new programmer-friendly feature.

During the years when it was on my web site, I received a number of email comments. I responded to them all, but no one — other than their authors and me — ever saw the comments and my responses. By moving this piece onto a blog, I hope that folks who feel like commenting can do so more easily, and can share their comments with a wider audience.

During the years when it was on my web site, virtually all of the comments that I received were from Java programmers. Some were calm and helpful, pointing out (for example) new programmer-friendly features of Java. Many were hot and angry and accused me of writing the piece for the sole purpose of bad-mouthing Java. If this describes you, please don’t fire off your angry counter-blast immediately. Go away, calm down, come back and read it again carefully.

I was recently asked if I still hold the opinions that I expressed in this article. I think that’s worth talking about… but in another post.

— Steve Ferg

Updated October 14, 2011 to fix a few minor typos

Note that this post has a companion post on the concepts of weak vs. strong, and static vs. dynamic, typing in programming languages.


Comparing Python and Java

A programmer can be significantly more productive in Python than in Java.

How much more productive? The most widely accepted estimate is 5-10 times. On the basis of my own personal experience with the two languages, I agree with this estimate.

Managers who are considering adding Python to their organization’s list of approved development tools, however, cannot afford to accept such reports uncritically. They need evidence, and some understanding of why programmers are making such claims. This page is for those managers.

On this page, I present a list of side-by-side comparisons of features of Java and Python. If you look at these comparisons, you can see why Python can be written much more quickly, and maintained much more easily, than Java. The list is not long — it is meant to be representative, not exhaustive.

This page looks only at programmer productivity, and does not attempt to compare Java and Python on any other basis. There is, however, one related topic that is virtually impossible to avoid. Python is a dynamically-typed language, and this feature is an important reason why programmers can be more productive with Python; they don’t have to deal with the overhead of Java’s static typing. So the debates about Java/Python productivity inevitably turn into debates about the comparative advantages and drawbacks of static typing versus dynamic typing — or strong typing versus weak typing — in programming languages. I will not discuss that issue here, other than to note that in the last five years a number of influential voices in the programming community have been expressing serious doubts about the supposed advantages of static typing.

For those who wish to pursue the matter, Strong versus Weak Typing: A Conversation with Guido van Rossum, Part V is a good place to start. See also Bruce Eckel’s weblog discussion Strong Typing vs. Strong Testing and Robert C. Martin’s weblog discussion Are Dynamic Languages Going to Replace Static Languages?. For background, see one of the papers that started it all in 1998 — Scripting: Higher Level Programming for the 21st Century by John Ousterhout.

Several of these discussions contain valuable comparisons of Java and Python. For other language comparisons, see the Python language comparisons page at www.python.org, and the PythonComparedToJava page at Python for Java Programmers.

Finally, it is important to note that asserting that a programmer can be more productive in Python than in Java, is not the same as asserting that one ought always to use Python and never to use Java. Programming languages are tools, and different tools are appropriate for different jobs. It is a poor workman whose toolbox contains only a hammer (no matter how big it is!), and it is a poor programmer (or software development organization) whose development toolkit contains only one programming language. Our toolboxes should contain both Python and Java, so that in any given situation we have the option of choosing the best tool for the job. So our claim is not that Python is the only programming language that you’ll ever need — only that the number of jobs for which Python is the best tool is much larger than is generally recognized.

Java vs. Python Productivity – an Overview

There are three main language characteristics that make programmers more productive with Python than with Java.

Java Python
statically typed

In Java, all variable names (along with their types) must be explicitly declared. Attempting to assign an object of the wrong type to a variable name triggers a type exception.That’s what it means to say that Java is a statically typed language.

Java container objects (e.g. Vector and ArrayList) hold objects of the generic type Object, but cannot hold primitives such as int. To store an int in a Vector, you must first convert the int to an Integer. When you retrieve an object from a container, it doesn’t remember its type, and must be explicitly cast to the desired type.

dynamically typed

In Python, you never declare anything. An assignment statement binds a name to an object, and the object can be of any type. If a name is assigned to an object of one type, it may later be assigned to an object of a different type. That’s what it means to say that Python is a dynamically typed language.

Python container objects (e.g. lists and dictionaries) can hold objects of any type, including numbers and lists. When you retrieve an object from a container, it remembers its type, so no casting is required.

For more information on static vs. dynamic typing, see this post.

verbose

“abounding in words; using or containing more words than are necessary”

concise (aka terse)

“expressing much in a few words. Implies clean-cut brevity, attained by excision of the superfluous”

not compact compact

In The New Hacker’s Dictionary, Eric S. Raymond gives the following definition for “compact”:

Compact adj. Of a design, describes the valuable property that it can all be apprehended at once in one’s head. This generally means the thing created from the design can be used with greater facility and fewer errors than an equivalent tool that is not compact.

Example

The classic “Hello, world!” program illustrates the relative verbosity of Java.

Java Python
public class HelloWorld
{
    public static void main (String[] args)
    {
        System.out.println("Hello, world!");
    }
}
print "Hello, world!"

print("Hello, world!") # Python version 3

Example

In the following example, we initialize an integer to zero, then convert it to a string, then check to see if it is empty. Note the data declaration (highlighted), which is necessary in Java but not in Python. Notice also how verbose Java is, even in an operation as basic as comparing two strings for equality.

Java Python
int    myCounter = 0;
String myString = String.valueOf(myCounter);
if (myString.equals("0")) ...
myCounter = 0
myString = str(myCounter)
if myString == "0": ...
// print the integers from 1 to 9
for (int i = 1; i < 10; i++)
{
   System.out.println(i);
}
 print the integers from 1 to 9
for i in range(1,10):
    print i


Example

Your application has 15 classes. (More precisely, it has 15 top-level public classes.)

Java Python
Each top-level public class must be defined in its own file. If your application has 15 such classes, it has 15 files. Multiple classes can be defined in a single file. If your application has 15 classes, the entire application could be stored in a single file, although you would probably want to partition it sensibly into perhaps 4, 5, or 6 files.

Example

In your application, method A calls B calls C calls D calls E calls F. You discover that F must throw exception SpecialException, and it must be caught by A.

Java Python
You must throw SpecialException in F, and catch it in A.
and
You must add “throws SpecialException” to the signatures of methods B, C, D, E, and F.
You must raise SpecialException in F, and catch it in A.Exceptions will propagate upward automatically; there is nothing more that you must do.

The reason for this is that Java, virtually alone among object-oriented programming languages, uses checked exceptions — exceptions that must be caught or thrown by every method in which they might appear, or the code will fail to compile. Recently (as of June 2003) there seems to be an increasing amount of unhappiness with Java’s use of checked exceptions. See Bruce Eckel’s “Does Java need Checked Exceptions?” and Ron Waldhoff’s “Java’s checked exceptions were a mistake”.

As chromatic, the Technical Editor of the O’Reilly Network, put it:

I like the idea of checked exceptions in some situations, but forcing every method to deal with (catching or throwing) all exceptions that its child calls or may call can be tedious. I’d rather be able to ignore an exception and let it propagate upwards. Sometimes, I’d rather not worry about exceptions at all.

Example

Your application has an Employee class. When an instance of Employee is created, the constructor may be passed one, two, or three arguments.

If you are programming in Java, this means that you write three constructors, with three different signatures. If you are programming in Python, you write only a single constructor, with default values for the optional arguments.

Java Python
public class Employee
{
    private String myEmployeeName;
    private int    myTaxDeductions = 1;
    private String myMaritalStatus = "single";

    //--------- constructor #1 -------------
    public Employee(String EmployeName)
    {
        this(employeeName, 1);
    }

    //--------- constructor #2 -------------
    public Employee(String EmployeName, int taxDeductions)
    {
       this(employeeName, taxDeductions, "single");
    }

    //--------- constructor #3 -------------
    public Employee(String EmployeName,
           int taxDeductions,
           String maritalStatus)
    {
       this.employeeName    = employeeName;
       this.taxDeductions   = taxDeductions;
       this.maritalStatus   = maritalStatus;
    }
...
class Employee():

    def __init__(self,
        employeeName
        , taxDeductions=1
        , maritalStatus="single"
        ):

        self.employeeName    = employeeName
        self.taxDeductions   = taxDeductions
        self.maritalStatus   = maritalStatus
...

In Python, a class has only one constructor.

The constructor method is simply another method of the class, but one that has a special name: __init__


Example

In Why Python? Eric S. Raymond notes that:

Python … is compact — you can hold its entire feature set (and at least a concept index of its libraries) in your head.

In Why I Love Python Bruce Eckel notes that Java is not compact.

I can remember many Python idioms because they’re simpler. That’s one more reason I program faster [in Python]. I still have to look up how to open a file every time I do it in Java. In fact, most things in Java require me to look something up.

Java Python
import java.io.*;
...

BufferedReader myFile =
    new BufferedReader(
        new FileReader(argFilename));
# open an input file
myFile = open(argFilename)

Example

Java’s string-handling capabilities are surprisingly weak. (But they have improved considerably with the addition of the split method to the String class in Java 1.4.)

Function or Method Java Python
Remove leading and trailing whitespace from string s s.trim() s.strip()
Remove leading whitespace from string s (not available) s.lstrip()
Remove trailing whitespace from string s (not available) s.rstrip()

Example

Code to add an int to a Vector, and then retrieve it.

Prior to Java 1.5, a new Integer object had to be created and initialized from the int before it could be added to a Vector. In order to retrieve the value, the member of the Vector had to be cast back to an Integer, and then converted back to an int.

Java (before version 1.5) Python
public Vector aList        = new Vector;
public int    aNumber      = 5;
public int    anotherNumber;

aList.addElement(new Integer(aNumber));
anotherNumber = ((Integer)aList.getElement(0)).intValue();
aList = []
aNumber = 5

aList.append(aNumber)
anotherNumber = aList[0]

This clumsiness was eliminated in Java 1.5 with the introduction of generics (which allows you to “type” a container object) and autoboxing (which automates conversion between primitive types and their corresponding wrapper classes). With generics, it is possible to code:

ContainerType<ContainedType>

which reads as:

ContainerType restricted to objects of ContainedType

Java (after version 1.5) Python
public Vector<Integer> aList = new Vector<Integer>;
public int    aNumber      = 5;
public int    anotherNumber;

aList.addElement(aNumber);
anotherNumber = aList.getElement(0);
aList = []
aNumber = 5

aList.append(aNumber)
anotherNumber = aList[0]

Example

Verbosity is not just a matter of increasing the number of characters that must be typed — it is also a matter of increasing the number of places where mistakes can be made. The Java code on the left has 5 control characters: ( ) { } ; where the corresponding Python code has only one control character, the colon. (Or two, if you count indentation. See below.)

Java Python
if ( a > b )
{
    a = b;
    b = c;
}
if  a > b :
    a = b
    b = c

Omitting or duplicating such characters is easy to do accidentally, and constitutes a severe error in the code. In my personal estimate, I spend 5 times as much time fixing such errors in Java as I do in Python. It really cuts into your productivity — and your creative energy — when you spend that much of your time just trying to satisfy the compiler.

Technically, Python has another control character that Java does not — indentation. But the requirement for correct indentation is the same in Java as it is in Python, because in both languages correct indentation is a practical requirement for human-readable code. The Python interpreter automatically enforces correct indentation, whereas the Java compiler does not. With Java, you need an add-on product such as the Jalopy code formatter to provide automated
enforcement of indentation standards.


Acknowledgments

Thanks to Skip Montanaro, Chris Lawrence, Donald McCarthy, Bengt Richter, and Christian Pohlmann for helpful feedback on earlier versions of this page.

Static vs. dynamic typing of programming languages

Updated 2010-10-20 — added a bit more information about Boo’s type inferencing.
Updated 2012-04-08 — This post is an appendix to a post comparing Java and Python. Some comments on this post are actually comments on that other post.

There is widespread confusion or disagreement about the meanings of the words static, dynamic, strong and weak when used to describe the type systems of programming languages.

Here is a description of the way (or at least one of the ways) these terms are most commonly used.

In a statically typed language, every variable name is bound both

  • to a type (at compile time, by means of a data declaration)
  • to an object.

The binding to an object is optional — if a name is not bound to an object, the name is said to be null.

Once a variable name has been bound to a type (that is, declared) it can be bound (via an assignment statement) only to objects of that type; it cannot ever be bound to an object of a different type. An attempt to bind the name to an object of the wrong type will raise a type exception.

In a dynamically typed language, every variable name is (unless it is null) bound only to an object.

Names are bound to objects at execution time by means of assignment statements, and it is possible to bind a name to objects of different types during the execution of the program.

static_typing dynamic_typing

Here is an example.

In a statically-typed language, the following sequence of statements (which binds an integer object, then a string object, to the name employeeName) is illegal. If employeeName had been declared to be an int, then the second statement would be illegal; if it had been declared to be a String, then the first statement would be illegal. But in a dynamically-typed language this sequence of statements is perfectly fine.

employeeName = 9
employeeName = "Steve Ferg"

Python is a dynamically-typed language. Java is a statically-typed language.

In a weakly typed language, variables can be implicitly coerced to unrelated types, whereas in a strongly typed language they cannot, and an explicit conversion is required. (Note that I said unrelated types. Most languages will allow implicit coercions between related types — for example, the addition of an integer and a float. By unrelated types I mean things like numbers and strings.) In a typical weakly typed language, the number 9 and the string “9” are interchangeable, and the following sequence of statements is legal.

a  = 9
b = "9"
c = concatenate(a, b)  // produces "99"
d = add(a, b)          // produces 18

In a strongly typed language, on the other hand, the last two statements would raise type exceptions. To avoid these exceptions, some kind of explicit type conversion would be necessary, like this.

a  = 9
b = "9"
c = concatenate(  str(a),  b)
d = add(a,  int(b)  )

Both Java and Python are strongly typed languages. Examples of weakly typed languages are Perl and Rexx.

A third distinction may be made between manifestly typed languages in which variable names must have explicit type declarations, and implicitly typed languages in which this is not required. Implicitly-typed languages use type inferencing rather than data declarations to determine the types of variables.

Most static languages, like Java, are also manifestly typed.  But Frank Mitchell notes that some are not: “Haskell and the dialects of ML, for example, can infer the type of any variable based on the operations performed on it, with only occasional help from an explicit type.” Scala is an interesting new statically-typed language for the Java Virtual Machine that uses type inference

Boo is a Python-like language with type inferencing that runs on the .NET CLI. Here is a snippet from the Boo page about Boo’s type inference:

Assignments can be used to introduce new variables in the current scope. The type for the new variable will be inferred from the expression on the right. Only the first assignment to a variable is taken into account by the type inference mechanism.

The following program is illegal:

        s = "I'm a string"   # s is bound with type string
        s = 42               # and although 42 is a really cool number s can only hold strings