OOP : we know the different basic types (these are often called primitive types) like int, short, float, double, and depending on the language, string (but not in java, I’ll explain). These are useful but often we will want to create more complex groups of variable to represent something else. In Object oriented programming, we will create things called Objects. At its core, an object is a collection of variables (often called its fields) that represent its data and functions (often called methods) that allow you to do actions upon an object’s data.
Now I have to distinguish between what an object, class and an instance is. A class is basically a type of object, every object is of a certain class. It defines what kinds of variables and methods those objects will have, and it is an abstract* representation of those objects. Think of it more like the “concept” of a type of objects. We can make the Car Class, which will define variables and methods common to every car. Here is where we define a Car will have (int) numOfWheels, (string) model, (int) yearOfMaking, (double) odometerReading and functions like stopCar(), turnOn(), fillGas(), etc.
An object is often a way to refer to an “instance” of a class. It is basically a specific, tangible group of data based upon the template set up by a class. In many contexts, “object” is a way to refer to an “instance”. In this sense, an object will have actual values filled in, so a car instance would be the trustyDaddyWagon object, which has wheels = 4, model = “Chevy Zafira”, yearOfMaking = 2002, odometerReading = 87642312, etc.
Think of it this way. Say you have a small company that owns multiple cars, and you’re setting up the paperwork for them. You would make up a paper template (class) for a certain kind of form concerning each car and its info. You’d make a bunch of fill-in boxes (fields) and then specify a protocol for how to log different changes and actions done to the car (method) on the form. Then your instances (objects) are the actual 5 paper forms of each car that have been filled out and are sitting on your desk. Neither of those is an actual car (your program isn’t actually storing cars on your hard drive), but an instance is a specific representation of a real-life thing that can be abstractly represented by the Car class.
There’s other concepts like inheritance, which is when you have a class that inherits certain values from another. Like you can have a vehicle superclass that has most of those variables, and you can have Car, Motorcycle, and Bicycle subclasses (a subclass is a class that inherits values from another class, the superclass), and then those subclasses can then only define variables specific to themselves, which could be (float) trunkVolume, (float) handleStrength and (float) chainLength, respectively.
Note*: “abstract” is an actual keyword in java relating to OOP, and its technical meaning is not what I’m using here. I’m using “abstract” as the normal english word.
Laymen’s terms for strongly typed: A language that will not automatically convert the type of a variable depending on context, and instead will give errors if you try to mix variable types together in an undefined way
Longer answer for strong typing: A variable can have different types. I can have an int (integer) variable, a short variable, a string variable, a char (character) variable and many other types. Generally, in Object Oriented languages (ask me if you need an explanation of these too), objects classes* can also be considered types, so you can have a Car variable, a Helper variable or a Model variable, for example.
[Something]-typed refers to how flexible a language is when interpreting the value of a variable. In the weakly-typed Javascript for example, I can declare a variable X = 5, a variable Y = “20” (“2” as in a 1 character string containing a 2 character), and then use the Math.max(val1, val2) function that returns the maximum value between val1, and val2. Math.max(X, Y) will give me an output of 20. Though Y was a string variable, the language automatically converts it to a number before passing the values to the function, giving me the desired value of 20.
Java, instead, will give you an exception if you do this. So if you want to do Math.max(X, Y) in Java, you will instead have to do some sort of casting or parsing (essentially two ways of “changing” the type a value is interpreted as) to do so. In Java, that would look like Math.max(X, Integer.parseInt(Y)) which will give a correct value of 20.
Strong typing can be a bit cumbersome at first to developers, but it is significantly more organized when it comes to understanding and using large programs with many different types of data being used with varying and possibly inconsistent variable naming schemes. Weird errors can sometimes pop up with weak typing that might take you hours to find, which a strongly typed language wouldn’t have even let you compile the program with. That’s why things like Typescript popped up, which improves the support for Typing in Javascript, and is essentially a strongly typed version of JS.
Laymen’s terms for multithreading: A computer’s processor’s core can only run one command at a time*, and so, it can only really be executing one line of code at a time for a program. To be efficient and not stall, it will instead divide its time between the many programs that are waiting to be executed. Multi-core processors can run multithreaded programs. So a program can divide a chunk of its code into a “thread” that can run at the same time as the rest of the program, but in a different CPU core. This lets you speed up parallel tasks, but it introduces a lot of potential problems that are tricky to solve, like “race conditions” where a program’s output depends solely on the near-random order in which different threads were executed.
Longer answer for multithreading: CPU cores will run code from one thread at a time. A thread is a chunk of code (more specifically, CPU instructions), and most simple programs will just create a single thread to run off of. A CPU core will use different types of priority queues to keep a track of the threads it is executing, and execute the highest priority one until another thread requires attention. Imagine a stimulant-fueled super fast cook working alone on 20 different orders at a time all by himself. He will divide his time up between parts of an order, while at the same time they’ll slightly prioritize the orders which have been waiting the longest. Some tasks require him to wait (like an item being cooked in an oven for 10 minutes), so he’ll do other tasks meanwhile. Some times the waiter or manager will interrupt his work and get him to do short, important tasks like making a sauce he forgot to make (which in computing are often things like hardware interactions such as clicking a mouse, which have to be quick and processed urgently).
A single threaded program would be like a bread, where you have to do each step one after the other, with very few parallel tasks possible (assuming the oven is preheated). In this sense, each order is a program. A single core can cook multiple orders at the same time (run multiple programs), but they can only actually actively work on one order (on one program’s thread) at a time. A multithreaded program is like cooking pasta. Boiling the pasta could be the main thread, while making the sauce can be a separate thread, as you can work on the sauce while the pasta boils, and then you can add the sauce to the pasta once the pasta is done. Multi-threaded programs can split certain tasks into a separate thread, that can run separately and at the same time if possible. Eventually, once various threads are done, you can stop and combine their outputs together. As a practical example, most programs run logic and the user interface on separate threads, so your program doesn’t freeze while a network request is made, or a large file is loaded. A multi-threaded food on a multicore kitchen would be like a well-choreographed kitchen with many cooks, where each cook is working on different parts of multiple orders at the same time. Cook 1 and 2 may be working both on Order 57’s different parts, while Cook 3 juggles frying eggs for Order 23, 75, and 52 at the same time.
This allows you to use your computer’s cores to not only run multiple programs at the same time, but run a single program more efficiently. The downside is that multithreading a program is NOT automatic, and it is a process that requires a lot of care, as multithreading introduces a lot of problems that can be very hard to solve. I detailed race conditions, but other problems can be like when two threads both try to access and change the same variable at the same time, or something called a “Deadlock” occurs, when two threads are both paused (sleeping) waiting for a certain signal produced by the opposite thread to keep being executed, but since both are waiting, that signal will never come, and the two will wait forever, freezing the program. This is why you see a lot of video games barely take advantage of multithreading, as it can be very difficult to wrap your head around and design your program in a way compatible with it. There’s certain tasks that just aren’t possible to multithread, so that’s another limitation