| 1 |
| 00:00:06,000 --> 00:00:06,000 |
| Hello, Jim. |
|
|
| 2 |
| 00:00:06,000 --> 00:00:10,000 |
| So they are going to answer questions, what are generics in Java and how they work? |
|
|
| 3 |
| 00:00:11,000 --> 00:00:14,000 |
| We'll start from understanding of why do we need generics. |
|
|
| 4 |
| 00:00:14,000 --> 00:00:19,000 |
| After that, we'll understand how you can parametrized your mascots and classes. |
|
|
| 5 |
| 00:00:19,000 --> 00:00:22,000 |
| You're going to understand what Boundy generics in Java are. |
|
|
| 6 |
| 00:00:23,000 --> 00:00:27,000 |
| We'll discuss generics with multiple mounts also in this class. |
|
|
| 7 |
| 00:00:27,000 --> 00:00:30,000 |
| And we are going to learn what the wild cards are and how to use them. |
|
|
| 8 |
| 00:00:31,000 --> 00:00:35,000 |
| Today, we're going to have a lot of practice that will help you to understand generics. |
|
|
| 9 |
| 00:00:35,000 --> 00:00:41,000 |
| And at the end of the lesson, I will explain what a type is and what type erasure is. |
|
|
| 10 |
| 00:00:41,000 --> 00:00:45,000 |
| Let's start and to make you understand what generics are. |
|
|
| 11 |
| 00:00:45,000 --> 00:00:50,000 |
| I suggested starting from examples to make you understand what problem generics intended to solve. |
|
|
| 12 |
| 00:00:51,000 --> 00:00:52,000 |
| Imagine the next iteration. |
|
|
| 13 |
| 00:00:52,000 --> 00:00:57,000 |
| You have array of strings and you want to have mastered that process is data. |
|
|
| 14 |
| 00:00:57,000 --> 00:01:02,000 |
| For the sake of example, let's imagine that you need to have masses that would print all elements of |
|
|
| 15 |
| 00:01:02,000 --> 00:01:04,000 |
| array to console in some custom way. |
|
|
| 16 |
| 00:01:04,000 --> 00:01:11,000 |
| Here I created massive print array that takes array of strings as Masad argument inside a grade for |
|
|
| 17 |
| 00:01:11,000 --> 00:01:14,000 |
| each loop and before printing any new element. |
|
|
| 18 |
| 00:01:14,000 --> 00:01:19,000 |
| I also print words aliment and only after that some element is printed. |
|
|
| 19 |
| 00:01:19,000 --> 00:01:25,000 |
| Now you realized that you have not only array of strings in your program, you also want to apply the |
|
|
| 20 |
| 00:01:25,000 --> 00:01:27,000 |
| same behavior for an array of integers. |
|
|
| 21 |
| 00:01:27,000 --> 00:01:32,000 |
| But the existing method will not work with an array of integers since it is specified that it works |
|
|
| 22 |
| 00:01:32,000 --> 00:01:34,000 |
| only with the array of strings. |
|
|
| 23 |
| 00:01:34,000 --> 00:01:38,000 |
| Let me uncommon this line and you can see a compilation error here. |
|
|
| 24 |
| 00:01:39,000 --> 00:01:44,000 |
| What to do in this case, create another method that will work with array of integers, I assure. |
|
|
| 25 |
| 00:01:45,000 --> 00:01:50,000 |
| What would you do in case you would need the same method for array of numbers or array of your custom |
|
|
| 26 |
| 00:01:50,000 --> 00:01:51,000 |
| type user, for example? |
|
|
| 27 |
| 00:01:52,000 --> 00:01:54,000 |
| That is definitely not the best option. |
|
|
| 28 |
| 00:01:54,000 --> 00:02:00,000 |
| But what I would recommend to do in this case, it would be perfect to create the method that would |
|
|
| 29 |
| 00:02:00,000 --> 00:02:03,000 |
| work with arrays of different types, what they think. |
|
|
| 30 |
| 00:02:03,000 --> 00:02:09,000 |
| But how to do this in Java, that is exactly what generic mechanism is created for. |
|
|
| 31 |
| 00:02:09,000 --> 00:02:14,000 |
| In other words, we can create parameterized methods and classes that would work with different types. |
|
|
| 32 |
| 00:02:15,000 --> 00:02:21,000 |
| And here you already can see the first advantage of using generics you can avoid of code duplication |
|
|
| 33 |
| 00:02:21,000 --> 00:02:23,000 |
| and increase cautery usage in your program. |
|
|
| 34 |
| 00:02:24,000 --> 00:02:27,000 |
| Let me comment this parametrized method and explain use syntax. |
|
|
| 35 |
| 00:02:28,000 --> 00:02:34,000 |
| This method is similar to the one we already have, but before the type of returns value, we have just |
|
|
| 36 |
| 00:02:34,000 --> 00:02:35,000 |
| word here. |
|
|
| 37 |
| 00:02:35,000 --> 00:02:38,000 |
| I write it in Diamond Operator. |
|
|
| 38 |
| 00:02:38,000 --> 00:02:45,000 |
| These characters from both sides are called together as diamond operator whispered Sify, our parameterized |
|
|
| 39 |
| 00:02:45,000 --> 00:02:46,000 |
| type in the diamond operator. |
|
|
| 40 |
| 00:02:47,000 --> 00:02:52,000 |
| This is also called generic and will explain in simple words what this is about. |
|
|
| 41 |
| 00:02:53,000 --> 00:02:55,000 |
| This is a placeholder for some specific type. |
|
|
| 42 |
| 00:02:56,000 --> 00:02:58,000 |
| Theoretically, I can write Annunziata here. |
|
|
| 43 |
| 00:02:59,000 --> 00:03:05,000 |
| The main thing is that letter that I specified here will be the same as in the Massett parameters and |
|
|
| 44 |
| 00:03:05,000 --> 00:03:06,000 |
| Method Masmoudi. |
|
|
| 45 |
| 00:03:07,000 --> 00:03:15,000 |
| And after I wrote it here, I can treat this E as a specific type and use it with parameters, for example, |
|
|
| 46 |
| 00:03:15,000 --> 00:03:17,000 |
| or anywhere inside the method. |
|
|
| 47 |
| 00:03:17,000 --> 00:03:23,000 |
| But here you can see that I have array of type E and while iterating over each element in this area, |
|
|
| 48 |
| 00:03:23,000 --> 00:03:26,000 |
| I also use E type for my variable here. |
|
|
| 49 |
| 00:03:27,000 --> 00:03:34,000 |
| Now I can call this method for most string and integer array the same as for all other types. |
|
|
| 50 |
| 00:03:34,000 --> 00:03:40,000 |
| Let me comment, Prenter, a message that works only with strings and leave my generic method awesome. |
|
|
| 51 |
| 00:03:40,000 --> 00:03:45,000 |
| And you can see that I don't have any compilation error anymore here. |
|
|
| 52 |
| 00:03:45,000 --> 00:03:48,000 |
| Let's make a definition of generic method now. |
|
|
| 53 |
| 00:03:48,000 --> 00:03:52,000 |
| Generic method is a method that introduce its own type parameters. |
|
|
| 54 |
| 00:03:53,000 --> 00:03:57,000 |
| I believe now you understand what generics are and why do we need them. |
|
|
| 55 |
| 00:03:57,000 --> 00:04:04,000 |
| Also, you know how to parametrized your methods now, but what is a potential issue in this case? |
|
|
| 56 |
| 00:04:04,000 --> 00:04:07,000 |
| In this case, for the type inside the method body? |
|
|
| 57 |
| 00:04:07,000 --> 00:04:13,000 |
| I can use only Massett that are available for object type, but not any other methods that are specific |
|
|
| 58 |
| 00:04:13,000 --> 00:04:21,000 |
| to string or integer or any other type Y because compiler doesn't know what type will be here during |
|
|
| 59 |
| 00:04:21,000 --> 00:04:22,000 |
| the runtime. |
|
|
| 60 |
| 00:04:22,000 --> 00:04:29,000 |
| I can't call here any string methods because compiler can guarantee that only objects of type streambed |
|
|
| 61 |
| 00:04:29,000 --> 00:04:30,000 |
| will be here. |
|
|
| 62 |
| 00:04:31,000 --> 00:04:37,000 |
| As we can see on this example, objects of any type might be here and what to do in case I need some |
|
|
| 63 |
| 00:04:37,000 --> 00:04:40,000 |
| behavior that is related to some specific hierarchy of objects. |
|
|
| 64 |
| 00:04:41,000 --> 00:04:45,000 |
| What if I know that this method wouldn't work with any objects at all? |
|
|
| 65 |
| 00:04:45,000 --> 00:04:50,000 |
| But this method has to work with any type that implements comparable interface. |
|
|
| 66 |
| 00:04:50,000 --> 00:04:57,000 |
| In this case, I can count on the fact that objects inside my body will have compared to Masset and |
|
|
| 67 |
| 00:04:57,000 --> 00:05:00,000 |
| I will be able to use this API in the mess and body. |
|
|
| 68 |
| 00:05:01,000 --> 00:05:01,000 |
| Does it make sense? |
|
|
| 69 |
| 00:05:02,000 --> 00:05:08,000 |
| To help you understand this, let me open another example here, I opened another file where I prepared |
|
|
| 70 |
| 00:05:08,000 --> 00:05:10,000 |
| other examples for you. |
|
|
| 71 |
| 00:05:10,000 --> 00:05:16,000 |
| Let's imagine that I have to create a that would be able to find the greatest value out of three variables. |
|
|
| 72 |
| 00:05:16,000 --> 00:05:23,000 |
| And I want to implement generic method, but not a bunch of separate methods that works with only strings, |
|
|
| 73 |
| 00:05:23,000 --> 00:05:25,000 |
| only integers, only double values. |
|
|
| 74 |
| 00:05:26,000 --> 00:05:30,000 |
| How to do that generic with boundaries will help us with this task. |
|
|
| 75 |
| 00:05:30,000 --> 00:05:33,000 |
| They're also called bounded type parameters. |
|
|
| 76 |
| 00:05:34,000 --> 00:05:36,000 |
| Here you can see massive declaration. |
|
|
| 77 |
| 00:05:36,000 --> 00:05:38,000 |
| The methods name is max value. |
|
|
| 78 |
| 00:05:38,000 --> 00:05:45,000 |
| The next thing that you can notice here is that we use different letter here now instead of E, we have |
|
|
| 79 |
| 00:05:45,000 --> 00:05:51,000 |
| key and he is parameterization of my method here in Diamond Operator. |
|
|
| 80 |
| 00:05:51,000 --> 00:05:58,000 |
| I say that this method should work with some type that extends comparable and comparable in turn is |
|
|
| 81 |
| 00:05:58,000 --> 00:06:00,000 |
| parameterized with this type. |
|
|
| 82 |
| 00:06:00,000 --> 00:06:08,000 |
| In other words, some type T should use it extends comparable interface or implement comparable interface. |
|
|
| 83 |
| 00:06:08,000 --> 00:06:14,000 |
| This is called upper bound with parameterization because we set boundary from the top. |
|
|
| 84 |
| 00:06:14,000 --> 00:06:15,000 |
| Doesn't make sense. |
|
|
| 85 |
| 00:06:16,000 --> 00:06:17,000 |
| Also, one more common here. |
|
|
| 86 |
| 00:06:18,000 --> 00:06:23,000 |
| It is possible to make multiple sounds like it is specified here in command line. |
|
|
| 87 |
| 00:06:23,000 --> 00:06:28,000 |
| I will leave it here, command it so that you could learn this when you will download the source code |
|
|
| 88 |
| 00:06:28,000 --> 00:06:30,000 |
| that I am showing right now. |
|
|
| 89 |
| 00:06:30,000 --> 00:06:37,000 |
| So you can say that we should extend both comparable interface and compare the interface. |
|
|
| 90 |
| 00:06:37,000 --> 00:06:39,000 |
| That's just for the sake of example. |
|
|
| 91 |
| 00:06:39,000 --> 00:06:46,000 |
| I believe you understand that instead of comparator, you can specify any other type here and only in |
|
|
| 92 |
| 00:06:46,000 --> 00:06:50,000 |
| case our custom type T will implement both of these interfaces. |
|
|
| 93 |
| 00:06:51,000 --> 00:06:57,000 |
| Only in this case we could work with this method and methods, arguments of type T, you even can see |
|
|
| 94 |
| 00:06:57,000 --> 00:07:03,000 |
| that I have a compilation error because neither string or integer nor verbal implements both of these |
|
|
| 95 |
| 00:07:03,000 --> 00:07:04,000 |
| interfaces simultaneously. |
|
|
| 96 |
| 00:07:04,000 --> 00:07:11,000 |
| Let me erase this to proceed with our demo potentially that you can also use time that is specified |
|
|
| 97 |
| 00:07:11,000 --> 00:07:17,000 |
| for parameterization as a returned type so you can get the type that was used as parameters here. |
|
|
| 98 |
| 00:07:18,000 --> 00:07:24,000 |
| The main thing and all of this is that this type should be the same everywhere across the MassArt in |
|
|
| 99 |
| 00:07:24,000 --> 00:07:26,000 |
| case the first argument is string. |
|
|
| 100 |
| 00:07:26,000 --> 00:07:32,000 |
| It is not possible that other arguments wouldn't be of different type or return type would be different. |
|
|
| 101 |
| 00:07:32,000 --> 00:07:37,000 |
| And now Compiler is aware that this type will be compatible with comparable interface. |
|
|
| 102 |
| 00:07:37,000 --> 00:07:43,000 |
| That means that all variables that are passed as arguments to this method have compared to MassArt. |
|
|
| 103 |
| 00:07:43,000 --> 00:07:49,000 |
| That's why all logic that is written in this method is rely on the fact that we can use this method |
|
|
| 104 |
| 00:07:50,000 --> 00:07:52,000 |
| and there are no any compilation errors. |
|
|
| 105 |
| 00:07:52,000 --> 00:07:53,000 |
| That's great. |
|
|
| 106 |
| 00:07:53,000 --> 00:07:59,000 |
| And here you can see in my method that I can invoke max value method with different types of arguments. |
|
|
| 107 |
| 00:07:59,000 --> 00:08:06,000 |
| No matter is as this integer double or string type, let me run this program from the console output. |
|
|
| 108 |
| 00:08:06,000 --> 00:08:09,000 |
| We can conclude that our method works as expected. |
|
|
| 109 |
| 00:08:10,000 --> 00:08:13,000 |
| Now you know how the Parameterize method was bound. |
|
|
| 110 |
| 00:08:13,000 --> 00:08:15,000 |
| Hobbs's makes things clearer. |
|
|
| 111 |
| 00:08:15,000 --> 00:08:18,000 |
| Let's go to the next example and this example. |
|
|
| 112 |
| 00:08:18,000 --> 00:08:21,000 |
| I'm going to show you how you can parameterize your class here. |
|
|
| 113 |
| 00:08:21,000 --> 00:08:25,000 |
| You can see Diamont operator right next to my class name. |
|
|
| 114 |
| 00:08:25,000 --> 00:08:29,000 |
| That means I parametrized my class, for example. |
|
|
| 115 |
| 00:08:29,000 --> 00:08:37,000 |
| I can declare property of type key and Masset parameters like in this set method also can be of my type, |
|
|
| 116 |
| 00:08:37,000 --> 00:08:42,000 |
| e.g. I can initialize my field with the values that will be passed as massas argument here. |
|
|
| 117 |
| 00:08:43,000 --> 00:08:48,000 |
| The method will return me a value of type that we used to parametrized my class. |
|
|
| 118 |
| 00:08:48,000 --> 00:08:49,000 |
| And here's example. |
|
|
| 119 |
| 00:08:50,000 --> 00:08:52,000 |
| I declare the variable of type generic. |
|
|
| 120 |
| 00:08:52,000 --> 00:08:58,000 |
| Mazrui was a name integer in box and used Diament operator to parameterize this type by integer. |
|
|
| 121 |
| 00:08:59,000 --> 00:09:05,000 |
| After that I created the object and used Diament operator after Anjelah version seven. |
|
|
| 122 |
| 00:09:05,000 --> 00:09:11,000 |
| There is no need to duplicate parameterization type in Diament operator here, but you can if you wish. |
|
|
| 123 |
| 00:09:12,000 --> 00:09:18,000 |
| For example, here I left integer type and then my second variable was a name string box that I parametrized |
|
|
| 124 |
| 00:09:18,000 --> 00:09:19,000 |
| by string. |
|
|
| 125 |
| 00:09:19,000 --> 00:09:22,000 |
| I left blank my second Diament operator. |
|
|
| 126 |
| 00:09:22,000 --> 00:09:26,000 |
| In most cases type is specified only when you declare a variable. |
|
|
| 127 |
| 00:09:27,000 --> 00:09:33,000 |
| And here you can see that my integer box can work only with integers and there is a compilation error |
|
|
| 128 |
| 00:09:33,000 --> 00:09:35,000 |
| in case I would try to set any string. |
|
|
| 129 |
| 00:09:35,000 --> 00:09:38,000 |
| Object is a similar story with my string box. |
|
|
| 130 |
| 00:09:39,000 --> 00:09:44,000 |
| That is because these two variables are parametrized with different types and in the first case set |
|
|
| 131 |
| 00:09:44,000 --> 00:09:46,000 |
| Masset except on the integers. |
|
|
| 132 |
| 00:09:46,000 --> 00:09:50,000 |
| And in the second case, set method accepts only strings. |
|
|
| 133 |
| 00:09:51,000 --> 00:09:55,000 |
| When I use get MassArt and receive integer and string type accordingly. |
|
|
| 134 |
| 00:09:55,000 --> 00:10:01,000 |
| And here you can see that I print values to console and used special format specifiers for that some. |
|
|
| 135 |
| 00:10:02,000 --> 00:10:08,000 |
| Numbers and string accordingly, let me run this program, you can see that everything works as expected |
|
|
| 136 |
| 00:10:08,000 --> 00:10:09,000 |
| without any errors. |
|
|
| 137 |
| 00:10:10,000 --> 00:10:12,000 |
| Let's create a definition of generic type. |
|
|
| 138 |
| 00:10:12,000 --> 00:10:19,000 |
| Now, when you saw the example and generic type is a generic class or interface that is parameterized |
|
|
| 139 |
| 00:10:19,000 --> 00:10:20,000 |
| over types. |
|
|
| 140 |
| 00:10:20,000 --> 00:10:22,000 |
| And now let's continue our lesson. |
|
|
| 141 |
| 00:10:23,000 --> 00:10:28,000 |
| Even if you would not use parameterization and generics for your own custom classes, you would use |
|
|
| 142 |
| 00:10:28,000 --> 00:10:31,000 |
| generics a lot with classes from Java collections framework. |
|
|
| 143 |
| 00:10:32,000 --> 00:10:38,000 |
| It is super useful because it wasn't possible to create collections for all possible types. |
|
|
| 144 |
| 00:10:38,000 --> 00:10:43,000 |
| That's why all types from Java collections framework are parametrized and use generics. |
|
|
| 145 |
| 00:10:44,000 --> 00:10:46,000 |
| Let me open source code of arriviste. |
|
|
| 146 |
| 00:10:46,000 --> 00:10:54,000 |
| You can see that it is parameterized with each type and if I open at Masset, you can see that it adds |
|
|
| 147 |
| 00:10:54,000 --> 00:10:55,000 |
| elements of each type. |
|
|
| 148 |
| 00:10:59,000 --> 00:11:06,000 |
| And get maced in return elements of each type, does it make sense sometimes even parametrized with |
|
|
| 149 |
| 00:11:06,000 --> 00:11:12,000 |
| two types, for example, on implementations specify separate type for key and value. |
|
|
| 150 |
| 00:11:12,000 --> 00:11:15,000 |
| Let me open hash map or squad here. |
|
|
| 151 |
| 00:11:15,000 --> 00:11:23,000 |
| You can see that I can specify type for key and a separate type for Lélia just to placeholders and input |
|
|
| 152 |
| 00:11:23,000 --> 00:11:23,000 |
| MassArt. |
|
|
| 153 |
| 00:11:23,000 --> 00:11:31,000 |
| You can see that I put key of type K and value of type we and type of return value is the same as type |
|
|
| 154 |
| 00:11:31,000 --> 00:11:37,000 |
| of the value we, because according to this interface we receive the last value that is associated with |
|
|
| 155 |
| 00:11:37,000 --> 00:11:38,000 |
| a given key. |
|
|
| 156 |
| 00:11:38,000 --> 00:11:44,000 |
| But the details of the interfaces of our collections framework are covered in the separate lessons. |
|
|
| 157 |
| 00:11:44,000 --> 00:11:50,000 |
| Now you know how to parameterize your class and you know how types from Java collections framework are |
|
|
| 158 |
| 00:11:50,000 --> 00:11:51,000 |
| parametrized. |
|
|
| 159 |
| 00:11:52,000 --> 00:11:55,000 |
| We have one more important and practical thing to talk about. |
|
|
| 160 |
| 00:11:55,000 --> 00:11:59,000 |
| I want to talk with you about the wild cards with upper and lower bounds. |
|
|
| 161 |
| 00:12:00,000 --> 00:12:03,000 |
| Let me open another demo file that I prepared before this lesson. |
|
|
| 162 |
| 00:12:04,000 --> 00:12:09,000 |
| To make you understand this example, let me show you all classes that will take part in our demo. |
|
|
| 163 |
| 00:12:10,000 --> 00:12:16,000 |
| I declared all classes in one file to keep everything grouped for the demo and to not switch tabs and |
|
|
| 164 |
| 00:12:16,000 --> 00:12:17,000 |
| engines that we have. |
|
|
| 165 |
| 00:12:17,000 --> 00:12:22,000 |
| Some parent class and child class extends parent and grandchild. |
|
|
| 166 |
| 00:12:22,000 --> 00:12:24,000 |
| Class extends child. |
|
|
| 167 |
| 00:12:24,000 --> 00:12:25,000 |
| Is it clear? |
|
|
| 168 |
| 00:12:26,000 --> 00:12:26,000 |
| Cool. |
|
|
| 169 |
| 00:12:26,000 --> 00:12:27,000 |
| Let's move on. |
|
|
| 170 |
| 00:12:28,000 --> 00:12:34,000 |
| Now imagine that I have at least parametrized by type child and I have mastered that can work with any |
|
|
| 171 |
| 00:12:34,000 --> 00:12:37,000 |
| list objects that are parametrized by time parent. |
|
|
| 172 |
| 00:12:37,000 --> 00:12:39,000 |
| It is called process parent elements. |
|
|
| 173 |
| 00:12:40,000 --> 00:12:45,000 |
| How do you think MacColl process span's elements MassArt and POS collection of child elements there? |
|
|
| 174 |
| 00:12:46,000 --> 00:12:53,000 |
| Logically, it seems to be OK since each child class should have all methods that parent class has and |
|
|
| 175 |
| 00:12:53,000 --> 00:12:55,000 |
| compilers should not be worried about this. |
|
|
| 176 |
| 00:12:55,000 --> 00:13:00,000 |
| But if I ask you this question, you already suspected something, don't you? |
|
|
| 177 |
| 00:13:00,000 --> 00:13:01,000 |
| You are right. |
|
|
| 178 |
| 00:13:01,000 --> 00:13:03,000 |
| If you are suspicious, this wouldn't work. |
|
|
| 179 |
| 00:13:04,000 --> 00:13:05,000 |
| You can see compilation error here. |
|
|
| 180 |
| 00:13:06,000 --> 00:13:06,000 |
| Why? |
|
|
| 181 |
| 00:13:07,000 --> 00:13:11,000 |
| Because list of child elements is not a list of parent elements. |
|
|
| 182 |
| 00:13:11,000 --> 00:13:14,000 |
| That said, what what to do in this case. |
|
|
| 183 |
| 00:13:14,000 --> 00:13:17,000 |
| Usually in this case, engineers use wild cards. |
|
|
| 184 |
| 00:13:17,000 --> 00:13:23,000 |
| Let me show you the next method we have process elements, method, the text list of elements that is |
|
|
| 185 |
| 00:13:23,000 --> 00:13:26,000 |
| parametrized by any type that extends Berent. |
|
|
| 186 |
| 00:13:27,000 --> 00:13:31,000 |
| This question mark is called wildcard and can be treated as any type. |
|
|
| 187 |
| 00:13:32,000 --> 00:13:34,000 |
| This is called upper bound at wild card. |
|
|
| 188 |
| 00:13:35,000 --> 00:13:40,000 |
| In this case, I can pass list that contains elements of type child to this method. |
|
|
| 189 |
| 00:13:40,000 --> 00:13:43,000 |
| And here you can see that there are no errors. |
|
|
| 190 |
| 00:13:43,000 --> 00:13:44,000 |
| Does it make sense? |
|
|
| 191 |
| 00:13:45,000 --> 00:13:48,000 |
| Now I want you to put all the attention to the next example. |
|
|
| 192 |
| 00:13:49,000 --> 00:13:54,000 |
| When you use cards, that means you can get elements of type parent from this collection. |
|
|
| 193 |
| 00:13:54,000 --> 00:14:00,000 |
| I believe that is clear that you will not be able to extract element of type child from this list because |
|
|
| 194 |
| 00:14:00,000 --> 00:14:05,000 |
| there is no guarantee what type would be here instead of the question mark during the runtime. |
|
|
| 195 |
| 00:14:06,000 --> 00:14:09,000 |
| It can be child, but it also can be parent type. |
|
|
| 196 |
| 00:14:09,000 --> 00:14:13,000 |
| And that's why custom foreign object to child type would cause exception. |
|
|
| 197 |
| 00:14:13,000 --> 00:14:19,000 |
| And most likely, parent doesn't have all methods and behavior that is described in the child type. |
|
|
| 198 |
| 00:14:19,000 --> 00:14:20,000 |
| Is it clear? |
|
|
| 199 |
| 00:14:21,000 --> 00:14:26,000 |
| OK, we understood that we can get elements of type parent in case we use upper bound at wild card. |
|
|
| 200 |
| 00:14:27,000 --> 00:14:29,000 |
| But can we add elements to this content? |
|
|
| 201 |
| 00:14:30,000 --> 00:14:31,000 |
| Unfortunately we can't. |
|
|
| 202 |
| 00:14:32,000 --> 00:14:39,000 |
| And here the examples you can see that I can't add neither parent nor child nor grandchild objects I |
|
|
| 203 |
| 00:14:39,000 --> 00:14:40,000 |
| cannot only know value. |
|
|
| 204 |
| 00:14:41,000 --> 00:14:48,000 |
| You might be wondering why why I can't add object of parent type to collection of elements, parametrized |
|
|
| 205 |
| 00:14:48,000 --> 00:14:49,000 |
| by parent type. |
|
|
| 206 |
| 00:14:49,000 --> 00:14:52,000 |
| But let's look at this from another side. |
|
|
| 207 |
| 00:14:52,000 --> 00:14:57,000 |
| This is a very smart mechanism created in Java to save engineers from potential errors. |
|
|
| 208 |
| 00:14:57,000 --> 00:15:04,000 |
| The main issue is that because we don't know what type would be here during the runtime, that's why |
|
|
| 209 |
| 00:15:04,000 --> 00:15:07,000 |
| interactions with such collections are limited. |
|
|
| 210 |
| 00:15:07,000 --> 00:15:13,000 |
| Imagine that during the runtime I will pass list of elements of type child and I will add element of |
|
|
| 211 |
| 00:15:13,000 --> 00:15:14,000 |
| time parent. |
|
|
| 212 |
| 00:15:15,000 --> 00:15:21,000 |
| And after I modified this collection in this method, I will get the element and I would think that |
|
|
| 213 |
| 00:15:21,000 --> 00:15:27,000 |
| all elements in this container are of child type and I will call some child specific method. |
|
|
| 214 |
| 00:15:27,000 --> 00:15:28,000 |
| What will happen? |
|
|
| 215 |
| 00:15:28,000 --> 00:15:36,000 |
| I will get error during the runtime because indeed I will get here object of parent time and this object |
|
|
| 216 |
| 00:15:36,000 --> 00:15:38,000 |
| will have child specific method. |
|
|
| 217 |
| 00:15:39,000 --> 00:15:46,000 |
| That is why Compiler wants to eliminate cases like this and just doesn't allow me to add any elements |
|
|
| 218 |
| 00:15:46,000 --> 00:15:47,000 |
| in this method. |
|
|
| 219 |
| 00:15:47,000 --> 00:15:52,000 |
| Does it make sense and leave now you understood how upper bound at wild cards work. |
|
|
| 220 |
| 00:15:53,000 --> 00:15:55,000 |
| Now let's take a look at another case. |
|
|
| 221 |
| 00:15:55,000 --> 00:15:58,000 |
| What to do in case I have to create. |
|
|
| 222 |
| 00:15:58,000 --> 00:16:04,000 |
| That will be able to add new elements to the collection in this case, we have to use lower bound at |
|
|
| 223 |
| 00:16:04,000 --> 00:16:08,000 |
| wild cards here you can see that I created two more lists. |
|
|
| 224 |
| 00:16:09,000 --> 00:16:14,000 |
| One of them is parametrized by parent type and another one is parametrized by child type. |
|
|
| 225 |
| 00:16:14,000 --> 00:16:20,000 |
| And you can see that I call process elements to Masset and parse the first and the second list object |
|
|
| 226 |
| 00:16:20,000 --> 00:16:20,000 |
| there. |
|
|
| 227 |
| 00:16:21,000 --> 00:16:25,000 |
| But I can't pass list of elements that are parametrized by grandchild type. |
|
|
| 228 |
| 00:16:26,000 --> 00:16:28,000 |
| Let's investigate process elements to MassArt. |
|
|
| 229 |
| 00:16:29,000 --> 00:16:31,000 |
| This method has lower bound and wild card. |
|
|
| 230 |
| 00:16:32,000 --> 00:16:34,000 |
| You can see super keyword here. |
|
|
| 231 |
| 00:16:34,000 --> 00:16:35,000 |
| What does that mean? |
|
|
| 232 |
| 00:16:36,000 --> 00:16:42,000 |
| That means that this method can take as an argument any object of type liste parametrized by any type |
|
|
| 233 |
| 00:16:42,000 --> 00:16:47,000 |
| that is parent or in other words, super type with respect to child type. |
|
|
| 234 |
| 00:16:48,000 --> 00:16:52,000 |
| That's why I can't pass Barrentine or super type of child. |
|
|
| 235 |
| 00:16:52,000 --> 00:16:57,000 |
| This could be any super type, including parent and even object is clear. |
|
|
| 236 |
| 00:16:58,000 --> 00:17:00,000 |
| If yes, then let's proceed. |
|
|
| 237 |
| 00:17:00,000 --> 00:17:05,000 |
| In this case I can get on the elements of type object and I believe you already understood why. |
|
|
| 238 |
| 00:17:06,000 --> 00:17:11,000 |
| Because there is no guarantee what super type of child type will be here during the runtime. |
|
|
| 239 |
| 00:17:11,000 --> 00:17:18,000 |
| But what types I can put into this collection, I can put any time that this child with respect to child |
|
|
| 240 |
| 00:17:18,000 --> 00:17:23,000 |
| type here, you can see that I can add object of type child and grandchild. |
|
|
| 241 |
| 00:17:24,000 --> 00:17:32,000 |
| And also I always can add now, for example, I can't add any super type of type child, including parent |
|
|
| 242 |
| 00:17:32,000 --> 00:17:38,000 |
| type and object y if this sounds completely not logical, then consider the next case. |
|
|
| 243 |
| 00:17:39,000 --> 00:17:45,000 |
| Imagine that we have passed here container full of objects of type child and in case compiler let me |
|
|
| 244 |
| 00:17:45,000 --> 00:17:46,000 |
| add the parent object. |
|
|
| 245 |
| 00:17:46,000 --> 00:17:52,000 |
| And after this collection was modified, I retrieve object of child type from here and called child |
|
|
| 246 |
| 00:17:52,000 --> 00:17:59,000 |
| specific method and program fails because that object doesn't have child specific behavior and case |
|
|
| 247 |
| 00:17:59,000 --> 00:18:05,000 |
| I passed here at least parametrized by any other type that is super with respect to child type. |
|
|
| 248 |
| 00:18:05,000 --> 00:18:12,000 |
| There is no harm in this at all to add child or grandchild object in this container because each of |
|
|
| 249 |
| 00:18:12,000 --> 00:18:16,000 |
| the specific types for sure has behavior of its parent type. |
|
|
| 250 |
| 00:18:16,000 --> 00:18:17,000 |
| Does it make sense? |
|
|
| 251 |
| 00:18:18,000 --> 00:18:24,000 |
| We can make a conclusion in case you want to create a method that will work with collections, parametrized |
|
|
| 252 |
| 00:18:24,000 --> 00:18:30,000 |
| by different types, and you want to use this method to modify the collection and to add elements there |
|
|
| 253 |
| 00:18:30,000 --> 00:18:32,000 |
| you have to use lower bound at wild cards. |
|
|
| 254 |
| 00:18:32,000 --> 00:18:38,000 |
| But in case you wanted to use this method only to read elements from the container to process that data, |
|
|
| 255 |
| 00:18:38,000 --> 00:18:45,000 |
| then you have to use upper bound at wild cards because upper bound wild cards allow us to read from |
|
|
| 256 |
| 00:18:45,000 --> 00:18:50,000 |
| the container specific type and use its methods to get all necessary data. |
|
|
| 257 |
| 00:18:50,000 --> 00:18:56,000 |
| You already learned how to use bounded wild cards, but should we use wild cards without bounds? |
|
|
| 258 |
| 00:18:57,000 --> 00:18:59,000 |
| I would say that this is super rare case. |
|
|
| 259 |
| 00:19:00,000 --> 00:19:00,000 |
| That's why. |
|
|
| 260 |
| 00:19:01,000 --> 00:19:02,000 |
| Let me show you this on example. |
|
|
| 261 |
| 00:19:03,000 --> 00:19:05,000 |
| Let me open source code of absurd collection. |
|
|
| 262 |
| 00:19:06,000 --> 00:19:09,000 |
| You can see that absolute collection is parametrized by any type. |
|
|
| 263 |
| 00:19:10,000 --> 00:19:11,000 |
| But let's look at contains all. |
|
|
| 264 |
| 00:19:11,000 --> 00:19:14,000 |
| Macit, can you see wild card here. |
|
|
| 265 |
| 00:19:15,000 --> 00:19:21,000 |
| That means that contains some method can work with any collection that contains any types inside. |
|
|
| 266 |
| 00:19:21,000 --> 00:19:24,000 |
| Then what is the difference between each type and wild card? |
|
|
| 267 |
| 00:19:25,000 --> 00:19:31,000 |
| The point is that each type will be erased and substituted with a specific type everywhere with the |
|
|
| 268 |
| 00:19:31,000 --> 00:19:38,000 |
| type that we will specify, whereas wild cards would always mean any type, but not the exactly one |
|
|
| 269 |
| 00:19:38,000 --> 00:19:41,000 |
| type that we used to parameterize instance of our object. |
|
|
| 270 |
| 00:19:41,000 --> 00:19:43,000 |
| Does it make things clearer? |
|
|
| 271 |
| 00:19:43,000 --> 00:19:48,000 |
| I will leave linked to this example in attachments to this Larssen so that you could investigate it. |
|
|
| 272 |
| 00:19:48,000 --> 00:19:55,000 |
| But pay attention that this specific example you won't be able to run because I described various scenarios |
|
|
| 273 |
| 00:19:55,000 --> 00:19:57,000 |
| that causes compilation error. |
|
|
| 274 |
| 00:19:57,000 --> 00:20:03,000 |
| But still you can play around with compilation properties to understand wildcards together with upper |
|
|
| 275 |
| 00:20:03,000 --> 00:20:04,000 |
| and lower bounds. |
|
|
| 276 |
| 00:20:04,000 --> 00:20:09,000 |
| Let me open the next demo file to show you the next example and this example. |
|
|
| 277 |
| 00:20:09,000 --> 00:20:13,000 |
| I want you to understand the generic exist only for our compiler. |
|
|
| 278 |
| 00:20:14,000 --> 00:20:18,000 |
| There are no generics during the runtime because of the type erasure type. |
|
|
| 279 |
| 00:20:18,000 --> 00:20:25,000 |
| Erasure can be explained as a process of enforcing type constraints only at compile time and discarding |
|
|
| 280 |
| 00:20:25,000 --> 00:20:27,000 |
| the element type information at runtime. |
|
|
| 281 |
| 00:20:28,000 --> 00:20:34,000 |
| That means that during the runtime it can be that objects of another type will appear in collection. |
|
|
| 282 |
| 00:20:35,000 --> 00:20:42,000 |
| Let me show this example and give my comments as we go and create at least Werrimull and list is parametrized |
|
|
| 283 |
| 00:20:42,000 --> 00:20:43,000 |
| by integer type. |
|
|
| 284 |
| 00:20:43,000 --> 00:20:49,000 |
| Everything looks good so far, but now I created a list without specifying any generic type. |
|
|
| 285 |
| 00:20:50,000 --> 00:20:57,000 |
| That means that during the runtime, the EIB that is declared in the source code of list will be erased |
|
|
| 286 |
| 00:20:57,000 --> 00:20:57,000 |
| and. |
|
|
| 287 |
| 00:20:57,000 --> 00:21:04,000 |
| Aware where it was used, it will be substituted with object type, for example, at Mass, it will |
|
|
| 288 |
| 00:21:04,000 --> 00:21:05,000 |
| work with any object. |
|
|
| 289 |
| 00:21:06,000 --> 00:21:13,000 |
| But in case I use bouncin generics, like, for example, in our damos was a generic for our method |
|
|
| 290 |
| 00:21:13,000 --> 00:21:14,000 |
| during the compilation. |
|
|
| 291 |
| 00:21:14,000 --> 00:21:21,000 |
| This type will be erased and substituted with the first bound class, in this case comparable. |
|
|
| 292 |
| 00:21:21,000 --> 00:21:22,000 |
| Does it make sense? |
|
|
| 293 |
| 00:21:23,000 --> 00:21:27,000 |
| You can see that our compiler tells us that there is a one here. |
|
|
| 294 |
| 00:21:28,000 --> 00:21:32,000 |
| It is not an error, but still works of our attention in the opinion of compiler. |
|
|
| 295 |
| 00:21:33,000 --> 00:21:36,000 |
| If I am a mouse over this warning, I see explanation. |
|
|
| 296 |
| 00:21:36,000 --> 00:21:39,000 |
| Message that tells me is at least is a type. |
|
|
| 297 |
| 00:21:39,000 --> 00:21:41,000 |
| What is a raw type. |
|
|
| 298 |
| 00:21:41,000 --> 00:21:45,000 |
| A raw type is the name of a generic class or interface. |
|
|
| 299 |
| 00:21:45,000 --> 00:21:46,000 |
| Without any type arguments. |
|
|
| 300 |
| 00:21:47,000 --> 00:21:49,000 |
| We can still work with such types. |
|
|
| 301 |
| 00:21:49,000 --> 00:21:52,000 |
| But Compiler wants to warn us that something bad may happen. |
|
|
| 302 |
| 00:21:53,000 --> 00:21:59,000 |
| Now I Telx at least reference is pointing out to the same object as integers reference. |
|
|
| 303 |
| 00:22:00,000 --> 00:22:02,000 |
| And I put string object in that list. |
|
|
| 304 |
| 00:22:02,000 --> 00:22:07,000 |
| And again, I see he has a warning about time safety, but not an error. |
|
|
| 305 |
| 00:22:08,000 --> 00:22:11,000 |
| This is very unlikely that you will be able to reproduce this mistake. |
|
|
| 306 |
| 00:22:12,000 --> 00:22:18,000 |
| But I want to prove you that generics exist only to help us during the compilation time, but not during |
|
|
| 307 |
| 00:22:18,000 --> 00:22:18,000 |
| the runtime. |
|
|
| 308 |
| 00:22:19,000 --> 00:22:25,000 |
| And as you can see, I successfully edit my string object to the list, but when in other parts of the |
|
|
| 309 |
| 00:22:25,000 --> 00:22:32,000 |
| program or somewhere else will use the reference of our parametrized type integers and when will call |
|
|
| 310 |
| 00:22:32,000 --> 00:22:38,000 |
| that method, we will get object of type integer because this variable has parameterized type. |
|
|
| 311 |
| 00:22:38,000 --> 00:22:40,000 |
| But what would happen during the runtime? |
|
|
| 312 |
| 00:22:41,000 --> 00:22:42,000 |
| What do we think? |
|
|
| 313 |
| 00:22:42,000 --> 00:22:44,000 |
| Lets me around the program and show you this. |
|
|
| 314 |
| 00:22:45,000 --> 00:22:49,000 |
| And we see runtime exception, glossiest exception. |
|
|
| 315 |
| 00:22:49,000 --> 00:22:54,000 |
| Java tells us that in line 15 it can't costarring object to integer. |
|
|
| 316 |
| 00:22:55,000 --> 00:22:56,000 |
| I believe you got the trick. |
|
|
| 317 |
| 00:22:57,000 --> 00:22:58,000 |
| That's it. |
|
|
| 318 |
| 00:22:58,000 --> 00:23:02,000 |
| Now you know about even more than some senior software engineers, believe me. |
|
|
| 319 |
| 00:23:03,000 --> 00:23:05,000 |
| Let's recap what we have learned today. |
|
|
| 320 |
| 00:23:06,000 --> 00:23:08,000 |
| Today, we learned a lot of different things. |
|
|
| 321 |
| 00:23:08,000 --> 00:23:13,000 |
| Now you know what generics are and what potential problems they help us to solve. |
|
|
| 322 |
| 00:23:13,000 --> 00:23:20,000 |
| Youso how to parameterize your method in Java, we learned what Boundy generics are together. |
|
|
| 323 |
| 00:23:20,000 --> 00:23:22,000 |
| We created parameterized Closs. |
|
|
| 324 |
| 00:23:22,000 --> 00:23:24,000 |
| You saw what wild cards are. |
|
|
| 325 |
| 00:23:24,000 --> 00:23:29,000 |
| And we practice a bit with upper bound at wild cards and lower bound with wild cards. |
|
|
| 326 |
| 00:23:29,000 --> 00:23:33,000 |
| And at the end of the lesson, we talked about hyperalgesia during the runtime. |
|
|
| 327 |
| 00:23:34,000 --> 00:23:36,000 |
| And now let's look at your homework. |
|
|
| 328 |
| 00:23:36,000 --> 00:23:42,000 |
| I believe you already implemented our custom list from the other homework I left link to that homework |
|
|
| 329 |
| 00:23:42,000 --> 00:23:44,000 |
| here just in case. |
|
|
| 330 |
| 00:23:44,000 --> 00:23:50,000 |
| Also, I count on the fact that you implemented Iterator and listed the return for this container. |
|
|
| 331 |
| 00:23:50,000 --> 00:23:53,000 |
| Here is a link to the homework about iterators. |
|
|
| 332 |
| 00:23:53,000 --> 00:24:00,000 |
| Now, I want you to make my list Interface Parametrized, and I want you to use generics for the fourth |
|
|
| 333 |
| 00:24:00,000 --> 00:24:06,000 |
| E class implementation myside that I want you to make here in your classes that implements Iterator |
|
|
| 334 |
| 00:24:06,000 --> 00:24:08,000 |
| and least iterator interfaces. |
|
|
| 335 |
| 00:24:08,000 --> 00:24:09,000 |
| Also parametrized. |
|
|
| 336 |
| 00:24:10,000 --> 00:24:15,000 |
| This will be a great practice for you to work with generics that it home. |
|
|
| 337 |
| 00:24:15,000 --> 00:24:17,000 |
| This task will be like a piece of cake for you. |
|
|
| 338 |
| 00:24:18,000 --> 00:24:20,000 |
| That's all what I have for you for today. |
|
|
| 339 |
| 00:24:21,000 --> 00:24:22,000 |
| Thanks a lot for your attention. |
|
|
| 340 |
| 00:24:22,000 --> 00:24:24,000 |
| See you in the next lesson. |
|
|
|
|