-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjava-basics-generics.html
203 lines (164 loc) · 41.6 KB
/
java-basics-generics.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
<!DOCTYPE html><html lang="de-ch"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Java basics: Generics - Finecloud</title><meta name="description" content="What are Generics? What if we could write a single sort method that sort the elements in an Integer array, a String array, or an array of any type that supports ordering? Java Generics enable programmers to specify, with a single method declaration, a set…"><meta name="generator" content="Publii Open-Source CMS for Static Site"><link rel="stylesheet" href="https://www.finecloud.ch/media/plugins/syntaxHighlighter/prism-black.css"><link rel="canonical" href="https://www.finecloud.ch/java-basics-generics.html"><link rel="alternate" type="application/atom+xml" href="https://www.finecloud.ch/feed.xml"><link rel="alternate" type="application/json" href="https://www.finecloud.ch/feed.json"><meta property="og:title" content="Java basics: Generics"><meta property="og:site_name" content="Finecloud"><meta property="og:description" content="What are Generics? What if we could write a single sort method that sort the elements in an Integer array, a String array, or an array of any type that supports ordering? Java Generics enable programmers to specify, with a single method declaration, a set…"><meta property="og:url" content="https://www.finecloud.ch/java-basics-generics.html"><meta property="og:type" content="article"><link rel="shortcut icon" href="https://www.finecloud.ch/media/website/finecloud.png" type="image/png"><link rel="stylesheet" href="https://www.finecloud.ch/assets/css/style.css?v=39da73365516a098a9b73b721fc970e2"><script type="application/ld+json">{"@context":"http://schema.org","@type":"Article","mainEntityOfPage":{"@type":"WebPage","@id":"https://www.finecloud.ch/java-basics-generics.html"},"headline":"Java basics: Generics","datePublished":"2022-08-23T17:29","dateModified":"2022-08-23T17:29","description":"What are Generics? What if we could write a single sort method that sort the elements in an Integer array, a String array, or an array of any type that supports ordering? Java Generics enable programmers to specify, with a single method declaration, a set…","author":{"@type":"Person","name":"Finecloud","url":"https://www.finecloud.ch/authors/finecloud/"},"publisher":{"@type":"Organization","name":"Finecloud"}}</script><meta name="google-site-verification" content="seFY9U12uiEq5U3_MyZiX6XWzk0AVFl9zITr2ZKsytY"></head><body><div class="site-container"><header class="top" id="js-header"><a class="logo" href="https://www.finecloud.ch/">Finecloud</a><nav class="navbar js-navbar"><button class="navbar__toggle js-toggle" aria-label="Menu" aria-haspopup="true" aria-expanded="false"><span class="navbar__toggle-box"><span class="navbar__toggle-inner">Menu</span></span></button><ul class="navbar__menu"><li><a href="https://www.finecloud.ch/" target="_self">Blog</a></li><li><a href="https://www.finecloud.ch/tags/" target="_self">Tags</a></li></ul></nav><div class="search"><div class="search__overlay js-search-overlay"><div class="search__overlay-inner"><form action="https://www.finecloud.ch/search.html" class="search__form"><input class="search__input js-search-input" type="search" name="q" placeholder="search..." aria-label="search..." autofocus="autofocus"></form><button class="search__close js-search-close" aria-label="Close">Close</button></div></div><button class="search__btn js-search-btn" aria-label="Search"><svg role="presentation" focusable="false"><use xlink:href="https://www.finecloud.ch/assets/svg/svg-map.svg#search"/></svg></button></div></header><main><article class="post"><div class="hero"><figure class="hero__image hero__image--overlay"><img src="https://www.finecloud.ch/media/website/download.jpg" srcset="https://www.finecloud.ch/media/website/responsive/download-xs.jpg 300w, https://www.finecloud.ch/media/website/responsive/download-sm.jpg 480w, https://www.finecloud.ch/media/website/responsive/download-md.jpg 768w, https://www.finecloud.ch/media/website/responsive/download-lg.jpg 1024w, https://www.finecloud.ch/media/website/responsive/download-xl.jpg 1360w, https://www.finecloud.ch/media/website/responsive/download-2xl.jpg 1600w" sizes="100vw" loading="eager" alt=""></figure><header class="hero__content"><div class="wrapper"><div class="post__meta"><time datetime="2022-08-23T17:29">August 23, 2022</time></div><h1>Java basics: Generics</h1></div></header></div><div class="wrapper post__entry"><div class="post__toc"><h3>Table of Contents</h3><ul><li><a href="#mcetoc_1gb5849tosv">What are Generics?</a></li><li><a href="#mcetoc_1gb5849tot0">Example Szenario</a><ul><li><a href="#mcetoc_1gb5il12127i">The Challenge</a><ul><li><a href="#mcetoc_1gb5il12127j">The bad way</a></li><li><a href="#mcetoc_1gb5il12127k">There's a better way</a></li><li><a href="#mcetoc_1gb5il12127l">Associate an ID</a></li><li><a href="#mcetoc_1gb5imo5327n">Implement a Get ID method</a></li><li><a href="#mcetoc_1gb5l3vod2g2">Implement IDable in person class</a></li></ul></li><li><a href="#mcetoc_1gb5l3vod2g3">Use generics on static methods</a></li></ul></li></ul></div><h2 id="mcetoc_1gb5849tosv">What are Generics?</h2><p>What if we could write a single sort method that sort the elements in an Integer array, a String array, or an array of any type that supports ordering?</p><p>Java Generics enable programmers to specify, with a single method declaration, a set of related methods, or with a single class declaration, a set of related types.<br><br>Generics also provide compile-time type safety that allows programmers to catch invalid types at compile time.<br><br>You will find them most commonly with collections, although they can be used with more than just collections. Typically, though, when they're used with classes like collections, they allow us to constrain the types of data that can be associated with the class that we are using the generics on.</p><p>So in general, generics allow us to kind of constrain what types of data we can associate with a with a class. Additionally, because they allow us to specify those data types, more specifically, they also enable us to avoid, in many cases, needing to cast types any more. We can use generics on methods and things that return data types as well. And in that case, if you use a generic for those methods that can return something, then you have a better shot at not needing to cast whatever the data type was that comes off of those methods.<br><br>And then finally, they can protect us from certain types of runtime errors because if you're not using generics, but you're working with code that is expecting to work with certain data types, we don't have a really strong way of enforcing that. Then you're likely going to be casting data into the assumed types that you need to work with. And if the objects that you're casting aren't actually cast the ball into the data type that you're expecting, you're going to get errors.</p><h2 id="mcetoc_1gb5849tot0">Example Szenario</h2><p>Lets assume we have the following Java Class:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">import</span> java.util.ArrayList;
<span class="hljs-keyword" style="color: #cc7832;">import</span> java.util.List;
<span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">class</span> <span class="hljs-title" style="color: #ffc66d;">Repository</span> </span>{
<span class="hljs-keyword" style="color: #cc7832;">private</span> List<String> records = <span class="hljs-keyword" style="color: #cc7832;">new</span> ArrayList<>();
<span class="hljs-function">List<String> <span class="hljs-title" style="color: #ffc66d;">findAll</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword" style="color: #cc7832;">return</span> records;
}
<span class="hljs-function">String <span class="hljs-title" style="color: #ffc66d;">save</span><span class="hljs-params">(String record)</span> </span>{
records.add(record);
<span class="hljs-keyword" style="color: #cc7832;">return</span> record;
}
<span class="hljs-function">String <span class="hljs-title" style="color: #ffc66d;">findById</span><span class="hljs-params">(<span class="hljs-keyword" style="color: #cc7832;">long</span> id)</span> </span>{
<span class="hljs-keyword" style="color: #cc7832;">return</span> records.get(Long.valueOf(id).intValue());
}
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-keyword" style="color: #cc7832;">static</span> <span class="hljs-keyword" style="color: #cc7832;">void</span> <span class="hljs-title" style="color: #ffc66d;">main</span><span class="hljs-params">(String[] args)</span> </span>{
Repository repo = <span class="hljs-keyword" style="color: #cc7832;">new</span> Repository();
repo.save(<span class="hljs-string" style="color: #6a8759;">"house"</span>);
repo.save(<span class="hljs-string" style="color: #6a8759;">"tree"</span>);
repo.save(<span class="hljs-string" style="color: #6a8759;">"boat"</span>);
System.out.println(repo.findAll());
}
}</pre><h3 id="mcetoc_1gb5il12127i">The Challenge</h3><p>So there we have our collection of Strings like house, tree and boat. What if we wanted this repository to be capable of working with virtually any data type there is right now? Currently it can only store strings.</p><h4 id="mcetoc_1gb5il12127j">The bad way</h4><p>One way that we could do it would be to remove the <String> notation in the private List declaration and maybe either just not have any generic type at all. Or similarly, just change <em><String></em> to <em><Object></em>. </p><p>I think those two approaches would be functionally similar to each other, if not identical. So what would be the pros and cons to doing that? Well, one potential con of that approach would be that when we retrieve items using the <em>findById </em>in particular, we would then have to cast them to whatever their actual data type was. That kind of opens us up to some runtime errors if we are making assumptions as to what data type we stored in there.</p><h4 id="mcetoc_1gb5il12127k">There's a better way</h4><p>So the better thing to do would be to make our own classes generic, so we can actually make this repository class generic pretty much exactly the way that the list is set to Type String.</p><p>Note: We can make this for a given instance of the repository. Now this is key for a given instance of the repository. We can only use one data type. So if you want to use another data type you have to use, you have to create another instance of the repository.<br><br>So let's see what that would look like: <span style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);">We use a letter typically to refer to our generic, our generic data type. And the most common letter that you will find when doing this is </span><em style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);">T</em><span style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);"> standing for type. By doing this, we are telling Java that this class is generic. We must use this </span><em style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);">T</em><span style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);"> in various key places now.</span></p><p>All we need to do is replacing each <span style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);">String declaration or Type with the Letter <em>T:</em></span></p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">import</span> java.util.ArrayList;
<span class="hljs-keyword" style="color: #cc7832;">import</span> java.util.List;
<span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">class</span> <span class="hljs-title" style="color: #ffc66d;">RepositoryGeneric</span><<span class="hljs-title" style="color: #ffc66d;">T</span>> </span>{
<span class="hljs-keyword" style="color: #cc7832;">private</span> List<T> records = <span class="hljs-keyword" style="color: #cc7832;">new</span> ArrayList<>();
<span class="hljs-function">List<T> <span class="hljs-title" style="color: #ffc66d;">findAll</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword" style="color: #cc7832;">return</span> records;
}
<span class="hljs-function">T <span class="hljs-title" style="color: #ffc66d;">save</span><span class="hljs-params">(T record)</span> </span>{
records.add(record);
<span class="hljs-keyword" style="color: #cc7832;">return</span> record;
}
<span class="hljs-function">T <span class="hljs-title" style="color: #ffc66d;">findById</span><span class="hljs-params">(<span class="hljs-keyword" style="color: #cc7832;">long</span> id)</span> </span>{
<span class="hljs-keyword" style="color: #cc7832;">return</span> records.get(Long.valueOf(id).intValue());
}
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-keyword" style="color: #cc7832;">static</span> <span class="hljs-keyword" style="color: #cc7832;">void</span> <span class="hljs-title" style="color: #ffc66d;">main</span><span class="hljs-params">(String[] args)</span> </span>{
RepositoryGeneric repo = <span class="hljs-keyword" style="color: #cc7832;">new</span> RepositoryGeneric();
repo.save(<span class="hljs-string" style="color: #6a8759;">"house"</span>);
repo.save(<span class="hljs-string" style="color: #6a8759;">"tree"</span>);
repo.save(<span class="hljs-string" style="color: #6a8759;">"boat"</span>);
System.out.println(repo.findAll());
}
}
</pre><p>It still works. Nothing broke. Why? Because Java is replacing <em><T></em> with <em><Object></em>. 🤣</p><p>If we want this repository instance to be truly generic, however, we can go ahead and do that. All we need to do is defining a repository of string like so:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"> RepositoryGeneric<String> repo = <span class="hljs-keyword" style="color: #cc7832;">new</span> RepositoryGeneric<>();</pre><p>Now we're creating a repository of string. Obviously, this isn't bringing a whole lot of value in this particular example where we were already working with string, right?<br><br>But what if we also have a record Class that models a Person:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"> <span class="hljs-function">record <span class="hljs-title" style="color: #ffc66d;">Person</span><span class="hljs-params">(String fristName, String lastName)</span></span>{};</pre><p>Lets create another instance of a repository now, but this one will work for person instances, we call it <em>pRepo</em>. If I try to add a String like in the <em>"house"</em> in the existing Repo, I'm getting an error now, and if I hover over this, it's basically just telling me that, I'm trying to supply a string, but I'm really expecting a person:</p><figure class="post__image"><img loading="lazy" src="https://www.finecloud.ch/media/posts/58/Screenshot-2022-08-23-at-14.27.30.png" alt="" width="669" height="325" sizes="100vw" srcset="https://www.finecloud.ch/media/posts/58/responsive/Screenshot-2022-08-23-at-14.27.30-xs.png 300w, https://www.finecloud.ch/media/posts/58/responsive/Screenshot-2022-08-23-at-14.27.30-sm.png 480w, https://www.finecloud.ch/media/posts/58/responsive/Screenshot-2022-08-23-at-14.27.30-md.png 768w, https://www.finecloud.ch/media/posts/58/responsive/Screenshot-2022-08-23-at-14.27.30-lg.png 1024w, https://www.finecloud.ch/media/posts/58/responsive/Screenshot-2022-08-23-at-14.27.30-xl.png 1360w, https://www.finecloud.ch/media/posts/58/responsive/Screenshot-2022-08-23-at-14.27.30-2xl.png 1600w"></figure><p>So therefore, whatever I pass in here has to be a person. If we change this and add new Person's everything works, no matter if we have a Repo of Strings or a Repo of Persons:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">import</span> java.util.ArrayList;
<span class="hljs-keyword" style="color: #cc7832;">import</span> java.util.List;
<span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">class</span> <span class="hljs-title" style="color: #ffc66d;">RepositoryGeneric</span><<span class="hljs-title" style="color: #ffc66d;">T</span>> </span>{
<span class="hljs-function">record <span class="hljs-title" style="color: #ffc66d;">Person</span><span class="hljs-params">(String fristName, String lastName)</span></span>{};
<span class="hljs-keyword" style="color: #cc7832;">private</span> List<T> records = <span class="hljs-keyword" style="color: #cc7832;">new</span> ArrayList<>();
<span class="hljs-function">List<T> <span class="hljs-title" style="color: #ffc66d;">findAll</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword" style="color: #cc7832;">return</span> records;
}
<span class="hljs-function">T <span class="hljs-title" style="color: #ffc66d;">save</span><span class="hljs-params">(T record)</span> </span>{
records.add(record);
<span class="hljs-keyword" style="color: #cc7832;">return</span> record;
}
<span class="hljs-function">T <span class="hljs-title" style="color: #ffc66d;">findById</span><span class="hljs-params">(<span class="hljs-keyword" style="color: #cc7832;">long</span> id)</span> </span>{
<span class="hljs-keyword" style="color: #cc7832;">return</span> records.get(Long.valueOf(id).intValue());
}
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-keyword" style="color: #cc7832;">static</span> <span class="hljs-keyword" style="color: #cc7832;">void</span> <span class="hljs-title" style="color: #ffc66d;">main</span><span class="hljs-params">(String[] args)</span> </span>{
RepositoryGeneric<String> repo = <span class="hljs-keyword" style="color: #cc7832;">new</span> RepositoryGeneric<>();
repo.save(<span class="hljs-string" style="color: #6a8759;">"house"</span>);
repo.save(<span class="hljs-string" style="color: #6a8759;">"tree"</span>);
repo.save(<span class="hljs-string" style="color: #6a8759;">"boat"</span>);
RepositoryGeneric<Person> pRepo = <span class="hljs-keyword" style="color: #cc7832;">new</span> RepositoryGeneric<>();
pRepo.save(<span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-string" style="color: #6a8759;">"Chuck"</span>, <span class="hljs-string" style="color: #6a8759;">"Norris"</span>));
pRepo.save(<span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-string" style="color: #6a8759;">"Max"</span>, <span class="hljs-string" style="color: #6a8759;">"Müller"</span>));
pRepo.save(<span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-string" style="color: #6a8759;">"Hans"</span>, <span class="hljs-string" style="color: #6a8759;">"Wurst"</span>));
System.out.println(repo.findAll());
System.out.println(pRepo.findAll());
}
}
</pre><p>output:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;">[house, tree, boat]
[Person[fristName=Chuck, lastName=Norris], Person[fristName=Max, lastName=Müller], Person[fristName=Hans, lastName=Wurst]]
Process finished with exit code <span class="hljs-number" style="color: #6897bb;">0</span></pre><h4 id="mcetoc_1gb5il12127l">Associate an ID</h4><p>So now that we have the ability to pass in more complex objects like this person class, a very common thing that we will encounter as professional developers using frameworks that implement the repository pattern is that our objects that will interact with the repository typically will have an ID associated with them.</p><p>So let's add an ID property to the person class and execute the program again:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">import</span> java.util.ArrayList;
<span class="hljs-keyword" style="color: #cc7832;">import</span> java.util.List;
<span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">class</span> <span class="hljs-title" style="color: #ffc66d;">RepositoryGeneric</span><<span class="hljs-title" style="color: #ffc66d;">T</span>> </span>{
<span class="hljs-function">record <span class="hljs-title" style="color: #ffc66d;">Person</span><span class="hljs-params">(String fristName, String lastName, Long id)</span></span>{};
<span class="hljs-keyword" style="color: #cc7832;">private</span> List<T> records = <span class="hljs-keyword" style="color: #cc7832;">new</span> ArrayList<>();
<span class="hljs-function">List<T> <span class="hljs-title" style="color: #ffc66d;">findAll</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword" style="color: #cc7832;">return</span> records;
}
<span class="hljs-function">T <span class="hljs-title" style="color: #ffc66d;">save</span><span class="hljs-params">(T record)</span> </span>{
records.add(record);
<span class="hljs-keyword" style="color: #cc7832;">return</span> record;
}
<span class="hljs-function">T <span class="hljs-title" style="color: #ffc66d;">findById</span><span class="hljs-params">(<span class="hljs-keyword" style="color: #cc7832;">long</span> id)</span> </span>{
<span class="hljs-keyword" style="color: #cc7832;">return</span> records.get(Long.valueOf(id).intValue());
}
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-keyword" style="color: #cc7832;">static</span> <span class="hljs-keyword" style="color: #cc7832;">void</span> <span class="hljs-title" style="color: #ffc66d;">main</span><span class="hljs-params">(String[] args)</span> </span>{
RepositoryGeneric<String> repo = <span class="hljs-keyword" style="color: #cc7832;">new</span> RepositoryGeneric<>();
repo.save(<span class="hljs-string" style="color: #6a8759;">"house"</span>);
repo.save(<span class="hljs-string" style="color: #6a8759;">"tree"</span>);
repo.save(<span class="hljs-string" style="color: #6a8759;">"boat"</span>);
RepositoryGeneric<Person> pRepo = <span class="hljs-keyword" style="color: #cc7832;">new</span> RepositoryGeneric<>();
pRepo.save(<span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-string" style="color: #6a8759;">"Chuck"</span>, <span class="hljs-string" style="color: #6a8759;">"Norris"</span>, <span class="hljs-number" style="color: #6897bb;">10L</span>));
pRepo.save(<span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-string" style="color: #6a8759;">"Max"</span>, <span class="hljs-string" style="color: #6a8759;">"Müller"</span>, <span class="hljs-number" style="color: #6897bb;">20L</span>));
pRepo.save(<span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-string" style="color: #6a8759;">"Hans"</span>, <span class="hljs-string" style="color: #6a8759;">"Wurst"</span>, <span class="hljs-number" style="color: #6897bb;">30L</span>));
Person foundPerson = pRepo.findById(<span class="hljs-number" style="color: #6897bb;">30L</span>);
System.out.println(foundPerson);
System.out.println(repo.findAll());
System.out.println(pRepo.findAll());
}
}
</pre><p>output:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;">Exception in thread <span class="hljs-string" style="color: #6a8759;">"main"</span> java.lang.IndexOutOfBoundsException: Index <span class="hljs-number" style="color: #6897bb;">30</span> out of bounds <span class="hljs-keyword" style="color: #cc7832;">for</span> length <span class="hljs-number" style="color: #6897bb;">3</span>
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:<span class="hljs-number" style="color: #6897bb;">64</span>)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:<span class="hljs-number" style="color: #6897bb;">70</span>)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:<span class="hljs-number" style="color: #6897bb;">266</span>)
at java.base/java.util.Objects.checkIndex(Objects.java:<span class="hljs-number" style="color: #6897bb;">359</span>)
at java.base/java.util.ArrayList.get(ArrayList.java:<span class="hljs-number" style="color: #6897bb;">427</span>)
at section11_loose_ends.datastore.RepositoryGeneric.findById(RepositoryGeneric.java:<span class="hljs-number" style="color: #6897bb;">20</span>)
at section11_loose_ends.datastore.RepositoryGeneric.main(RepositoryGeneric.java:<span class="hljs-number" style="color: #6897bb;">34</span>)
Process finished with exit code <span class="hljs-number" style="color: #6897bb;">1</span></pre><p>Wow - we got an index out of bounds exception because we ask for Item 30 and there's only three items in here. This is because we implemented <em>findById</em> very simplistic.</p><p>But we can not just change <em>finyById</em> to grab the Persons ID, because to allow this we would need to hardcode the Type to Person, which would not bring us more than when we initially had the hardcoded List Type of String.</p><h4 id="mcetoc_1gb5imo5327n">Implement a Get ID method</h4><p>We could introduce an interface that implements a Get ID method like this:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">interface</span> <span class="hljs-title" style="color: #ffc66d;">IDable</span><<span class="hljs-title" style="color: #ffc66d;">T</span>> </span>{
<span class="hljs-function">T <span class="hljs-title" style="color: #ffc66d;">id</span><span class="hljs-params">()</span></span>;
}</pre><p>To ensure that <em>T</em> needs to be something that implements the <em>IDable</em> interface, I can now come up here and constrain our class a little bit, like so:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">class</span> <span class="hljs-title" style="color: #ffc66d;">RepositoryGeneric</span><<span class="hljs-title" style="color: #ffc66d;">T</span> <span class="hljs-keyword" style="color: #cc7832;">extends</span> <span class="hljs-title" style="color: #ffc66d;">RepositoryGeneric</span>.<span class="hljs-title" style="color: #ffc66d;">IDable</span>> </span>{</pre><p>Now our <em>IDable</em> interface is itself generic, and that means that we could pass in a generic type here as well. But the question would be, what should we pass in? The answer is that up here, we don't have to actually decide a specific data type. We can leave it generic. And this brings us to another little lesson that I want to point out, which is when we are creating generic classes are generic classes or interfaces, whatever. Our generic types can have more than one parameter. So right now, our our repository class has just one parameter, one generic parameter, which is <em>T</em>, but we can actually have multiple generic parameters. And in fact, some of the functional interfaces do in fact, work with two or even three parameters. Like any of the functional interfaces that are called by or binary or something like that, frequently they're going to take at least two parameters, right? So we can add another parameter to the repository class, and that parameter will be used to specify what the data type is for our IDs.<br><br>So the way we can do that is I'm going to put a comma here and then I'm going to introduce another parameter and I will call this V. We can call it whatever we want:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">class</span> <span class="hljs-title" style="color: #ffc66d;">RepositoryGeneric_v2</span><<span class="hljs-title" style="color: #ffc66d;">T</span> <span class="hljs-keyword" style="color: #cc7832;">extends</span> <span class="hljs-title" style="color: #ffc66d;">RepositoryGeneric_v2</span>.<span class="hljs-title" style="color: #ffc66d;">IDable</span><<span class="hljs-title" style="color: #ffc66d;">V</span>>, <span class="hljs-title" style="color: #ffc66d;">V</span>> </span>{</pre><p>Note that person is not a class and string are not classes that extend from <em>IDable</em>.<br>Now I can tell you now we're never going to make it happy for string, and that's by design. We're done with string, so I'm going to go ahead and delete all String Stuff. That's never going to work because we didn't write the string class, nor would I care for it to work anyway. But the person class we can do something about.</p><h4 id="mcetoc_1gb5l3vod2g2">Implement <em>IDable</em> in person class</h4><p><br>And so it is appropriate and correct to actually go ahead and state the actual type that we want tied to this interface here as being type long. This interface, when used in the context of the person class, will have an ID method that is actually showing up as a returning type long:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-function">record <span class="hljs-title" style="color: #ffc66d;">Person</span><span class="hljs-params">(String fristName, String lastName, Long id)</span> implements IDable<Long></span>{};</pre><p>So now that we've done that, let's come back down to the Person Repo, here we need to pass another argument, since we need two type arguments now. And that makes sense because we now are saying that to create a repository, you need to pass in T and you also have to pass in the right type of IDs. In this case it's long.</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"> RepositoryGeneric_v2<Person, Long> pRepo = <span class="hljs-keyword" style="color: #cc7832;">new</span> RepositoryGeneric_v2<>();</pre><p>Lets summarize what we've achieved so far:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">import</span> java.util.ArrayList;
<span class="hljs-keyword" style="color: #cc7832;">import</span> java.util.List;
<span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">class</span> <span class="hljs-title" style="color: #ffc66d;">RepositoryGeneric_v2</span><<span class="hljs-title" style="color: #ffc66d;">T</span> <span class="hljs-keyword" style="color: #cc7832;">extends</span> <span class="hljs-title" style="color: #ffc66d;">RepositoryGeneric_v2</span>.<span class="hljs-title" style="color: #ffc66d;">IDable</span><<span class="hljs-title" style="color: #ffc66d;">V</span>>, <span class="hljs-title" style="color: #ffc66d;">V</span>> </span>{
<span class="hljs-function">record <span class="hljs-title" style="color: #ffc66d;">Person</span><span class="hljs-params">(String fristName, String lastName, Long id)</span> implements IDable<Long></span>{};
<span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">interface</span> <span class="hljs-title" style="color: #ffc66d;">IDable</span><<span class="hljs-title" style="color: #ffc66d;">U</span>> </span>{
<span class="hljs-function">U <span class="hljs-title" style="color: #ffc66d;">id</span><span class="hljs-params">()</span></span>;
}
<span class="hljs-keyword" style="color: #cc7832;">private</span> List<T> records = <span class="hljs-keyword" style="color: #cc7832;">new</span> ArrayList<>();
<span class="hljs-function">List<T> <span class="hljs-title" style="color: #ffc66d;">findAll</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword" style="color: #cc7832;">return</span> records;
}
<span class="hljs-function">T <span class="hljs-title" style="color: #ffc66d;">save</span><span class="hljs-params">(T record)</span> </span>{
records.add(record);
<span class="hljs-keyword" style="color: #cc7832;">return</span> record;
}
<span class="hljs-function">T <span class="hljs-title" style="color: #ffc66d;">findById</span><span class="hljs-params">(<span class="hljs-keyword" style="color: #cc7832;">long</span> id)</span> </span>{
<span class="hljs-keyword" style="color: #cc7832;">return</span> records.stream().filter(p -> p.id().equals(id)).findFirst().orElseThrow();
}
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-keyword" style="color: #cc7832;">static</span> <span class="hljs-keyword" style="color: #cc7832;">void</span> <span class="hljs-title" style="color: #ffc66d;">main</span><span class="hljs-params">(String[] args)</span> </span>{
RepositoryGeneric_v2<Person, Long> pRepo = <span class="hljs-keyword" style="color: #cc7832;">new</span> RepositoryGeneric_v2<>();
pRepo.save(<span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-string" style="color: #6a8759;">"Chuck"</span>, <span class="hljs-string" style="color: #6a8759;">"Norris"</span>, <span class="hljs-number" style="color: #6897bb;">10L</span>));
pRepo.save(<span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-string" style="color: #6a8759;">"Max"</span>, <span class="hljs-string" style="color: #6a8759;">"Müller"</span>, <span class="hljs-number" style="color: #6897bb;">20L</span>));
pRepo.save(<span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-string" style="color: #6a8759;">"Hans"</span>, <span class="hljs-string" style="color: #6a8759;">"Wurst"</span>, <span class="hljs-number" style="color: #6897bb;">30L</span>));
Person foundPerson = pRepo.findById(<span class="hljs-number" style="color: #6897bb;">30L</span>);
System.out.println(foundPerson);
<span class="hljs-comment" style="color: grey;">// System.out.println(pRepo.findAll());</span>
}
}
</pre><p>output: </p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;">Person[fristName=Hans, lastName=Wurst, id=<span class="hljs-number" style="color: #6897bb;">30</span>]
Process finished with exit code <span class="hljs-number" style="color: #6897bb;">0</span></pre><h3 id="mcetoc_1gb5l3vod2g3">Use generics on static methods</h3><p>So we're going to create a static method that honestly isn't going to really have anything to do with this existing class. We're going to make a static method that is going to simulate the ability to encode data. So you're going to pass in some data of a type. And then this method will return an encrypted representation of that data. Now, we're not really going to make any real encryption stuff here. This will be fake. But this will allow us to see how we can make generic static methods, which actually can be quite useful at times:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"> <span class="hljs-keyword" style="color: #cc7832;">static</span> <T,V> <span class="hljs-function">V <span class="hljs-title" style="color: #ffc66d;">encrypt</span><span class="hljs-params">(T data, Function<T, V> func)</span> </span>{
<span class="hljs-keyword" style="color: #cc7832;">return</span> func.apply(data);
}</pre><p>Important to note: The generic type <em>T </em>on the static method has nothing to do with the generic types that may exist on their enclosing class.</p><p>This allows us to make things like this:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"> System.out.println(RepositoryGeneric_v3.<String, String>encrypt(<span class="hljs-string" style="color: #6a8759;">"Hello"</span>, m -> m.toUpperCase()));
System.out.println(RepositoryGeneric_v3.<String, Integer>encrypt(<span class="hljs-string" style="color: #6a8759;">"Test"</span>, m -> m.hashCode()));</pre><p>output:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;">HELLO
<span class="hljs-number" style="color: #6897bb;">2603186</span>
Process finished with exit code <span class="hljs-number" style="color: #6897bb;">0</span></pre><p> </p></div><footer class="wrapper post__footer"><p class="post__last-updated">This article was updated on August 23, 2022</p><ul class="post__tag"><li><a href="https://www.finecloud.ch/tags/generics/">generics</a></li><li><a href="https://www.finecloud.ch/tags/java/">java</a></li><li><a href="https://www.finecloud.ch/tags/java-basics/">java basics</a></li><li><a href="https://www.finecloud.ch/tags/softwareentwicklung/">software development</a></li></ul><div class="post__share"></div></footer></article><nav class="post__nav"><div class="post__nav-inner"><div class="post__nav-prev"><svg width="1.041em" height="0.416em" aria-hidden="true"><use xlink:href="https://www.finecloud.ch/assets/svg/svg-map.svg#arrow-prev"/></svg> <a href="https://www.finecloud.ch/java-exceptions.html" class="post__nav-link" rel="prev"><span>Previous</span> Java basics: Exceptions</a></div><div class="post__nav-next"><a href="https://www.finecloud.ch/java-basics-optionals.html" class="post__nav-link" rel="next"><span>Next</span> Java basics: Optionals </a><svg width="1.041em" height="0.416em" aria-hidden="true"><use xlink:href="https://www.finecloud.ch/assets/svg/svg-map.svg#arrow-next"/></svg></div></div></nav><div class="post__related related"><div class="wrapper"><h2 class="h5 related__title">You should also read:</h2><article class="related__item"><div class="feed__meta"><time datetime="2022-05-26T14:07" class="feed__date">Mai 26, 2022</time></div><h3 class="h1"><a href="https://www.finecloud.ch/java-collection-iteratoren.html">Java Collection Iteratoren</a></h3></article><article class="related__item"><div class="feed__meta"><time datetime="2022-05-26T13:28" class="feed__date">Mai 26, 2022</time></div><h3 class="h1"><a href="https://www.finecloud.ch/java-collection-sets.html">Java Collection Sets</a></h3></article><article class="related__item"><div class="feed__meta"><time datetime="2022-05-26T13:19" class="feed__date">Mai 26, 2022</time></div><h3 class="h1"><a href="https://www.finecloud.ch/java-collection-listen.html">Java Collection Listen</a></h3></article></div></div></main><footer class="footer"><div class="footer__copyright"><p>Powered by Publii</p></div><button onclick="backToTopFunction()" id="backToTop" class="footer__bttop" aria-label="Back to top" title="Back to top"><svg><use xlink:href="https://www.finecloud.ch/assets/svg/svg-map.svg#toparrow"/></svg></button></footer></div><script>window.publiiThemeMenuConfig = {
mobileMenuMode: 'sidebar',
animationSpeed: 300,
submenuWidth: 'auto',
doubleClickTime: 500,
mobileMenuExpandableSubmenus: true,
relatedContainerForOverlayMenuSelector: '.top',
};</script><script defer="defer" src="https://www.finecloud.ch/assets/js/scripts.min.js?v=6ca8b60e6534a3888de1205e82df8528"></script><script>var images = document.querySelectorAll('img[loading]');
for (var i = 0; i < images.length; i++) {
if (images[i].complete) {
images[i].classList.add('is-loaded');
} else {
images[i].addEventListener('load', function () {
this.classList.add('is-loaded');
}, false);
}
}</script><script defer="defer" src="https://www.finecloud.ch/media/plugins/syntaxHighlighter/prism.js"></script></body></html>