MatthewC
MatthewC

Reputation: 41

Get value of java object variable name

I have 7 boolean variables in a java object for the days of the week (Monday through Sunday). I am trying to find a succinct way from a for loop of a list of days to say the following:

    private boolean isWorkDay(String day, Object pgMasterTaskList) {
        if(day=="Sunday" && pgMasterTaskList.Sunday==true) {
            return true;
        }
        if(day=="Monday" && pgMasterTaskList.Monday==true) {
            return true;
        }
        if(day=="Tuesday" && pgMasterTaskList.Tuesday==true) {
            return true;
        }
        if(day=="Wednesday" && pgMasterTaskList.Wednesday==true) {
            return true;
        }
        if(day=="Thursday" && pgMasterTaskList.Thursday==true) {
            return true;
        }
        if(day=="Friday" && pgMasterTaskList.Friday==true) {
            return true;
        }
        if(day=="Saturday" && pgMasterTaskList.Saturday==true) {
            return true;
        }
        else return false;
    }

I'm hoping I can minimize the repetition with something like...

private boolean isWorkDay(String day, Object pgMasterTaskList) {
        if(pgMasterTaskList.getVariableByName(day)==true) {
            return true;
        }
        else return false;
    }

My thought is to use reflection to check if the value of the variable named "Monday" and so on, but I'm not sure how to use it in such a way.

Edit

I have submitted an answer that works for my specific case. A little more detail...

I'm writing this information out to a pdf so I was handling string comparisons because I have to map them to field names in the pdf. So I was trying to be consistent. ANY combination of days could be a work day. I think this leaves me with 128 combos? (2^7). The information is being fed in by csv so I wanted to read day in as a string since it's coming in as such.

Upvotes: 1

Views: 2019

Answers (5)

Anonymous
Anonymous

Reputation: 86280

If you can modify your task list object to hold a Set of working days rather than 7 Boolean values, you don’t even need a loop. A table lookup in linear time will do.

    DateTimeFormatter dowFormatter = DateTimeFormatter.ofPattern("cccc", Locale.ENGLISH);

    EnumSet<DayOfWeek> workdays = EnumSet
            .of(DayOfWeek.MONDAY, DayOfWeek.TUESDAY, DayOfWeek.THURSDAY);
    String day = "Tuesday";

    DayOfWeek dow = dowFormatter.parse(day, DayOfWeek::from);
    boolean isWorkDay = workdays.contains(dow);

    System.out.println("Is work day? " + isWorkDay);

Output from the example:

Is work day? true

An EnumSet is implemented as an array of Boolean values.

I trust you to fit the EnumSet into your object and wrap the code in a method similar to what you are doing in the question.

The pattern letter c that I am using in the format pattern string used for defining the formatter for day of week is not often used. Frankly I am in doubt whether it is correct to use it here. According to the documentation it gives us the standalone form of the localized day of week text. Since the day of week standa alone — it is not part of a date string — I figured it might be right. If not, use the more common EEEE. At least for English, both work.

Edit: Even though your 7 boolean values come from a CSV file, I would probably still use the set approach. For initializing the set, I don’t think I’d resort to reflection, but accept 7 if statemnts (here condensed more than most of us do in real code):

    boolean sunday = false;
    boolean monday = true;
    boolean tuesday = true;
    boolean wednesday = false;
    boolean thursday = true;
    boolean friday = false;
    boolean saturday = false;

    Set<DayOfWeek> workdays = EnumSet.noneOf(DayOfWeek.class);
    if (sunday) workdays.add(DayOfWeek.SUNDAY);
    if (monday) workdays.add(DayOfWeek.MONDAY);
    if (tuesday) workdays.add(DayOfWeek.TUESDAY);
    if (wednesday) workdays.add(DayOfWeek.WEDNESDAY);
    if (thursday) workdays.add(DayOfWeek.THURSDAY);
    if (friday) workdays.add(DayOfWeek.FRIDAY);
    if (saturday) workdays.add(DayOfWeek.SATURDAY);

    System.out.println(workdays);

[MONDAY, TUESDAY, THURSDAY]

Edit 2:

Here is a simple example of converting a line of Boolean values from a CSV file to an EnumSet<DayOfWeek>.

    String lineFromCsv = "false;true;true;false;true;false;false";

    String[] workDayStrings = lineFromCsv.split(";");
    Set<DayOfWeek> workdays = EnumSet.noneOf(DayOfWeek.class);
    // Sunday
    if (Boolean.valueOf(workDayStrings[0])) {
        workdays.add(DayOfWeek.SUNDAY);
    }
    // Monday through Saturday
    for (int i = 1; i < workDayStrings.length; i++) {
        if (Boolean.valueOf(workDayStrings[i])) {
            workdays.add(DayOfWeek.of(i));
        }
    }
    System.out.println(workdays);

[MONDAY, TUESDAY, THURSDAY]

Link

Upvotes: 2

MatthewC
MatthewC

Reputation: 41

I have found an answer to my question using the following method:

  public static Object getValueOf(Object clazz, String lookingForValue)
      throws Exception {
    Field field = clazz.getClass().getField(lookingForValue);
    Class clazzType = field.getType();
    if (clazzType.toString().equals("double"))
      return field.getDouble(clazz);
    else if (clazzType.toString().equals("int"))
      return field.getInt(clazz);
    // else other type ...
    // and finally
    return field.get(clazz);
  }

I call it as following now:

    private boolean isWorkDay(String day, PlanGridMasterTaskList pgMasterTaskList) throws Exception {
        System.out.println(getValueOf(pgMasterTaskList, day));
        if ((boolean) getValueOf(pgMasterTaskList, day)) {
            return true;
        }
        else
            return false;
    }

I found it at this link: https://www.rgagnon.com/javadetails/java-0038.html

Thank you to everyone who took the time to respond (and so quickly at that!).

Upvotes: 1

QuickSilver
QuickSilver

Reputation: 4045

Try creating an enum and then you method logic would simply look like below,

public class WeekMap {

    public static void main(String[] args) {
        System.out.println(isWorkDay("SUNDAY",WeekDays.SUNDAY));
        System.out.println(isWorkDay("sunday",WeekDays.SUNDAY));
        System.out.println(isWorkDay("sunday",WeekDays.SATURDAY));
        System.out.println(isWorkDay("ABS",WeekDays.SATURDAY));
    }

    private static boolean isWorkDay(String day, WeekDays pgMasterTaskList) {
        WeekDays day1 = WeekDays.valueOf(day.toUpperCase()); // Fetch the mapped day for the string
        try{
            day1 = WeekDays.valueOf(day.toUpperCase());
        } catch (IllegalArgumentException iex) {
            iex.printStackTrace(); // this can be suppress
        }
        return day1 == pgMasterTaskList;
    }
}

enum WeekDays{ // Create enum for week day names
    SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY;
}

Upvotes: 0

AnonymousFox
AnonymousFox

Reputation: 118

You can use the Object class .getClass().getFields() method to fetch all the variables in a class or use specific .getClass().getField("variableName") to fetch a particular variable.

The java reflection api will allow to fetch the variable as a Field (java.lang.reflect)

  private boolean isWorkDay(String day, Object pgMasterTaskList)
      throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
    Object obj = null;
    if (pgMasterTaskList.getClass().getField(day).get(obj).equals(true)) {
      return true;
    } else
      return false;
  }

The line Object obj = null; in above is just a placeholder to fetch of the variable using .get().

However, this will work only when the value for day parameter exactly matches the variable name as defined in pgMasterTaskList class. If you want a fetch based on case-insensitive scenario you can use the .getFields() method. Below is an example for the same:

  private boolean isWorkDay(String day, Object pgMasterTaskList) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
    Object obj = null;
    for (Field field : pgMasterTaskList.getClass().getFields()) {
      if (day.equalsIgnoreCase(field.getName())) {
        obj = field.get(obj);
        if ((boolean) obj == true)
          return true;
      }
    }
    return false;
  }

The .get(obj) will return an object of class type of your variable (your variable was boolean, then return obj will be of type boolean).

Upvotes: 1

Dave
Dave

Reputation: 2049

You must use reflection for this:

private boolean isWorkDay(String day, Object pgMasterTaskList) throws NoSuchFieldException, NullPointerException, SecurityException {
    return pgMasterTaskList.getClass().getField(day);
}

NOTE: callers must handle the cases where they pass a day that's null or just wrong, or the boolean member aren't public.

Upvotes: 0

Related Questions