Introducing Java from the perspective of a JavaScript and Ruby developer

It was a beautiful sunny day in mid-May, I was diligently learning Ruby with wonderful peers when a friend at the table had mentioned the code we were looking at would’ve been 5x longer had it been in Java. Of course that was pretty shocking already, but did I understand what he actually meant? No, I mean how could I? Java is its own beast. And frankly, it was the very beginning of my dev career!
A company presented a code challenge to candidates and even if you didn’t know Java previously, you were tasked to learn it and program a basic application to showcase your potential to learn and willingness to learn. So I set out to do just that! I knew I was going to learn Java sooner or later — guess it came sooner than later!
JavaScript
was my first programming language — HTML and CSS aren’t programming languages after all despite their importance. So when I kept bumping into familiar methods or functions, it was a great relief! Dealing with a new language, new syntax and rearranging one’s thoughts when trying to code can be a task and anything to help make it easier is definitely welcome.
[1, 2, 3, 4, 5].length;array.forEach();"MAY thE foRce bE WITh You".toLowerCase();for(int i=0; i<array.length; i++) {};Integer.parseInt('123');777.toString();
Ruby
Although I first took up JS, Ruby was the first programming language I reached a decent level in. Thanks Flatiron, my instructors and TCFs! Ruby, if you didn’t know, is an object-oriented language and everything is an object. It resembles Java in this aspect. And since I was already familiar with OOP — abstraction, inheritance, encapsulation and polymorphism — thank the old and new gods for that!

Static Languages
With Java you code away and when you want to execute your program, you have to first compile it and then run it. The compiler essentially translates your code into a more readable format for the computer to process. And a major responsibility of the compiler is to check types.
In Java you must define what type a variable is — whether it’s a number, string, array or other primitive data structure or object. Now coming from Ruby and JavaScript I’ve had the pleasure of not having to think about such things. It is wonderful because you can focus on the core functionality and design of the program without having to get too detailed.
javac Animal.java ==> produces a Animal.class file if it compiles
java Animal ==> executes the Animal.class compiled file
Java
There were a few key points I learned which are fundamental to coding in Java:
- Each file can only have a single public class
- There’s a proper setup for a project
- Declare the type of inputs/arguments for methods
- Must define whether or not a function has a return value and if so of what type
- Where to actually place semi-colons so the compiler won’t complain
- It is difficult constructing a hash (Ruby) / object (JS) in Java
Single Public Class
You can have a single file with multiple classes, and it will compile into separate .class files, but you can’t execute said files because they need to be public for you to do so. With that said you can’t refer or make an instance of any of those classes, besides the one that is declared as public, because they’re not publicly available. This is why it is general to adhere to a single class to a file since you’re trying to construct a polymorphic and scalable application after all!
Proper Setup
Originally I started a “project” with the terminal and creating a directory and an initial .java file to start tinkering around. Once I made a couple or a few classes, each in their own file and made publicly available, I wanted to test them out. They were all in the same directory at the same level and were able to compile and execute properly.
But in the IDE, an warning notification always presented itself saying it couldn’t find the external class — symbol it said — for some reason my IDE couldn’t understand the relationship between the files in the same folder. Eventually I just created a new project within the IDE (Netbeans, since it was easier to install than Eclipse) and that issue was a thing of the past!
Type Checking
Personally I already knew you had to declare the type of inputs to each and every function — if there was an argument at all — but I hadn’t really thought about the function itself.
I had previously seen void here and there when reading blogs and posts online written in Java and some C language, but had never really understood it. If you see void next to the function, it is telling you that the function doesn’t return any value — say you’re changing an object’s property or attribute, or simply printing something out to the console.
Hashes / HashMaps / Dictionaries / Objects
Furthermore, you have to declare the type of data to be held within arrays and such objects too! It means you can only have an array of integers, or only of strings and you couldn’t mix and match! For arrays this may not seem like a big issue, but think about hashes (Ruby) or objects (JS). They tend to hold all kinds of types.
A common example would be of an address:
const address = {
door: 123,
street: "Main Street",
city: "Philadelphia",
state: "Pennsylvania",
zipcode: 11923,
country: "USA"
}
Here we have a combination of numbers and strings. In other words we can’t have this in Java.
You actually can, but you have to do what is called casting. Casting is the process of taking an object and applying another type onto it. With this process, you can declare a hash / hashmap to accept objects and insert the data you need into it. With Java 5+, I believe or was it 8?, it will cast it for you! Then when you retrieve the data, you can cast that info into the type you know it to be true.
HashMap<String, Object> address = new HashMap<>();address.put("door", 123);
address.put("street", "Main Street");int doorNum = (int) address.get("door");
And previously you couldn’t even add primitives into objects! Coming from a wonderful place of not having to care about this made it very difficult to create a valid system design for a simple program.
Pleasing the Compiler;
There are many reasons for why a compiler would fail at compiling a file and I won’t be getting into it, but semi-colons can and are a nuisance when it comes to this. Coding in Java made me learn exactly where they need to be!
I used to add them after almost everything:
in JavaScriptconst doubleNum = (num) => {
return num*2;
};
But actually you don’t need that extra semi-colon after the ending brace declaring the end of that block! I definitely knew this at the beginning and then forgot…
Object-Oriented Programming
Can’t properly talk about Java without touching upon some OOP concepts!

Abstraction
the process of removing physical, spatial, or temporal details[2] or attributes in the study of objects or systems in order to more closely attend to other details of interest[3]; it is also very similar in nature to the process of generalization; — Wikipedia
Take your pet dog/cat — what is it’s name? Who cares about its name! Just kidding. What is it? It’s a pet. But what is a pet? It’s an animal. And what is an animal? It’s an organism.
We can infer these generalizations because they each have similar attributes or defining properties and actions. Not all animals can be pets, but those that are pets all have similar characteristics. We tend to pet pets, feed them and cuddle and sleep together.

class Pet {
// beStroked
// beFed
// cuddle
}
This is generalization / abstraction. But why is this important? It is essential for a program. To further illustrate it, we shall briefly look at inheritance first.
Inheritance
Continuing with the example demonstrated above we have the following abstracted diagram of your pet dog:
Animal → Pet → Dog
Animals all fundamentally have similar attributes right? That’s how scientists got around to defining what they are and how we think of them today. Think of how come a plant isn’t considered an animal. Some of these characteristics may be that they can move, eat to stay alive, do not possess human-like intelligence and rely more on instincts and feelings more than we do.
class Animal {
// move
// makeSound
// respondWithInstinct
}
Then if we continue with the things mentioned above about pets — everything that applies to an animal also applies to the pet and all other animals. This is basically inheritance! The extends is the process of extending or inheriting these attributes, characteristics and actions to another class.
class Pet extends Animal {
// move
// makeSound
// respondWithInstinct
// beStrokedWithoutKilling
// beFed
// cuddle
}
But pets have extra or special attributes that all animals do not have. Therefore we can update the diagram to account for all animals to:
Animal
/ \
Wild Pet
/ / \
Tiger Cat Dog
Now cats and dogs both can be petted without killing that person and tigers can be as they were in the wild minding their own business. But then again, cats and tigers have similar attributes as well right? I guess we should go back to the drawing board and rethink our approach!
Animal
/ \
Feline Canine
/ \ / \
Tiger Cat Dog Wolf
This feels much better! All felines, cat or tiger, make sounds in a similar fashion which we refer to meowing — it’s official term. And the same can be said about dogs and wolves, but with barking or howling. But now we’re left with the case of pets! If a class only inherit from another class only once, then what are we to do with this situation?
Polymorphism
Just like with modules in Ruby, you can give certain groups of actions or methods to a class that is already inheriting from another class with what they call an interface. With an interface you implement a group of methods to another class.
interface Pet {
// beStrokedWithoutKilling
// beFed
// cuddle
}class Cat extends Feline implements Pet {
...
}
Interfaces are generally meant for classes without any relationship or similar attributes, so I assume someone would say you should redesign your structure so can use inheritance instead of an interface — but this is just an example anyways!
So if you had a human class as well, you can have an interface for actions like move, eat and sleep. Then a class inheriting from animal and from human can also access these actions too.
Single Source of Truth
Man does this bring back some more memories! When learning OOP with Ruby our instructor would say this on the daily and I really took it to heart trying to adhere to best practices and get into this kind of mindset.
The single source of truth is the practice of structuring a program so that every piece of information is only stored once. Even if it is relevant to multiple models or classes, you would have to refer to it externally. This saves valuable space in programs and databases which could also affect processing speeds.
If we have the following models/classes: Artist, Song and Genre. What is their relationship with one another assuming we care about relationships and such a database?
in Ruby# create instances of each class
jayz = Artist.new("Jay-Z")
99probs = Song.new("99 Problems")
rap = Genre.new("Rap")# connect each
99probs.genres << rap
jayz.songs << 99probs
# the shovel operator can append to an array
An artist can have multiple songs and songs can have multiple genres. Therefore an artist can have an indirect relationship with various genres through the songs they make and sing.
# at first you would have to do something like this
jayz.songs[0].genres# => [Hip-hop, Rap, R&B]# but then you could set up a shortcut to formulate this
jayz.genres# => [Hip-hop, Rap, R&B]
But the artist object only stores info on itself, the song itself and the genre itself. An artist instance — an object created from a class — would refer to its song data on a song instance and so on.
in JavaArtist jayz = new Artist("Jay-Z");// declaring a variable of type Artist and initializing it with a string of Jay-Z
Encapsulation
can mean a couple of things but I want to touch upon the the process and significance of creating attributes or properties on a class and specific getters and setters to access and manipulate or change its data.

in Javapublic class BankAccount {
public int accountNum;
public String password;
}
If you had direct access to those attributes and able to change them as you’d like, it would pose a security concern to say the least. This is why a step up would be to create getters and setters:
in Javapublic class BankAccount {
private int accountNum;
private String password public BankAccount(int number, String pw) {
accountNum = number;
password = pw;
} public int getAccountNum(){
return accountNum;
} public void setAccountNum(int newNumber){
accountNum = newNumber;
}
public int getPassword(){
return password;
} public void setPassword(String newPass){
password= newPass;
}
}
Now you have completed a step to better protecting sensitive information. In the setter methods you can further add instructions to check the data coming in, check who is making the request, verify whether or not this user is authorized to do so etc.
Thoughts
What they say about programming in static languages taking more time than dynamic and interpreted languages, is most definitely true. There are more steps to consider and a lot more structure to implement. But in that, a finished program will be easier to scale, debug and safer against simple mistakes.
It’s difficult learning a new language with its unique bells and whistles. At times I didn’t know whether or not to use a List, an Array, or an ArrayList for the case I was considering. It’s a matter of looking at the documentation, understanding its usage and capabilities and how it can interact with data. There’s a learning curve there to know which works for which scenario and why.
With that said, Java is widely used and a powerful language that many still use. But being preferable to JS, I think I’ll look into Typescript now that I understand the basics of type-checking!
