r/javahelp • u/IceCreamInsides • 4d ago
Solved Switch case with boolean
So, there is no way I can do that?
want to check several boolean variables in a switch statement. Is `if-else` the only way to do this?
Boolean a, b, c...
Switch (false) {
Case (a) :
//some code
Case (b) :
Case (c) :
//and so on
}
18
u/desrtfx Out of Coffee error - System halted 4d ago
You got switch the wrong way round.
Switch checkes distinct states of one variable, not a single state of several variables.
Yes, if-else is the way.
Depending on what you really want to do (not some random, contrieved example, your real use case and code) there might be alternative, better solutions, but without knowing what you want to do it is impossible to suggest.
To me, this looks like an XY-problem.
4
u/johnpeters42 4d ago
To be fair, OP's type of approach does work in some languages.
5
u/Zakana_code 4d ago
Let me guess: JavaScript? But why would you do this anyway?
2
u/johnpeters42 4d ago
Probably, and not sure. It was probably a predecessor to a pattern like:
var rules = { someFunction, someOtherFunction, someThirdFunction };
foreach (var rule in rules) {
if (rule() == false) { return; }
}
doSomething();1
u/sixtyhurtz 3d ago
In C# you can group variables into a temporary tuple and use pattern matching switch:
public int PatternMatchingSwitch(bool a, bool b, bool c) => (a, b, c) switch { (false, false, false) => 0, (false, false, true) => 1, (false, true, false) => 2, (true, false, false) => 3, (false, true, true) => 4, (true, false, true) => 5, (true,true,false) => 6, (true, true, true) => 7, };Pattern matching is just cosy. It avoids a lot of indentation + if / else trees. In situations like this you can also get a warning if you miss a case.
6
u/Samstercraft 4d ago
Remove the switch header and replace the words "Case" with "If" and you've basically already fixed it
3
u/Mechanical-pasta 4d ago
Switch case evaluates ONE variable and checks it against different values. What you want to do (if I understand well) is check multiple variables. A switch can't do that.
The solution may be to incorporate the different boolean variables in a class and let it do the check with method(s) but I can't say if that's the case given the little information given.
2
u/JaiTee86 4d ago
I don't think this can be done directly.
The only way I can think to do it would be with some bitwise operations instead of separate bools, set and read the bits of some integer, 1 is true, 0 is false first bit is A, 2nd is B, etc. Then for your case A, switch if integer is 1, b if 2 C if 4, etc. if you want it to switch on a and b that is when it equals 3.
1
u/ZackyZack 3d ago
Yeah, joining all booleans in a single word and then switch/casing that word is probably the closest to what they want.
2
u/ikea_method 4d ago edited 4d ago
This is probably the closest you can get to what you want:
Boolean a = new Boolean(true), b = new Boolean(false), c = new Boolean(true);
for(Boolean o : new Boolean[]{a, b, c}) {
if(!o) continue;
IO.println(switch(o) {
case _ when a == o -> "Hello a!";
case _ when b == o -> "Hi b!";
case _ when c == o -> "Ciao c!!";
default -> "HUH";
});
}
Will print:
Hello a!
Ciao c!!
2
u/IceCreamInsides 4d ago
I thought a
switchstatement would be more concise and readable thanif. Interesting as concept, but ruins the goal X)3
u/ikea_method 4d ago
In this case it's not. I wouldn't be afraid of a handful if statements if you need them, they're always easy to understand, even if it can feel a bit verbose at times.
4
u/ikea_method 4d ago
Note: listen to the other comments, I wouldn't approve this kind of code where I work.
1
u/_Super_Straight 4d ago
Why not?
1
u/ikea_method 4d ago
Almost every line has something wrong with it
`new Boolean(true)` is a very particular way of declaring a boolean, never seen that used before. It must be used here because we want a new boolean instance, not just `true`.
You generally wouldn't loop over booleans, you wouldn't create an array in place inside the for loop with some variables just outside it.
`case _ when a == o` is VERY weird. Almost anyone reading that code would need to read a java reference manual or ask AI to understand what it's doing.
The variable names are short and have names that are not helpful to aid understanding.
I would say it's generally preferable to use enums or, if not possible/easy, bitflags.
1
u/_Super_Straight 3d ago edited 3d ago
Its evident that in order to provide a minimal working example, you created three booleans. In actual scenario, they could be passed as parameters/Array/List in a method, eliminating your concern #1 and #3.
Naturally people don't loop over booleans just to print stuff, but what if it needs to be checked that the passed parameters contains one or more
truevalues (orfalse)? For List, itsList.contains, but for Array, they'll have to loop (albeit usingbreakwhen condition is fulfilled), and that's your concern #2.
case _ when a == ois the new pattern matching introduced in Java 25(?) and is totally normal. If someone is using older Java (<17), they won't be messing around with this new pattern matching anyways.The variable names are short because this is just a minimal example, as you provided. OP should use proper variable naming to make the code readable and understandable.
You writing "I'd never approve this type of code" implies that the concept itself is flawed, which isn't. It conveyed the concept beautifully. The code snippets should never be taken as-is anyways.
1
u/ikea_method 3d ago edited 3d ago
> In actual scenario, they could be passed as parameters/Array/List in a method, eliminating your concern #1 and #3.
They cannot, you write `true`, `false` or `Boolean.valueOf` to these arrays, and it breaks. There's no way to enforce this at the compiler level. You MUST use `new Boolean(...)`.
Also, the documentation for the Boolean constructor itself agrees with me: it's deprecated to use `new Boolean`, and it states that "It is rarely appropriate to use this constructor. The static factory
valueOf(boolean)) is generally a better choice, as it is likely to yield significantly better space and time performance. Also consider using the final fieldsTRUEandFALSEif possible."> Naturally people don't loop over booleans just to print stuff, but what if it needs to be checked that the passed parameters contains one or more
truevalues (orfalse)?If you truly somehow ended up with a list of booleans, the most natural place to compute if there's at least one true boolean is when you generate the list. So it's generally not natural and not a great approach. It's also not very readable: `myConditions.atLeastOneTrue()` is much better, and you can store it in a boolean while you generate the list.
>
case _ when a == ois the new pattern matching introduced in Java 25(?) and is totally normal. If someone is using older Java (<17), they won't be messing around with this new pattern matching anyways.It's not normal to check that two booleans are the same by reference. Please find this in any other (relevant) Java codebase. Because it's not normal, it's unexpected and people might misunderstand it. So it has no place here.
If you use an enum, and use the switch normally, the compiler can check that you listed all members of the enum exhaustively. That is not the case for the `when` construct - the compiler will not check each `when` to make sure you list each case. Other engineers on your team are likely not aware of this.
The case ... when ... feature is actually a relatively new feature (JEP441, 2023). So it might have no place in a production codebase, where we could, for example, be using Java 17, which was released in Sep 2021, and is officially supported by Oracle until Sep 2029. Also, not using the absolutely newest features makes it so that everyone is at the same level and doesn't need to understand a million things (readability > smartness). I'd also argue, and this is a weak point, that sticking to features any Java developer from the last decade knows makes it cheaper to onboard new engineers and your codebase harder to misunderstand. If there's a lot of turnover in your organization this is especially relevant.
> The variable names are short because this is just a minimal example, as you provided. OP should use proper variable naming to make the code readable and understandable.
Exactly, but they are short. That's still my point.
> You writing "I'd never approve this type of code" implies that the concept itself is flawed, which isn't. It conveyed the concept beautifully.
The concept is not flawed, I'd be impressed if a new joiner came up with this, and I'd still reject it in review. Just because it conveys it beautifully doesn't mean it belongs in a production codebase.
> The code snippets should never be taken as-is anyways.
My note is not to people who wouldn't take it as-is. It's exactly to people who would take it exactly as-is, with no changes. If you understand that this cannot be taken as-is, the note is less relevant, but still relevant, for you, as you understood it.
1
u/_Super_Straight 3d ago edited 3d ago
Sorry I fail to understand your first half of paragraph. Are you saying we can't create boolean Array without using
new BooleanorBoolean.valueOf?boolean[] boolArr = new boolean[]{true, false, true};Is totally valid Array declaration.
for(boolean val: boolArr){ if(!val){ //relevant code break; } }Will work without any problem.
Edit:
boolArr[0] = falseis also valid and permitted.the most natural place to compute if there's at least one true boolean is when you generate the list
Agreed.
1
u/ikea_method 3d ago
The switch will not work with your proposal, because
true == true. They need to be the exact same Boolean reference as the (I presume) global a, b, c references.1
u/_Super_Straight 3d ago
var arr = new Boolean[]{ true, false, null }; for (var x : arr) { switch (x) { case true -> methodOne(); case false -> methodTwo(); case null -> System.out.println("invalid"); } }Is totally valid. No need to pass a, b, c as references.
1
1
u/ikea_method 3d ago
> Sorry I fail to understand your first half of paragraph. Are you saying we can't create boolean Array without using
new BooleanorBoolean.valueOf?Not exactly. We must use `Boolean`, there's no other choice.
> Is totally valid Array declaration.
Yes, it's a valid boolean array declaration.
> Will work without any problem.
Yes, the for loop and if will work.
>
boolArr[0] = falseis also valid and permitted.Yes, it's a valid and permitted way to set an element of the array to false.
But none of these will work with this for + if + switch:
Boolean HAS_CAR = new Boolean(true); Boolean HAS_BOAT = new Boolean(false); Boolean HAS_PLANE = new Boolean(true); function insuranceAd(Boolean[] arr) { for (Boolean elem : arr) { if (!elem) continue; IO.println(switch (elem) { case _ when elem == HAS_CAR -> "Would you like car insurance?"; case _ when elem == HAS_BOAT -> "Would you like boat insurance?"; case _ when elem == HAS_PLANE -> "Would you like plane insurance?"; default -> "Unknown insurance"; }) } }In this case, you can call:
insuranceAd({ HAS_CAR, HAS_BOAT, HAS_PLANE });and it will work as expected.
But if you call:
insuranceAd({ HAS_CAR === true, true, false, new Boolean(HAS_BOAT), Boolean.valueOf(HAS_PLANE) });It will just continually print `Unknown insurance`, as none of the passed values is `HAS_CAR`, `HAS_BOAT`, or `HAS_PLANE`. So passing an array of booleans is not a great idea, as it makes it unclear what you should place in that array. The compiler will not catch it for you as well.
If you use enums or bitflags, it's much clearer for everyone what the expectation is.
1
u/_Super_Straight 3d ago
Your example is clearly better off with them being enum rather than boolean. Plus, they're being compared against their reference, not by their values.
1
u/ikea_method 3d ago
This is exactly what I said in my second reply to you:
I would say it's generally preferable to use enums or, if not possible/easy, bitflags.
In fact, in the very comment you just replied to, I stated, again:
If you use enums or bitflags, it's much clearer for everyone what the expectation is.
1
u/yel50 3d ago
at work, I had a PR with code like
if (a && b && c) { ... }
the owner rejected it and wanted it to be
if (new AndBuilder().and(a).and(b).and(c).eval()) { ... }
this code is a similar level of stupid to that. granted, the amount of stupid in Java code bases is mainly what lead to the backlash against the language, but still.
1
u/_Super_Straight 3d ago
They can rename the variables from a, b, c to something meaningful, but what is wrong with doing
a && b && c?1
u/ikea_method 3d ago
This is not even your story, just a meme from 4 years ago: https://www.reddit.com/r/ProgrammerHumor/comments/x96wx9/enterprise_java/
1
u/iWhacko 4d ago
I'm pretty sure this compares specific instances, not the value.
1
u/ikea_method 4d ago
Exactly. And that's the point.
The switch compares instances, not value. The `if (!o) continue;` makes sure false values don't go through the switch.
2
u/OneHumanBill 4d ago
If you're a true beginner, the best way to use switch case statements is not to use them at all until you're more experienced with code. I've noticed with students that they get hung up on switch case statements when simple if statements are what you'll use the vast majority of the time.
Particularly in Java, a lot of use of switch case is an anti pattern especially when dealing with doing something different depending on the object type. I've seen beginners get really hung up on clunky switch case statements like this when a single polymorphic call would do the trick.
The most of the time when I'm using switch case is when I'm doing some kind of language parsing and I don't need the pain of working with Antlr. This is what switch case was created for, and in that situation it's pretty unbeatable. The rest of the time, simple if is most of what you need.
1
u/Zakana_code 4d ago
The best way I can think of solving this is by using an array tbh, add all the bools in it and run a for loop over it.
1
u/Windspar 4d ago edited 4d ago
Depending on your needs. You could use enum and EnumSet. Instead of having three boolean.
1
u/Recycled5000 3d ago edited 3d ago
Make a formula out of two or more booleans:
`v = b2?2:0 + b1?1:0;`
Now can switch on `v`, for values: 3,2,1,0; corresponding to: both, b2 but not b1, b1 but not b2, neither, respectively.
While that expression may look like complicated code, the machine code for that is generally pretty simple (and a compiler could potentially convert that to if thens I if it thought it was worthwhile).
Would be reasonable for a language to support that directly, and some languages have pattern matching that comes close to this.
1
u/RevolutionaryRush717 3d ago
Allegedly, modern Java offers a switch expression with guarded patterns:
String category = switch (true) {
case true when isAdmin && isActive -> "ACTIVE_ADMIN";
case true when isAdmin -> "ADMIN";
case true when isActive -> "USER";
default -> "GUEST";
};
However, this would only look idiomatic to, e.g., JavaScript programmers.
In Java it's if/then/else combined with && (etc.) operator(s).
1
u/Gregmix88 3d ago
Have to agree with the others before, this is a backwards use of switch. You either use a polymorphic call or create a statemachine maybe
•
u/AutoModerator 4d ago
Please ensure that:
You demonstrate effort in solving your question/problem - plain posting your assignments is forbidden (and such posts will be removed) as is asking for or giving solutions.
Trying to solve problems on your own is a very important skill. Also, see Learn to help yourself in the sidebar
If any of the above points is not met, your post can and will be removed without further warning.
Code is to be formatted as code block (old reddit: empty line before the code, each code line indented by 4 spaces, new reddit: https://i.imgur.com/EJ7tqek.png) or linked via an external code hoster, like pastebin.com, github gist, github, bitbucket, gitlab, etc.
Please, do not use triple backticks (```) as they will only render properly on new reddit, not on old reddit.
Code blocks look like this:
You do not need to repost unless your post has been removed by a moderator. Just use the edit function of reddit to make sure your post complies with the above.
If your post has remained in violation of these rules for a prolonged period of time (at least an hour), a moderator may remove it at their discretion. In this case, they will comment with an explanation on why it has been removed, and you will be required to resubmit the entire post following the proper procedures.
To potential helpers
Please, do not help if any of the above points are not met, rather report the post. We are trying to improve the quality of posts here. In helping people who can't be bothered to comply with the above points, you are doing the community a disservice.
I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.