I have a switch method, and I want that if the type of fetch is ALL, the switch runs in all the statments, (HOUSE AND PLAYER), but it doesn't work because of the break, it only runs in HOUSE, removing the break works, but then if the type is not ALL, it will also runs on the others statments and not only in the given type. Whats is a proper solution for that?
public static void fetch(FetchType fetchType) {
switch (updateType) {
case ALL: // if this is the case, then it should run for HOUSE, PLAYER
case HOUSE:
// code here
break;
case PLAYER:
// code here
break;
default:
throw new IllegalArgumentException();
}
}
Well you can either create private methods for that:
public static void fetch(FetchType fetchType) {
switch (updateType) {
case ALL:
doHouse();
doPlayer();
break;
case HOUSE:
doHouse();
break;
case PLAYER:
doPlayer();
break;
default:
throw new IllegalArgumentException();
}
}
private static void doHouse(){ ... }
private static void doPlayer(){ ... }
Or use Runnable to avoid using polluting the local private namespace:
public static void fetch(FetchType fetchType) {
Runnable house = () -> { ... };
Runnable player = () -> { ... };
switch (updateType) {
case ALL:
house.run();
player.run();
break;
case HOUSE:
house.run();
break;
case PLAYER:
player.run();
break;
default:
throw new IllegalArgumentException();
}
}
If I understand it right you might need to create methods for each case in the Main class and then call all methods if the fetch type is "ALL"
static void methodForHouse() {
System.out.println("I just got executed!");
}
static void methodForPlayer() {
System.out.println("I just got executed!");
}
And then
public static void fetch(FetchType fetchType) {
switch (updateType) {
case ALL:
methodForHouse();
methodForPlayer();
break;
case HOUSE:
methodForHouse();
break;
case PLAYER:
methodForPlayer();
break;
default:
throw new IllegalArgumentException();
}
}
Related
I need to simplify my methods I need to run this method for all weekdays:
if (!getAbsenceSo().equals("-")) {
switch (getAbsenceSo()){
case "uabgelehnt": setAbsenceSo("-"); break;
case "urlaubbeantragt": setAbsenceSo("-"); break;
case "urlaubgenehmigt": setAbsenceSo("Urlaub"); setArbeitMinutenSo((int)(wochenarbeitstunden*60/5)); break;
case "sonderurlaub": setAbsenceSo("Sonderurlaub"); setArbeitMinutenSo((int)(wochenarbeitstunden*60/5)); break;
case "ueabsetzer": setAbsenceSo("Ü-Absetzer"); break;
case "krank": setAbsenceSo("Krank"); setArbeitMinutenSo((int)(wochenarbeitstunden*60/5)); break;
case "kindkrank": setAbsenceSo("Kindkrank"); setArbeitMinutenSo((int)(wochenarbeitstunden*60/5)); break;
case "fbschule": setAbsenceSo("FB/Schule"); setArbeitMinutenSo((int)(wochenarbeitstunden*60/5)); break;
case "kurzarbeit": setAbsenceSo("Kurzarbeit"); setArbeitMinutenSo((int)(wochenarbeitstunden*60/5)); break;
case "unentschuldigt": setAbsenceSo("Unentschuldigt"); break;
}
}
so the next code snippet would look like this:
if (!getAbsenceMo().equals("-")) {
switch (getAbsenceMo()){
case "uabgelehnt": setAbsenceMo("-"); break; and so on...
is there a way that I can use to prevent duplicate code?
I have not really much knowledge about Java - can you give me a hint?
That I can call a method within the object put together from a string.
e.g. how can I call "setAbsense"+item("-"); ??? Or better how should this be done??? Thanks a lot!!!
Do not try to dynamically construct a method call. Instead, rethink your design. You've code that needs to be performed for multiple instances of the same type (same data, same methods). This already indicates: use a class. Every instance (Mo, Tu, ...) will have the same information, but you can manipulate it on that very instance itself.
Quick example to get you going:
public class App {
static class Absence {
private DayOfWeek dayOfWeek;
private String reason;
private int arbeitMinuten;
public Absence(DayOfWeek dayOfWeek, String reason) {
this.dayOfWeek = dayOfWeek;
this.reason = reason;
}
public DayOfWeek getDayOfWeek() {
return dayOfWeek;
}
public void setDayOfWeek(DayOfWeek dayOfWeek) {
this.dayOfWeek = dayOfWeek;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public int getArbeitMinuten() {
return arbeitMinuten;
}
public void setArbeitMinuten(int arbeitMinuten) {
this.arbeitMinuten = arbeitMinuten;
}
}
public static void main(String[] args) throws IOException {
int wochenarbeitstunden = 40;
List<Absence> absenceList;
// Build from your Datasource
absenceList = List.of(new Absence(DayOfWeek.MONDAY, "uabgelehnt"), new Absence(DayOfWeek.TUESDAY, "Krank"), new Absence(DayOfWeek.WEDNESDAY, "Kurzarbeit"));
for (Absence absence : absenceList) {
switch (absence.getReason()) {
case "uabgelehnt" -> absence.setReason("-");
case "urlaubbeantragt" -> absence.setReason("-");
case "urlaubgenehmigt" -> {
absence.setReason("Urlaub");
absence.setArbeitMinuten(wochenarbeitstunden * 60 / 5);
}
case "sonderurlaub" -> {
absence.setReason("Sonderurlaub");
absence.setArbeitMinuten(wochenarbeitstunden * 60 / 5);
}
case "ueabsetzer" -> absence.setReason("Ü-Absetzer");
case "krank" -> {
absence.setReason("Krank");
absence.setArbeitMinuten(wochenarbeitstunden * 60 / 5);
}
case "kindkrank" -> {
absence.setReason("Kindkrank");
absence.setArbeitMinuten(wochenarbeitstunden * 60 / 5);
}
case "fbschule" -> {
absence.setReason("FB/Schule");
absence.setArbeitMinuten(wochenarbeitstunden * 60 / 5);
}
case "kurzarbeit" -> {
absence.setReason("Kurzarbeit");
absence.setArbeitMinuten(wochenarbeitstunden * 60 / 5);
}
case "unentschuldigt" -> absence.setReason("Unentschuldigt");
default -> {}
}
}
}
}
i have an enum like below:
public enum TripType {
TRIP1,
TRIP2,
TRIP3,
TRIP4
}
Then i have a method which receives a string parameter setupTravel(String tripType) and i need to check the value of tripType with a TripType. I wish to use a switch-case as below:
setupTravel(String tripType){
switch (tripType){
case TripType.TRIP1.toString():
setup1();
break;
case TripType.TRIP2.toString():
setup2();
break;
}
}
But, in the line TripType.TRIP1.toString() it complains with:
Constant expression required
How can i fix it?
setupTravel(String tripType) {
try {
switch (TripType.valueOf(tripType)) {
case TRIP1:
setup1();
break;
case TRIP2:
setup2();
break;
}
} catch (IllegalArgumentException ex) {
// Handle invalid trip type here
}
}
Since your method seems to switch on the Enum string, why not just use the Enum? You may want to include a default unless you have all Enums in the switch block.
setupTravel(TripType type){
switch (type){
case TRIP1:
setup1();
break;
case TRIP2:
setup2();
break;
}
}
You would call it as
setupTravel(TripType.TRIP1)
If it will be useful for you, You can use an enum constructor instead of using a switch case.
Something like this:
public enum TripType {
TRIP1("setup1"), TRIP2("setup2");
String setup;
private TripType(String setup) {
this.setup = setup;
}
public String getSetup() {
return setup;
}
public static TripType getTripTypeByName(String name) {
return Arrays.stream(TripType.values()).filter(t -> t.name().equalsIgnoreCase(name)).findAny().orElse(null);
}
}
And getting enum based on the name, you can use like this:
TripType tripType = TripType.getTripTypeByName("trip1");
System.out.println(tripType != null ? tripType.getSetup() : null);
I want to create a finite state machine and most of the example code I can find uses enums and I was just wondering if it gives an advantage over just using a string or int to store the state.
With Enum:
class TrafficLight {
enum State {
RED, YELLOW, GREEN
};
State state = State.GREEN;
public void iterate() throws InterruptedException {
switch (this.state) {
case RED:
System.out.println("RED");
Thread.sleep(1000);
this.state = State.GREEN;
break;
case GREEN:
System.out.println("GREEN");
Thread.sleep(1000);
this.state = State.YELLOW;
break;
case YELLOW:
System.out.println("YELLOW");
Thread.sleep(1000);
this.state = State.RED;
break;
}
}
public class Main {
public static void main(final String[] args) throws InterruptedException {
final TrafficLight a = new TrafficLight();
while (true) {
a.iterate();
}
}
}
With String
public class TrafficLight {
String state = "GREEN";
public void iterate() throws InterruptedException {
switch (state) {
case "RED":
System.out.println("RED");
Thread.sleep(1000);
state = "GREEN";
break;
case "GREEN":
System.out.println("GREEN");
Thread.sleep(1000);
state = "YELLOW";
break;
case "YELLOW":
System.out.println("YELLOW");
Thread.sleep(1000);
state = "RED";
break;
}
}
}
(Both use the same main method)
They both seem to be exactly the same to me I am just wondering if there are any cases in which enums are better or a string wouldn't work.
Thanks.
Main advantage for Enum over String : this is more specifically typed as Enum specifies possible values.
This makes your code both more robust and also better documented.
For a FSM and more generally bounded values, it is what you are looking for.
But for problems/domains where possible values are defined at runtime and not at compile time (retrieving from a database or whatever), Enum is not the best candidate.
Example of Enum interest in your case
With Enum, it will not compile as REDD is not declared in the State enum class:
case REDD:
System.out.println("RED");
Thread.sleep(1000);
this.state = State.GREEN;
break;
But with String, it will compile and just not work as expected :
case "REDD":
System.out.println("RED");
Thread.sleep(1000);
state = "GREEN";
break;
Enumerated values are instances of the enum class with own values for instance fields but also overriding abilities for instance methods
This is another advantage of enum in the FSM or any domain where the enumerated values are associated to specific properties/processings and where according to enumerated value, the fields values or the method behavior could differ.
For example, here we specify the behavior to get the next transition :
enum State {
YELLOW(){
#Override
public State next() {
return RED;
}
},
RED(){
#Override
public State next() {
return GREEN;
}
},
GREEN(){
#Override
public State next() {
return YELLOW;
}
};
public abstract State next();
}
Now, the enum holds enough logic to make the switch statement not needed any longer :
public void iterate() throws InterruptedException {
System.out.println(state);
Thread.sleep(1000);
state = state.next();
}
Inside public class we want switchcase based on package name in every case we are calling one public URL.. i tried this way it is not working switch case
public class AllChanges {
Context context;
Switch(getPackageName()) {
case "com.agilerise.package1":
public static String gurl = "http://google.com/index.php";
break;
case "com.agilerise.package2":
public static String gurl = "http://bing.com/index.php";
case "com.agilerise.package2":
public static String gurl = "http://stackoverlfow.com/index.php";
break;
}
}
public class AllChanges {
public static String gurl ="";
public void seturl()
{
Switch(getPackageName()) {
case "com.agilerise.package1":
gurl = "http://google.com/index.php";
break;
case "com.agilerise.package2":
gurl = "http://bing.com/index.php";
break;
case "com.agilerise.package2":
gurl = "http://stackoverlfow.com/index.php";
break;
}
}
}
call like this
AllChanges allchanges=new AllChanges();
allchanges.seturl();
The better way is to use polymorphism here:
Instead of examining the classes package (which may vary and result in duplicated entries for subclasses) you should define an interface:
interface SearchEngineSelector{
URL getSearchEngineUrl();
}
Then You have specialized sub interfaces with default methods:
interface GoogleSearchEngineSelector extends SearchEngineSelector{
URL THE_URL = new URL("http://google.com/index.php");
default public URL getSearchEngineUrl(){
return THE_URL;
}
Your classes then can implement one of the specialized sub interfaces :
class SomeClass implements GoogleSearchEngineSelector {
// ...
}
and your code code change to: Nothing
because there is nothing to do for a subclass...
Java doesn't work that way. You can write statements only inside functions in Java. And declarations of variables can come in class outside of functions.
I would suggest you to read about scope.
https://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.3
You need to declare your variables in the class scope. And your switch case has to be within a function. Your example has a duplicated case, you should probably fix that. com.agilerise.package1, com.agilerise.package2, com.agilerise.package3
public class AllChanges {
public static String gurl = "";
Context context;
private void myFunction(){
switch(getPackageName()) {
case "com.agilerise.package1":
gurl = "http://google.com/index.php";
break;
case "com.agilerise.package2":
gurl = "http://bing.com/index.php";
break;
case "com.agilerise.package3":
gurl = "http://stackoverlfow.com/index.php";
break;
}
}
}
This is a more elegant solution. You should try to avoid static variables. You could then call this function by String url = getUrl(myFunction());
private String getUrl(String s){
switch(s) {
case "com.agilerise.package1":
return "http://google.com/index.php";
case "com.agilerise.package2":
return "http://bing.com/index.php";
case "com.agilerise.package3":
return "http://stackoverlfow.com/index.php";
default:
return "SomeDefaultUrl";
}
}
So im making an application that works via console commands (think of "database new db_name"). Whats the most elegant way to handle this sort of thing?
Heres my little prototype, basicly just tons of switches. I mean it works but it gets kinda messy once I want to add stuff like putting out all the parameters if you pass a wrong one or too few, so im wondering if theres a better option:
public static void main(String[] args) {
while (running) {
Scanner in = new Scanner(System.in);
String cmd = in.nextLine();
parseCmd(cmd);
}
}
private static void parseCmd(String s) {
String[] cmd = s.split(" ");
try {
switch (cmd[0]) {
case "exit":
running = false;
System.out.println("Shutting down...");
break;
case "database":
switch (cmd[1]) {
case "new":
databases.add(new Database(cmd[2]));
break;
default:
System.out.println("Unknown parameter");
break;
}
break;
default:
System.out.println("Unknown command");
break;
}
} catch (Exception ArrayIndexOutOfBoundsException) {
System.out.println("Too few arguments passed");
}
}
I don't know about the most elegant way, but I've done something like this a couple of times and came up with this solution.
Make a class for "database" that represents the command, once you find the string "database", you retrieve an instance of this class and pass it the remaining arguments, so it can do the rest of the parsing.
class DataBaseCommand implements Command {
#Override
public void eval(String[] args) {...}
}
You can then keep a static map of these commands mapped to their names:
private static final Map<String, Command> commands = new HashMap<>();
static {
commands.put("database", new DataBaseCommand());
}
switch (cmd[0]) {
case "exit":
running = false;
System.out.println("Shutting down...");
break;
default:
if(commands.contains(cmd[0])) {
commands.get(cmd[0]).eval(cmd);
} else {
System.out.println("Unknown command");
}
break;
}
Maybe you could use a library that does a lot of those command parsing for you, like joptsimple?
I would suggest using http://jcommander.org/.Its simple and elegant. In it you can use inbuilt annotations
e.g Create a class like this using jcommander annotaions
#Parameters(commandNames = {"test", "Manages dates"})
public class CommandOption {
#Parameter(names = {"-e", "--exit"}, description = "bla bla")
public boolean exit = false;
}
then in main method
public static void main(String... args){
CommandOption opt = new CommandOption();
JCommander jc = new JCommander(opt);
jc.parse(args);
//and now use
System.out.println("value" +opt.exit)
}
and then can pass parmaeters as java class-e true or maybe better if you can create jar and then java -jar 'jar' -e true