2

I have a problem with a variable that is being initialized inside a switch over an enum. It seems that Android Studio (and Eclipse) is ignoring the fact that I'm initializing the variable in all the cases and stated: "Variable 'x' might not have been initialized". I do not want to put a default case.

Code example:

public enum  eTest {
    One,
    Two
}


public class Test {
    public void method(eTest value) {
        String toPrint;

        switch (value) {
            case One:
                toPrint = "One";
                break;
            case Two:
                toPrint = "Two";
                break;
        }

        System.out.println(toPrint); // <-- said error
    }
}

I do not want to initialize the variable but I'm not sure there is a way to do this without initializing (I'd love to learn I'm wrong). Assuming this is not possible I wanted to make sure that new enum values will have to be added to this switch.

First try:
I've tried adding the "Enum 'switch' statement that misses case" to the Android Studio settings, but that has two issues:

  1. It does not fail the build (only shows the place with a red marker).
  2. It depends on the local configuration, and I'd like something that can be enforced on all users.

Second try:
I found that this should be possible with lintOptions in the build.gradle file (I'm using Android Studio, as mentioned), however I could not make it work as desired. I've added the following options to the build.gradle:

lintOptions {
    enable 'EnumSwitchStatementWhichMissesCases'
    abortOnError true
}

This did not work as well, I'm assuming because of two possible issues:

  1. The name is wrong (I took it from the xml that Android Studio created when using the settings).
  2. The default severity of this issue is warning and not error, however I could not find how to change the severity of an issue.

Third try:
It should be possible to add a lint.xml to the Android Studio project, I tried this as well but it did not fail the build, so I'm assuming I did something wrong there. I put the following in the AndroidManifest location:

<?xml version="1.0" encoding="UTF-8"?>
<lint>
    <issue id="EnumSwitchStatementWhichMissesCases" severity="error" />
</lint>

Furthermore:
I've seen this answer, but this is not what I'm looking for, and since this is about a specific build process, I hope that there's a better solution.

The question:
Is it possible to:

1. Solve the original problem. edit: this cannot be done (thanks Blackbelt - see comment below)
and if not:
2. Add the said option to the build process (any option that can be enforced on other users is welcome).

Edit: clarification - I would like to know how to prevent enums with missing cases in compile time, using lint in Android Studio

Community
  • 1
  • 1
MikeL
  • 2,756
  • 2
  • 23
  • 41
  • "I found that this should be possible with lintOptions in the build.gradle file" -- since that is not coming from Android Lint, I doubt it. What you are configuring there in Android Studio, in your first try, is an IntelliJ IDEA inspection, one not from the Android Lint category. "It should be possible to add a lint.xml to the Android Studio project" -- again, this is not an Android Lint check. Android Lint focuses on Android (hence, the name). `enum` is a general Java language construct. – CommonsWare Apr 12 '15 at 13:27
  • You could see if something like [the checkstyle plugin](https://gradle.org/docs/current/userguide/checkstyle_plugin.html) can be configured to catch this thing and fail the build. – CommonsWare Apr 12 '15 at 13:29
  • *Either there is a default label in the switch block or V is [un]assigned after the switch expression.*. [Here](http://docs.oracle.com/javase/specs/jls/se7/html/jls-16.html#jls-16.2.9) – Blackbelt Apr 12 '15 at 13:37
  • @CommonsWare I am finding it hard to understand your comment, are you referring to 'EnumSwitchStatementWhichMissesCases'? Also, I think it will be better not to rely on a plugin if possible, but if no other solution will come I will definitely look into it. Either way, thanks! – MikeL Apr 12 '15 at 14:09
  • Yes. That's an IntelliJ IDEA thing, which Android Studio inherits since it is based off of IDEA. It is not an Android Lint thing or a Gradle thing, which is why I will be stunned if you can configure it using the techniques from your "second try" and your "third try" (using the terminology from your question). – CommonsWare Apr 12 '15 at 14:13
  • @Blackbelt thanks! I wish it was different, this makes no sense to me. – MikeL Apr 12 '15 at 14:34

2 Answers2

1

This error comes from the Java compiler, not from an IntelliJ IDEA inspection or the Android linter. You will see exactly the same error if you compile a regular Java class (non-Android) with the command-line Java compiler. Because of that, none of your attempts to fix it work. The EnumSwitchStatementWhichMissesCases inspection detects a different kind of problem which doesn't occur in this situation.

The reason why the Java compiler reports this as an error is because Java supports separate compilation of classes. Even if right now your switch covers all possible cases of the enum, it's possible that the enum class will be recompiled at a later time and will include additional entries, which will not be handled by your switch.

Because of that, you need to make sure that the variable is initialized even if an unknown enum entry is passed to the method. You can do so either by adding an initializer to the variable declaration or by adding a default branch to the switch (the code in the branch can simply throw an error).

yole
  • 92,896
  • 20
  • 260
  • 197
  • Thanks for your answer, but I think you are answering the the first question, and the fact that this cannot be done has already been established by Blackbelt in the comments above, I'll edit my question to reflect this. – MikeL Apr 13 '15 at 07:01
0

Create a default case.

enum myEnum(one, two, error)
String toPrint;

switch (myEnum)
{
case(one):
toPrint = "one";
break;

case (two):
toPrint = "two";
break;

default:
toPrint = "error";
}
  • Thanks, but I mentioned that I do not want to use a default case. – MikeL Aug 02 '15 at 11:18
  • Out of curiousity I would like to know why you don't wish to use a default since it doesn't have to do anything. What is the gain? Understand I'm not being contrary here. I am genuinely curious. – Brandon Thompson Sep 20 '15 at 18:05
  • The goal is to obligate using all the enum values and getting an error (compile time) otherwise (if new ones are added later on), and the default case does not solve this. – MikeL Oct 06 '15 at 14:01