We all have seen and used annotations in Java. To be honest I have never before created my own annotation. From now on, when the opportunity arises, I will make sure to start adding my own annotations. To read more about the subject at hand, take a look at this page in Wikipedia.
To get a more in depth definition, you might look into this tutorial and the Oracle Java docs.
Hacker Rank has a code segment that is quite useful to solve the challenge. The code segment follows:
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @interface FamilyBudget { String userRole() default "GUEST"; } class FamilyMember { public void seniorMember(int budget, int moneySpend) { System.out.println("Senior Member"); System.out.println("Spend: " + moneySpend); System.out.println("Budget Left: " + (budget - moneySpend)); } public void juniorUser(int budget, int moneySpend) { System.out.println("Junior Member"); System.out.println("Spend: " + moneySpend); System.out.println("Budget Left: " + (budget - moneySpend)); } } public class Solution { public static void main(String[] args) { Scanner in = new Scanner(System.in); int testCases = Integer.parseInt(in.nextLine()); while (testCases > 0) { String role = in.next(); int spend = in.nextInt(); try { Class annotatedClass = FamilyMember.class; Method[] methods = annotatedClass.getMethods(); for (Method method : methods) { if (method.isAnnotationPresent(FamilyBudget.class)) { FamilyBudget family = method .getAnnotation(FamilyBudget.class); String userRole = family.userRole(); int budgetLimit = family.budgetLimit(); if (userRole.equals(role)) { if(spend<=budgetLimit){ method.invoke(FamilyMember.class.newInstance(), budgetLimit, spend); }else{ System.out.println("Budget Limit Over"); } } } } } catch (Exception e) { e.printStackTrace(); } testCases--; } } }
In the @interface for FamilyBudget the userRole() and default has been defined. What has not been define is a way to define the amount each family member has been allowed. By looking at the sample test case, seems like a SENIOR has access to $100 and a JUNIOR to $50. We need to find a way to make such values available. It seems that the available funds are passed via a variable named budgetLimit.
For the FamilyMeber class we need to pass for SENIOR a budgetLimit of $100 and $50 for a JUNIOR.
In the Solution class we get the name for the limit which seems to be budgetLimit and the last change is in the if() statement.
The completed annotation follows:
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @interface FamilyBudget { String userRole() default "GUEST"; int budgetLimit() default 0; }
This code will enable us to associate the UserRole and the MoneySpent.
class FamilyMember { @FamilyBudget(userRole = "SENIOR", budgetLimit = 100) public void seniorMember(int budget, int moneySpend) { System.out.println("Senior Member"); System.out.println("Spend: " + moneySpend); System.out.println("Budget Left: " + (budget - moneySpend)); } @FamilyBudget(userRole = "JUNIOR", budgetLimit = 50) public void juniorUser(int budget, int moneySpend) { System.out.println("Junior Member"); System.out.println("Spend: " + moneySpend); System.out.println("Budget Left: " + (budget - moneySpend)); } }
To put it all together we now look at the edited Solution.
/* * */ public class Solution { /* * */ public static void main(String[] args) { Scanner in = new Scanner(System.in); int testCases = Integer.parseInt(in.nextLine()); // **** **** while (testCases > 0) { // **** get the user role and money spent **** String role = in.next(); int spend = in.nextInt(); // ???? ???? System.out.println("role ==>" + role + "<== spend: " + spend); try { // **** **** Class annotatedClass = FamilyMember.class; // **** list all methods **** Method[] methods = annotatedClass.getMethods(); // **** traverse all methods **** for (Method method : methods) { // **** look for FamilyMember **** if (method.isAnnotationPresent(FamilyBudget.class)) { // ???? ???? System.out.println("method: " + method); // **** **** FamilyBudget family = method.getAnnotation(FamilyBudget.class); // ???? ???? System.out.println("family: " + family); String userRole = family.userRole(); int budgetLimit = family.budgetLimit(); // ???? ???? System.out.println("userRole ==>" + userRole + "<== budgetLimit: " + budgetLimit); // **** check if the roles match **** if (userRole.equals(role)) { if(spend <= budgetLimit) { method.invoke(FamilyMember.class.newInstance(), budgetLimit, spend); } else { System.out.println("Budget Limit Over"); } // ???? ???? System.out.println(); } } } } catch (Exception e) { e.printStackTrace(); } testCases--; } } }
It should be easier to follow with an updated console screen capture:
1 SENIOR 75 role ==>SENIOR<== spend: 75 method: public void FamilyMember.seniorMember(int,int) family: @FamilyBudget(userRole=SENIOR, budgetLimit=100) userRole ==>SENIOR<== budgetLimit: 100 <=== userRole matched role Senior Member Spend: 75 Budget Left: 25 method: public void FamilyMember.juniorUser(int,int) family: @FamilyBudget(userRole=JUNIOR, budgetLimit=50) userRole ==>JUNIOR<== budgetLimit: 50 <=== userRole did NOT match role 1 JUNIOR 45 role ==>JUNIOR<== spend: 45 method: public void FamilyMember.juniorUser(int,int) family: @FamilyBudget(userRole=JUNIOR, budgetLimit=50) userRole ==>JUNIOR<== budgetLimit: 50 <=== userRole matched role Junior Member Spend: 45 Budget Left: 5 method: public void FamilyMember.seniorMember(int,int) family: @FamilyBudget(userRole=SENIOR, budgetLimit=100) userRole ==>SENIOR<== budgetLimit: 100 1 SENIOR 40 role ==>SENIOR<== spend: 40 method: public void FamilyMember.seniorMember(int,int) family: @FamilyBudget(userRole=SENIOR, budgetLimit=100) userRole ==>SENIOR<== budgetLimit: 100 <=== userRole matched role Senior Member Spend: 40 Budget Left: 60 method: public void FamilyMember.juniorUser(int,int) family: @FamilyBudget(userRole=JUNIOR, budgetLimit=50) userRole ==>JUNIOR<== budgetLimit: 50 <=== userRole did NOT match role
My complete solution (with the comments and print statements in the Solution class) can be found in my GitHub repository.
Keep on reading and experimenting, you need both to learn.
If you have comments or questions regarding this or any other post in this blog, or if you need help on a software development project, please do not hesitate and leave a message bellow. Request messages will remain private.
John
Follow me on Twitter: @john_canessa