Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialjames white
78,399 PointsFinal challenge - stuck on last two tasks..
I have obviously missed something I was supposed to have grasped...
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Test {
int num() default 1;
boolean enabled() default true;
String stringy() default "stupid";
}
public class SocialNetworkTest {
@Test(num = 2)
public void testTweet() {
}
@Test(enabled = false)
public void testInsta() {
}
@Test(stringy = "something")
public void testFacebook() {
}
public void testPinterest() {
}
public void testSnapchat() {
}
}
public class TestAnalyzer {
/**
* Counts the number of methods in the class given by `clazz` that have been annotated
* with the @Test annotation.
*/
public static int getNumAnnotatedMethods(Class<?> clazz) {
return 0;
}
}
The code to 'Test.java' gets past the first two challenges.
The @Test lines of code added to 'SocialNetworkTest.java' just gives me:
Bummer! It appears that at least one of your annotations either omits one of your defined elements in the @Test annotation or has used the same value as the default.
The Preview screen showing output.txt shows no compile errors so the java code is good --just not what the answer analyzer is looking for..
Hmmmm..?
Well, since neither the "using-reflection-on-our-annotation" video or
the final zip download file seems to have an example of
defining custom annotation elements and then using them without default values
I found/followed theses examples:
http://www.mkyong.com/java/java-custom-annotations-example/
http://softwarecave.org/2014/05/02/custom-annotations-in-java/
So, okay, here's another permutation (based on that last example).
What if it wants both elements defined in Test.java to show non-default elements?
So I changed the two sets of code
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Test {
int num() default 1;
boolean enabled() default true;
}
public class SocialNetworkTest {
@Test(num = 2, enabled = false)
public void testTweet() {
}
@Test(num = 4, enabled = false)
public void testInsta() {
}
@Test(num = 5, enabled = false)
public void testFacebook() {
}
public void testPinterest() {
}
public void testSnapchat() {
}
}
...and lo and behold, the Bummer is gone.
Don't really understand why, but it works?!
On to task 4 of 4.
import java.lang.reflect.Method;
public class TestAnalyzer {
/**
* Counts the number of methods in the class given by `clazz` that have been annotated
* with the @Test annotation.
*/
public static int getNumAnnotatedMethods(Class<?> clazz) {
int count = 0;
for (Method m : clazz.getMethods()) {
//if (m.hasAnnotation()) {
count++;
//}
}
return count;
}
}
This gives:
Bummer! Your method is not returning the correct number. Do you have a loop that iterates over the declared methods of
clazz
, keeping a count of the ones wherehasAnnotation
is true?
However (and this is a big thing): no compiler errors in the Preview output.txt (Yeah!)
If I get rid of the commenting it gives:
Bummer! Oops, there is a compiler error! Don't forget to add import statements for any outside classes you're using.
./TestAnalyzer.java:11: error: cannot find symbol
if (m.hasAnnotation()) {
^
symbol: method hasAnnotation()
location: variable m of type Method
1 error
Also tried changing things to:
import java.lang.reflect.Method;
public class TestAnalyzer {
/**
* Counts the number of methods in the class given by `clazz` that have been annotated
* with the @Test annotation.
*/
public static int getNumAnnotatedMethods(Class<?> clazz, Class<?> annotation) {
int count = 0;
for (Method m : clazz.getMethods()) {
if (m.hasAnnotation(annotation)) {
count++;
}
}
return count;
}
}
..but it just gives me another compiler error:
JavaTester.java:203: error: method getNumAnnotatedMethods in class TestAnalyzer cannot be applied to given types;
int actual = TestAnalyzer.getNumAnnotatedMethods(sampleClass);
^
required: Class,Class
found: Class
reason: actual and formal argument lists differ in length
./TestAnalyzer.java:11: error: cannot find symbol
if (m.hasAnnotation(annotation)) {
^
symbol: method hasAnnotation(Class)
location: variable m of type Method
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ?
2 errors
So is it really another import statement that is missing or the wrong way code for testing hasAnnotation?
Who knows..time to give up for now and go to sleep..zzzzzzz
7 Answers
james white
78,399 PointsFrom the last output.html above I felt I was getting close.
Played with it for another hour and finally came up with:
import java.lang.reflect.Method;
public class TestAnalyzer {
/**
* Counts the number of methods in the class given by `clazz` that have been annotated
* with the @Test annotation.
*/
public static int getNumAnnotatedMethods(Class<?> clazz) {
int count = 0;
for (Method m : clazz.getMethods()) {
if (m.isAnnotationPresent(Test.class)) {
count++;
}
}
return count;
}
}
Did I learn anything - absolutely not.
It was pure brute force trial and error that came up with the code that passed!
james white
78,399 PointsHi Chris, Thanks for correcting the misleading error message.
I'm sure I'm not the only only that got confused by the referencing of a hasAnnotation method.
As regard the specific "method signature" needed, I'm not sure what you mean..
I guess I will have to do some more research latter to come to an understanding of just exactly why I wouldn't be able get it to pass just by adding a Class parameter to getNumAnnotatedMethods.
I also noticed that at this point in time there aren't many forum threads that have been started for this course yet.
Maybe people are still working through it or haven't even had time to start the course yet (with all other content TeamTreehouse provides).
I guess I'll wait a while to see if anyone else was confused by (or stuck on) the last task of the last challenge.
EDIT (later):
Have to go to work, but spent a few minutes researching 'isAnnotationPresent'
.
Of course because the course has no .srt video transcipt file it's pretty much impossible
to search the videos for this term using Google search,
so here's some semi-random non-Treehouse-video related results:
http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/AnnotatedElement.html
http://www.tutorialspoint.com/java/lang/package_isannotationpresent.htm
http://www.coderanch.com/t/513044/java/java/isAnnotationPresent-returning-false
https://keyholesoftware.com/2014/09/15/java-annotations-using-reflection/
https://www.altamiracorp.com/blog/employee-posts/inheriting-annotations-on-java
http://isagoksu.com/2009/creating-custom-annotations-and-making-use-of-them/
http://codereview.stackexchange.com/questions/42332/model-simulation-using-java-annotations
Of course none of these give an example of using 'isAnnotationPresent' in a loop
with count ++ as well as an If test.
Found this github code which had several examples of using 'isAnnotationPresent' in different ways (which was very valuable):
Digging thru that karuradev github, this particular code snippet was the most interesting (for its simplicity -- although the 'SupportJavascriptInterface.class' is probably doing most of the "heavy lifting" here):
@SuppressLint("NewApi")
private int signatureCount(Class<?> clazz) {
int count = 0;
for (Method method : clazz.getDeclaredMethods()) {
if (!method.isAnnotationPresent(SupportJavascriptInterface.class)) {
continue;
}
count++;
}
return count;
}
Lastly (from a satisficing heuristic result possibly the most relevant example), I found this stackoverflow thread:
http://stackoverflow.com/questions/1833533/java-reflection-count-of-methods-with-an-annotation
..which had this code:
public class AnnotationUtils {
public static int countMethodsWithAnnotation(Class<?> klass,
Class<?> annotation) {
int count = 0;
for (Method m : klass.getMethods()) {
if (m.isAnnotationPresent(annotation)) {
count++;
}
}
return count;
}
// Other methods for custom annotation processing
}
Similar type code found at the bottom of this stackoverflow thread:
http://stackoverflow.com/questions/2685404/how-to-get-number-of-attributes-in-a-java-class
.
Will have to fool around though (using all of the above) to develop a challenge solution, later...
incredibly INCREDIBLY tedious --but I went through the last reflection video second by second:
03:03 If method.isAnnotationPresent(Doc.class)) {
03:48 Doc doc = method.getAnnotation(Doc.class);
04:38 int annotated ParamCount = doc.params().length;
Of course this helps me not-at-all in answering task 4 of 4 because there is no reference to 'doc'.
Truly a bummer (and very frustrating), it's almost like this final challenge
had absolutely nothing to do with the code that was presented in this course.
Tobias Mahnert
89,414 PointsJM this line of code if (m.isAnnotationPresent())
needs to be
if (m.isAnnotationPresent(Test.class))
Chris Ramacciotti
Treehouse Guest TeacherHi James,
Thank you for your feedback. As for the first of the two tasks you were having difficulty with, yes, it was intended that you specify non-default values for each of the two elements you included in your annotation definition. Looks like you arrived at the solution, so nicely done there.
As for the one you're stuck on - I apologize. There was a misleading error message that I've corrected. The error message references a hasAnnotation
method. This is incorrect. The method name, as used in the videos, is isAnnotationPresent
. When you use that method, don't forget to pass the Class
object of the Test
annotation. Also, the tests won't pass by adding a Class
parameter to getNumAnnotatedMethods
since my tests specifically need the provided method signature. Your decision to do this would be a great one in a scenario where you also write the call to your method. Alas, I must call it here. :)
No worries though, you don't need a parameter since you know the value of the Class
that you must pass to the isAnnotationPresent
method. When you wake up from those zzzzzzz's (and I do hope they were good zzzzzzz's), give it a shot.
Araz kuberin
6,199 PointsHello Chris, Why should i pass Test.class and not SocialNetworkTest.class ??? since all the "@Test" is inside SocialNetworkTest.class!!!
james white
78,399 PointsBack at it again...
Here's the current task 4 of 4 code I'm working with:
import java.lang.reflect.Method;
public class TestAnalyzer {
/**
* Counts the number of methods in the class given by `clazz` that have been annotated
* with the @Test annotation.
*/
public static int getNumAnnotatedMethods(Class clazz) {
int count = 0;
for (Method m : clazz.getMethods()) {
if (m.isAnnotationPresent()) {
count++;
}
}
return count;
}
}
When I Preview on this code I get:
Bummer! Oops, there is a compiler error! Don't forget to add import statements for any outside classes you're using. Click Preview to see the exact message
Of course the import statement is there.
The compiler (output.html) error is:
./TestAnalyzer.java:11: error: no suitable method found for isAnnotationPresent(no arguments)
if (m.isAnnotationPresent()) {
^
method AnnotatedElement.isAnnotationPresent(Class) is not applicable
(actual and formal argument lists differ in length)
method AccessibleObject.isAnnotationPresent(Class) is not applicable
(actual and formal argument lists differ in length)
1 error
...also tried:
import java.lang.reflect.Method;
public class TestAnalyzer {
/**
* Counts the number of methods in the class given by `clazz` that have been annotated
* with the @Test annotation.
*/
public static int getNumAnnotatedMethods(Class<?> clazz,
Class<?> annotation) {
int count = 0;
for (Method m : clazz.getMethods()) {
if (m.isAnnotationPresent(annotation)) {
count++;
}
}
return count;
}
}
..which gave the following for output.html:
JavaTester.java:203: error: method getNumAnnotatedMethods in class TestAnalyzer cannot be applied to given types;
int actual = TestAnalyzer.getNumAnnotatedMethods(sampleClass);
^
required: Class,Class
found: Class
reason: actual and formal argument lists differ in length
./TestAnalyzer.java:12: error: no suitable method found for isAnnotationPresent(Class)
if (m.isAnnotationPresent(annotation)) {
^
method AnnotatedElement.isAnnotationPresent(Class) is not applicable
(argument mismatch; Class cannot be converted to Class)
method AccessibleObject.isAnnotationPresent(Class) is not applicable
(argument mismatch; Class cannot be converted to Class)
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ?
2 errors
Also tried this code:
import java.lang.reflect.Method;
public class TestAnalyzer {
/**
* Counts the number of methods in the class given by `clazz` that have been annotated
* with the @Test annotation.
*/
public static int getNumAnnotatedMethods(Class<?> clazz) {
int count = 0;
for (Method m : clazz.getMethods()) {
if (m.isAnnotationPresent(Class)) {
count++;
}
}
return count;
}
}
..which gave the same Bummer! mesage, but a different output.html:
./TestAnalyzer.java:11: error: cannot find symbol
if (m.isAnnotationPresent(Class)) {
^
symbol: variable Class
location: class TestAnalyzer
1 error
Chris Ramacciotti
Treehouse Guest TeacherGlad you're back at it! It looks like your call to m.isAnnotationPresent()
is still missing the required Class
parameter, which is what I referenced a couple times in my last response. Also, the code snippet you scraped from 3:03 is exactly like the one you'll need here, except that you don't want to pass Doc.class
, but rather _____.class
.
In case you're looking for the docs on the isAnnotationPresent
method, here it is:
Though you call this method on a Method
object (kind of meta, I know - but such is the nature of reflection) the method itself is actually inherited from the AccessibleObject
class, which is in the inheritance chain when climbing from the Method
class all the way up to the Object
class. In any case, notice that the isAnnotationPresent
method requires a Class
object as its only parameter.
Try passing a reference to your annotation's class (like the one mentioned at 3:03), and see if it passes. I smell success in your near future.
Araz kuberin
6,199 PointsHello Chris, why passing Test.Class works but not SocialNetworkTest.class??? All the "@Test" is in the SocialNetworkTest.class
Chris Needham
1,871 PointsYeah, the videos didn't really seem to point too much to the last two assignments.... And there's not much coding... it's supposed to be simple but it's too abstractly coded. I hate bizarre code like that.