Generics In Java - Full Simple Tutorial

Coding with John
20 Dec 202117:34

Summary

TLDRこのビデオでは、Javaのジェネリクスについて徹底解説します。ジェネリクスが初めての人にとっては、Tや?、<、>などの記号が混乱を招くかもしれませんが、ビデオの終わりには、ジェネリクスが何であるか、なぜ存在するのか、どのように役立つのか、そしてどのように自分のプログラムで使用できるのかを正確に理解できるようになります。ジェネリクスがJava開発者が以前直面していた問題をどのように解決するのか、そして型安全性を保ちながら様々な型に対応できるクラスを作成する方法を、簡潔かつ理解しやすい方法で共有します。

Takeaways

  • 👥 Before generics existed in Java, developers had to duplicate code across multiple classes to support different data types
  • 🌟 Generics provide the ability to declare type parameters (like T) so you can make a class or method work with many data types
  • ⚙️ To use a generic class, you specify the type parameter in angle brackets (<>): Printer<Integer>
  • 🔎 The T type parameter in a generic class represents the data type that class will work with
  • 💡 Generics promote type safety because at compile time you'll know the types that will be used
  • 📦 Java's collections framework (like ArrayList) uses generics extensively to define types for lists
  • 🧩 You can constrain generics with extends to narrow which types can be passed in
  • ☕️ In addition to generic classes, you can have generic methods by putting type parameters on the method signature
  • 🎯 Wildcards (?) allow you to define methods or fields that can work with unknown generic types
  • 🎓 By the end of the video you should understand the motivation, syntax and many applications for generics in Java

Q & A

  • ジェネリクスとは何ですか?

    -ジェネリクスは、複数のデータ型で機能できるクラスやメソッドを作成するための機能です。1つの汎用的なコードを書くことができます。

  • ジェネリクスを使う主な利点は何ですか?

    -コードの重複を減らし、タイプセーフティを高めることができます。

  • ジェネリクスの代表的な使用例を教えてください。

    -コレクションフレームワーク(ArrayListなど)が良い例です。リストの内容のデータ型を指定できます。

Outlines

00:00

📚ジェネリクス入門

このセクションでは、Javaのジェネリクスについての基本的な導入を提供します。ジェネリクスが最初は複雑に見えるかもしれないが、Tや?、<、>などの記号の意味を理解することで、その有用性が明らかになると説明しています。ジェネリクスがどのようにJava開発者が型安全性を向上させ、コードの重複を減らすのに役立つか、実際の例(IntegerPrinterなど)を通じて説明します。ジェネリクスを使用することで、異なる型のオブジェクトを処理するために複数のクラスを作成する代わりに、一つの汎用クラスを作成することが可能になります。

05:01

🔄ジェネリクスの応用

ジェネリクスを使用して、さまざまなデータ型(ダブル、文字列など)で機能する単一のプリンタークラスを作成する方法を説明します。このセクションでは、ジェネリクスの実践的な応用に焦点を当て、JavaのArrayListの例を引き合いに出して、ジェネリクスがどのように型安全性を提供し、コードの柔軟性を向上させるかを示します。また、ジェネリクスがなければ、異なる型のオブジェクトを含むリストを作成する際に直面する型安全性の問題についても触れています。

10:04

🔍ジェネリクスの高度な使用法

ジェネリクスを使用して特定の基底クラスやインターフェースを継承する型のみを受け入れるクラスを作成する方法を紹介します。これにより、ジェネリクスの「境界」(bounds)という概念が導入され、型パラメータに制約を加えることで、より精密な型安全性を実現します。例えば、「Animal」クラスを継承する型のみを許可するプリンタークラスの作成が挙げられます。また、ジェネリックメソッドや複数のジェネリック型を持つメソッドの作成についても説明しており、ジェネリクスの柔軟性と強力な機能を示しています。

15:04

🎓ジェネリクスのワイルドカードと型安全性

ジェネリクスのワイルドカード(?)の使用法と、それが型安全性にどのように貢献するかを解説します。具体的には、任意の型のオブジェクトを含むリストを受け入れるメソッドの作成方法を示し、この機能がJavaの型システムの柔軟性をどのように高めるかを説明します。また、ワイルドカードを使用して「Animal」クラスを拡張する型のリストのみを受け入れるように制限する例を通じて、ジェネリクスの「境界付きワイルドカード」の概念を紹介します。このセクションは、ジェネリクスがJavaプログラミングにおける型安全性とコードの再利用性をどのように向上させるかを強調して終わります。

Mindmap

Keywords

The video is abnormal, and we are working hard to fix it.
Please replace the link and try again.

Highlights

Generics offer the ability to create classes flexible for many types, with structure and type safety

Java's collections framework uses generics, like ArrayLists specifying the type to hold

Bounded generics limit the type passed in, like only animals for a Printer class

Generic methods can take in any type of parameter using a generic type parameter

Wildcards allow methods to take Lists of unknown generic typed objects

Transcripts

play00:00

in this video we're going to talk all

play00:01

about generics in java generics can be

play00:03

super confusing the first time you see

play00:05

them with all the t's and question marks

play00:07

and angle brackets and k's and v's but i

play00:09

promise by the end of this video you'll

play00:10

know exactly what generics are why they

play00:13

exist and why they're useful and how you

play00:15

can use them in your own programs my

play00:17

name is john i'm a lead java software

play00:18

engineer and i love sharing what i've

play00:19

learned with you in a clear and

play00:21

understandable way i also have a full

play00:22

job of course available and a link down

play00:24

in the description if you're interested

play00:25

first to have a good understanding of

play00:27

what generics do and why they exist it

play00:29

helps to know the kinds of problems that

play00:31

java developers were running into before

play00:34

generics existed let's say i wanted to

play00:36

create a class where all it would do is

play00:38

hold an integer value that i give it and

play00:41

then print out that integer whenever i

play00:43

wanted to so we might call something

play00:45

like that integer printer you can go

play00:47

ahead and click finish and create that

play00:49

so this class would be pretty simple we

play00:50

would have an integer field for the

play00:52

thing that we want to print so we can

play00:54

call it thing to print and we can have a

play00:57

constructor for this class that takes in

play00:59

this thing to print so that would be

play01:01

public integer printer then it takes in

play01:04

an integer for the thing to print and

play01:06

that would just set this dot thing to

play01:08

print equal to the thing to print that

play01:11

was passed in and we can have one method

play01:13

to actually print this out whenever we

play01:15

want to so that would be public void

play01:18

print and all that does is just print

play01:20

out the thing to print to the console so

play01:23

system.out.printline thing to print so

play01:26

if we wanted to use this integer printer

play01:28

class we would just create an integer

play01:30

printer printer equals new integer

play01:33

printer

play01:34

and pass in the integer that we want to

play01:36

print here in the constructor so let's

play01:38

say we want to print out the number 23

play01:40

now of course we can call printer.print

play01:43

and when we run our program of course it

play01:45

prints out 23. but what if we wanted to

play01:47

do exactly the same thing for a double

play01:50

instead of an integer well we couldn't

play01:52

use this class right because it only

play01:54

holds an integer it doesn't hold a

play01:56

double so what can we do well basically

play01:58

what we have to do is make a copy of

play02:01

this entire class and we can call it

play02:03

double printer and then inside that

play02:05

double printer we would basically have

play02:08

all of the exact same code except

play02:10

instead of integer we would have double

play02:13

so this new class will work great for

play02:15

holding and printing doubles but what if

play02:17

we now want a class that'll do exactly

play02:19

the same thing but work for strings well

play02:22

of course you have to do the exact same

play02:23

thing again you have to copy that class

play02:25

make a new class called string printer

play02:28

and change all these doubles to strings

play02:30

if you want your class to be able to

play02:32

print strings so now we have three

play02:34

completely separate versions of

play02:35

essentially the same kind of class and

play02:37

you can start to see the problem we

play02:39

would need a whole other class if we

play02:40

wanted to do this with floats or dogs or

play02:43

cats or cars or trucks or whatever type

play02:46

of object that we wanted to print so

play02:47

we'd end up with a ton of code

play02:49

duplication and this is with a really

play02:51

simple class if you had a more

play02:52

complicated class the code duplication

play02:54

would be even worse well that is where

play02:56

generics come in generics offer you the

play02:59

ability to have one class like this that

play03:01

is flexible for many many different

play03:03

types so let's go back to our original

play03:06

integer printer and make it generic so

play03:08

first instead of calling it integer

play03:10

printer let's just call it printer

play03:11

because it should be able to print

play03:13

anything now when you want to use

play03:14

generics in a class like this in java

play03:17

right here after the class name in the

play03:18

declaration but before the curly braces

play03:21

you have to define what is called a type

play03:23

parameter and you'll put your type

play03:24

parameter in angle brackets like this by

play03:27

convention in java typically you'll see

play03:29

this type parameter just called t but

play03:31

technically you can call this type

play03:33

parameter whatever you want but i'm

play03:36

going to just be using t so you can kind

play03:38

of get used to seeing it because that's

play03:39

the convention that you'll see elsewhere

play03:41

you can think of it as standing for type

play03:43

in this class what this t represents is

play03:46

the type of thing that this printer is

play03:48

going to be able to hold and print so

play03:50

instead of just having an integer field

play03:53

here it's going to be of type t

play03:56

right now as we're coding this class we

play03:58

don't know what types of things this

play04:00

printer is going to be asked to print

play04:02

but this gives the ability to create

play04:04

printers for any types that you want so

play04:07

of course we also have to change the

play04:08

name of our constructor to just printer

play04:10

to match the class name and that

play04:12

constructor also instead of taking in an

play04:14

integer is going to take in something of

play04:17

type t so now this class is a generic

play04:20

printer for whatever type we want but

play04:22

now how do we actually use this class if

play04:25

we want to for example create an integer

play04:28

printer like we had before well back

play04:29

here in our main method instead of an

play04:31

integer printer now of course we're

play04:33

going to just create a printer but now

play04:35

you can see that we have a warning here

play04:37

that printer is a raw type and

play04:39

references to generic type printer

play04:41

should be parameterized it wants to know

play04:43

the type of thing that we want to be

play04:45

able to print and in this example we

play04:47

want to be able to print integers so how

play04:50

we specify that is in angle brackets

play04:52

here after printer we type in integer

play04:56

that tells java i want a printer for

play04:58

integers and we have a similar warning

play05:01

here to get rid of that you just need to

play05:03

put in angle brackets after the class

play05:05

name printer in older versions of java

play05:07

you used to have to put the type in

play05:09

there again but you don't have to do

play05:11

that anymore this integer here that

play05:13

we're passing in in the angle brackets

play05:15

is what's going to be used as this

play05:17

t-type in this printer object that we

play05:20

are creating now we can run our program

play05:22

as we did before and it still prints out

play05:24

23. but now what's cool is we can go in

play05:27

and get rid of those two extra classes

play05:29

that we made the double printer and the

play05:31

string printer we can just delete those

play05:34

because now we can use our generic

play05:36

printer class to be able to create

play05:38

printers for doubles and strings also so

play05:41

now all we have to do if we want to

play05:42

create a printer for doubles we just say

play05:45

printer and pass in double or t the type

play05:48

that we want this printer to be able to

play05:50

print we can call it double printer

play05:52

equals new printer and give it a value

play05:55

like 33.5 and we can call

play05:57

doubleprinter.print and of course it

play05:59

prints out 33.5 so now we've created one

play06:02

printer class that can print any type

play06:05

that we get it doubles ants longs floats

play06:08

pigs monkeys cars trucks whatever one

play06:10

thing to note though is that generics

play06:12

don't work with primitive types like

play06:14

lowercase int and lowercase long but all

play06:16

you have to do is just use the wrapper

play06:18

classes like integer and everything

play06:20

should just work the same way one place

play06:22

that you've probably already used

play06:23

generics all the time is with java's

play06:26

collections framework for example if you

play06:28

wanted to create an arraylist you've

play06:30

probably done this where you've

play06:32

specified in angle brackets the type of

play06:34

thing that you want to have in your list

play06:37

so if you want to create an arraylist of

play06:38

cats you say arraylist cat we'll call it

play06:41

cats equals new array list this gives

play06:45

you an arraylist that you can only add

play06:47

cats to so you can say cats.add

play06:50

new cat and that works fine but if you

play06:52

try to do cats.add

play06:55

and pass in a new dog instead you get an

play06:58

error because we specified that cat was

play07:01

the type of thing that this list was

play07:02

going to hold and if we try to give it a

play07:04

dog we get an error in the same way up

play07:07

here where we created a printer for

play07:10

doubles if we try to pass in a string

play07:13

hey there

play07:14

we get a similar error because we told

play07:16

java that this was going to be a printer

play07:18

for doubles and here we're trying to

play07:20

give it a string but you might be

play07:21

thinking well hey john if we want to be

play07:23

able to create a list of anything we

play07:25

want why do we have to deal with all

play07:27

these generics why can't we just create

play07:29

like an array of just objects and then

play07:32

we can put whatever we want in it well

play07:34

it is true that you can do that and your

play07:36

code will work but it won't be type safe

play07:39

at all let me show you what i mean let's

play07:41

say that our arraylist instead of

play07:43

holding cats just holds objects this is

play07:45

the kind of thing you'd have to do if

play07:47

generics didn't exist you just have to

play07:49

create an arraylist that can hold

play07:51

whatever so in this imaginary world

play07:53

without generics we still want to create

play07:55

a list of cats so we've added our new

play07:58

cat to our list but let's say sometime

play08:00

later on in the code we want to be able

play08:01

to get stuff off our list and use it so

play08:04

if we want to get this first cat off the

play08:05

list and put it in a variable we would

play08:07

want to create a cat call it my cat

play08:10

equals cats.get

play08:12

the first element of the list at index

play08:14

0. but here we get an error that we have

play08:17

a tight mismatch you can't convert from

play08:19

object to cat java doesn't know that

play08:21

this is supposed to be a list of cats it

play08:23

just knows it's a list of objects so we

play08:26

have to tell java yes i know this is a

play08:28

cat so you can go ahead and cast it to a

play08:30

cat so i can store it in this variable

play08:32

but what if instead of adding a cat to

play08:34

the list somebody adds a dog well the

play08:37

code all looks the same there's no

play08:39

compilation errors or anything but of

play08:41

course if you try to run it you're going

play08:43

to get a classcast exception

play08:45

right here on this line because you're

play08:48

trying to cast this element in the list

play08:50

as a cat but it's actually a dog so just

play08:53

having an arraylist that can hold

play08:54

whatever type of object causes all types

play08:57

of these type safety issues and generics

play09:00

solves that problem for us so now we can

play09:02

say yes i want to create a list of cats

play09:05

so then in the code if somebody tries to

play09:07

add a dog to that list they get an error

play09:10

and it won't even compile and also since

play09:12

java knows that this is a list that can

play09:15

only contain cats whenever you get a

play09:17

thing off of that list it is 100

play09:19

guaranteed to be a cat and you don't

play09:22

have to do any special casting that's

play09:24

how generics help us they offer the

play09:26

ability to create classes that can

play09:28

accommodate tons of different types but

play09:30

also the structure and the type safety

play09:33

of knowing exactly which type you're

play09:36

using that class with at the moment but

play09:38

there are even more cool advanced things

play09:40

that you can do with generics let's go

play09:42

back to our generic printer class so

play09:44

right now we can create a printer of

play09:46

whatever class that we want to right but

play09:48

what if instead of being a printer for

play09:51

any type we want this to be a more

play09:53

specialized printer for animals for

play09:55

example i have this cat class here that

play09:58

extends the animal class and i also have

play10:01

a dog class here that extends the animal

play10:03

class so if we want this to just be a

play10:05

printer for any type of animal instead

play10:07

of just saying t we can say t

play10:10

extends

play10:11

animal now back here in our main method

play10:13

we now get an error when we try to

play10:15

create a printer for integers or doubles

play10:18

because now this printer only works for

play10:19

animals so we can create a cat printer

play10:22

and in the constructor we can pass in a

play10:25

new cat or we can create a printer for a

play10:28

dog and pass in a new dog but what's

play10:31

cool about that is now in our printer

play10:33

class since we know that whatever is

play10:36

passed in as this type extends animal

play10:39

any method that is defined in the animal

play10:41

class is available to us in our thing to

play10:45

print variable because we know that this

play10:47

thing to print this t is going to be

play10:50

some type of an animal so now because we

play10:52

know this thing to print is an animal

play10:55

down here in our print method we can

play10:56

call thing to print dot

play10:59

eat because this eat method is available

play11:02

in the animal class so if we didn't have

play11:05

this extends animal if we just took in

play11:07

any type at all we can't call the eat

play11:09

method because this tea type isn't

play11:12

guaranteed to be an animal at all so

play11:14

there's no way to know whether it will

play11:16

have an eat method available on it or

play11:17

not when you do this type of thing it's

play11:19

called a bounded generic because you're

play11:21

giving a certain bound a limit on the

play11:23

type that's able to be passed in you can

play11:26

also use bounds with interfaces let's

play11:28

say you wanted to guarantee that this

play11:30

type implemented the serializable

play11:32

interface you just put in extends

play11:34

serializable you might think that

play11:36

because this is an interface you should

play11:38

put implements here instead of extends

play11:40

but no it's just not the proper syntax

play11:42

it still has to be extends even though

play11:44

it's a little bit weird another cool

play11:45

thing you can do is have multiple bounds

play11:47

let's say you wanted to make sure that

play11:48

it was a subclass of animal and also

play11:51

implemented the serializable interface

play11:53

to do that you can just say extends

play11:55

animal

play11:56

and serializable here with an ampersand

play12:00

and you can list as many things as you

play12:01

want here all separated by ampersands

play12:04

there's just a couple restrictions you

play12:05

can only have one class which makes

play12:07

sense because java doesn't support

play12:09

multiple inheritance and you always have

play12:10

to list the class name first with any

play12:13

interfaces after that if you try to

play12:15

switch it around and put the interface

play12:16

first you'll get an error in addition to

play12:18

having generic classes you can also have

play12:20

generic methods let's say we wanted to

play12:23

make a method that can take in any type

play12:25

of object and print it out with

play12:27

exclamation points private static void

play12:30

let's call it shout since it'll print

play12:31

things out with exclamation points it'll

play12:33

take in some kind of type that we're

play12:36

going to call t we'll call it thing to

play12:38

shout and inside that method all we're

play12:41

going to do is print out that thing to

play12:43

shout with a bunch of exclamation points

play12:45

after it so right now we're getting an

play12:47

error here because java is saying hey t

play12:49

isn't the type what do you want me to do

play12:50

with this to tell java that this t is

play12:53

supposed to be a generic type right here

play12:55

in the method signature right before the

play12:57

return type you put that generic type in

play13:01

angle brackets again you can call this

play13:03

whatever as long as it matches here and

play13:06

in the parameters but by convention

play13:08

you're still just going to see t most of

play13:10

the time so now here in our main method

play13:12

we can call our shout method with

play13:13

whatever we want you can send in a

play13:15

string like john you can send in an int

play13:18

57 or you can even send in a cat so this

play13:22

can take in any type of parameter that

play13:24

we want to send and when we run it it'll

play13:26

print them out with exclamation points

play13:28

java also supports the ability to have

play13:30

multiple different generic types here so

play13:32

in addition to taking in this t thing to

play13:34

shout we can also take in say

play13:36

the

play13:37

other thing to shout all we have to do

play13:39

is add this v to our angle brackets here

play13:42

and separate them with a comma and now

play13:44

this method will take in two of any sort

play13:47

of type so we can pass in john and 74

play13:50

and also go ahead and print out

play13:52

other thing to shout and that works and

play13:55

is now flexible with any two types at

play13:57

all if you want you can also have

play13:59

multiple generic types like this in your

play14:01

generic classes so over here in our

play14:03

printer class if we wanted to have

play14:05

another field here let's call it v

play14:09

other thing and all we have to do is

play14:11

specify that up here in our angle

play14:13

brackets as well separated by a comma if

play14:15

you happen to want to return one of

play14:17

these generic values that are being

play14:19

passed into your generic methods all you

play14:21

have to do is specify that return type

play14:24

as the return type here so instead of

play14:25

void if you want to return something of

play14:28

type t you just put t here as the return

play14:31

type and then in here of course you just

play14:32

have to return something of type t which

play14:35

can just be this

play14:36

thing to shout the other advanced

play14:38

generics topic i want to talk about is

play14:40

wild cards let's talk about a situation

play14:42

where you might want to use a wild card

play14:44

and then we'll show how you can do it

play14:46

let's say we wanted to be able to create

play14:47

a method that can take in a list that

play14:50

holds any type of objects and we want to

play14:52

be able to print out that list so we

play14:55

might call that print list so how do we

play14:57

specify in the parameters here that we

play14:59

want to be able to take in a list that

play15:01

contains any type of thing you might

play15:04

think that we can just say okay i want

play15:05

to take in a list of objects we can call

play15:09

it my list and all we'll do is just

play15:11

print out that list to the console so

play15:13

now up here we can create a list of

play15:16

integers

play15:17

call it in list

play15:19

equals new array list we can take our

play15:22

int list

play15:23

and add the number three and then we can

play15:25

try and call our print list method with

play15:28

our int list as the parameter but if we

play15:31

try and do that we get an error here

play15:32

that says we can't pass in this list of

play15:35

integers as this parameter that's

play15:36

supposed to be a list of objects but it

play15:39

might feel like you should be able to do

play15:40

that right of course an integer is a

play15:42

subclass of object so shouldn't we be

play15:44

able to pass in just a list of integers

play15:47

well even though integer is a subclass

play15:49

of object a list of integers is not a

play15:53

subclass of a list of objects so this

play15:55

doesn't work this is where a wild card

play15:58

will work to solve your problem so

play15:59

instead of saying that this is a list of

play16:01

objects we say that this is going to be

play16:03

a list of unknown by passing in a

play16:06

question mark this question mark is the

play16:09

wild card you use a wild card a question

play16:12

mark as the type parameter when you're

play16:14

using a generic when you don't know

play16:17

what exactly that generic type is going

play16:19

to be so it's saying hey java i've got

play16:21

this method here and i want it to be

play16:23

able to take in a list of anything but i

play16:25

don't know what it's going to be a list

play16:27

of so now you can call this method with

play16:29

a list of whatever you want in this case

play16:31

we're doing it with a list of integers

play16:33

but you can also do it with a list of

play16:35

anything else let's say we had a list of

play16:37

cats add a new

play16:39

cat to that list change this to catlist

play16:42

here and pass the catlist into our print

play16:45

list method and it now works with lists

play16:47

of both types with no errors you can

play16:50

also have bounded wild cards similarly

play16:53

to how we did in our generic class so

play16:55

instead of being a list of anything at

play16:58

all we can say this has to be a list of

play17:00

something that extends the animal class

play17:04

but now you can see up here that we're

play17:05

getting an error when we're trying to

play17:07

call this method with a list of integers

play17:09

and that's because integer doesn't

play17:11

extend animal we don't get that same

play17:14

error here when we're calling it with a

play17:16

list of cats because cat does extend

play17:18

animal if you enjoyed this video or

play17:20

learned something please let me know by

play17:21

leaving a like and be sure to subscribe

play17:23

so you don't miss each new java tutorial

play17:25

and of course don't stop now keep

play17:26

learning by watching one of the other

play17:28

videos below thank you so much for

play17:29

watching i really appreciate you being

play17:31

here with me i'll see you next time