How to declare a constant hierarchical data structure in Java? - java

I'd like to be able to declare a Java class Ref such that I could, elsewhere in code, do things like this:
switch (v)
{
case Ref.LicenseCode: ....;
case Ref.Widget.MaxWeight: ....;
case Ref.Widget.MolyBolt.ThreadsPerInch: ....;
}
Ref is intended to be constant data structure representing a hierarchical set of constant values, such as often appears in standards documents or other reference material. I want values that are truly constant (so they can be used in a case statement).
I thought I might be able to do this by nesting class definitions, and it works... to a point. For example this:
public final class Ref
{
public final static int LicenseCode = 800;
public final class Widget
{
public final static int MaxWeight = 5000;
}
}
lets me write this:
switch (v)
{
case Ref.LicenseCode: ....;
case Ref.Widget.MaxWeight: ....;
}
but when I try to nest down to the third level:
public final class Ref
{
public final static int LicenseCode = 800;
public final class Widget
{
public final static int MaxWeight = 5000;
public final class MolyBolt
{
public final static int ThreadsPerInch = 12;
}
}
}
I am told that:
"Ref.Widget.MolyBolt cannot be resolved or is not a field."
Am I doing something wrong? Or have I bumped up against one of the edges of Java? Is there some other way to accomplish my goal? I am running under Windows Vista, JCK 1.6.0-21, using Eclipse Java Development Tools 3.5.2.r352.

Looks like bill of material information to me. Embedding this in Java classes as static data seems to be terribly rigid to me. It's far more natural to store it in a relational, hierarchical, object, or graph database.
The other problem is that the code to process this will be a spaghetti forest of if/then/else or switch statements to process.
It's hard to overstate just how wrong-headed this appears to be. You might get an answer that will allow you to proceed, but this can only end in grief.

How are you referencing the ThreadsPerInch field? This works for me:
public final class Ref {
public final static int LicenseCode = 800;
public final class Widget {
public final static int MaxWeight = 5000;
public final class MolyBolt {
public final static int ThreadsPerInch = 12;
}
}
public static void main(String[] args) {
int v = Integer.valueOf(args[0]);
switch (v) {
case Ref.LicenseCode:
break;
case Ref.Widget.MaxWeight:
break;
case Ref.Widget.MolyBolt.ThreadsPerInch:
break;
}
}
}
The only thing I'd change is to make inner classes static, though you're probably not going to instantiate any objects of this class anyway.

Related

Legitimate uses for static initializer?

I remember a couple years ago I was using static initializers to call class-level setup operations. I remember it having very bizarre behaviors and I just decided to steer clear from them. Maybe it was because I was messing up the top-bottom order or being a newbie. But I am encountering a need to revisit them and I want to make sure there is not a better way that is just as concise.
I know it is not fashionable, but I often have data-driven classes that maintain a static list of instances imported from a database.
public class StratBand {
private static volatile ImmutableList<StratBand> stratBands = importFromDb();
private final int minRange;
private final int maxRange;
private static ImmutableList<StratBand> importFromDb() {
//construct list from database here
}
//constructors, methods, etc
}
When I have dozens of table-driven classes like this one, this pattern is very concise (yes I know it tightly couples the class with one source of data/instances).
However, when I discovered the goodness of Google Guava I want to use the EventBus to update the static list when a certain event posted. I would create a static final boolean variable just to call a static method that initialized the registration.
public class StratBand {
private static volatile ImmutableList<StratBand> stratBands = importFromDb();
private static final boolean subscribed = subscribe();
private final int minRange;
private final int maxRange;
private static ImmutableList<StratBand> importFromDb() {
//construct list from database here
}
//constructors, methods, etc
private static boolean subscribe() {
MyEventBus.get().register(new Object() {
#Subscribe
public void refresh(ParameterRefreshEvent e) {
stratBands = importFromDb();
}
});
return true;
}
}
This got annoying very quickly, because the compiler would throw warnings over the subscribed variable never being used. Also, it just added clutter. So I'm wondering if it is kosher to use the static initializer, and there really is no better way if I do not decouple this into two or more classes. Thoughts?
public class StratBand {
private static volatile ImmutableList<StratBand> stratBands = importFromDb();
static {
MyEventBus.get().register(new Object() {
#Subscribe
public void refresh(ParameterRefreshEvent e) {
stratBands = importFromDb();
}
});
}
private final int minRange;
private final int maxRange;
private static ImmutableList<StratBand> importFromDb() {
//construct list from database here
}
//constructors, methods, etc
}
So I'm wondering if it is kosher to use the static initializer
The funny thing is that
private static final boolean subscribed = subscribe();
and
private static final boolean subscribed;
static {
subscribed = subscribe();
}
get compiled to exactly the same bytecode. So using the needless static variable is strictly worse.
But until we are ready to scale up to a DI-driven framework,
Discover Guice. Don't call it framework (though it is). It's easy to use and let's you get rid of static.
Or do it manually. Rewrite your class by dropping all static modifiers and pass it everywhere you need it. It's rather verbose sometimes, but stating dependencies explicitly allows you to test classes in isolation.
The way it is, you can't test StratBand without hitting the database, no matter how trivial the method under test is. The problem is the coupling of every StratBand instance to the list of all StratBands.
Moreover, you can't test the behavior dependent on the stratBands contents as it always get loaded from the DB (sure, you can fill your DB correspondingly, but it's a big pain).
For starters, I'd create StratBandManager (or StratBands or whatever name you like) and move all the static functionality to it. In order to easy the transition, I'd create a temporary class with static helpers like
private static StratBandManager stratBandManager = new StratBandManager();
public static ImmutableList<StratBand> stratBands() {
return stratBandManager.stratBands();
}
Then deprecate it all and replace it by DI (using Guice or doing it manually).
I find Guice useful even for small projects. The overhead is tiny as often there's no or hardly any configuration.

Can I assign a static nested class to a variable?

I have a few different button layouts for some controllers mapped inside nested classes. Here's an example:
public class ControllerMap{
public static class Type1{
public static final int BUTTON_A = 1,
BUTTON_B = 2;
}
public static class Type2{
public static final int BUTTON_A = 2,
BUTTON_B = 1;
}
}
I want to make a variable to reference which one to use throughout my code. Something like layout = ControllerMap.Type1;. I'm pretty sure this isn't actually possible, but is there any other way I can do this?
If you want them to be used as layout templates, you could do something like this:
public class Template
{
public static final Template type1 = new Template(1, 2);
public static final Template type2 = new Template(2, 1);
public int buttonA;
public int buttonB;
public Template(int buttonA, int buttonB)
{
this.buttonA = buttonA;
this.buttonB = buttonB;
}
}
And then you can use the layout variable like this:
public static Template layout = Template.type1;
Yes you could refer it from anywhere since both your class are public and class variables are public too like:
int button = ControllerMap.Type1.BUTTON_A;//from anywhere and is resolved at compile time
But if you need it runtime, you could just inject appropriate instance and create getter/setter instead of exposing the field directly.
I think you are trying to use 'static' in an OO way which will never work. In this case you can use the Strategy Pattern to solve your issue, but you will have to adapt your code.
Make your class Type1 and Type2 implement a interface (iController). Then anywhere in your code you can can assign:
iController controller = new Type1();

Assign each enum instance a growing ID

I'm just starting my first steps with Java, learned all the basics but then found a problem with an enum I need, so forgive me, if the solution to my problem is something very obvious:
So I've got this enum and want to add a unique id to each instance counting from 0 upwards, but without having to add another parameter to each constructor calling (because this can later on lead to errors ofc).
public enum TerrainTile{
WATER(1), GRASSLAND(1), HILL(2), FORREST(2), BLANK(99);
private final int id;
private final int moveCost;
private boolean hidden = true;
private TerrainTile(int moveCost) {
this.moveCost = moveCost;
}
And I thought to just add a
static int nextID = 0;
and edit the constructor to
private TerrainTile(int moveCost) {
this.id = nextID++;
this.moveCost = moveCost;
}
But I get an error message that it can not refer to a static field inside the initializer.
Is there any workaround?
You can use the ordinal() method for it. It is based on the order in which the members are declared in the source-code and counted from zero. So I guess, exactly what you need.
Just a note:
You can get your original enum member from ordinal number by calling .values()[index]
example:
int hillOrdinal = TerrainTile.HILL.ordinal(); // 2
TerrainTile hill = TerrainTile.values()[hillOrdinal];
It sounds like you are trying to combine class features into an enum. I'd be particularly wary of non-final, non-static member fields in an enum declaration. The behaviour you want seems to be best served by using a TerrainTile class (possibly a flyweight if you truly want the single-instance-per-type behaviour) and a TerrainTileType (or TerrainTile.Type) enum. Something like this:
public class TerrainTile {
public enum Type {
WATER(1), GRASSLAND(1), HILL(2), FORREST(2), BLANK(-1);
public final int MOVE_COST;
private TerrainTile(int moveCost) {
this.MOVE_COST = moveCost;
}
public boolean isTraversable() {
return (MOVE_COST > 0);
}
}
private final Type type;
private final Image texture;
...
private TerrainTile(Type type) {
this.type = type;
}
private static final Map<Type, TerrainTile> tiles = new EnumMap<>();
static {
// instantiate one TerrainTile for each type and store into the tiles Map
for (Type type: Type.values()) {
// Eventually, also load tile textures or set Color in this step
tiles.put(type, new TerrainTile(type));
}
}
public static TerrainTile getTile(Type type) {
// return the reference to the TerrainTile of this type
return tiles.get(type);
}
...
}

Are enums less maintainable than public static final constants?

I was recently discussing enums vs public static final constants with a friend. I told him that public static final constants are more maintainable than enums, sometimes faster (android developer docs confirm this), and more convenient as well. I also said that you lose functionality when using enums as well:
You cannot extend an enum.
You cannot instantiate an enum.
He then said you shouldn't be using an enum if you need to instantiate or extend an enum. I then replied that's why we should just use constants because it is more maintainable; What if mid project we need to instantiate an enum or extend it? Then we would have to change everything.
An example demonstrating enums vs constants I made to illustrate my point:
public enum WeekDay {
/*
* We will start at 1 for demonstration
*/
SUNDAY("Sunday", 1), MONDAY("Monday", 2), TUESDAY("Tuesday", 3), WEDNESDAY(
"Wednesday", 4), THURSDAY("Thursday", 5), FRIDAY("Friday", 6), SATURDAY(
"Saturday", 7);
/*
* Notice we cannot do this...This is where enums fail.
*/
// LUNES("lunes",1), MARTES("martes",2);
private String dayName;
private int dayIndex;
private WeekDay(String dayName, int dayIndex) {
this.dayName = dayName;
this.dayIndex = dayIndex;
}
public String getDayName() {
return dayName;
}
public void setDayName(String dayName) {
this.dayName = dayName;
}
public int getDayIndex() {
return dayIndex;
}
public void setDayIndex(int dayIndex) {
this.dayIndex = dayIndex;
}
#Override
public String toString() {
return this.dayName + ": " + this.dayIndex;
}
}
What if we need Spanish week days as well? The enum falls short because you cannot extend it (you would have to do some copy and paste action).
Contrast the enum with this:
public class WeekDayClass {
private int dayIndex;
private String dayName;
public WeekDayClass(int dayIndex, String dayName) {
super();
this.dayIndex = dayIndex;
this.dayName = dayName;
}
public int getDayIndex() {
return dayIndex;
}
public void setDayIndex(int dayIndex) {
this.dayIndex = dayIndex;
}
public String getDayName() {
return dayName;
}
public void setDayName(String dayName) {
this.dayName = dayName;
}
#Override
public String toString() {
return this.dayName + ": " + this.dayIndex;
}
abstract static class Constants {
}
public static void main(String[] args) {
WeekDayClass init = new WeekDayClass(10, "I can init new days here");
}
}
And then I can extend it and make AmericanWeekDays:
public class AmericanWeekDay extends WeekDayClass {
public AmericanWeekDay(int dayIndex, String dayName) {
super(dayIndex, dayName);
}
static class AmericanConstants extends Constants {
public static final WeekDayClass SUNDAY = new WeekDayClass(1, "Sunday");
public static final WeekDayClass MONDAY = new WeekDayClass(2, "Monday");
/*
* And so on...
*/
}
}
Or Spanish Week Days:
public class SpanishWeekDays extends WeekDayClass {
public SpanishWeekDays(int dayIndex, String dayName) {
super(dayIndex, dayName);
}
static class SpanishConstants extends Constants {
public static final SpanishWeekDays LUNES = new SpanishWeekDays(2, "lunes");
/*
* And so on...
*/
}
}
Also to go even further:
public class WeekDayClass {
private int dayIndex;
private String dayName;
public WeekDayClass(int dayIndex, String dayName) {
super();
this.dayIndex = dayIndex;
this.dayName = dayName;
}
public int getDayIndex() {
return dayIndex;
}
public void setDayIndex(int dayIndex) {
this.dayIndex = dayIndex;
}
public String getDayName() {
return dayName;
}
public void setDayName(String dayName) {
this.dayName = dayName;
}
#Override
public String toString() {
return this.dayName + ": " + this.dayIndex;
}
static class AmericanConstants {
/*
* Insert Constants Here
*/
}
static class SpanishConstants {
/*
* Insert Constants Here
*/
}
}
I understand with an enum you could perhaps make a workaround using data structures (Lists) so you accommodate this shortcoming but why bother? With using public static constants I gain inheritance from the base class, cleaner code, possibly shorter code, and easier maintainability.
I also read that you can use enum's to better design "input parameters" but you could also do the same with the public static final constants as shown above.
Enums have the advantage of being able to be used in switch statements and have the inherited enum methods like values(). These methods can also be replicated if needed in "public static final constant" classes. Aside from the switch I don't see any enum advantages.
In conclusion, is an enum really better than public static final constants? If so, where did I go wrong? Is their something I am missing?
EDIT:
You cannot use generics in enums as well.
Enums get you a lot more than you seem to give them credit for, and while sometimes constants are required, this case is probably a win for enums.
First of all, there is no real difference between an "English weekday" and a "Spanish weekday", they represent the same values. Therefore, the best solution would be to do the conversion to string independently of what the values actually are through some kind of localization method. The values don't change with the language, their representation does.
This is entirely doable quickly and easily with enums. Just write it like this (a little pseudocode-y):
public enum Weekday {
MONDAY,
TUESDAY,
WEDNESDAY,
...;
public String toLocalizedString(Language l) {
// interact with localization files
}
}
You are conflating the ideas of external representation and internal representation. Your data should be as homogenous as possible because there is only ever going to be one Monday. It might be called different things, but it's still the same value.
Enums also get you a lot of niceness for free, though, which makes your code much clearer and more maintainable in the long run. Type checking, == comparison, and usability in switch are a few, with no boilerplate to speak of.
I think you're taking the usage of enums way to far and then come to a conclusion that they are not useful.
Enums are simply telling you that there's a limited and predefined number of options to choose from. Nothing more than that. For example, when you see a parameter that is an enum (let's say State) and it has 3 values (Pending, InProgress, Closed), you know that a state of some object can have one of those and only one of those values.
Enums provide an easy way of validating that a proper value is used as you cannot easily select a value that is not proper when coding. They are also a way of documenting as you can easily see what options are available.
Enumerations wouldn't exist if they weren't useful - the same can be said of constants. Just like a screwdriver can remove a screw while a hammer can remove a nail - different tools in your programmer "toolbox" can be used for unique and important purposes. I suggest reading more about enumerations and constants and I think you will find why they exist and when to use them.

Regarding alternative to interfaces and acessing with static imorts

I was going through a research in which I dont want to store the constants in the interface itself, so I was looking for alternatives like enums but another approach I have found is that ....t instead of using an interface, use a final class with a private constructor. (Making it impossible to instantiate or subclass the class, sending a strong message that it doesn't contain non-static functionality/data. and we can also take the advantage of static import in that case
Public final class KittenConstants
{
private KittenConstants() {}
public static final String KITTEN_SOUND = "meow";
public static final double KITTEN_CUTENESS_FACTOR = 1;
}
two independent things. 1: use static imports instead of abusing inheritance. 2: If you must have a constants repository, make it a final class instead of an interface . Please advise is this approach is correct..!!
To avoid some pitfalls of the constant interface (because you can't prevent people from implementing it), a proper class with a private constructor should be preferred (example borrowed from Wikipedia):
public final class Constants {
private Constants() {
// restrict instantiation
}
public static final double PI = 3.14159;
public static final double PLANCK_CONSTANT = 6.62606896e-34;
}
And to access the constants without having to fully qualify them (i.e. without having to prefix them with the class name), use a static import (since Java 5):
import static Constants.PLANCK_CONSTANT;
import static Constants.PI;
public class Calculations {
public double getReducedPlanckConstant() {
return PLANCK_CONSTANT / (2 * PI);
}
}
Please show how we can do same ting with enum also..!
You can achieve your "constants" via an enum:
public enum Animal {
Kitten("meow", 1),
Puppy("woof", 2);
private final String sound;
private final double cuteness;
Animal (String sound, double cuteness) {
this.sound = sound;
this.cuteness = cuteness;
}
public String getSound() {
return sound;
}
public double getCuteness() {
return cuteness;
}
}
To use:
String sound = Animal.Kitten.getSound();
double cuteness = Animal.Kitten.getCuteness();
The simple answer is that you can't do that with an enum. An enum defines a set of related constants with the same type.
What you have in the KittenConstants case is a set of constants with fundamentally different types. This doesn't fit the enum model. (If you change the problem a bit; e.g. by generalizing over different kinds of SFA, you can make it fit ... as #Bohemian does ... but if that's not what you are trying to achieve, enum is not the right solution.)
What you have in the Constants case is a bunch of named floating point constants that you want to use as values. (All the same type ... which helps!) Now you could declare them as an enum as follows:
public enum Constants {
PLANCK_CONSTANT(6.62606896e-34),
PI(3.14.59);
public final double value;
Constants(double value) {this.value = value);
}
The snag is that you need to use ".value" to access each named constant's numeric value; e.g.
import static Constants.*;
....
public double getReducedPlanckConstant() {
return PLANCK_CONSTANT.value / (2 * PI.value);
}
.... which is kind of ugly, and I don't think there is any way around the ugliness.
Bottom line - enums are not an ideal replacement for all kinds of constant.

Categories

Resources