Python’s rising status as one of the most popular programming languages in the world is undeniable. Meanwhile, Java’s popularity in the market has been on the decline (for example, check the TIOBE index and this Stackoverflow developer survey). 

Tiobe Index April 2021
Source: Tiobe Index April 2021

In fact, Java has been declining from a recent peak of 7.6M users compared to Python’s 8.2M developers in 2019, and that gap has only widened since.

Stack Overflow Developer Survey 2020
Source: Stack Overflow 2020 Developer Survey

None of which is to say that Java will be disappearing any time soon, but if you want to keep up with your peers in 2021, it’s probably time to take a look at Python. So If you’re a member of the Java community interested in learning Python, or if you’d just like to explore the differences between the two, this post is for you.

Java versus Python: Interpreted Languages

In Java, you must compile your code before executing it. Python, on the other hand, interprets your code at runtime. This means you can rely on the Java compiler to detect errors for you, such as syntax errors, unknown dependencies, etc, and be confident it will produce optimized runtime code. This process is executed once, after which you can reuse the compiled code at any time. 

The Python approach requires the source code to be parsed, interpreted, and executed every time it’s run. This process creates a simple Read-Evaluate-Print-Loop (REPL) that helps programmers code, test, and make changes in an efficient way. Knowing a good thing when they see it, Java has included a tool called JShell since Java v9, which allows you to interactively run snippets of code. 

Java versus Python: Dynamically-Typed Languages

Variables in Java must be declared with their type before they can be used. Any casting errors (which occur when values have been assigned types that are different from the ones declared) will be detected during compile time. In that case, testing in JShell will produce an exception:

|  Welcome to JShell -- Version 11.0.10
|  For an introduction type: /help intro
jshell> Integer a = 10;
a ==> 10
jshell> a= "10";
|  Error:
|  incompatible types: java.lang.String cannot be converted to java.lang.Integer
|  a= "10";
|     ^--^

Python is also known as a strong dynamically typed language, which means that the interpreter dynamically infers the types of variables. It also prevents the mixing of different types of variables in operations during runtime. For example:

Python 3.8.5 (default, Jan 27 2021, 15:41:15)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> a = 10
>>> print(a)
10
>>> a = '10'
>>> print(a)
10
>>> a = a + 10
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str

As you can see, the dynamic nature of Python allows the variable a to be set to an integer and then to a string. But when we try to perform the operation “string + integer,” the strong type prevents the execution.

Java versus Python Syntax: Simple but Not Simpler

There are many notable differences between the Java and Python syntaxes. Three of the most common changes that will likely trip you up are:

Multiline comments: Python does not provide a multiline comment character. The single-line comment character is #, and some people use the multiline string ”’ (three single quotation marks) as a workaround.
Indentation: In Java, each statement ends with a semicolon, which allows you to write code with improper indentation and still have it compile satisfactorily. In Python, all code must be properly formatted. For example, Java code blocks must be enclosed in braces { }, but Python code blocks must be started with a colon and ended with a new line.
List and dict comprehension: In Python, a list comprehension is a syntactic construct that allows you to create a list from the iteration of another list in a single line. You can also do the same with Python dictionaries. In Java, you can stream a list and build something similar, but in a more verbose way:

jshell> for(int i=0;i<5;i++){
	   ...> /*Notice the multiline
   ...> comment and the
   ...> lack of indentation for several statements */
   ...> System.out.println(i);i++;i--;
   ...> }
0
1
2
3
4

In Python, list comprehension using similar code looks like this:

>>> srcList = [i for i in range(5)]
>>> print(srcList)
[0, 1, 2, 3, 4]
>> for x in srcList:
...     print(x)
...     x += 1
...     x -= 1
...
0
1
2
3
4

Java versus Python: Object Oriented Programming

Object Oriented Programming (OOP) is one of the most common approaches to programming. Put simply (or perhaps overly simply), the OOP paradigm promotes the ideas of encapsulation (meaning that you should take care of your business by ensuring that you don’t expose anything except what is essential), polymorphism (meaning that things can behave differently according to the input received), and inheritance (meaning that it’s ok to use knowledge that has been passed down, or to rebuild it according to your own criteria). Both Java and Python support implementations of OOP, but they do so in different ways:

Design – Java is designed to be a pure OOP language in which everything is a class (a template that generates instances or objects). Python supports OOP, but it can also run code in a script mode without declaring any class at all.
Encapsulation – In Java, encapsulation is defined by the visibility of a class’s attribute or method using access modifiers: none, private, protected, and public. In Python, all attributes are public by default, but you can use a trick to make them less accessible:

>>> class A:
...     def __init__(self):
...             self.attrPublic = 'Visible'
...             self.__attrPrivate = 'Invisible'
...
>>> instance = A()
>>> print(instance.attrPublic)
Visible
>>> print(instance.__attrPrivate)
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute '__attrPrivate'
>>> dir(instance)
['_A__attrPrivate', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'attrPublic']
>>> print(instance._A__attrPrivate)
Invisible

In the example above, we first declared a simple class with a constructor method and no arguments, as well as two instance-level attributes: attrPublic and __attrPrivate. Then we instantiated a new object of class A and printed the value of the two attributes. As you can see, the public attribute was printed, but the attribute that begins with a double underscore gave an error. That is because Python has internally changed the name of the “private” attribute to _ClassName__AttributeName to hide its visibility. You can always use the dir function to list the attributes and methods of an object if you need them.  

Polymorphism – In Java, polymorphism includes method overloading and method overriding. Method overriding implies that a subclass can implement an inherited method in its own way. Python also supports this class of polymorphism. Due to its dynamic typed nature, though, you can also call methods that have the same name from unrelated classes:

>>> class A:
...     def greeting():
...             print('Ahoy')
...
>>> class B:
...     def greeting():
...             print('Bye bye')
...
>>> def poly(anInstance):
...     anInstance.greeting()
...
>>> a = A()
>>> b = B()
>>>
>>> poly(B)
Bye bye
>>> poly(A)
Ahoy

As you can see, the two classes implement the same method, which is greeting() in this example. Since you can call both implementations using a function that doesn’t need to know the class of the argument, you can’t have direct method overloading in Python. For example:

>>> def myMethod(a,b):
...     return a+b
...
>>> def myMethod(a,b,c):
...     return a*b+c
...
>>> myMethod(1,2)
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: myMethod() missing 1 required positional argument: 'c'

As you can see, the interpreter cannot detect that we are calling the first implementation of myMethod.

Inheritance – Both Java and Python provide single instance inheritance, meaning that you can extend a single class without having to have multiple parent classes. In addition, both languages include the concept of interface, which is a way to define methods that must be implemented by a class. Unlike Java, Python implements based upon the idea of abstract base classes:

>>> import abc
>>> class salutable(abc.ABC):
...     @abc.abstractmethod
...     def greeting():
...             pass
...
>>> class A(salutable):
...     def greeting():
...             print('Ahoy')
...
>>> class B(salutable):
...     def otherMethod():
...             pass
...
>>> a = A()
>>> b = B()
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class B with abstract methods greeting

In the example above, we defined an abstract class by subclassing the ABC class from the abc package, and then declaring a method as abstract by using the @abc.abstractmethod decorator. We then defined two subclasses that must implement the interface, but we forgot to implement the abstract method in class B. The interpreter cannot create a new instance of the class without an implementation.

Java versus Python: Which is Better in 2021?

As with most programming languages, it’s difficult to say one is categorically better than the other since they all have their pros and cons. Similarly, both Java and Python have been designed with great features to help simplify and streamline code creation, but they do it in different ways. If you’re a Java programmer trying Python for the first time in 2021, many of the conveniences Python offers are going to look and feel strange to you.

In this post, we’ve shown you some of the key differences to illustrate the way in which programmers from the Java community will have to change their mindsets before they can get comfortable with Python. Of course, practice is the best way to master a programming language, and Python offers plenty of tools and opportunities to do just that. 

In fact, ActiveState’s “How to” blog series offers numerous small projects (with code examples) that can help you build something practical in Python, while improving your coding skills. And each of them comes with their own runtime environment, which includes a version of Python and all the packages you need to build the project. Give them a try:

These Python use cases and tutorials will also introduce you to our open source languages platform. You can use it for free to build Python runtimes for each of your projects. If you haven’t downloaded Python yet, you can download our ActivePython distribution from the platform.

ActiveState language distribution

ActivePython bundles up the most popular third party libraries, packages and modules for you so you can get started right away.
And any time you start a new project, you should always create a new virtual environment for it.

Runtime Configuration

Related Reads

Python vs. Java: Duck Typing, Parsing on Whitespace and Other Cool Differences

Oracle Charges for Java Updates: Now What?