How to replace switch-case to OOP - java

I have methods with which I get data from a database.
Depending on the variable that the user entered through the console, I must execute the desired method
while (flag) {
try {
sw = new ScannerWrapper();
menuHeader();
int choice = sw.readInt();
switch (choice) {
case 1:
System.out.println("Input first name: ");
String name = sw.readLine().toUpperCase();
printResults(DataParser.getFilmByName(name));
break;
case 0:
System.out.println("Bye-bye. Come again");
flag = false;
break;
default:
System.out.println("Please enter correct number");
}
} catch (Exception e) {
System.out.println("Enter correct data");
} finally {
DBConnector.getInstance().closeConnection();
}
}
This code is very bad.There are more than 5 cases with methods and the code becomes redundant

You should have a look at the Strategy design pattern. That will allow you to abstract the logic related to an action.
On top of that, you want to replace the switch to find the right strategy according to the input variable. That is the job of the Factory design pattern, which in your case would return one of the different strategies according to the database value.
Basically:
interface UserAction {
public void execute();
}
class ListMovies implements UserAction {
public void execute() {
// List the movies
}
}
class ExitProgram implements UserAction {
public void execute() {
// Kill kenny
}
}
class Noop implements UserAction {
public void execute() {
// Do nothing
}
}
And a factory:
class UserActionFactory {
public UserAction make(int actionId) {
switch (actionId) {
0: return new ListMovies();
1: return new ExitProgram();
default: return new Noop();
}
}
}
Which then allows:
UserActionFactory factory = new UserActionFactory();
ScannerWrapper sw = new ScannerWrapper();
while (true) {
menuHeader();
int choice = sw.readInt();
UserAction action = factory.make(choice);
action.execute();
}
This could also be the Command design pattern, depends on how you name things and instantiate objects for the rest of the classes.

Related

Best way execute code according enum value

The following code is an example of my problem.
I would like to simplify the code without having to repeat the call for the same methods, on different switch statements.
public void simulate(String given, Status status) {
switch (status){
case A:
simulateA(given);
break;
case B:
simulateA(given);
simulateB(given);
break;
case C:
simulateA(given);
simulateB(given);
simulateC(given);
break;
}
PS 1: The order of the calling methods matters!
PS 2: I am not looking for another way of doing the switch, I am looking for another way of modelling the problem, maybe using some kind of class composition with the methods.
I do not know the nature of your enum but if you have many simulation calls you could forgo the switch statement and do it like this. But there is nothing wrong with your current approach. This would also change slightly if your methods were static and not instance. The one advantage of this is that it has the potential to scale.
There are many other ways to to this. You could have a list of method references and the enum arguments could be variable arrays of which methods to call by index.
public class Simulations {
static List<BiConsumer<Simulations, String>> sims =
List.of(Simulations::simulateA, Simulations::simulateB,
Simulations::simulateC);
enum Status {
A(1), B(2), C(3);
private int val;
private Status(int v) {
this.val = v;
}
public int getVal() {
return val;
}
}
public static void main(String[] args) {
Simulations simulation = new Simulations();
simulation.simulate("A", Status.A);
System.out.println();
simulation.simulate("B", Status.B);
System.out.println();
simulation.simulate("C", Status.C);
}
public void simulate(String given, Status status) {
for (int i = 0; i < status.getVal(); i++) {
sims.get(i).accept(this, given);
}
}
public void simulateA(String s) {
System.out.println(s);
}
public void simulateB(String s) {
System.out.println(s);
}
public void simulateC(String s) {
System.out.println(s);
}
}
In this case, the order of simulations always cascades "downwards", e.g. Simulating an B is simulating an A plus some extra's. This matches an inheritance pattern, e.g. a Mammal is an Animal with some extras. Thus, letting simulations inherit from each other fixes the pattern:
interface Simulation
{
void simulate( final String given );
}
class ASimulation implements Simulation
{
#Override
public void simulate( String given )
{
// simulate this given!
}
}
class BSimulation extends ASimulation
{
#Override
public void simulate( String given )
{
super.simulate( given );
// simulate this given some more!
}
}
class CSimulation extends BSimulation
{
#Override
public void simulate( String given )
{
super.simulate( given );
// simulate this given even more!
}
}
Note that this is fragile, as all inheritance trees are. Another solution can be achieved with composition and delegation. This is called a chain:
class LeafSimulation
implements Simulation
{
#Override
public void simulate( String given )
{
// simulate this given!
}
}
class ChainedSimulation
implements Simulation
{
private final Simulation delegate;
ChainedSimulation( final Simulation delegate )
{
this.delegate = delegate;
}
#Override
public void simulate( String given )
{
delegate.simulate( given );
// simulate this given some more!
}
}
To instantiate the chain, use the following order:
final var aSimulation = new LeafSimulation();
final var bSimulation = new ChainedSimulation( aSimulation );
final var cSimulation = new ChainedSimulation( bSimulation );
This code approaches the problem statement more naturally and eliminates the repetition, but it is not concise.
Once you have set up a mapping of status values to method calls, you can use a SortedSet or EnumSet.range to get the enum values after a particular value:
Map<Status, Consumer<String>> simulators = new EnumMap<>(Map.of(
Status.A, this::simulateA,
Status.B, this::simulateB,
Status.C, this::simulateC));
if (!simulators.keySet().equals(EnumSet.allOf(Status.class))) {
throw new RuntimeException(
"Not all Status values have simulators defined.");
}
// ...
SortedSet<Status> all = new TreeSet<>(EnumSet.allOf(Status.class));
Collection<Status> remainingValues = all.tailSet(status);
// Or:
//Status[] allStatuses = Status.values();
//Status lastStatus = allStatuses[allStatuses.length - 1];
//Collection<Status> remainingValues = EnumSet.range(status, lastStatus);
for (Status s : remainingValues) {
simulators.get(s).accept(given);
}
Another option to consider, which avoids switch / if. Declare a map of actions per Status value which can be used with a getOrDefault lookup default for unhandled values:
Consumer<String> simA = this::simulateA;
Map<Status, Consumer<String>> actions = new EnumMap<>(Map.of(
Status.A, simA,
Status.B, simA.andThen(this::simulateB),
Status.C, simA.andThen(this::simulateB).andThen(this::simulateC)
));
actions.getOrDefault(status, s -> {}).accept(given);
If you want to guard against missing / unhandled mappings you should validate the map (as in #VGR answer) or swap the no-operation default with an exception handler:
actions.getOrDefault(status,
s -> { throw new RuntimeException("Missing action for status: "+status); }
).accept(given);
Assuming your first status is A you can do something like this:
public void simulate(String given, Status status) {
if (status != Status.A) {
int indexOfStatus = status.ordinal();
simulate(given, Status.values()[indexOfStatus - 1]);
}
switch (status){
case A:
simulateA(given);
break;
case B:
simulateB(given);
break;
case C:
simulateC(given);
break;
// here you still need to put all your "simulateX" calls but without repetitions
}
}
you don't need to write simulateA(given) to all your cases, just moved it to top
public void simulate(String given, Status status) {
simulateA(given);
switch (status){
case C:
simulateC(given);
case B:
simulateB(given);
break;
case A:
break;
}}
You can try the fallthrough mechanism of switch statement. refer to this
In your example, the code can be(not tested):
Edited:
public void simulate(String given, Status status) {
switch (status){
case C:
simulateC(given);
case B:
simulateB(given);
case A:
simulateA(given);
}
}
Original(Wrong):
public void simulate(String given, Status status) {
switch (status){
case A:
simulateA(given);
case B:
simulateB(given);
case C:
simulateC(given);
}
}
When the reader has the fallthrough concept in mind, the code above is cleaner and easier to read than the code in question. But that is not always the case. My recommendation would be to restructure your code so as to eliminate both the repetitive calls and the fallthroughs.

Getting rid of if/else while calling similar classes Java

I have the problem that I want to and need to get rid of some if else cases. I got the following code in my project:
if (ar[4].equals("week")) {
WeekThreshold wt = new WeekThreshold();
firstTime = unparsedDate.format(wt.getStartDate().getTime());
secondTime = unparsedDate.format(wt.getEndDate().getTime());
} else if (ar[4].equals("month")) {
MonthThreshold mt = new MonthThreshold();
firstTime = unparsedDate.format(mt.getStartDate().getTime());
secondTime = unparsedDate.format(mt.getEndDate().getTime());
} else if (ar[4].equals("quarter")) {
quarterThreshold();
} else if (ar[4].equals("year")) {
YearThreshold yt = new YearThreshold();
firstTime = unparsedDate.format(yt.getStartDate().getTime());
secondTime = unparsedDate.format(yt.getEndDate().getTime());
}
That three classes WeekThreshold, MonthThreshold and YearThreshold extend from an AbstractThreshold class where they get dates from a calendar, but that is not important. The method quarterThreshold() is special and can stay there. But how can I get rid of that if else blocks and have one statement to call different classes?
EDIT: Forgot to mention, the classes that need to be called are from a variety of the array ar[]. If the array ar[4] is month, MonthThreshold must be called, etc.
Multiple possibilities... Do the XYZThreshold classes have a common interface, like Threshold? Then you could assign a variable with that, for example...
Threshold threshold = null;
if ((ar[4].equals("week")) {
threshold = new WeekThreshold();
} else ... {
}
firstTime = unparsedDate.format(threshold.getStartDate().getTime());
secondTime = unparsedDate.format(threshold.getEndDate().getTime());
That would be a first step. If you wanted, you could, for example, use an enum to store your Thresholds:
enum Thresholds {
WEEK("week") {
public Threshold getThreshold() {
return new WeekThreshold();
}
},
etc.
private String period;
private Thresholds(String period) {
this.period = period;
}
public abstract Threshold getThreshold();
// ...add a static class to iterate and search by period,
// ...so you can write Threshold threshold = Thresholds.getByPeriod("week").getThreshold();
}
Using enums is a personal taste, of course, you can do the same thing with normal classes or by simply putting your if-block for the Threshold-choosing into a seperate class.
You can merge the common code (unparsedDate.format(...)) outside like this:
AbstractThreshold at = null;
switch(ar[4]) {
case "week":
at = new WeekThreshold();
break;
case "month":
at = new MonthThreshold();
break;
case "year":
at = new YearThreshold();
break;
case "quarter":
quarterThreshold();
break;
}
if(at != null) {
firstTime = unparsedDate.format(at.getStartDate().getTime());
secondTime = unparsedDate.format(at.getEndDate().getTime());
}
Of course an overengineered version is possible. Here's just an illustration how it can be implemented using the Java-8 features:
// Map can be initialized only once, then used many times
Map<String, Supplier<AbstractThreshold>> thresholdSuppliers = new HashMap<>();
thresholdSuppliers.put("week", WeekThreshold::new);
thresholdSuppliers.put("month", MonthThreshold::new);
thresholdSuppliers.put("year", YearThreshold::new);
AbstractThreshold at = thresholdSuppliers.getOrDefault(ar[4], () -> null).get();
if(at != null) {
firstTime = unparsedDate.format(at.getStartDate().getTime());
secondTime = unparsedDate.format(at.getEndDate().getTime());
} else if(ar[4].equals("quarter"))
quarterThreshold();
}
Here you can make good use of the FactoryPattern
class ThresholdFactory
{
public static AbstractThreshold getThreshold(String criteria)
{
if ( criteria.equals("week") )
return new WeekThreshold();
if ( criteria.equals("month") )
return new MonthThreshold();
if ( criteria.equals("year") )
return new YearThreshold();
return null;
}
}
The rest of the code looks then like this:
AbstractThreshold at = ThresholdFactory.getThreshold(ar[4]);
if(at != null){
firstTime = unparsedDate.format(at.getStartDate().getTime());
secondTime = unparsedDate.format(at.getEndDate().getTime());
} else {
quarterThreshold();
}
first create threshold factory,
static enum ThresholdsFactory {
week(new WeekThreshold()), month(new MonthThreshold())/* etc */;
static private Map<String,ThresholdsFactory> lookup = new HashMap<String, ThresholdsFactory>();
static{
for(ThresholdsFactory val : ThresholdsFactory.values()){
lookup.put(val.name(), val);
}
}
public AbstractThreshold threshold;
public static ThresholdsFactory find(String name){
return lookup.get(name);
}
ThresholdsFactory(AbstractThreshold th) {
threshold = th;
}
}
now all what you need to do is
AbstractThreshold th = ThresholdsFactory.find(ar[4]);
if (th!=null){
firstTime = unparsedDate.format(th.getStartDate().getTime());
secondTime = unparsedDate.format(th.getEndDate().getTime());
}
Here is an example of how to use interfaces and Factory design pattern
If your multiple implementors share common code, have them all extend an Abstract class that implements the interface. It is a good idea to refer to your methods through the interface, not the concrete class to take advantage of polymorphism ... see code below ...
public class Example {
public static void main(String[] args) {
String[] intervals = {"week", "week", "quarter", "month", "year", "week"};
IThreshold[] objects = new IThreshold[intervals.length];
// Create your objects using Factory pattern
for(int index = 0; index < intervals.length; index++) {
objects[index] = ThresholdFactory.createInstance(intervals[index]);
}
// Now iterate through your objects and refer to them through a common interface
for(IThreshold object : objects) {
int start = object.getFirstTime();
int end = object.getFirstTime();
}
}
}
interface IThreshold {
public int getFirstTime();
public int getLastTime();
}
abstract class AbstractThreshold implements IThreshold {
#Override
public int getFirstTime() {
// TODO Auto-generated method stub
return 0;
}
#Override
public int getLastTime() {
// TODO Auto-generated method stub
return 0;
}
}
class WeekThreshold extends AbstractThreshold {}
class MonthThreshold extends AbstractThreshold {}
class QuarterThreshold extends AbstractThreshold {}
class YearThreshold extends AbstractThreshold {}
class ThresholdFactory {
public static final IThreshold createInstance(String interval) {
IThreshold instance = null;
if(interval.equals("week")){
instance = new WeekThreshold();
}
else if(interval.equals("month")){
instance = new MonthThreshold();
}
else if(interval.equals("quarter")){
instance = new QuarterThreshold();
}
else {
if(interval.equals("year")){
instance = new YearThreshold();
}
}
return instance;
}
}
You could use a switch statement
String typeOfDay;
switch (dayOfWeekArg) {
case "Monday":
typeOfDay = "Start of work week";
break;
case "Tuesday":
case "Wednesday":
case "Thursday":
typeOfDay = "Midweek";
break;
case "Friday":
typeOfDay = "End of work week";
break;
case "Saturday":
case "Sunday":
typeOfDay = "Weekend";
break;
default:
throw new IllegalArgumentException("Invalid day of the week: " + dayOfWeekArg);
}
You can replace the example that I stole from java documentation, with your own code
switch(periodType){
case "week":
WeekThreshold wt = new WeekThreshold();
break; // add your other cases
}
firstTime = unparsedDate.format(wt.getStartDate().getTime());
secondTime = unparsedDate.format(wt.getEndDate().getTime());

java loses values from ManagedBeans

I try to write an application to create PDF files, it uses the JavaServer Faces. I struggle with a problem when I give the value of the text box from bean to factory class, the values ​​are lost. I wonder why this happens, already tried many solutions, but they will cause expansion of the code and do not help.
Bean code:
#ManagedBean
#ViewScoped
public class PanelInneBean extends AbstractPanel implements Serializable {
private static final long serialVersionUID = 1L;
private final int CODE = 4;
private boolean use;
private String tytul, opis;
private PdfFactory pdf = PdfFactory.getPdfObject();
public PanelInneBean() {
use = false;
}
public boolean getUse() {
return use;
}
public String getTytul() {
return tytul;
}
public void setTytul(String tytul) {
this.tytul = tytul;
}
public String getOpis() {
return opis;
}
public void setOpis(String opis) {
this.opis = opis;
}
public int getCode() {
return CODE;
}
private void add() {
use = true;
}
public void addBean() {
add();
pdf.addElement(this);
System.out.println("InnePanel after pdf.addElement() this.opis:" + this.opis);
// This sysout prints the correct value after give object to factory
}
}
Factory piece of code:
public int addElement(PdfElement element) {
pdfType = true;
if (element.getUse()) {
elementList.add(element);
return 1;
}
return 0;
}
public void prepare() {
for (PdfElement element : elementList) {
System.out.println("element.code:" + element.getCode());
switch (element.getCode()) {
case 0:
if (nF != null)
break;
nF = new NaglowekFactory(element, Counter.getNumber());
break;
case 1:
if (pF != null)
break;
pF = new ProduktyFactory(element, Counter.getNumber());
prodSum = pF.getProdukty().getSuma();
euroData = pF.getProdukty().getEuroData();
break;
case 2:
if (mF != null)
break;
mF = new MontazFactory(element, Counter.getNumber());
servSum = mF.getMontaz().getSuma();
break;
case 3:
if (uF != null)
break;
uF = new UslugiFactory(element, Counter.getNumber());
asmSum = uF.getUslugi().getSuma();
break;
case 4:
if (iF != null)
break;
iF = new InneFactory(element, Counter.getNumber());
//here Opis value is empty
break;
}
}
System.out.println("factory.prepare() ->");
}
Constructor of InneFactory:
PanelInneBean inne;
public InneFactory(PdfElement element, int order) {
inne = (PanelInneBean) element;
System.out.println("innerFactory constructor, inne.getTytul(): "
+ inne.getTytul());
//here values are empty
this.order = order;
list = new ArrayList<Element>();
}
public int getOrder() {
return order;
}
what I'm doing wrong?
I think you are running into a common misconception about how #ViewScoped beans really work. The bean object itself is created on every Faces request and destroyed after every Faces response.
After the bean is re created however JSF will enter the first lifecycle phase RestoreView. During this phase it will fetch the last good values for this bean from the View State and apply them to the beans Managed Properties.
Basically what is happening is that you are invoking an action, which generates a seperate request than the one that loaded the page, and at this point the reference you added to the PdfFactory is now lost because the PdfFactory in the last object was destroyed!
The best way to resolve this would be to make PdfFactory a Managed Bean. You can initialize the factory in the #PostConstruct method and you can inject other Managed Beans into your PdfFactory bean using the #ManagedProperty annotation.
#ManagedBean
#RequestScoped
public PdfFactory extends ... implements Serializable {
#ManagedProperty("#{myViewBean}")
private MyViewBean viewBean;
#PostConstruct
public initializeFactory() {
//Do stuff
}
public void prepare() {
// prepare stuff
}
}

Weird error - doesn't do anything after breaking from menu

This is for coursework. I've built the whole program, and it does everything right, apart from this one thing.
I have a class called 'Schedule' this method is at the very end of schedule:
public void bookSeatMenu()
{ boolean leaveBookSeatMenu = false;
String seatBookingMenuStr;
int seatBookingMenuInt = 14;
boolean isInteger = false;
Scanner input = new Scanner(System.in);
System.out.println("Press 1 to add an individual booking, 2 to cancel a booked seat or 3 to go back");
seatBookingMenuStr = input.nextLine();
try {
seatBookingMenuInt = Integer.parseInt(seatBookingMenuStr);
isInteger = true;
}
catch (NumberFormatException e) {
}
switch (seatBookingMenuInt) {
case 1:
bookSeat();
break;
case 2:
cancelSeat();
break;
case 3:
leaveBookSeatMenu = true;
break;
default:
System.out.println("Invalid Choice");
} while (leaveBookSeatMenu == false);
}
I know you all know what a switch menu looks like, but I thought I'd throw it in there anyway, in case (pardon the pun) I'm going wrong here.
Moving on, I have the bookSeat method, this is where the user books a seat (which works fine). Then afterwards it displays the bookSeatMenu() just it displays the menu. But then it won't go back to the previous one.
public void bookSeat()
{
Scanner input = new Scanner(System.in);
boolean isSeatBooked = true;
showSeatPlan();
int seatNum = 0;
int rowNum = 90;
int columnNum = 16;
boolean isInt = false;
while (isSeatBooked == true)
{
System.out.println("Please pick column of a seat to book");
columnNum = input.nextInt();
System.out.println("Please pick row of a seat to book");
rowNum = input.nextInt();
seatNum = (columnNum + ((rowNum) * 15));
if (seats[seatNum] == false)
{
isSeatBooked = false;
}
else
{
System.out.println("This seat is already booked");
}
}
seats[seatNum] = true;
System.out.println("");
bookSeatMenu();
}
Now not for love nor money am I able to get it to go back to the previous menu after it's booked a seat.
Basically the process is:
Book a seat --> go to bookSeatMenu --> press 4 to go back --> Arrive at previous menu.
If I don't book a seat, the program will happily go back to the menu before hand, but after, it just keeps on going on to a new line in the command prompt, not doing anything else, no error etc.
I'm pretty tempted to say this might be a problem with BlueJ, although a bad workman blames his tools, and I don't wanna be 'that guy'
I also need to make a 'testing class' - having never used a 'testing class' before, and the assignment asking us to look in the 'textbook' which noone bothered to buy, I actually have no idea!
There's no switch...while so I assume your problem is as soon you do choose 3, you end up in while(true); which is an infinite loop.
correct pseudo-code:
do {
// read System.in
// handle menu options with your switch
} while(...)
By the way, design is bad IMHO, you should try to think about your model (in your case I would see something like Room, Seat, Scheduler, Menu) and make those object interact with each others :
public class Room {
private Seat[][] seats;
public String toString() {
// like showSeatPlan() using toString() of Seat
}
}
public class Seat {
private int row, column;
private boolean isBooked;
public void book() { /* ... */ }
public void cancel() { /* ... */ }
public String toString() { /* "X" or " " */ }
}
public final class Scheduler {
// "main class" with a "main" method
}
public class Menu {
private Room room;
public String toString() {
// print out menu
}
public void bookSeat() { /* ... */ }
public void cancelSeat() { /* ... */ }
}
(something like that)
For the test part, each class have a test class and each method have a test method, as an example, for Seat:
public class Seat {
public void book() {
if (this.isBooled) {
throw new CannotBookException("seats is taken!");
}
this.isBooled = true;
}
}
public class SeatTest {
#Test // when I book a seat, it's markedas booked.
public void testBook() {
final Seat seat = new Seat();
seat.book();
assertTrue(seat.isBooked)
}
#Test(expected = CannotBookException.class) // when I book an already booked seat, I get an exception.
public void testBookAlreadBooked() {
final Seat seat = new Seat();
// book the seat
seat.book();
assertTrue(seat.isBooked)
// try to book again
seat.book();
}
}

Can I call a method with a field value in Java?

Is is possible in Java to call a method based on a field value? For example, I ask the user what soda they want. They enter their selection and the value of the field that holds their selection is used to call the method.
Obviously the below code doesn't work. But I'm hoping it will illustrate my intent. Is this sort of thing even possible in Java?
The goal is to effectively switch without using IF or SWITCH statements.
import java.util.Scanner;
public class FieldResolutionTest
{
public static void main (String[] args)
{
Scanner inputScanner = new Scanner(System.in);
MethodTester test = new MethodTester();
System.out.println("Please enter ONE or TWO");
String selection = inputScanner.nextLine();
test.(selection)();
}
}
public class MethodTester
{
public void ONE()
{
System.out.println("You ran method ONE");
}
public void TWO()
{
System.out.println("You ran method TWO");
}
}
It is technically possible with reflection, but if you have a finite number of known possible methods, it would be much simpler to use a switch statement (or if/else if you don't have Java 7):
switch (selection) {
case "ONE":
test.ONE();
break;
case "TWO":
test.TWO();
break;
// etc.
default:
System.out.println("Invalid method!");
break;
}
If the methods are dynamic or you are testing lots of classes, and you still want to go the reflection route, it would look something like this:
try {
Method m = MethodTester.class.getMethod(selection);
m.invoke(test);
} catch (NoSuchMethodException nsme) {
System.out.println("Invalid method!");
}
A nice approach is with enum:
public class FieldResolutionTest
{
public static void main (String[] args)
{
Scanner inputScanner = new Scanner(System.in);
System.out.println("Please enter ONE or TWO");
String selection = inputScanner.nextLine();
FieldResolutionTest.valueOf(selection).run();
}
}
public enum MethodTester
{
ONE { public void run()
{
System.out.println("You ran method ONE");
}},
TWO { public void run()
{
System.out.println("You ran method TWO");
}};
public abstract void run();
}
You can use reflection. This is your example with minimal modifications:
import java.lang.reflect.Method;
import java.util.Scanner;
public class FieldResolutionTest {
public static void main (String[] args) throws Exception {
Scanner inputScanner = new Scanner(System.in);
MethodTester test = new MethodTester();
System.out.println("Please enter ONE or TWO");
String selection = inputScanner.nextLine();
Method method = MethodTester.class.getMethod(selection);
method.invoke(test);
}
}
class MethodTester {
public void ONE() {
System.out.println("You ran method ONE");
}
public void TWO() {
System.out.println("You ran method TWO");
}
}
Of course, you need to add some error handling. For example, you should check that the user entered the name of one of the allowed methods, like this:
Map<String, Method> methods = new HashMap<String, Method>();
for (Method m: MethodTester.class.getMethods()) {
methods.put(m.getName(), m);
}
if (methods.containsKey(selection)) {
methods.get(selection).invoke(test);
} else {
System.err.println("No such method: " + selection);
}
You need to test the input value and call the corresponding method:
if(selection.equals("ONE")) test.ONE();
else if (selection.equals("ONE")) test.TWO();
else System.out.println("Unknown input!");
Since Java 7 was released, it is possible to perform the switch-case method on a string type variable
switch(selection) {
case "ONE":
test.ONE();
break;
case "TWO":
test.TWO();
break;
}
Again, only available since Java 7.
As told by mellamokb you can use reflection to invoke the method. Typically the code will look like test.getClass().getMethod("ONE", null).invoke(..)

Categories

Resources