I am working to make a Advent Calendar for Christmas and needed to use a switch statement. My biggest dilemma is the fact that each (daysAway) case opens a new class designed for that day in particular. I am working off of what Google and Stack overflow can provide. I was wondering if there was any other way to compact this?
public void onClick(View v) {
//Calculate the days between (date - 12/7/20)
LocalDate dateBefore = java.time.LocalDate.now();
LocalDate dateAfter = LocalDate.of(2020, Month.DECEMBER, 25);
int daysAway = (int) ChronoUnit.DAYS.between(dateBefore, dateAfter);
switch(daysAway){
case 24:
openDay1();
break;
case 23:
openDay2();
break;
case 22:
openDay3;
break;
case 21:
openDay4;
break;
case 20:
openDay5;
break;
case 19:
openDay6;
break;
case 18:
openDay7;
break;
case 17:
openDay8;
break;
case 16:
openDay9;
break;
case 15:
openDay10;
break;
case 14:
openDay11;
break;
case 13:
openDay12;
break;
case 12:
openDay13;
break;
case 11:
openDay14;
break;
case 10:
openDay15;
break;
case 9:
openDay16;
break;
case 8:
openDay17;
break;
case 7:
openDay18;
break;
case 6:
openDay19;
break;
case 5:
openDay20;
break;
case 4:
openDay21;
break;
case 3:
openDay22;
break;
case 2:
openDay23;
break;
case 1:
openDay24;
break;
case 0:
openChristmas;
break;
default:
notTime.start();
break;
}
}
I know it is a giant mess and that is what I am trying to fix! I appreciate any feedback you can give!
Advertisement
Answer
Use Java 14 switch expression syntax:
switch (daysAway) { case 24 -> openDay1(); case 23 -> openDay2(); case 22 -> openDay3(); case 21 -> openDay4(); // ... case 4 -> openDay21(); case 3 -> openDay22(); case 2 -> openDay23(); case 1 -> openDay24(); case 0 -> openChristmas(); default -> notTime.start(); }Since the code is very simple, just collapse it on one line:
switch (daysAway) { case 24: openDay1(); break; case 23: openDay2(); break; case 22: openDay3(); break; case 21: openDay4(); break; // ... case 4: openDay21(); break; case 3: openDay22(); break; case 2: openDay23(); break; case 1: openDay24(); break; case 0: openChristmas(); break; default: notTime.start(); }Use an array of Java 8 method references (notice reversed order):
Runnable[] OPEN_METHODS = { this::openChristmas, this::openDay24, this::openDay23, this::openDay22, this::openDay21, // ... this::openDay4, this::openDay3, this::openDay2, this::openDay1 };if (daysAway >= 0 && daysAway <= 24) { OPEN_METHODS[daysAway].run(); } else { notTime.start(); }Since you said that “each (daysAway) case opens a new class designed for that day”, use an interface (e.g.
Runnable) and an array of class literals:Class<?>[] OPEN_CLASSES = { OpenChristmas.class, OpenDay24.class, OpenDay23.class, OpenDay22.class, OpenDay21.class, // ... OpenDay4.class, OpenDay3.class, OpenDay2.class, OpenDay1.class };if (daysAway < 0 || daysAway > 24) { notTime.start(); } else { Runnable clazz; try { clazz = (Runnable) OPEN_CLASSES[daysAway].getConstructor().newInstance(); } catch (ReflectiveOperationException e) { throw new AssertionError("Oops: " + e, e); } clazz.run(); }You can also build the class name dynamically (no array or
switchstatement):if (daysAway < 0 || daysAway > 24) { notTime.start(); } else { String className = (daysAway == 0 ? "OpenChristmas" : "OpenDay" + (25 - daysAway)); Runnable clazz; try { clazz = (Runnable) Class.forName(className).getConstructor().newInstance(); } catch (ReflectiveOperationException e) { throw new AssertionError("Oops: " + e, e); } clazz.run(); }