I have a simple enum class in which I would like to have a field called name.
enum class DeviceFieldQuery(val clazz: Class<*>) {
id(Int::class.java),
name(String::class.java),
}
Unfortunately, this does not seem to work in Kotlin. Compilation fails with the message:
Error:(9, 5) Kotlin: Conflicting declarations: enum entry name, public final val name: String
The same Enum class as Java code works fine. How may I solve this in Kotlin?
Enums in Kotlin already have a name property already defined (like Java). This is conflicting with your enum called name. To fix it, you could capitalize it, which is more idiomatic:
enum class DeviceFieldQuery(val clazz: Class<*>) {
Id(Int::class.java),
Name(String::class.java),
}
Related
I'm trying to serialize and deserialize an enum with Jackson.
My enum:
public enum class Type {
#JsonProperty("Typ A")
TypeA,
#JsonProperty("Typ B")
TypeB,
}
Serializing Type.TypeA results in the desired outcome of "Typ A". However Deserializing "Typ A" results in the following error:
java.lang.IllegalArgumentException: No enum constant de.advisori.pzp.task.TaskType.Typ A
I have tried other variations that I found online, such as this:
public enum class Type (#JsonValue val value: String) {
TypeA("Typ A"),
TypeB("Typ B"),
}
but they all yield the same result. Serialization works, deserialization results in the error above.
How do I correctly deserialize an enum with Jackson?
If it makes any difference: I am using it in a Spring Boot RequestMapping as a #RequestParam and return value.
As #dnault pointed out, Jackson isn't used for deserialization here. #RequestParams are never treated as JSON, hence Jackson is never used on them.
Two possible solutions are:
Using Kotlins ability to use spaces in names:
public enum class Type { `Typ A`, `Typ B` } (suggested by #DodgyCodeException)
Using a explicitly defined converter: https://stackoverflow.com/a/69031139/12898394 (pointed in the right direction by #Michal Ziober
I don't think any annotations will work to change the enum values. For this you need to write your own Serializer and Deserializer.
You will likely want to do this:
Create a Serializer by subclassing StdSerializer
Create a Deserializer by subclassing StdDeserializer
If you intend on using the enum as a key in JSON you will need KeyDeserializer too
Create a Module to wrap these up that you can pass to the configuration of Jackson, for that you use SimpleModule
There are many tutorials for this, e.g. https://www.baeldung.com/jackson-deserialization
I have a simple sealed class
sealed class Target {
class User(val id: Long) : Target()
class City(val id: String) : Target()
}
that is used as a parameter of s Spring bean method. I'd like to cache the method via the #Cacheable conditionally only when the parameter is User.
#Cacheable(CACHE_NAME, condition = "#target is Target.User")
open fun getFeed(target: Target): Map<String, Any?> { ... }
However I get an error: '(' or <operator> expected, got 'is'
How can I use is in the condition string?
Thanks to Raphael's answer I was able to find out that
Instead of Kotlin's is there's Java's instanceof.
SpEL has a special syntax for using instanceof where you need to use a wrapper around the class: filterObject instanceof T(YourClass).
The fully qualified class name must be used for classes from any other package than java.lang.
The fully qualified name available on runtime for a class defined inside the body of a sealed class is <package>.<SealedClass>$<SubClass>. In my case it was net.goout.feed.model.Target$User.
Putting all this together yeilds this SpEL
#target instanceof T(net.goout.feed.model.Target$User)
As far as I know, SpEL is java-based, and Java does not have an operator called 'is'. The Java equivalent of 'is' is 'instanceof'. Since Java and Kotlin are interoperable and you can work with Kotlin classes in a Java context, #target instanceof FeedTarget.User should work fine.
I'm trying to save a variable to persistent storage (as described here) but the complier doesn't recognise the 'Current' member of 'Application' class. I'm trying this:
Application.Current.Properties["id"] = id;
but VS2015 assumes that 'application' is an instance of the 'Application' class, not the class itself. (the error given is: 'application' does not contain a definition for 'Current').
The instance is defined in a library module:
public Application Application { get; }
I've tried GetType() and MethodBase.GetCurrentMethod() without success. Sorry if this is basic c# knowledge that I've forgotten.
Use the fully qualified type name including the namespace where the class is declared in:
Xamarin.Forms.Application.Current.Properties["id"] = id;
Kotlin already have number of "static" methods for enum class, like values and valueOf
For example I have enum
public enum class CircleType {
FIRST
SECOND
THIRD
}
How can I add static method such as random(): CircleType? Extension functions seems not for this case.
Just like with any other class, you can define a class object in an enum class:
enum class CircleType {
FIRST,
SECOND,
THIRD;
companion object {
fun random(): CircleType = FIRST // http://dilbert.com/strip/2001-10-25
}
}
Then you'll be able to call this function as CircleType.random().
EDIT: Note the commas between the enum constant entries, and the closing semicolon before the companion object. Both are now mandatory.
As Bloch states in Item 3 ("Enforce the singleton property with a private constructor or an enum type") of Effective Java 2nd Edition, a single-element enum type is the best way to implement a singleton. Unfortunately the old private constructor pattern is still very widespread and entrenched, to the point that many developers don't understand what I'm doing when I create enum singletons.
A simple // Enum Singleton comment above the class declaration helps, but it still leaves open the possibility that another programmer could come along later and add a second constant to the enum, breaking the singleton property. For all the problems that the private constructor approach has, in my opinion it is somewhat more self-documenting than an enum singleton.
I think what I need is an annotation which both states that the enum type is a singleton and ensures at compile-time that only one constant is ever added to the enum. Something like this:
#EnumSingleton // Annotation complains if > 1 enum element on EnumSingleton
public enum EnumSingleton {
INSTANCE;
}
Has anyone run across such an annotation for standard Java in public libraries anywhere? Or is what I'm asking for impossible under Java's current annotation system?
UPDATE
One workaround I'm using, at least until I decide to actually bother with rolling my own annotations, is to put #SuppressWarnings("UnusedDeclaration") directly in front of the INSTANCE field. It does a decent job of making the code look distinct from a straightforward enum type.
You can use something like this -
public class SingletonClass {
private SingletonClass() {
// block external instantiation
}
public static enum SingletonFactory {
INSTANCE {
public SingletonClass getInstance() {
return instance;
}
};
private static SingletonClass instance = new SingletonClass();
private SingletonFactory() {
}
public abstract SingletonClass getInstance();
}
}
And you can access in some other class as -
SingletonClass.SingletonFactory.INSTANCE.getInstance();
I'm not aware of such an annotation in public java libraries, but you can define yourself such a compile time annotation to be used for your projects. Of course, you need to write an annotation processor for it and invoke somehow APT (with ant or maven) to check your #EnumSingleton annoted enums at compile time for the intended structure.
Here is a resource on how to write and use compile time annotations.