What I've learned in Java up to Nov' 7th '22


As mentioned in the previous blog post, I started learning Java just to be able to understand solutions to Leetcode problems & solutions discussed in 'Cracking the Coding Interview' book.

This blogpost is going to focus a little less on being didactic and more about me just rambling on about what I've learned in the past few weeks.

Part 1 - The Basics

Java was developed by James Gosling at Sun Microsystems and released in May 1995 according the Java page on Wikipedia.

To start writing and developing program in Java, we will first need the JDK (Java Development Kit) which provides all the tools, executables, and binaries required to compile, debug, and execute a Java Program. JDK is a platform-specific software and that’s why we have separate installers for Windows, Mac, and Unix systems. 

Java versioning is kinda weird (much like Samsung's S series) but what we need to know is that the long-term supported versions are 8, 11, and 17. I've installed JDK for Java 17 on my Mac and PC so all of the code that I've ran so far worked on that version.

In Java, we write our program in a 'Source code file' which is then compiled by the compiler application thereby outputting a 'byte code' file which is used by Java Virtual Machine (JVM) to run the program.

So, in our source code file, we start with 'a class' which holds 'methods' which has 'statements'. The JVM looks for a 'main method' in the program to start execution. A java program must have at least one main method in it. The whitespaces for the most part doesn't matter in Java programs. 

The following is a snippet of code for a simple 'Hello World' program in Java.

// Hello World class
public class Hello {
    // Main method
public static void main (String[] args) {
        // Print statement
System.out.print("Hello there!");
}
}

This gets saved to a file with a '.java' extension, e.g. 'Hello.java'. Then compiled using 'javac Hello.java' command on the command line (will only work if JDK is installed on the machine and Java has been added to the PATH variable).

As we can see, Java is a very 'Object-Oriented' programming language. The advantage of that is the ability to extend code without having to touch previously tested, working code. All of Java code is defined in 'classes' which are like blueprints from which 'objects' are generated. An object knows things (instances variables) and does things (methods). A class can inherit instance variables and methods from a more abstract superclass.

Since it would be difficult to manage multiple individual Java files, we can put all application files into a Java Archive - a .jar file that's based on the pkzip format.

Part 2 - Variables, Methods, Java API, Inheritance & Polymorphism

Let's talk about the 2 types of variables, the primitives and the reference variables.

The primitive variables can be remember by the Mnemonic "Be Careful, Bears Shouldn't Ingest Large Furry Dogs". 


To create a variable in Java, you need to provide the name and type of the variable. The only restrictions with the names is that it must start with a letter, underscore, or a dollar sign. It also cannot be any of the reserved keywords. Below code snippet shows some examples:
int size = 32;
char initial = 'j';
double d = 456.789;
boolean isLearning;
isLearning = true;
int y = 456;

An object reference variable holds bits that represent a way to access an object. The 3 steps of object creation are declaration, creation, & assignment.
Dog mydog = new Dog();

In the above example, 'myDog' is the reference variable to the 'Dog()' object. Instance variables are variables that are defined inside a class but not in a method. Local variables are variables defined under methods in a class. The difference is that 'instances variables' are assigned default values whereas 'local variables' are not. Use '.equals()' to see if 2 objects are equivalent.

The concept of 'Encapsulation' is hard to understand just by the definition and better understood by looking at an example:

Say you have a 'theCat' object with a public instance variable 'height', anybody can change the height to any value using the dot operator, e.g. 'theCat.height=0', now we obviously don't want height to be set to zero but we don't have control in the previous example since we didn't use 'encapsulation'. Here's an example with encapsulation:

class goodDog {
private int size;

public void setSize (int s) {
if (s > 0) {
size = s;
}
}

public void getSize () {
return size
}
}

In the above example, 'getSize' is a getter method aka accessor and 'setSize' is a setter aka mutator.

Good Java coding practice involves coding in 3 stages, prep code, test code, & real (Java) code. Choose 'for' loops over 'while' loops when you know how many times you want to repeat the loop code. New improved way of defining 'for' loops:
for (String name:nameArray){}

Classes are grouped into packages. Can be imported into your Java program, e.g. 'import java.util.ArrayList', here 'java.util' is the package name and 'ArrayList' is the class name. To use a class in a package other than 'java.lang', you must tell Java the full name of the class. This can be done either by typing an import statement at the top of the code or by typing the full name every time you use the class in your code.

A subclass extends a superclass. The sanity test for this is to verify that a subclass IS-A superclass. An 'overloaded' method is a method with the same name but takes different arguments. An 'override' method has the same arguments and the same return type & also cannot be less accessible (e.g. public cannot become private).

An 'abstract' class is one that cannot be instantiated. For it to have any purpose, it needs to be extended. The opposite of abstract is 'concrete'. 'Abstract methods' are those that need to be override by the first concrete subclass, abstract methods have no bodies. If you have even one 'abstract method' in a class, the class must be marked 'abstract'. All object extend 'Object'. 'Object' has methods such as 'toString()', 'hashCode()', 'equals()', & 'getClass()'. You can call a method on an object only if the class of the reference variable has that method.

An 'interface' solves the issue with multiple inheritance. An interface is like a 100% abstract class. Interfaces need to be 'implemented'. All methods in an interface must be 'abstract'. 
public interface Pet {
public abstract void beFriendly();
public abstract void play();
}

Java has 2 areas of memory known as the 'Stack' and the 'Heap'. All local variables live on the stack, in the frame corresponding to the method where the variables were declared. All objects live on the heap, regardless of whether the reference is a local or instance variable.

A 'constructor' has the code that runs when you instantiate an object using the 'new' keyword. Every class you write has a constructor, even if you don't write on yourself. It looks like a class but doesn't have a return variable type in the definition. Overloaded constructors must have different argument list. The superclass constructor is always called before the current class constructor, even if you don't put 'super()' in your code. Use 'this()' to call a constructor from another overloaded constructor in the same class.
import java.awt.Color;

class Mini extends Car {
private Color color;
// no-arg constructor supplies a default color
public Mini() {
this(Color.RED);
}
// Real constructor that does the work of initializing the object.
public Mini(Color c) {
super("Mini");
color = c;
}
}

Part 3 - Things to be learned in the coming days:

Numbers, Data Structures, Lambdas & Streams, Exceptions, GUI, Swing, Working with Files, Networking, Multithreading/concurrency are the topic that I have yet to study. Will update blog posts as I get through them.

---

References




[4] Head First Java by Kathy Sierra (link)

Comments

Popular posts from this blog

Playing around with Dell R520 server

Experience Interviewing for an Infrastructure Engineer - Continuous Delivery position

2023 Summer Reading List Summary