Alright, in this video I’m going to cover
the differences between Java and C#. To be honest, there aren’t many differences,
but I’ll cover the differences that we do have. Now, just to be clear, I am not going to cover
all the differences, just the big, major differences, but there will definitely be a few other little
things you might come across that you’ll need to look up when you start writing Java
code. One thing you will notice is a moment is that
Java takes a lot more work than C# to get setup, you see, Java is an interpreted language… Well, sort of. When you compile Java code it gets compiled
to Java bytecode. And this bytecode is then executed inside
something called the JVM. The JVM is the “Java Virtual Machine”,
and your Java bytecode is executed within this JVM. This of course makes sense since the whole
idea is Java can run on any platform, as long as there’s a version of the JVM for that
platform. In many ways, this is similar to C#, C# compiles
to a language called “IL”, which is then embedded in the EXE file and, provided the
machine has the .NET Framework or mono installed, then compiled to the native machine’s code
live as the program runs. So, they’re pretty similar. And, this means that anytime you want to run
a program that needs Java, like Minecraft, you need to install Java, you need to have
that JVM to be able to run this bytecode. So, in that case you download Java from the
official Java website, which they only just modernized. And when you want to run Java programs, what
you will end up downloading from the website is something called the “JRE”, the Java
Runtime Environment. And this provides the JVM and various other
things Java needs to run. It doesn’t come with any developer tools,
like a compiler, however. To get those we need something called the
JDK. This is the “Java Development Kit”, this
has the compiler and other development tools we need to make programs using Java. One thing that is important to note is the
JDK comes with everything the JRE has. So, the JDK is essentially just the JRE with
some extra stuff thrown in there for development, like a compiler, that’s it. This means that if you don’t have the JRE
installed on your machine, you don’t need to install it, the JDK comes with all of the
JRE things too, like the JVM, so we won’t have any problems running our program after
we’ve compiled it. OK, now, there’s something important be
aware of, that’s just recently come up with the JDK. Oracle has introduced a new licensing system
which means if you use the JDK for developing commercial programs, you have to buy a license. So, sure, for personal use, it’s fine but
if you want to use Java for an application that will get you even the slightest money,
you either have to pay for a license, or, use something called the “OpenJDK”. OpenJDK is an open-source Java Development
Kit, based on the original JDK, and not only is completely free, so you won’t need a
license, but Oracle themselves have made it quite clear that they absolutely support what
OpenJDK is. Which of course begs the question of: What’s
the point in paying for the official Oracle JDK when you can just use OpenJDK for everything,
including commercial use? And, the biggest reasons are that with the
official, payed JDK, you get support from Oracle if something gets wrong, you have access
to loads more tools than you get in OpenJDK, and, biggest of all, all updates are straight
from Oracle, while they’ll be from the open-source community on OpenJDK. So, that’s something to keep in mind, and
because of this, we’ll go over how to install both the official Java JDK and OpenJDK, don’t
worry, this shouldn’t take too long, then we’ll start looking at how Java differs
from C#. We’ll nice and quickly cover this for Windows,
Mac OS and Linux, they’re all very similar. Let’s try and get through this quite quickly
so we can cover the language. And these apply to both OpenJDK and the Oracle
JDK, there will be some differences, but they are mostly the same, I’ll show the Oracle
JDK, but they’re both configured the same way. On Windows, you can just get the installer
and run it, no problems there. But there is more configuration we have to
do once this is done just in case it hasn’t already been done from the installer. On Mac OS, it’s essentially the same, we’ll
download the installer and run it, but there’s more to this, and we’ll get to that in a
moment. If you’re on Linux, there are a range of
choices, and on Debian-based systems and systems that support installation from rpm files,
you could most likely just use the packages provided, but I won’t cover that, and from
what I tried they didn’t exactly seem to just “work”. So, what would be easier, since we know what’s
going on ourselves, and in my opinion the best way, because this just straight-up works
across all distributions of Linux is to download the binaries from the Oracle website, in the
“tar.gz” file. Then, extract out that archive and you’ll
get a folder from the archive. Now, all we need to do move this folder we
just extracted over to /usr/lib, we’ll need to do this as root of course. Now, this alone isn’t enough because they
aren’t in the PATH, but we need to be able to run “java” to run our programs and
“javac” to compile our programs. So, we’ll just very simply create a symlink
to those files, which is just the equivalent to a shortcut, in the “/usr/bin” directory,
where they are accessible through the PATH. To do that, we’ll use “ln -s” followed
by the source and destination. The source, so, where the java and javac executable
files are is inside the folder we just moved over, and within the “bin” directory within
that, so, you’ll end up with something like this, the version numbers will be probably
different though. Let’s do “java” first. Then, we just follow that by where we want
to create the shortcut, which is in “/usr/bin” and we’ll just call it “java”. Then, we’ll do exactly the same but instead
of “java” we’ll do “javac” so we can compile java code. And, later on you might find yourself using
other executables, like “javaws”, so you create the links for those as you need them. And, now, you should be able to write “java
-version” and “javac -version” without any errors, which means it works. Alright, but, now across all platforms, there
are some other things we need to do, we need to make sure the PATH is correct and another
Environment variable called “JAVA_HOME” are configured. On Windows, you can either access this by
just searching “environment variables” or searching “This PC” and hitting “Properties”
and “Advanced system settings”. Now, we just choose “Environment variables”
down here and we’ll see all the “Environment variables”. If we take a look at PATH, it should have
something related to the JDK in it. However, if it doesn’t, we need to add that,
so, we’ll add to the PATH where Java is, we’ll find Java inside “Program Files”,
and just “Java”, then we choose the JDK version we just installed, and the “bin”
directory within that is what we’ll set it to. On top of that, if there isn’t a “JAVA_HOME”
variable, we also need to set that, and we set it to the folder that the “bin” folder
is in, not the bin folder itself, so, it’s slightly different from the PATH, it’s one
folder up. Now, in order for this to work you need to
restart your computer after doing this, and that is so important. On Mac OS, we don’t need to worry about
the PATH since the installer handled all that for us. However, JAVA_HOME, isn’t configured. So, within the “bash_profile” file (in
our home directory), we’ll need to set it, and we can do that by writing “export”,
followed by “JAVA_HOME” and setting it to the “/usr/libexec/java_home”. This will only apply to this user though. Similarly, on Linux, we need to fill in the
“JAVA_HOME”, PATH is already sorted since we created the link in “/usr/bin”, but
we still need to set “JAVA_HOME”, if we want to do that for all users on the system,
we’ll modify “/etc/profile” to set JAVA_HOME to the directory our JDK was stored in, so,
we’ll write “export” followed by “JAVA_HOME”, an equals sign and the folder we copied, that
was in “/usr/lib”, since I’m in vim I can check what the folder name was so I
can set it correctly. Great! Now everything is properly configured, regardless
of your platform. Alright, let’s dig down on the code, I’m
going to be using the IDE IntelliJ Idea which is very similar to Visual Studio in many ways
and will take essentially no effort to get going provided you set JAVA_HOME and everything
else set correctly. However, you absolutely don’t have to use
it, you can use “java” in the command line to execute your Java programs and “javac”
to compile your programs, there’s lots of documentation and I’m sure you can figure
it out. Now, if you are using IntelliJ, we’ll just
create an Empty Project. To do that, make sure “Java” is selected
in the “New Project” window, choose an SDK version, don’t worry about any of these,
make sure they aren’t ticked, and hit “Next”, then tick this and choose “Command line
app” otherwise things aren’t going to work, and then we’ll give our project a
name. Now, notice how it’s asking us for a “Base
package”, so, that’s our first thing: What are packages? Well, packages are essentially namespaces,
that’s all they are. So, if I have a package called “A”, within
that package we can put classes in there. So, it’s exactly the same as the folder
structure you can get in your C# projects. Then, if I want to access that class from
outside from that package, we need to import that class. Now, this is different from C#, in C#, you
say “using” followed by whole namespaces, and that makes everything inside that namespace
accessible. In Java, you use something called “import”,
and you have to import individual classes. So, if I wanted to access this “Hello”,
I would say “import A.Hello”. However, you can also use wildcards, so you
can say “import A.*” which will import everything within the package “A”, you’ll
find that IntelliJ lets you just import classes as you need them by putting your mouse over
them though so you generally don’t need to worry about this yourself. You’ll also notice that if I make a package,
and make a package within there, it will join up into one “A.B” for neatness. Now, one important thing to point out is that
these packages are only in the source files. Essentially, all of your project’s code
is contained within a “src” folder, and that’s where you have your packages. It’s only the actual code that’s put into
packages, everything else, like resources are stored in just normal folders. But, wait, how are these packages different
from just folders, then? Well, technically they aren’t, these packages
are stored as folders in our file system, they’re just called packages, it’s just
a clearer way of representing them. But, really, they’re just a fancy name for
folders that behave exactly like C# namespaces that you use to organise your code. So, the base package is the whole package
that our entire project is going to be put in. So, now we need to look at naming this base
package. The first thing you need to keep in mind when
naming packages is that they need to be lowercase, do not put uppercase characters in the package. And, you also can only put letters and underscores
in package names, nothing else, so that’s important to keep in mind too. Now, there’s a general naming convention
when naming your base package, the package that your whole project will go into. You’re supposed to name it based on your
website. So, for me, my website is “abworld.ml”,
so you do that in reverse, meaning my base package name would be “ml.abworld”. But what if you don’t have a website? Well, then things get a bit tricky, Java doesn’t
really say what you should set it to in that case. But, just make sure to set it to something
that’s unlikely to conflict with something else, since that’s the whole point of it. Maybe I would call “com.abworld” or “com.abmedia”
or something if I didn’t have a website, up to you. So, once we’ve set that package name, we
can just go ahead and create the project! Right, finally, we’re here in the code. Now, we can use “System.out.println”,
giving it a string to print out some text to the console. Then, when we execute it, we’ll find our
text displayed in the “Run” section down here. Great! Let’s start off by focusing on the types. Now, in C# every single class or data type
inherits from one big base object called “object”. This means that every single object has “Equals”,
“GetType”, “GetHashCode” and “ToString” on them. And that’s everything, from strings, to
integers… To just everything. However, Java has a similar system, where
it also has an object type, but not everything inherits from it. Some primitive types, like integers don’t… But, for the most part, more complex data
types do, so that’s something to keep in mind. In Java, anything that isn’t a primitive
will have a capital letters at the start, for example, a “String” isn’t considered
a primitive, therefore it has a capital “S”, and it does inherit from “Object”. Alright, another thing that’s different
with the type system is “enumerations”. In C#, enumerations are literally just integers,
there’s nothing more to them. They just fancy integers, just syntactical
sugar, if you like. If I make an “enum” in C# and put four
values in there. Each of these values will automatically be
set to 0, 1, 2, 3 and so on. But we can manually set each of these to a
different number. These pretty much just get substituted for
numbers, there’s nothing too special about them. In Java, however, it’s a whole different
story. Enums are essentially classes and arrays joined
together. Now, fundamentally, it’s looks almost the
same, and you can use it almost the same way too, let’s hop into the code and take a
look. Let’s make an enum called “Device”,
and within here, we’ll have a phone, a tablet, a laptop and a desktop. Now, yes, in Java you often put the things
within enums as all capitals, so keep that in mind. So far, this is the same as C#. And, we can use these the same way. But we need to know what’s going on here
to take this to the next level. You see this enum is actually just a class,
and each of these are instances of this class. So, this where things get clever, and this
can be quite useful too, I can put some fields in this enum. Now, it’s important that this always stays
right at the top of the enum, so we’ll put this below. Let’s put a screenWidth, and a screenHeight
field in there. Now, watch this, if make a variable of type
“Device” and set it to “Device.PHONE”, there’s now a “screenWidth” and a “screenHeight”
within this. If I write “Device.TABLET”, it has a “screenWidth”
and “screenHeight” on it. What happening is this enum is essentially
a class, and these are just constant instances of the class. I could do exactly this with a plain class,
I would create the class, give it these two fields, then create each of these as constant
static instances of this class. But, of course, that would take more effort,
an enum just gives us this in an easier-to-use format. Alright, fine, but let’s take this up to
the next level. What we can now do to take this even further
is to make a constructor on this enum, that takes in the width and height and sets them
properly. Now, we can provide the parameters of this
constructor for each of these. So, these are just random numbers that I’m
making up, but let’s just say that the phone screen is 600 pixels wide and 1200 pixels
high. We’ll do some brackets, because we’re
providing the arguments for this constructor, followed by the width and height. And, you’ll notice here that IntelliJ is
showing us what parameters we’re providing the values for, this is just something IntelliJ
does, it’s quite convenient when I think about it, it would be nice is Visual Studio
had this because it tells you exactly which argument is going to which parameter. So, let’s just set some random sizes for
every single one of these. Now, each of these have a different width
and different height, and we could add even more sub-properties to these, I think you
can see how this is quite powerful in comparison to C# enums. We can also put methods in here too and pretty
much anything else that you can get in a class. Right then, the next topic to talk about is
properties! This is something you’ll definitely notice. In Java, properties don’t exist… At all. Instead, you use something called “accessor
and mutator methods” Java. This isn’t really a feature of Java, but
it’s a pattern that almost all Java developers use. Let’s create a class, and call it “C”,
for class. Then, within this class, we’ll have a string
variable in here, but we’ll keep it private. Then, we create a getting method and a setting
method. And these will do what you would expect. This is the accessor method here, and this
is the mutator method here. If we want to have a variable that we can
only get, we just don’t provide the “setter” and this is an extremely common pattern in
Java, this is everywhere. Let’s take a look at Exceptions next. Now this is something that is quite different
between Java and C#. In Java, you have two different types of things
that can go wrong. You have something called an “Error” and
something called an “Exception”. Now, an “Error” is a major error that
comes from something internal in the language, like the JVM or something like that, changes
are you will never need to handle “Error”s or even look at them. However, “Exceptions” are different. Now, “Exception” if look at what’s going
on inside “Exception” we have a range of exceptions, but also something called a
“RuntimeException”. And there’s a pretty big difference between
the two. Anything here, that just inherits from “Exception”
is something called a checked exception. And anything that inherits from “RuntimeException”
is something called an unchecked exception. But what does this mean? Well, a checked exception is an exception
that you must handle. You have to handle that exception at some
point down the line. While an unchecked exception is an exception
that you don’t have to handle. And unchecked exceptions usually come internally
from Java, so, things like dividing by 0 or trying to access an invalid method in a class,
or something along those lines. When you make exceptions, you should always
make checked exceptions, never unchecked exceptions. In C#, all exceptions are unchecked, you don’t
have to handle them, they’ll just crash the application if they occur. So, how does the checked system work in Java? Well, let’s think about a very simple application. We have three methods, like that. And this is the call stack, so we’re in
a method called “Method1”, that we called from “Method2”, which was called from
“Method3”. Then, inside “Method1”, we throw a checked
exception. What happens is we get a compiler error inside
Method1, saying that the exception is unhandled. So, it’s telling us that we need to deal
with this exception. And we need to handle this Exception inside
“Method1”. So, we could deal with the exception inside
“Method1”, we could put a “try…catch” in the same method the Exception is thrown. And, now, we don’t get an error anymore,
because we’ve handled the exception, that’s how you handle exceptions, you just catch
them in a “try…catch”. But what if it needs to be handled somewhere
higher up? Of course, sometimes you can’t handle all
these errors at the same level you throw them, in a way that kind of defeats the point, sometimes
they need to be sorted out at a higher level. For example, if we have a method that makes
a connection to a server, and then we have another method that prepares the address. If we failed to prepare the address and threw
an exception in here, we don’t want to handle that exception inside here, we want to sort
that out in the place we’re trying to make the connection to the server, because that’s
the level where we’re able to say to whoever wanted to make the connection that the address
was invalid. That’s where we want to handle it. We don’t want to deal with it in the smaller
part that processes the address. So, back to our three methods, in order to
tell Java that this exception needs to get handled from the person that calls Method1,
instead of Method1 itself, we add to the method’s declaration the word “throws”, followed
by the exact type of exception this throws. So, this tells Java that this method can throw
that exception, unhandled, and now the responsibility is pushed up to “Method2”, now it’s
up to “Method2” to handle the exception. We could also do the same to “Method2”
if we wanted. We can add to “Method2”’s declaration
that it throws a given type of exception, which, once again tells Java that this method,
“Method2” can throw that exception unhandled, and now yet again, the responsibility has
been moved up to “Method3”, now it’s up to “Method3” to catch the exception. And we can add multiple exceptions to this
“throw”s thing here. We can specifically handle some exception
but leave other exceptions to be handled higher up. Now, there is a lot of controversy surrounding
checked exceptions, some people think they’re good, some people think they’re bad. Because on the one hand they make sure you’re
code always handles exceptions at some point, your application is way less likely to crash,
but on the other hand, this “throws” bit here can get exponentially bigger as you can
see in this image here, the amount of exceptions this method can throw, that need to be handled
just gets bigger and bigger. And, on top of that, some people also don’t
like it because some developers will just leave empty catch blocks to stop it from having
to be handled properly, but that’s really bad, please don’t do that. Now then, what about unchecked exceptions,
if we have this great checked system, why are some exceptions unchecked? There’s a class called the “RuntimeException”
class, and if you make an exception based on that, it’s unchecked and doesn’t need
all that, what’s that for? Well, remember that earlier I said that internal
exceptions are unchecked, like for example dividing by 0, that’s an unchecked exception. That’s because Java decided that it would
be near madness to try and work out every single little exception that could come from
things like that. Imagine if every single time you divided by
a number, you had to say that this method can potentially throw a “DivideByZeroException”,
things would get very messy, very quickly. And that’s why the absolute fundamental
things, like division or accessing members on an object are unchecked exceptions. Essentially, the official way Java looks at
it, (although as I’ve said people do have different opinions about this) is never make
unchecked exceptions in anything you do, it’s the only the absolute fundamental things that
should give off unchecked exceptions. Right, hopefully that makes sense, it’s
really difficult to explain that, but try it out in your own code and you’ll get an
idea of how it works. Next thing to talk about is inheritance, one
of the most important parts of object-oriented programming. The biggest difference is how you make a class
inherit from something. If you’re inheriting from an interface,
you write “implements” followed by the interface. And if you’re inheriting from another class,
you write “extends” followed by the class. In addition to that, in C#, you need an override
keyword when you’re replacing a method in a subclass, however, in Java you don’t need
to override. If I make class “A” and class “B”
and put a method within class “A”. Then, make class “B” inherit from class
“A”. I just put in a method with the same name
as the one in class “A”, and it will replace the one in class “A”. Most other things are the same, however, one
thing you will notice is that virtual isn’t a thing in Java. All Java methods are virtual. You’ll notice that I can provide code for
the method in class “A” and class “B” will just replace that code, I don’t have
to mark it virtual. I only have to mark it abstract if I provide
no code for it, as well as making the class abstract of course. Alright, I’ll just quickly mention some
of the other smaller differences you have. You’ll notice that if I can only have one
public class per file, and that public class needs to have the same name as the file it’s
in. We can make lots of smaller, non-public classes,
but it’s one public class per file, which is of course different in C#. Also, the equivalent of the C# term “const”
is “final” in Java. And, in C# you can use “using” to make
sure an object gets disposed, in Java that’s called “try”. In Java, there are no multi-dimensional arrays
(thank god). In Java, you can create arrays like this,
with the square brackets after the variable name, and it’s exactly the same as putting
the square brackets after the type. In C#, you can add internal to a class to
make sure that class can only be accessing from within the current project. In Java, you can add “package” to a class
to make it can only be accessed from within this package. In Java, there’s a keyword called “strictfp”
that you can add to classes or methods that make sure floating-point numbers are handled
the same across all different systems. Alright, well, I hope this video was helpful,
I dove into some of the biggest differences between C# and Java, the biggest difference
being the installation – if you want to see more videos, mainly related to C# or C++,
feel free to subscribe, and feel free to suggest any videos, this video came from a suggestion
in fact. Alright, bye!