Using Reflection on Our Annotation9:06 with Chris Ramacciotti
During this final video of the course, we'll use what we learned about reflection to examine the
MathUtils class, checking to see if proper
@Doc annotations have been applied.
Popular Libraries Leveraging Annotations
Java libraries that make heavy use of annotations are seemingly endless. Here are just a few of the most popular ones:
- Spring - writing standard web applications, creating a RESTful API, running batch processes, and more!
- JUnit - create small, repeatable tests that ensure the functionality of your application's individual components
- Hibernate - wire Java objects to databases
- Butter Knife - wire GUI elements from Android views to the code that controls them
If you didn't take the time earlier to scan the logic of this class, go ahead and 0:00 pause the video now and take a peek. 0:03 When you get the gist of it, un-pause and we'll continue. 0:05 Everything that needs to be done is documented with a to do comment, so 0:08 let's jump right in. 0:11 To check if an annotation is present on a class or 0:13 a method, the code is quite simple and intuitive. 0:15 We'll use the class objects, isAnnotationPresent() method. 0:18 So in place of true, I will type clazz. 0:23 I'm gonna call this variable clazz, so 0:27 it's not confused with class, isAnnotationPresent(). 0:30 And I'll press Doc.class. 0:35 So, I tell the class object exactly what annotation I'm looking for. 0:36 Next up is looping over the declared methods of the class object. 0:42 We did this while practicing. 0:45 So here, instead of looping over an empty array, which I have right here, we'll use 0:46 the getDeclaredMethods method to return an array of the classesDeclared methods. 0:52 clazz.getDeclaredMethods(). 0:58 Now, let's get the modifiers the current method. 1:04 This is accomplished with the get modifiers method. 1:07 Remember, this comes back as an int. 1:09 We'll be making more meaningful use of this int in just a moment. 1:11 So in place of this string approach that we took in practicing reflection, 1:14 we're gonna store this as an int. 1:19 int, and I'll call it modifierInt 1:21 = method.getModifiers. 1:27 Getting the method name was also simple and straightforward. 1:31 We use the getName() method. 1:34 So in place of null, method.getName(). 1:36 Now back to those modifiers. 1:41 We need to use what's store in modifierInts to check whether or 1:43 not the private modifier is present. 1:46 We could use the approach we did earlier. 1:48 Convert the int to a modifier string and 1:50 then check to see if that string contains the word private. 1:52 But, there's another method in the Modifier class 1:55 that will get us there one step sooner. 1:58 It's the isPrivate() method, and it's a static method. 2:01 So in place of true I will check to see if the modifier is private and 2:04 I'll pass it the modifierInt that I got back from calling getModifiers() up above. 2:10 Now of course, I want to check to see if the method is non-private, so I'm going to 2:18 negate this boolean value that comes back with the exclamation point. 2:22 I also realized that I'd introduced the Modifier class for 2:26 the first time in this file. 2:29 So let's go to the top and import the modifier class. 2:31 Import jaba.lang.reflect.Modifier. 2:35 Brilliant, scrolling back down, 2:40 next we'll need to check and see if the annotation appears on the method. 2:43 Right here, in place of this true, 2:48 will also call the isAnnotationPresent() on the method. 2:50 So, I'll call method.isAnnotationPresent(). 2:53 Again, past the .class, so it knows which annotation we're actually looking for. 2:59 The next to do is a critical one, and one we haven't practiced yet, but 3:05 it's also really easy. 3:08 This will be the piece of code that gives us access to the actual element values 3:10 on the individually placed annotations. 3:14 That is, we'll be able to read the details of a specific annotation. 3:16 For example, what description was indeed provided? 3:20 Or, how many parameters were actually documented? 3:24 What we need to do is fetch the annotation itself as a doc object, so that we can 3:28 call the interface methods, or elements, that we defined in the annotation. 3:32 To do this, we'll call the methods getAnnotation() method. 3:37 method.getAnnotation(), again specifying which 3:41 annotation it is that we'd like to get. 3:46 The rest of our coding falls into the two methods at the bottom of the class. 3:50 getNumMissingParams(), right here, as well as hasReturnDescription(), 3:53 the last method at the bottom here. 3:58 Let's start with getNumMissingParams(). 4:00 Our first order of business is comparing the number of parameters to 4:04 the number of parameters document. 4:07 We'll first put each piece of information into a variable and 4:09 then use those values in simple comparison. 4:12 So, after these to do comments, I'll create a couple of variables. 4:14 The first one I'm gonna call annotedParamCount. 4:17 This will be the number of parameters that were documented in the annotation itself. 4:21 So, to find that I will say doc.paramas().length. 4:26 Remember, the params element that we declared in the annotation is 4:32 a string array. 4:36 Since it's a string array, we have access to the length property. 4:38 Okay, my next variable I'm going to call actualParamCount. 4:42 This variable will store the actual number of parameters on the method object. 4:47 method.GetParameterCount(). 4:52 Finally, to compare the two values in place of true, 4:57 we'll use those two variable names that we just declared and stored values into. 5:00 So if the annotatedParamCount < actualParamCount 5:05 Then we must have some missing parameters. 5:14 So, how do we calculate that? 5:16 Well, that is simply a subtraction problem between those two values. 5:17 So, numMissing = actualParamCount- annotatedParamCount. 5:21 On to our last method, hasReturnDescription(). 5:31 For this method, we want to return true in two scenarios. 5:35 Either a, the method is a void method, or 5:39 b, the method's annotation has a non-empty return val element. 5:41 Let's write a boolean expression for just that. 5:46 To return true in the first scenario, 5:49 I'll check to see if the method's return type is Void. 5:51 To do this, I'll call the getReturnType() method on the method object, 5:53 getReturnType(), and we'll see if its value equals Void.TYPE. 5:58 In the second scenario, 6:06 we wanna return true when the annotations returnVal element is empty. 6:07 So to check that, we'll say doc.returnVal.isEmpty. 6:13 We wanna check for nonempty returnVals, so 6:19 again, I'll negate that boolean value with the exclamation point. 6:22 At this point we've finished coding the analysis of our annotation. 6:29 One of the cool things here, is that there's nothing that we wrote that is 6:32 specific to the MathUtils class, which means that we can 6:35 use this DocProcessor class to analyze the doc annotation of any class we like. 6:39 Let's test all this code by hopping over to the Main class and 6:44 calling the DocProcessor's, processor method. 6:47 I'll first remove all of our test code that we wrote while we were practicing 6:50 reflection. 6:53 So I'll call DocProcessor.process and pass it MathUtils. 6:56 And we're ready to compile and run. 7:05 So back in our console, I'll compile with javac. 7:08 Specify the out directory as a placement for our class files, set the class 7:12 path as the src directory, and we'll type the file that we wanna compile. 7:17 It looks like we have an error here. 7:30 Let's check it out and see if we can troubleshoot this. 7:31 Looks like I mistyped a variable name in DocProcessor.java on line 109. 7:35 Let's hop over there and correct that error and recompile. 7:40 Line 109 is right here. 7:44 Looks like that should be annotatedParamCount. 7:49 I'll correct that, and let's see if that was our only error. 7:52 It's saying one error in our compiler results. 7:55 So, I'm pretty confident here. 7:57 Recompile. 8:00 Great, I'm gonna clear. 8:04 Give myself a little more room for output. 8:06 And let's run this program. 8:09 I'll set the class path as the out directory and 8:11 let's run com.teamtreehouse.docgen.Main. 8:16 Great, it finds both our sufficient and 8:23 insufficient documentation on the MathUtils class. 8:25 I'll leave fixing the insufficient documentation as an exercise for 8:29 you after this video. 8:32 Now that we've looked at the basics of annotations, 8:35 experimented with the built-in annotations and 8:37 even built one of our own, you're ready to encounter them in the wild. 8:40 I've linked to some resources in the teacher's notes for 8:44 further research, including a few popular libraries that utilize annotations. 8:46 Having trouble with a specific library? 8:52 Be sure to hit up the forums of those libraries, or 8:54 even broader coding forums like StackOverflow. 8:57 Chances are, 9:00 the answer you're looking for is sitting out there waiting for your visit. 9:01 Happy annotating! 9:05
You need to sign up for Treehouse in order to download course files.Sign up