尝试在一个通用枚举类中使用valueOf。

huangapple go评论59阅读模式
英文:

Trying to use valueOf with a generic enum class

问题

I can help with the translation. Here is the translated text:

我正在创建一个类,在其构造函数中接受一个 enum class,问题是我希望它能够接受任何枚举,所以我正在使用以下泛型定义:<T extends Enum<T>>

我的问题是为什么我不能使用 enumClass.valueOf(string)?(我收到以下错误:The method valueOf(String) is undefined for the type Class<T>)。我发现使用 Enum.valueOf(enumClass, string) 可以正常工作,但我不理解 为什么,任何帮助都将不胜感激。

public class ValidadorEntradaEnum<T extends Enum<T>> {
    private final Class<T> enumClass;

    public ValidadorEntradaEnum(Class<T> enumClass) {
        this.enumClass = enumClass;
    }

    public boolean containsString(String string) {
        try {
            Enum.valueOf(enumClass, string);
            return true;
        } catch (IllegalArgumentException e) {
            return false;
        }
    }
}
英文:

I'm making a class that takes in an enum class in it's constructor, the thing is that I want it to be able to take in any enum so I'm using the following generic definition: &lt;T extends Enum&lt;T&gt;&gt;.

My question is why can't I use enumClass.valueof(string)? (I get the following error: The method valueOf(String) is undefined for the type Class&lt;T&gt;). I've found that using Enum.valueOf(enumClass, string) works but I don't understand why, any help is appreciated.

public class ValidadorEntradaEnum&lt;T extends Enum&lt;T&gt;&gt; {
    private final Class&lt;T&gt; enumClass;

    public ValidadorEntradaEnum(Class&lt;T&gt; enumClass) {
        this.enumClass = enumClass;
    }

    public boolean containsString(String string) {
        try {
            Enum.valueOf(enumClass, string);
            return true;
        } catch (IllegalArgumentException e) {
            return false;
        }
    }
}

答案1

得分: 0

The problem is, enumClass is a Class<T extends Enum<T>>, not an enum. You probably did something like this to get enumClass populated.

final Class<T extends Enum<T>> enumClass = SomeEnum.class;

But remember, java.lang.Class does not have the valueOf method! The only ones that have valueOf is java.lang.Enum and this SomeEnum that I made!

I think I see the reason why you are confused.

SomeEnum represents your enum's class and gives up the static methods, fields, and values.

SomeEnum.class represents your enum's CLASS FILE! It's job is to DESCRIBE your enum's capabilities, but it cannot USE any of the capabilities of your enum!

Because if so, then you could do this.

SomeEnum.class.valueOf(someString) //WRONG, not possible

SomeEnum.valueOf(someString) just means "call the static method valueOf on SomeEnum for the parameter someString"

Now, if your next question is, how do I get the static method valueOf when I only have a java.lang.Class? Well, the easiest way is to use Enum.valueOf(someClass, someString), just like you already found. That's literally the reason why they created that method. They knew that someone like you would come around asking how to turn a String into an enum when you only have the Class of the enum. So, they made that method.

英文:

My question is why can't I use enumClass.valueof(string)?

In your example, enumClass is of type Class&lt;T extends Enum&lt;T&gt;&gt;. So, if we look at the documentation for java.lang.Class and do a Ctrl+F for valueOf, we see that there is no such method called valueOf.

However, if we go to the documentation for java.lang.Enum, we see that there is a valueOf method, which takes in 2 parameters -- a Class with a type parameter of &lt;T extends Enum&lt;T&gt;&gt; and a String.

Let's say that I have an enum called SomeEnum.

enum SomeEnum
{

    SOME_ENUM_VALUE,
    ;

}

When I press compile, java takes this enum definition and turns it into a class with a couple of special methods. One of those methods is the valueOf method which takes in a String. This is the one you seem to want.

Let's say that I have a String that I want to convert into SomeEnum.

final String someString = &quot;SOME_ENUM_VALUE&quot;;

So then your question is, why can't I do enumClass.valueOf(someString)?

The problem is, enumClass is a Class&lt;T extends Enum&lt;T&gt;&gt;, not an enum. You probably did something like this to get enumClass populated.

final Class&lt;T extends Enum&lt;T&gt;&gt; enumClass = SomeEnum.class;

But remember, java.lang.Class does not have the valueOf method! The only ones that have valueOf is java.lang.Enum and this SomeEnum that I made!

I think I see the reason why you are confused.

Some people see this...

SomeEnum.valueOf(someString)

...and think that it is equivalent to typing this...

SomeEnum.class.valueOf(someString)

...which is incorrect.

SomeEnum represents your enum's class and gives up the static methods, fields, and values.

SomeEnum.class represents your enum's CLASS FILE! It's job is to DESCRIBE your enum's capabilities, but it cannot USE any of the capabilities of your enum!

Because if so, then you could do this.

SomeEnum.class.valueOf(someString) //WRONG, not possible

SomeEnum.valueOf(someString) just means "call the static method valueOf on SomeEnum for the parameter someString"

Now, if your next question is, how do I get the static method valueOf when I only have a java.lang.Class? Well, the easiest way is to use Enum.valueOf(someClass, someString), just like you already found. That's literally the reason why they created that method. They knew that someone like you would come around asking how to turn a String into an enum when you only have the Class of the enum. So, they made that method.

答案2

得分: 0

以下是已翻译好的部分:

一参数的 valueOf() 方法和 values() 方法是静态方法,它们在每个枚举类型上都有定义,如Java语言规范的 "Enum Members" 部分所规定。

它们不是从 Enum 类或任何其他类中 "继承" 的,因为在Java中无法重写静态方法。因此,您在Java标准库文档中看不到这些方法。与实例方法不同,静态方法调用时要么 1) 明确指定类的名称,如 <类名>.<静态方法名称>(),2) 在不明确指定的情况下调用它,如 <静态方法名称>(),或 3) 在表达式上调用它,如 <某些表达式>.<静态方法名称>()。如果使用#1,则将调用命名类的方法。如果使用#2,则将调用代码所在类的方法。如果使用#3,则将使用表达式的编译时类型作为要使用的类。令人费解的是,它不会使用表达式的运行时值。因此,即使表达式的运行时值是对具有相同名称的静态方法的子类的引用,或者表达式的运行时值是 null,它仍然会在编译时类型上调用静态方法。

Enum 类不定义 values() 或一参数的 valueOf() 静态方法。即使它定义了这些方法,这些方法也将无用,因为您无法使用它们来调用枚举类型的 values() 或一参数的 valueOf() 静态方法,因为在编译时确定要调用静态方法的类。在Java中没有办法在运行时动态确定的类上调用静态方法,除非使用反射。您不能仅仅在表示您的枚举类型的 Class 实例上调用静态方法,因为静态方法不是 Class 实例上的方法,只有 文档中记录的 Class 类的方法可以在 Class 实例上调用。

因此,如果您愿意,可以通过反射调用您的类的一参数的 valueOf() 方法,它将工作:

Method m = enumClass.getMethod("valueOf", String.class);
T value = (T) m.invoke(null, string);

Java标准库的作者决定提供一个方便的API来实现这一点,而不使用反射,通过提供两参数的 Enum.valueOf() 方法,正如您已经发现的:T value = Enum.valueOf(enumClass, string)。这两参数的 Enum.valueOf() 方法与枚举类型的一参数的 valueOf() 方法完全无关,除了名称相同。它不是一种魔法语法,允许您通过使用两个参数调用动态确定的类上的静态方法 -- 它只是一个为这个用例提供的单独API。

英文:

The one-argument valueOf() method and the values() method are static methods that are defined on each enum type, as specified in the "Enum Members" section of the Java Language Specification.

They are not "inherited" from the Enum class or any other class, since static methods cannot be overridden in Java. So you will not see these methods in the Java standard library documentation. Unlike with instance methods, which class a static method is called on is fixed at compile time. To call a static method, you would either 1) explicitly specify the name of a class, like &lt;name of class&gt;.&lt;static method name&gt;(), 2) call it without explicitly qualifying it, like &lt;static method name&gt;(), or 3) call it on an expression, like &lt;some expression&gt;.&lt;static method name&gt;(). If you use the #1, it will call the method of the named class. If you use #2, it will call the method of the class the code is in. If you use #3, it will use the compile-time type of the expression as the class to use. Counterintuitively, it will not use the runtime value of the expression. So even if the runtime value of the expression was a reference to a subclass which has a static method of the same name, or the runtime value of the expression was null, it will still call the static method on the compile-time type.

The Enum class does not define the values() or one-argument valueOf() static methods. Even if it did, these methods would be useless -- you would not be able to use them to call the values() or one-argument valueOf() static methods of an enum type, because the class that a static method is called on is determined at compile time. There is no way in Java to call a static method on a class that is determined dynamically at runtime, except using reflection. You cannot just call the static method on the Class instance representing your enum type, because static methods are not methods on the Class instance -- only the methods documented as methods of the Class class can be called on Class instances.

So if you wanted, you could call the one-argument valueOf() method on your class via reflection, and it would work:

Method m = enumClass.getMethod(&quot;valueOf&quot;, String.class);
T value = (T) m.invoke(null, string);

The authors of the Java standard library decided to provide a convenience API to accomplish this without reflection, by providing the two-argument Enum.valueOf() method, as you have discovered: T value = Enum.valueOf(enumClass, string). This two-argument Enum.valueOf() method is completely unrelated to the one-argument valueOf() method of enum types, other than having the same name. It is not some magical syntax that allows you to call a static method on a dynamically-determined class by calling it with two arguments -- it is just simply a separate API provided for this one use case.


(As an aside, the same thing is true for the values() static method of enum types. There is no way to call it on a class dynamically determined at runtime, except using reflection. You can achieve it using reflection, and it works:

Method m = enumClass.getMethod(&quot;values&quot;);
T[] values = (T[]) m.invoke(null);

However, they also provided a convenience API to achieve this without reflection -- the getEnumConstants() method on the Class class representing the enum type: T[] values = enumClass.getEnumConstants().)

答案3

得分: -2

你可以使用Class.getEnumConstants从其类对象获取枚举的枚举值。每个枚举值都有一个value,您可以使用它来确定您的枚举是否包含您正在检查的字符串。

英文:

You can use Class.getEnumConstants to get the enum values of an enum from its class object. Each enum value has a value which you can then use to determine if your enum contains the string you're checking.

huangapple
  • 本文由 发表于 2023年5月11日 03:50:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76222121.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定