題目描述

Java註解(annotation)可以用來定義Java的類別或是類別中的元素的中繼資料(metadata)。在編譯階段的時候使用Java註解來指示編譯器建立程式碼的過程。註解其實也可以被用在執行階段的時候,用來取得類別元素們的屬性的內部資料,但實務上幾乎不會這樣做。



可以使用以下程式來替一個類別加入Java註解(annotation)。

@Entity
Class DemoClass{

}

也可以指定一個數值給註解的成員。舉例來說:

@Entity(EntityName="DemoClass")
Class DemoClass{

}

在Java中,已經有幾個內建好的註解,您也可以用以下方式定義您自己的註解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface FamilyBudget {
   String userRole() default "GUEST";
}

在這題目中,我們定義一個如下的FamilyBudget註解,FamilyBudget只擁有一個名為userRole的成員。userRole只接受字串型態的資料,預設的字串為「GUEST」。如果我們在使用FamilyBudget時,沒有定義任何的註解成員,它的成員將會使用預設的值。藉由使用「@Target」,我們可以決定註解能被用在哪裡,如以下的FamilyBudget只能被用在類別內的方法。「@Retention」定義了註解在執行階段是否可以使用。

@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--;
        }
    }
}

在這題目中,我們定義了不完整的FamilyMember註解,把使用者類型和使用者花的錢作為輸入。基於使用者的類型,您必須要去呼叫FamilyMember中適合的方法。如果使用者花的錢超過該使用者類型的預算,要輸出「Budget Limit Over」。

您的任務就是依照上面要求完成FamilyBudget註解和FamilyMember類別。

原題網址

https://www.hackerrank.com/challenges/java-annotations

輸入格式

輸入第一行是一個整數N,範圍在2到102之間(包含2和102),表示測試資料的數量。接下來的每組測試資料,都各有一行字串和整數。字串表示使用者的類型,字串長度為6,都是小寫英文字。整數表示使用者花的錢,範圍在0到2000之間(包含0和2000)。用空格分隔,如下:

UserRole MoneySpend

輸出格式

根據使用者的類型還有預算來輸出,在呼叫到的方法內輸出。如果使用者花的錢超過預算了,就輸出「Budget Limit Over」。

範例輸入

3
SENIOR 75
JUNIOR 45
SENIOR 40

範例輸出

Senior Member
Spend: 75
Budget Left: 25
Junior Member
Spend: 45
Budget Left: 5
Senior Member
Spend: 40
Budget Left: 60

解題概念

先完成FamilyBudget註解,接著將其用於FamilyMember類別內的方法。透過迴圈來取得FamilyMember類別內的Method物件,再使用Method物件的isAnnotationPresent方法來判斷方法是否有存在FamilyBudget註解,接著再取得FamilyBudget註解的物件來取得使用者類型和預算的資料。接著就可以利用輸入的使用者類型和使用者花的錢來決定輸出結果了!

參考答案

import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface FamilyBudget {
   String userRole() default "GUEST";
   int budgetLimit() default 100;
}

class FamilyMember {
   @FamilyBudget(userRole = "SENIOR")
   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));
   }
}

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--;
      }
   }
}