Including computed `static final` property in an annotation - java

This works,
#JsonRootName(Bay.PLURAL_FORM)
public class Bay {
public static final String PLURAL_FORM = "bays";
This does not (shows error in Eclipse: The value for annotation attribute JsonRootName.value must be a constant expression):
#JsonRootName(Bay.PLURAL_FORM)
public class Bay {
public static final String PLURAL_FORM =
English.plural(CaseFormat.UPPER_CAMEL.to(
CaseFormat.LOWER_CAMEL, Bay.class.getSimpleName()));
Is there a way to include a computed static final in an annotation?

No, there isn't. The annotation attribute values must be constant expressions. (Not exactly, the real value accepted depends on the return type of the annotation method. It's all described here.)
What you can do, however, is give it a key (a String value, enum value, or Class object) that can refer to a value retrieved at runtime. That's how you'll get your dynamic value.

Related

Assign to static final field of same name

To distinguish between an instance field and a local variable of the same name we can qualify access to the field with the prefix this.:
class Test {
public final Foo x;
public Test(Foo x) {
this.x = x;
}
}
I'm trying to do the same thing in a static context by qualifying access with the class name:
import java.util.*;
class Test {
public static final Map<String,Object> map;
static {
Map<String,Object> map = new HashMap<>();
// ...
// assume I fill the map with useful data here
// ...
// now I want to freeze it and assign it to the field
Test.map = Collections.unmodifiableMap(map);
}
}
The compiler wants nothing to do with this code. I have several variables like this and for all of them it keeps yelling: "cannot assign a value to final variable". If I don't assign to it, it complains "variable not initialized" instead. If I assign to the static field at the beginning and try to make the map unmodifiable afterwards, it complains "variable might already have been assigned". It's not happy with anything.
Is this a flaw in the language, or a bug in the compiler? What's the best way to squash the compiler into doing as its told?
The easiest way to solve is as follows:
import java.util.*;
class Test {
public static final Map<String,Object> map;
static {
Map<String,Object> contents = new HashMap<>();
map = Collections.unmodifiableMap(contents);
}
}
Somehow it seems that if you qualify the constant with the class name in Java 8, the compiler won't have it.
Update
After some more digging, it seems that the Java Language Specification explicitly states that the simple (unqualified) name needs to be used for the assignment of final fields (highlighting mine):
For every access of a local variable or blank final field x, x must be
definitely assigned before the access, or a compile-time error occurs.
Similarly, every blank final variable must be assigned at most once;
it must be definitely unassigned when an assignment to it occurs.
Such an assignment is defined to occur if and only if either the
simple name of the variable (or, for a field, its simple name
qualified by this) occurs on the left hand side of an assignment
operator.
It looks like it works to say
public static final <something> x;
static {
x = <whatever>;
}
but not
public static final <something> x;
static {
MyClass.x = <whatever>;
}
I'm not sure why, but that's the behavior I'm getting. To avoid this in your own example, simply change Test.map to map, and change the name of the other map variable.
P.S. Robby's answer explains the reason for the behavior.
I realized a workaround, using a method to init the field instead of a static block. Inside the method the variable can of course be named whatever the foo it wants to be named:
public static final Map<String,Object> map = initMap();
private static Map<String,Object> initMap() {
...
}

Is it possible to map Spring components through annotations using enums?

I'm working with Spring 4, and I have an enum declared like...
public static enum MY_ENUMS {
A(1, "enum1"),
B(2, "enum2");
private final int key;
private final String name;
MY_ENUMS(int key, String name) {
this.key = key;
this.name = name;
}
public String getName() {
return this.name;
}
public int getIndex() {
return this.key;
}
}
Then, from my component I'm attempting to do something like...
// #Named is the equivalent of #Component for this use case
// Making name public and trying this also does not work:
// #Named(MY_ENUMS.A.name)
#Named(MY_ENUMS.A.getName())
public class ServiceImplA implements IService {
#Override
public Object interfaceMethod() {
// Some code specific to ServiceImplA here....
}
}
This doesn't build and I know WHY this doesn't build. Basically, MY_ENUMS.A.getName() doesn't appear to the compilier as being constant, which would mean it cannot be used here. But the point of enums is that they allow you a method to declare constants in a useful way. So, with that being said, is there a way I can specify my component's name by referring to the value in the enum?
I feel this should be possible given that enums are a special case/implementation of constant values but I can't think of a way to work around Spring (or maybe Java's) expectation that the value of the annotation be a straight up constant.
is there a way I can specify my component's name by referring to the
value in the enum?
No, there is not. If the annotation attribute was expecting an enum, you could just use the enum. But invoking a method does not resolve to a constant expression. You might think that you could make the field public and access it directly
#Named(MY_ENUMS.A.name)
but that won't work either because MY_ENUMS.A.name isn't a constant expression either.
The actual reason theat isn't a constant expression is that an enum constant is basically a variable. There is such a thing as a constant variable, which is a constant expression. For a variable to be a constant variable, it needs to be final and initialized with a constant expression. An enum constant is final but is not initialized with a constant expression. Basically an enum constant is compiled to
public static final YourEnum constant = new YourEnum();
The new YourEnum() expression is not a constant expression. And therefore the constant is not a constant variable and can't be used to resolve a String variable which it may be a constant variable.

Instantiate enum class

Consider I am having the following enum class,
public enum Sample {
READ,
WRITE
}
and in the following class I am trying to test the enum class,
public class SampleTest {
public static void main(String[] args) {
testEnumSample(Sample.READ);
}
public static void testEnumSample(Sample sample) {
System.out.println(sample);
}
}
Here I am specifying Sample.READ then passing it as the parameter to the method testEnumSample.
Instead if we want to instantiate the enum class and pass it as parameter what we need to do?
Here I need to specifying Sample.READ to pass it as parameter. Instead if we want to instantiate the enum class and pass it as parameter what we need to do?
What would "instantiate the enum class" even mean? The point of an enum is that there are a fixed set of values - you can't create more later. If you want to do so, you shouldn't be using an enum.
There are other ways of getting enum values though. For example, you could get the first-declared value:
testEnumSample(Sample.values()[0]);
or perhaps pass in the name and use Sample.valueOf:
testEnumSample("READ");
...
Sample sample = Sample.valueOf(sampleName);
If you explained what you were trying to achieve, it would make it easier to help you.
Internally, enums will be translated to something like this
class Sample extends Enum {
public static final Sample READ = new Sample("READ", 0);
public static final Sample WRITE = new Sample("WRITE", 1);
private Sample(String s, int i)
{
super(s, i);
}
// More methods, e.g. getter
}
They should not and cannot be initialized.
Enums doesn't support public constructors and hence, cannot be instantiated. Enums are for when you have a fixed set of related constants. Exactly one instance will be created for each enum constant.
Check my answer in another post.
There are 2 ways:
Use Enum.valueOf() static function, then cast it into your enum type.
Enum v = Enum.valueOf(TheEnumClass, valueInString);
Use class.getEnumConstants() function to get the list of the enum constants, and loop this list and get.
Plugins[] plugins = Plugins.class.getEnumConstants();
for (Plugins plugin: plugins) {
// use plugin.name() to get name and compare
}
You cannot create a new enum instance. Otherwise it won't be an enum.
You can reference an already existing enum. As in your example
Sample sample = Sample.READ;
The elements within an Enum are objects that are instances of the class.
You no need to create an object of Enum.
Here is a similar issue
Refer this
You cannot instantiate an Enum, thats the whole point of having an Enum.
For example you would use enum when defining properties of some thing which would never change like:
enum TrafficLight {
RED("stop"),
YELLOW("look"),
GREEN("go")
}
private string value;
private TrafficLight(String value) {
this.value = value;
}
public getValue() {
return value;
}
Now if you want to get the value of the enum, you can use valueOf method of enums. The static methods valueOf() and values() are created at compile time and do not appear in source code. They do appear in Javadoc, though;
TrafficLight trafficLight = TrafficLight.valueOf("RED")
String value = trafficLight.getValue();
If you do TrafficLight.valueOf("XYZ"), it will throw an IllegalArgumentException
I'm answering to the first question. You can easily do it like this:
public static void main(String[] args) {
Sample.READ.testEnumSample();
}
public enum Sample {
READ,
WRITE;
public void testEnumSample() {
System.out.println(this);
}
}
Fetch a good book on Java Basics and read it.
Anyways, Enums in java are classes with fixed number of objects and objects are defined by its attributes.
Again, you can read something about it here

Extending String for Typesafety - Java

I am considering a design in Java where I want a string object but with more 'type-safety' than just being of class String. This because I have a number of 'POJO' objects for Hibernate, representing my database tables. Each of these classes has a large number of public static fields representing the properties of the class, I.e.:
public class PersistantBean {
public static String PROP_FIELD_COLUMN_ONE="columnOne";
public static String PROP_FIELD_COLUMN_TWO="columnTwo";
// [...]
These properties are used when we need to access a property in a generic way, e.g. for code I am currently writing .parseAndSet(PROP_FIELD_PRICE,"£3.00").
I would like to be able to add a stronger type to the PROP_FIELD_... fields so that I could write
public class PersistantBean {
public static PropertyName PROP_FIELD_COLUMN_ONE="columnOne";
public static PropertyName PROP_FIELD_COLUMN_TWO="columnTwo";
// [...]
with minimal changes to other parts of the project,
so that parseAndSet would look like:
public void parseAndSet(PropertyName prop, String priceToParse)
Essentially, I would like PropertyName to be a type that is like String in everyway apart from the compiler would error if I tried to put a String where a PropertyName was expected, is any design pattern like this possible.
(I am shying away from Enums, although now I mention it, Enums may be the way to go.)
For Java 1.5 and above, just use an enum type.
For Java 1.4 and below, use the typesafe enum pattern. E.g.
public class Suit {
private final String name;
public static final Suit CLUBS =new Suit("clubs");
public static final Suit DIAMONDS =new Suit("diamonds");
public static final Suit HEARTS =new Suit("hearts");
public static final Suit SPADES =new Suit("spades");
private Suit(String name){
this.name =name;
}
public String toString(){
return name;
}
}
enum(enumeration) is a better idea, which above mentioned scenario.
eg:
enum PROP_FIELD_COLUMN {
columnOne, columnTwo,etc
}
I'd use an Enum. That way you get compile-time checking.
If your Strings really have a good fairly standard naming convention, like "column" + "One", "Two", etc. as in your example, you could save a lot of work by combining an enum for the prefix with an int for the suffix. So, create a class or utility method that takes an enum for the prefix, e.g. COLUMN, and combines it with an int, say 2, to yield "columnTwo".
An alternative might be be for your code, like parseAndSet, to validate the passed in String against an array or Collection of legal Strings, or maybe a regex, and throw an IllegalArgumentException. You'd get runtime checking and if you have good unit tests this could work.
EDIT ADDED
#sethupathi.t had a nice idea in his answer - In some cases it may be preferable to make the 2nd argument (for which I used an int) also an enum.
As far as I can tell, there are two reasonable ways to do what you want to do.
The first way (and probably best way, if it works for you) is to use an enum, as mentioned in another answer.
The second way, which may be necessary if you do not know all of your PropertyName's at runtime, would be to use a PropertyNameFactory along the lines of:
public class PropertyNameFactory
{
public static PropertyName getPropertyName(String propertyName)
{
// Check validity of the propertyName against what ever rules we
// have defined (maybe valid propertyNames are read from a DB at
// startup, etc).
if (isValid(propertyName))
{
// Ideally get from a cache, but for the sake of the example
// we will create a new one...
return new PropertyName(propertyName);
}
throw new IllegalArgumentException("Invalid property name: " + propertyName);
}
}
This is not ideal in that it does not provide true type safety of your property names, but it does ensure their validity.
I have to second the Enum answers.
However, a more literal answer to your question is that Java provides an interface for String-like objects, java.lang.CharSequence, and many parts of the standard Java libraries have been updated to accept CharSequence where appropriate. This will not however give you the behavior that you want, which is to have your class behave as a subtype of String.

creating an enum/final class in java

I'm trying to figure out the best way to create a class whose sole purpose is to be a container for global static variables. Here's some pseudocode for a simple example of what I mean...
public class Symbols {
public static final String ALPHA = "alpha";
public static final String BETA = "beta";
/* ...and so on for a bunch of these */
}
I don't need constructors or methods. I just need to be able to access these "symbols" from everywhere simply by calling: Symbols.ALPHA;
I DO need the actual value of the String, so I can't use an enum type. What would be the best way to accomplish this?
Well, it's not clear what else you need beyond the code you've already given - other than maybe making the class final and giving it a private constructor.
However, in order to avoid accidentally using an inappropriate value, I suspect you would be better off making this an enum, like this:
public enum Symbol {
ALPHA("alpha"),
BETA("beta");
private final String value;
private Symbol(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
That way:
You can't accidentally use Symbol.ALPHA where you're really just expecting a string
You can't accidentally use a string where you're really expecting a symbol
You can still easily get the string value associated with a symbol
You can switch on the different symbol values if you need to
You can do that using an interface. No need to construct, values are public, static and final, and can obviously be strings. Such an interface would look similar to your class:
public interface Symbols {
public static final String ALPHA = "alpha";
public static final String BETA = "beta";
/* and so on */
}
You can access the fields directly from everywhere in your code (given it's public) as Symbols.ALPHA etc.
Or, you can use an enum even though you want strings - ALPHA.toString() will return "ALPHA" (and if you want a slightly different string, you can override toString())
Are these configuration parameters or simply "constants" which don't change no matter what? For the former, I'd rather create a configuration class and instantiate it with different values for each environment. Then simply use dependency injection to inject these configurations in different classes. If your requirement is the latter or you are not using DI (Spring/Guice), static classes/interfaces are good to go.

Categories

Resources