TOMMY MACWILLIAM: In this video, we're
going to write our first Android app.
To get started we're going to be using
an app called Android Studio to write
all of our Android code.
Android Studio is an IDE, or an
Integrated Development Environment,
that's provided by Google to
help you write Android apps.
So let's take a look at Android
Studio and create our first app.
So I'm going to open up Android Studio.
And now to get started, I'm going
to come over here and select
Start a New Android Studio Project.
Now here I have a bunch
of different options here.
Our app is going to be
pretty simple, so I'm just
going to select this third one
over here, this Empty Activity.
Then I'm going to click Next.
And then it's going to ask me just
some information about my project.
So first I'll give it a name.
I'm just going to call this JavaExample.
And then it's going to ask you
a few questions about where
to save your project.
I'm just going to put mine
on the desktop for now.
For package name you can
select whatever you want here.
A common convention when
writing Android and Java code
is to take some domain name you own and
have the package be that domain name
reversed.
So CS50's home page is cs50.harvard.edu,
so I've selected edu.harvard.cs50
as my package name.
And then the end here, this
javaexample, is just a lowercase version
of the project name that I selected.
For language we're going to select Java.
And lastly, this minimum API level.
This basically says, what is
the lowest version of Android
you want your app to support?
And you can see here that as
I change different versions
the IDE will tell me approximately
what percent of devices
out there that we're going to support.
So for these videos we're just
going to be using Android 5.0, which
is pretty widely supported.
But it's up to you what minimum
version you want to support.
And we have a couple
other questions here.
One is about supporting instant apps.
We're not going to worry about that.
And this last checkbox
is about using AndroidX.
And so this is basically just a
newer version of Android libraries.
So we're going to check this, since
that's sort of the new version
that we want to use.
After that we'll click Finish.
And here we go.
So now we're inside Android Studio.
And you can see that we actually
generated a bunch of files for us.
And so we'll go through those in a bit.
Before we do, we first need to create
an AVD, or an Android Virtual Device.
So this will basically allow you
to run Android apps on your laptop
rather than needing to
plug in an Android device.
So to create an AVD,
what we're going to do
is we're going to go
through Android Studio,
we're going to specify what type
of device we'd like to simulate,
as well as what version of
Android is installed, and so on.
And then once we've
created that, we're going
to be able to run apps on that device.
So let's go through
and create an AVD now.
So to create an AVD inside of Android
Studio, I'm going to come up here.
And in the top right, you'll see
this little Android logo and a phone.
And it says AVD Manager
when I hover over it.
So I'm going to click that.
And you see here that I already have
a couple of virtual devices created.
But just to walk you through creating
one, down on the bottom right here,
you'll see a button that
says Create Virtual Device.
So I'll click that.
And I'll have this pop-up appear.
And here you can see a bunch
of different types of phones.
So for example, if I wanted to emulate
a Pixel 3a, I can click on that.
Then I'll click Next.
And then here it's going to
ask you what version of Android
you want to put on that phone.
So, up to you which
version you want to use.
I try to use a recent version.
So I already have Android 9 downloaded.
But if I didn't have
Android 8 downloaded,
I could just click on Download here.
After you click Next, you have
a few different options here
around just some other sort of graphics
options and some advanced stuff.
You don't really have
to worry about that.
You can just click Finish
to create your AVD.
So before we get started
writing any Android code,
let's walk through a little bit of
the syntax of the programming language
that we'll be using
to write Android apps.
So we're going to be using Java
when writing our Android apps.
Google also supports this
programming language called Kotlin.
That's pretty similar to Java.
But throughout these videos
we'll just be using Java.
So Java is a little similar to C.
It has some differences but also
a lot of similarities.
Let's start by first looking at all
of these data types available in Java.
Some of these probably
look really familiar.
Much like in C, Java has
int and char, double, float.
All that stuff you're familiar
with is supported in Java.
And Java also has a whole lot of more
advanced data types like list and map
that we'll get into in a bit.
But the Java standard library, or
the sort of set of objects and APIs
and libraries that's provided to you
by using Java, is really, really large.
And so we won't go through
everything in these videos,
but we'll try to touch on some
classes that you'll really
commonly use while writing apps.
So here's our first
few lines of Java code.
And here we're just going to
initialize a few variables.
And this should look really familiar.
In this first line here we're
creating a new variable.
Its type is a String.
Notice that in Java that's capitalized.
And then we have an equal
sign, and the right-hand side
is just the value of that string.
Then the next line, we're creating an
int, setting its value equal to 50.
And then we can change that value
using the same exact syntax that you
used in C. Also notice that every
line ends with a semicolon, something
you're also used to from C.
Conditions look pretty much the same.
We can create another string variable.
In this first line here, notice how
I'm not using a double equal sign here.
I'm saying title.equals().
So we'll get into this a bit later.
But this is something that's called
a method on the String object.
So rather than saying equals equals
whenever you're comparing strings,
you'll have to remember
to say .equals(),
or else you won't actually
get the right comparison.
On the third line here this
is equivalent to printf in C.
This is how I would print
something out to the screen.
I can say System.out.println,
and that's going
to print something to standard out.
Else works sort of the same
way that you're used to in C.
Next up are arrays.
Again, pretty similar to
C. In this first line here
I'm declaring an integer
array called values.
And then on the right-hand
side, this is where
I'm assigning an initial
list of values to that array.
So to do that in Java, I'll
say new followed by int--
that's the type of the array again--
and then in braces 1, 2, 3.
So this syntax, a little bit different
than what you're used to seeing.
And then in the next few lines I'm going
to be iterating through that array.
So unlike in C, Java arrays
know how large they are.
So I can just say values.length in
order to get the length of this array.
So there's sort of no need for
me to pass that in separately.
With any array I can
always get its length.
And then the rest of this for
loop should look pretty familiar.
I'm creating a variable to start that
I'm going to use as my counter variable
to step through that array.
I want to keep looping until
that counter variable is less
than the length of my array, because
remember, arrays are zero-indexed.
They start at 0, not 1.
And then at the end of each loop I just
want to increment that counter variable
so its value is one more than it
was on the previous iteration.
So hopefully all this looks
pretty familiar at this point.
Java also supports
something called lists.
And you can think of a list as
basically a dynamically sized array.
So with arrays, once you
initialize them with some values,
it's really hard to add
on one or remove a value.
With lists it's actually really
easy to add and remove values.
So in this first line, this is
the syntax for creating a list.
So we're first saying my type is List.
And then you'll in angle
brackets here, we're
going to specify the type of
the element inside of the list.
So this is a list of strings.
So I have List, and then in brackets
String, which is just the type.
Then my list is called values.
And then I'm going to be creating
a new instance of a list.
So that's why I have this new operator.
And the type of list I want
to create is an ArrayList.
Java supports a few
different types of lists.
ArrayLists is the simplest, and
so we're just going to use that.
Then in these next two lines I'm going
to be adding an element to that list.
I can say values.add("one"),
values.add("two").
And after those two
lines execute, I now have
a list of strings with two elements.
So you can see I'm dynamically
adding element to that list.
Then to iterate over that list this,
this is called a for-in operator.
Basically it's just a shorthand
for that for i equals zero,
i is less than i++ syntax we just saw.
I can say for String value, followed by
a colon, and then the name of the list
I want to iterate over.
So by saying String value colon
values, I'm basically saying,
I want to iterate over every
element in this values array.
And then what I want to do at
that value is just print it out.
So I can say System.out.println,
and that's going to print the value.
So just to dive in a little
deeper on that syntax,
we saw that using that
angle bracket, we're
specifying the type that's
contained within the list.
In Java this is called a generic.
And it's basically a way
for one class or one type
to understand something
about what's inside of it.
So you can basically pass
a type to some other type.
So for example, if I wanted
to create a list of integers
rather than saying capital String,
I would just say capital Integer,
and then I can add integers
to that list in the same way.
Java also supports a
data type called a map.
In other languages this
might be called a dictionary,
or in JavaScript an object.
And the syntax is pretty similar.
You can think about a
map as, rather than just
being a list of values, a mapping
from some key to some other value.
Much like a dictionary maps words
to definitions, our Java map
is going to be kind of the same concept.
So in this first line
we're creating a map.
And this time inside
of my angle brackets
I'm specifying two
things instead of one.
And that's because we need to
give both the key and the value.
So by saying map string
comma string, I'm saying,
I want to create a map that
maps strings to strings.
Then the right-hand side,
I'm saying new HashMap.
And again, Java has a few
different types of maps.
HashMap is probably the simplest
so we're just going to use that.
And then notice inside of those
brackets on the right-hand side,
I don't have anything.
If I wanted to, I could technically
repeat string comma string there.
But the Java compiler
can understand, because I
said string comma string
on the left, I don't
need to say it again on the right.
So it's just sort of a shorthand.
These next two lines are how I might
insert something into that map.
So I can say airports.put().
And then I'm creating this
mapping between airport codes
and the name of the airport.
So I'm creating a new
entry with a key of "SFO"
and a value of "San Francisco."
Similarly I can create a key of
"BOS" and a value of "Boston."
Then to iterate through
that map, and say
I want to get everything
inside of that map
and understand what the keys and values
are, I can use that same for-in syntax.
So I'm going to say for.
And then the type of the object
I'm going to use to iterate
is going to be a Map.Entry.
So again, this is just
saying, I want to get
a pair of key and value-- sort of
a key and its corresponding value.
And to do that, I'm going
to say airports.entrySet().
And that's just going to give
me a list of those pairs.
So once I have that
list it's really easy.
I could just say
.getKey() or .getValue().
And those are going to do
exactly what you'd expect--
either get the key or the value
for each entry in that map.
So if I were to run this code, what this
would do is this would print out first,
"SFO" followed by a colon
followed by "San Francisco."
That would be the first
iteration of the for loop.
Then the second iteration of the for
loop would be "BOS" colon "Boston."
So basically, just
walk through that map,
and we can do whatever we
want with each key and value.
So list and map are actually
something called classes in Java.
And when we're writing Java, we're going
to be writing a lot of our own classes.
You can think about a class
as basically a struct that
can also have functions attached to it.
And when we write a
function inside of a class,
we're going to call that a method.
So here's the syntax for
creating a class in Java.
So we're going to start
by saying public class.
This "public" says that other
classes inside of your application
can also use this class.
You might also say
something like private class
if you wanted to say,
this class is private,
I don't want any other classes
in my application to use it.
But public is a reasonable default.
Then class, then the name of your class.
So here we're creating
a class called Person.
Notice that the class is uppercase,
just like list and map were.
And that's just sort of a Java
convention to start all of your classes
with an upper case letter.
Then we'll use an open
brace to start the class.
Now, this class has one field.
And this field is of type String.
And we're calling it name.
Last, we're going to create what's
called a constructor for the class.
And a constructor is
basically a special method
that's going to be called when you
create a new instance of that class.
So here my constructor
takes one parameter.
It's a parameter of type
String, and we called it name.
And all my body does is take the
parameter that's passed in by the user
and save it.
So that way, later on in
other methods of the class
it can use whatever the
user passed in to start.
So by saying this.name
equals name, I'm saying,
I want this name field that
I declared on the second line
here, I want the value of that to be
equal to whatever the user passed in.
And now to use my class, we
can look at this last line
here, where is starts with the type.
My type now is Person.
I basically defined a new
type by creating that class.
The name of that class is person
now, but with a lowercase letter,
since again, it's just
sort of a convention
that objects or
instances of a class will
start with lowercase
letters and the classes
themselves will start with uppercase.
Then I'm saying I want to create
a new, and then Person again.
And by passing in "Tommy," I'm
going to invoke this constructor
with the value "Tommy."
So I mentioned that classes
can also have methods.
And so here's an example of that.
Let's say that we still have that
constructor in that field name,
just as before.
And now I'm going to declare
a method on this class.
So we're starting by saying public.
Again, that's so that
other classes using
an instance of this class or
an object can call this method.
Next is the return type of the method.
It's just void, which means we're
not going to return anything.
And then the name of the method.
So here you'll notice
this is also camel case,
so starting with a lowercase
letter, and then every new word
will start with an uppercase letter.
This method doesn't take any parameters.
And its body is just one line.
We're just, again, going to print
something out to the screen.
And we're going to say, "I'm"
and then that name variable.
So you'll notice here that we don't
need to pass in again that name
variable to this method, because we
already passed it to the constructor,
and then we saved it.
So by just saying name here, Java
knows that this name actually
refers to that name field
inside of your class.
So now, to use this method I can
create that person just like before--
say new Person, pass in some value.
And then I can say person.sayHello().
And that's going to call this method.
So this is just like before when
we were looking at lists and maps.
When you said airports.put(), put()
is just a method on some map class
somewhere.
And we didn't write that
map class ourselves.
Someone else wrote that
and provided it to us.
But under the hood that's
basically what's happening here.
We could also have what
are called static methods.
And these are methods that
you can call on a class
without having an instance of it.
So instead of saying
public void wave, I've
just said public static void wave here.
We can define the
method in the same way.
The body of the method is
just like any other method.
But then to call this method, on this
last line here you can see I'm saying,
capital Person-- so that
refers to the class--
.wave().
So here we didn't have an
instance of that class.
We're not using an object.
We're just referencing the class
itself, and we're calling wave.
And this can be helpful if
there's any methods that you
have in a class where it doesn't really
make sense to instantiate a class,
or it's just sort of unnecessary
to have an object around.
And that's where a static
method might come in handy.
One of the more powerful features
of classes is inheritance.
And inheritance allows
you to say, I have
some base class or
some parent class that
defined some fields and some methods.
And I want to take that class
and modify it a little bit.
So maybe I have some other
class I need to write
that's really similar
to that first one, but I
want to change some of the
behaviors in this new version
and keep some of the other ones.
So let's walk through an example.
Here we have a class called Vehicle.
And this Vehicle class has two methods.
This first method you can
see it returns an integer.
I've just called it
wheels(), and it returns 4.
And this says, OK, for every
vehicle, it has four wheels.
Then I have another method called go().
That's just going to print something out
to the screen and not return anything.
So nothing new here.
This is just a regular class,
and we can instantiate that class
or create an object in the same way,
and call these methods in the same way.
But let's say now that I'm writing
a class to represent a motorcycle.
And a motorcycle is basically
a subclass of a vehicle.
You can think of a motorcycle
as a type of vehicle,
meaning it shares many
of the same properties,
but some things are a little different.
So to capture that, I'm going to start
declaring my class in the same way.
I'm going to say public
class Motorcycle.
And then I'm going to
say extends Vehicle.
So this in Java is how
you're saying this class
inherits from this other
parent class or superclass.
And after I say extends
Vehicle, now my Motorcycle class
has access to everything that
was in that Vehicle class.
So I could say Motorcycle.wheels()
and get back 4, Motorcycle.go(),
and it would print out something to the
screen, just as I could with Vehicle.
But now what I want to do is
override that wheels function.
Because motorcycles have
two wheels and not four.
And so to do that, I'm just going to
basically re-declare this wheels()
method.
I'm going to say public int wheels().
And then rather than returning
4, I'm going to return 2.
And you'll notice on this
second line I've also
added what's called an annotation.
It says @Override.
This is basically just
a signal to the compiler
telling the compiler that I
just overrided this method.
If I forget the override, that's OK.
But it's really helpful,
because if I had this @Override,
and I tried to override
a method that didn't
exist, the compiler would
tell me, hey, you're
not actually overriding anything.
You probably messed up somewhere.
So whenever you're
overriding a method it's
really helpful just to add this
@Override before you do that.
So that's extending classes.
And in Java you can also have
something called an interface.
And you can think of an interface
as basically a list of methods
that some class has to implement.
And if they don't implement
all of the methods
in some interface, the
compiler will tell you, hey,
you have an invalid class here.
You're not implementing
one of these methods
that you told me that you
were going to implement.
So here's an example.
So we'll start our interface
with public interface.
And we're going to name this Teacher.
And now, inside of
this interface we just
have one method which has a void type.
It's called teach().
But what's interesting about this
is there's no method body here.
We haven't specified at
all what it means to teach.
We've just said, in order to be a
teacher, you have to know how to teach.
It's basically the same
as signing some contract,
saying, if you're going
to use this interface,
you promise that you're going
to implement this method for me.
So now, to use this interface
it's pretty similar.
We can say public class
CS50Teacher implements Teacher.
And this says, there's some interface.
I'm implementing every method
inside of that interface.
And a class can implement as
many interfaces as it wants.
I could have said Teacher comma
and then some other interface.
But we can only ever extend one class.
So in Java you'll see really
commonly lots of interfaces,
and classes can conform
or implement a bunch.
But when you have a base
class or superclass,
you can only have one per class.
Now, to implement this
interface, same as before.
We're just going to declare
a method in our class
with the same name and the
same type as that interface.
So I'm going to say, @Override, just
to make sure the compiler would tell me
if I'm overriding it
incorrectly, public void teach().
And then this method is probably
a little complicated to implement,
so we're not going to
worry about that right now.
So now let's return to
that line we had before,
where we created a new list of strings.
And hopefully this is going to
make a little more sense now.
On the left List is
actually an interface.
So we want to say that
the type is something
that conforms to the List
interface or implements everything
inside of the List interface.
These brackets, remember, are a generic.
It's a way of telling the List
interface or this instance of a class,
I want you to know that you're
going to contain strings.
And String is a class.
And so we're passing on that
class to this other one.
And then the right-hand
side, this new ArrayList,
this is actually a class
somewhere that implements List.
So that's why the left and the
right-hand side are different.
The left-hand side is basically
a more general thing saying,
some type of list--
it could be anything.
But as long as it
implements a list, we're
OK, because we're only
going to be using methods
that are defined in the List interface.
And then the right-hand side,
ArrayList is a concrete class
that implements the List interface.
If I wanted to, I could have said
ArrayList strings equals new ArrayList.
But by convention you want to use the
type that's sort of the most general
and makes the most sense, because you
might not want to use an ArrayList.
It might be something
else under the hood.
And so you're kind of abstracting away
or hiding that detail under the hood
by just saying, I'm only
using these methods in a list.
As long as this class has those,
it doesn't really matter to me
under the hood what type of list it is.
Java also has this notion of packages.
And that's something we're
going to see pretty quickly.
But this basically provides you
a way to namespace your class.
So often in a Java
application you're going
to have a bunch of different
classes spread apart
a bunch of different files.
And packages basically provide
you a way of organizing those.
So you might want to do something
like, if your app has two screens, put
all of the classes used in one
screen inside of one package,
use all the classes contained in another
screen inside of another package.
And that way you can sort of
more cleanly organize your code.
Sort of equivalent to using folders to
organize your files in your computer,
we can more logically
organize things instead
of just having a list of 100 classes
all sort of at the same level.
So that's package.
And then to use a package, we're
going to use this import statement.
So to actually use those List and
Map classes in a real application,
I'd first have to import them.
And that's just telling the compiler,
I need to use a List class somewhere,
and here is where you can find
the definition of that List class.
So List, for example, is
located in the package java,
which means it's the Java standard
library-- we didn't write any of this,
it's just given to us
because we're using Java--
.util-- which means there's a
package somewhere called util,
which is short for utility--
and then the class name, and it's .List.
That's the name of the
class that we want to use.
So once in my file I've added
this import java.util.List,
that's going to mean I can use this
List class-- or this List interface,
actually-- wherever I
need to inside of my code.
So that's a whole bunch of syntax.
But we've basically
covered everything we're
going to need to start
writing some Android apps.
So now let's take a look at an example.
Let's return to Android Studio and
start writing some Java code of our own.
Over here on the left is all of the
files contained inside of my project.
And we'll go through these in a bit.
You can see there's a few folders.
The folder we care about right
now is a folder called java.
And that's where all of our
Java code is going to live.
Then here you can see the
package that we created.
So remember, we called that
edu.harvard.cs50.javaexample.
That's our package name.
And you can see here that the
file that was generated for us
happens to start with that package.
So hopefully that makes sense now.
And then the class that we've
created is called MainActivity.
It looks like it extends some other
base class called AppCompatActivity.
If I come over here to this
import line and click the plus,
we can see that, OK, it
looks like we've already
imported this class from somewhere, in
particular that AndroidX package which,
remember, is a bunch
of support libraries
that we can use to
build our application.
And then it looks like
we have some method here
that's already defined for us.
It's overriding some
method in the base class.
It has that @Override.
The visibility is protected.
And this means something basically
between public and private.
This means that if I subclass this class
that those subclasses can access this
method, but other classes can't.
Its return type is void.
The method name is onCreate().
And it takes one parameter.
The parameter has a type Bundle
which, from the looks of it,
is something that's also provided
to us from Android, since it's
being imported up here.
And the name of this parameter
is savedInstanceState.
OK.
So in this next line we're going
to be calling the method onCreate()
that's defined in AppCompatActivity.
And this is a really common pattern
when you subclass something.
Oftentimes when you're
overriding a method,
you don't want to
override it completely,
because maybe that method was
doing something important.
In this case the method in
AppCompatActivity probably
is doing something important.
So you also want to use that definition.
So by saying
super.onCreate(), I'm saying,
I want the method that's
defined in AppCompatActivity,
and I want to call that before I
override it and do something of my own.
So by doing that we're making sure that,
not only are we provided by our own
definition for onCreate(), we're
also taking advantage of whatever
AppCompatActivity has defined.
So we're passing it that one
argument, just savedInstanceState.
And lastly, it looks like we're
just calling some other method
that's defined on AppCompatActivity
called setContentView().
And let's not worry
about this right now.
We'll get into that a bit later.
But here is where we can
start writing some Java code.
And the first Java code
that we're going to write
is it really simple
sorting hat application.
So in CS50 we have a few
different tracks here.
We have one for games, one
for web, and one for mobile.
And so we're going to
write a really simple app
that just randomly sorts students
into one of those tracks.
So let's get started.
The first thing we want to do is
create a class to represent a track.
So let's do that.
Let's come back over here to the left.
And I'm going to Control-Click
on this package name.
And I'll see this long menu.
But what I care about is
creating a new Java Class.
So let's click that.
And they have this nice menu here.
It's going to ask me a few things.
First is the name of the class.
I'm going to call it Track,
because I'm creating a new track.
It's just going to be a regular class.
It's not extending anything, it's
not implementing any interfaces.
You can say its default
visibility is public.
Don't have any modifiers.
We're not worried about that right now.
And the package we want to add
that to is just the same package.
No need to create anything else here.
So let's click OK.
And there we go.
So Android Studio has nicely
generated this class for me.
And if I come back
over here to the left,
we can see that it's inside of that
same package as this other class
called MainActivity.
So let's see.
We want each class to
have a couple of fields.
Let's call one of the
fields a public String name.
And this will represent
the name of a track.
And let's call the other
field the instructor.
And that's going to be the
instructor for the track.
So after creating these two fields,
let's now create a constructor.
So remember, the constructor is just
going to be the same name as the class.
And you'll notice Android Studio
has this really nice autocomplete.
That's something you should definitely
take advantage of while you're coding.
So as I started typing "Track,"
Android Studio recognized,
hey, we've got a class called Track.
Maybe you meant to type that.
So if I just hit Enter, it's
going to autocomplete for me.
So now let's add those two
parameters-- one called
name, one called instructor-- again,
autocomplete being helpful here.
And all we want to do is
save those two things.
So we can say, this.name is name,
and this.instructor is instructor.
Using autocomplete you can look
like you're typing really fast
and impress your friends.
So that's it for this class.
We're not going to put any
methods on this quite yet.
We're just going to save.
It's basically a container
for these two data types.
So now let's come back to MainActivity.
The first thing we want to do
is create a list of tracks.
So let's do that.
Let's say we have a new List.
Again, Java being helpful
here, in this autocomplete,
if I just press Enter we're going to
have something really cool happen,
which is that Android Studio
automatically added that import for me.
So when I hit Enter, not only
did it type the word List,
it also added this import to the top of
my file saying, import java.util.List.
And again, that import is
necessary for me to use this class.
So Android Studio is just
being helpful with that.
OK.
So we have a list.
Remember, the type of our list is a
track, because it's a list of tracks.
That sounds good.
Let's call our variable tracks.
And then same as before, let's
just create a new ArrayList.
So we'll say new ArrayList.
If I hit Enter, notice that
it's imported automatically.
And that's it.
We don't have to specify the type
again in the right-hand side.
We can just do this left
right bracket thing.
OK.
So now let's add some
tracks to this list.
So remember, we're just
going to say tracks.add.
And then we want to create a new
track that takes two parameters.
The first one is the name of the track.
And again, Android Studio is
just being a little helpful
here by putting in that name prefix.
This actually isn't
part of the source code.
This is just something
that's displayed in the IDE.
But it's helpful just to remind you
what those variable names were called.
So let's create the mobile track.
The instructor is Tommy.
Again, being helpful with
these parameter names.
But this is not really
part of your source code.
You don't need to type
name colon anywhere.
So that's our first track.
Our second track is the web track.
And that's with Brian.
And the final track is the games track.
And that's with Colton.
OK.
So at this point we've now created
a class to represent each track,
we've created a list of
those tracks, and then
we've added these three instances
of those tracks to that list.
That looks good.
So now let's create a list of students.
So rather than saying
Track here, I'm going
to say String, since we'll just
represent each class as a string.
And you'll notice here that I
don't need to import String.
That's actually imported
for me automatically.
There's a package in
Java called java.lang.
And everything in that package
is automatically imported.
So no need to import that manually.
So then we'll call them students.
And again, let's just sort
of add some strings here.
We could say new ArrayList.
But there's also a nice
shorthand I can use in Java
rather than saying new
ArrayList add, add, add.
I can use this other
class called Arrays.
It's also in java.util,
imported automatically.
And there's this method on the
Arrays class called asList().
And this is an example
of a static method.
Notice that I didn't
say new Arrays anywhere.
Arrays is just the class itself, and
now I'm calling the static method.
And now I can just actually
put in a list of strings.
So I can say--
let's just pick three
totally random normal names
like Harry, Ron, and Hermione.
And there we go.
So this is actually going to
give me back a list of strings.
So now we want to do two things.
The first thing we want to do is
randomly assign students to tracks.
And then after that we want to
print out the resulting assignments.
So to do that assignment,
we're going to use a map.
And this map is going to map strings,
which represent students, to tracks.
So let's declare that map.
So we're going to say Map,
imported automatically.
And remember, this time we need
to specify two different types.
The first type is the type of
our key, which is a string.
And the second type is the type
of the value, which is a track.
So we'll call this map assignments.
And then we'll say new HashMap.
Again, Map is the interface
here, HashMap is the class.
Don't need to specify anything
on the right-hand side.
All right.
So now we have this map.
It's empty, so let's
put something in it.
So to do that, we're
almost surely going to need
to iterate through all of the students.
So let's use a for loop for that and
say, for String student in students--
so now that's just going to walk
through that list one by one.
And so what I want to
do with each student is,
I want to figure out how
to get a random track.
So luckily Java, again, has a nice class
that's part of the standard library
that we can use.
And that class is called Random,
also located in java.util.
I can just say Random, let's
just call this object random.
And it's going to be a new
instance of the Random class.
Constructor doesn't take any
arguments, so we can just say that.
And now to generate that
random number, I can just say,
my index is going to
be random.nextInt()--
again, autocomplete helping me out here.
And this is going to take one argument.
And this argument is going to
be the maximum random number
that you can generate.
And so that's just going
to be the size of my list.
So with the List object,
I can just say .size().
That's a method that's
defined on List that
will give me back an integer value
representing how many students are
in the list.
So now that we have this index, let's
use it to get one of our tracks.
So I'm going to say
assignments.put, just like before.
And autocomplete here
again, reminding me
it's going to take two
arguments, a key and to value.
My key is going to be a string.
And that's the current
student that I'm iterating.
And the value is going
to be one of the tracks.
So to get value out
of this ArrayList, I'm
going to say tracks.get,
pass in that index.
And that's going to get me
an object out of that array.
So notice here that in arrays you
can use that square bracket notation.
The ArrayList is just a regular
class that has methods defined on it,
and get() is a method.
You'll oftentimes when writing
code, much more frequently used
lists and maps compared to raw arrays.
But they're there if you need them.
OK.
So at this point in our code we
have defined a list of tracks,
we've assigned students to those tracks.
And now we just want to print everything
out to see what the result is.
So to do that, we're going
to use another for loop,
this time iterating over the map.
So we're going to say for.
Again, we have Map.Entry.
And this is basically a class
defined within the Map class
that represents a single pair of
key and values inside of the map.
The type of this is
going to be the same.
It's going to be mapping
a string to a track.
We'll just call this Entry entry.
And then we can say
assignments.entrySet.
So this entrySet is going to return a
set, which is very similar to a list.
It just says that everything
in this list is unique.
But for all our purposes
it's just a list.
And so now that I have
this entry, I just
want to print it out to the screen.
So when you're writing Java code, we saw
before we have that System.out.println.
And that's a way to just
print to standard out.
When you're debugging Android
code in Android Studio,
there's another class
you can use called Log.
And Log is basically going
to allow you to print
to the special area in Android Studio.
You can search over logs and
navigate them a bit more easily.
So we're going to use that.
So we're going to say Log.
It's this class defined in android.util.
And then there's a bunch of
methods to find on this object.
And a bunch of them
have a single letter.
So there is e() for error, there is
d() for debug, there's i() for info--
that basically just says what
level what we logging at.
So like, are we making
a debug print statement,
does this log represent
an error statement?
It doesn't matter too much.
We're just going to use d() for debug.
And we see here that this method takes
two arguments-- a tag and a message.
So the tag is a way for you to
really easily filter down messages.
So when we launch our Android app,
you're to see that a bunch of stuff
is going to be logged.
And much of it is going
to be from the system
or from other libraries we're using.
And so we want to easily
find our log statements
among all of those other ones.
So if we just create
a tag of cs50, that's
going to allow us to search for cs50
and easily find our log statement.
So that's our tag.
And then we want to
print out this entry.
And if I call the getKey() method,
that's going to give me the student.
So that's the student name.
We can concatenate strings
together with plus.
So we can say this "student got."
And now we can say
entry.getValue().name.
So this is going to be
the name of our track.
And then I can say "with" followed
by the name of the instructor,
which would be
entry.getValue().instructor.
And I forgot a plus, so
I'll add that over there.
OK.
So now let's run our app using the
AVD we created earlier to simulate
this Android app.
So up in the top right here
you'll see this Play button.
So I can just click
this, or as it tells me,
the keyboard shortcut is just Control-R.
So let's click that Play button,
which is going to open
up our Android emulator.
So here's my emulator.
You can see this Android app was sort
of automatically generated for us.
But we're looking for that log output
to see what our assignments were.
So if we come down to
the bottom here, we
have this thing here that says Logcat.
And this is basically just all of the
logs coming in from our application.
So you can see here there's a bunch
of stuff being logged by the system.
But if you scroll up, then you
can see our assignment here,
which just so happens to be
one person in every class.
And this is the result of our log.
So before we finish, let's
change one thing about our class.
Rather than exposing these
fields as public fields,
a pretty common convention
in Java is to provide what
are called getter and setter methods.
So to do that, I'm going to define
methods on this track called public
String getName().
All this is going to
do is return the name.
And another getter
called getInstructor().
And that's just going to
return the instructor.
And so now, rather than
exposing these fields publicly,
I can instead make them
private, which says
that you can't just access these fields,
because they're marked as private.
Instead you want to use the getters.
This is a pretty common Java
convention, because you might
want to do something inside the getter.
You might have a convention where
getting the value of something
isn't just the value, it's that value,
maybe it's modified a little bit,
maybe it's doing some
calculation on that value.
So you don't really want to
expose these fields directly.
It's common to put them behind getters.
And you'll notice in a lot of the code
that we've written so far we've already
used getters, like
getKey() and getValue().
So we're just following
that same convention.
So now to modify the code that we
have here, let's shorten this a bit.
And let's say that we
have a Track track.
And that's going to be
equal to entry.getValue().
So now we have a Track object.
And now we can say track.getName(),
use that method we just defined,
and track.getInstructor().
You'll notice it if I try to
use just track.instructor,
the compiler is going to let
me know that I have an error.
You'll see here it's highlighted in red.
And I have this little
message that says,
instructor has private
access in this class,
which means I can't access
it from outside of the class.
So by just saying getInstructor(),
now we should be good to go.
Let's run our app one more time.
So we're launching.
And you'll notice all
the log is cleared.
And if we just scroll up again,
we can see a new random result.
And by the way, this search
bar is pretty nice up here.
So I could, for example, search "Tommy."
And I'm going to filter down only
the log messages with "Tommy."
So I could say "with" and only
get the messages with "with."
So for example, if I changed this
tag just from "cs50" to something
like "assignment result," I could then
just search for "assignment result"
and only filter down those log messages.
So even though there's a
lot of stuff happening here,
that filter can be really
helpful to separate out
your log messages from a bunch
of stuff the system is logging.
So that's it for our
first few lines of Java.
In our next video we're going to write
our first Android UI application.
