How to only allow certain values as parameter for a method in Java?
Asked Answered
M

3

12

I want to write a method that only takes certain values for a parameter, like f.e. in the Toast class in Android. You can only use Toast.LENGTH_SHORT or Toast.LENGTH_LONG as duration for the method makeText(Context context, int resId, int duration). I had a look at the source code of the Toast class but found nothing there. How can I achieve that?

Menashem answered 12/7, 2014 at 16:41 Comment(2)
You want to show toast for a certain time other than the one provided by FrameWork?Teletypewriter
you can use Enum docs.oracle.com/javase/tutorial/java/javaOO/enum.htmlEncephaloma
C
8

Use an Enum Type, from the Java Tutorial,

An enum type is a special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it. Common examples include compass directions (values of NORTH, SOUTH, EAST, and WEST) and the days of the week.

As an example,

public enum MyEnum {
  ONE, TWO;
}

public static void myMethod(MyEnum a) {
  // a must be MyEnum.ONE or MyEnum.TWO (in this example)
}

Edit

To get String(s) from your enum types you can add field level values (which must be compile time constants) with something like,

public enum MyEnum {
  ONE("uno"), TWO("dos");
  MyEnum(String v) {
    value = v;
  }
  private String value;
  public String getValue() {
    return value;
  }
}
Cotillion answered 12/7, 2014 at 16:44 Comment(13)
I want the parameters to be of a certain type, let's say string. How can I do that with Enums? Is that even possible?Menashem
@Menashem You can give your Enum(s) String values, but they must be Enum types (which are actually constants). Let me edit to give you an example.Cotillion
@Menashem you want to give duration a custom value for the toast?Teletypewriter
@Teletypewriter No. I want my method to only accept certain fix values for a parameter.Menashem
@Menashem Then check the values to make sure they're allowable. You say "type", but you actually mean "value". You either need to use enums, types, or validate the values somehow.Whew
@Menashem You can define a ToastType (or ToastLength) enum similar to Elliott's example, but saving an int and constructing the two enumerations with int values Toast.LENGTH_LONG and Toast.LENGTH_SHORT. Now, have your methods use a ToastType argument instead of an int argument, and the methods can use getValue() to get the int when calling makeText.Shulem
@Shulem I understand. But how does this work with int as parameter type in the Toast class?Menashem
@Menashem you will have to have a Custom Toast class. If you want the features from the framework copy the same and modify the way you want.Teletypewriter
@Teletypewriter It's not about the Toast class. It was just an example for a general problem.Menashem
@Menashem You'd need a wrapper class or a wrapper method, i.e. your own makeText method that uses a ToastType argument and turns around and calls Toast.makeText. But if your aim is to prevent Toast.makeText from being called with illegal duration values, this will help accomplish that.Shulem
@Shulem How can I do that? Can you give me an example? I want something like myMethod(String myParam) where I can use only certain values for myParam. I'd prefer that those would be final Strings in my class that contains myMethod(String myParam). As I said, like in the Toast class. But maybe Google uses some other magic that we don't see here. ;-)Menashem
@Menashem If you're really set on using a String parameter, instead of defining another class (such as an enum) to represent the possible values, then this isn't going to work for you. Your alternative is to have the method check for valid inputs and throw an exception if they're not.Shulem
@Shulem You are right. But the solution using an Enum seems the better way because it cannot fail by throwing an Exception. Seems more safe though.Menashem
N
42

You can use @IntDef or @StringDef annotations for your methods like this:

@Retention(SOURCE)
@IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
public @interface NavigationMode {}
public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;
...
public abstract void setNavigationMode(@NavigationMode int mode);
@NavigationMode
public abstract int getNavigationMode();
Nedranedrah answered 10/5, 2016 at 20:43 Comment(2)
the exact answer, should be accepted instead of the other oneChristology
@OmarElDon the question was asked for Android specifically so I provided answer for Android. You can see the tags of the question.Nedranedrah
C
8

Use an Enum Type, from the Java Tutorial,

An enum type is a special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it. Common examples include compass directions (values of NORTH, SOUTH, EAST, and WEST) and the days of the week.

As an example,

public enum MyEnum {
  ONE, TWO;
}

public static void myMethod(MyEnum a) {
  // a must be MyEnum.ONE or MyEnum.TWO (in this example)
}

Edit

To get String(s) from your enum types you can add field level values (which must be compile time constants) with something like,

public enum MyEnum {
  ONE("uno"), TWO("dos");
  MyEnum(String v) {
    value = v;
  }
  private String value;
  public String getValue() {
    return value;
  }
}
Cotillion answered 12/7, 2014 at 16:44 Comment(13)
I want the parameters to be of a certain type, let's say string. How can I do that with Enums? Is that even possible?Menashem
@Menashem You can give your Enum(s) String values, but they must be Enum types (which are actually constants). Let me edit to give you an example.Cotillion
@Menashem you want to give duration a custom value for the toast?Teletypewriter
@Teletypewriter No. I want my method to only accept certain fix values for a parameter.Menashem
@Menashem Then check the values to make sure they're allowable. You say "type", but you actually mean "value". You either need to use enums, types, or validate the values somehow.Whew
@Menashem You can define a ToastType (or ToastLength) enum similar to Elliott's example, but saving an int and constructing the two enumerations with int values Toast.LENGTH_LONG and Toast.LENGTH_SHORT. Now, have your methods use a ToastType argument instead of an int argument, and the methods can use getValue() to get the int when calling makeText.Shulem
@Shulem I understand. But how does this work with int as parameter type in the Toast class?Menashem
@Menashem you will have to have a Custom Toast class. If you want the features from the framework copy the same and modify the way you want.Teletypewriter
@Teletypewriter It's not about the Toast class. It was just an example for a general problem.Menashem
@Menashem You'd need a wrapper class or a wrapper method, i.e. your own makeText method that uses a ToastType argument and turns around and calls Toast.makeText. But if your aim is to prevent Toast.makeText from being called with illegal duration values, this will help accomplish that.Shulem
@Shulem How can I do that? Can you give me an example? I want something like myMethod(String myParam) where I can use only certain values for myParam. I'd prefer that those would be final Strings in my class that contains myMethod(String myParam). As I said, like in the Toast class. But maybe Google uses some other magic that we don't see here. ;-)Menashem
@Menashem If you're really set on using a String parameter, instead of defining another class (such as an enum) to represent the possible values, then this isn't going to work for you. Your alternative is to have the method check for valid inputs and throw an exception if they're not.Shulem
@Shulem You are right. But the solution using an Enum seems the better way because it cannot fail by throwing an Exception. Seems more safe though.Menashem
L
1

To use ints as is done with the Toast class, you can do something like this:

public class MyClass {
    //by convention, constant names are all caps
    public static final int VALUE_ONE = 0;
    public static final int VALUE_TWO = 1;


    public void myMethod(int value) throws InvalidParameterException {
        if(value != VALUE_ONE || value != VALUE_TWO) {
            throw new InvalidParameterException();
            //or set default value instead of throwing an exception
        }
        else {
            //your code
        }
    }
}

VALUE_ONE and VALUE_TWO are static and final, meaning that throughout the entire application there will only be one instance of that variable, and its value will never change (if you know C, it is similar to a #DEFINE). Thus, when someone passes MyClass.VALUE_ONE as an argument, you know exactly what it is, every time, while the caller doesn't necessarily need to know the integer value behind the constant. And then you will want to do a runtime check to make sure that what was passed in was one of the valid values, and if not, throw an exception. Or, if the value passed in isn't very critical, you could just set a default value if the argument is incorrect rather than throw an exception.

Longshoreman answered 12/7, 2014 at 17:18 Comment(1)
I see. I hab something like that in mind but I was looking for a solution where I can avoid something like throwing an Exception. So I'm going with the Enum solution. But if someone wants to avoid using Enums, your solution seems correct.Menashem

© 2022 - 2024 — McMap. All rights reserved.