How would I use enum on my project? - java

I have a class with an instance field lockAction, value 1 is lock and 3 is unlock. I'd like to introduce enum on to my EJB project. How do I got about that?
public enum lockUnlock {
LOCK, //1
UNLOCK, //3
}

you can use something like this.
public enum lockUnlock {
LOCK(1), UNLOCK(3);
int value;
lockUnlock(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
class Test {
public static void main(String[] args) {
lockUnlock[] b = lockUnlock.values();
for (lockUnlock b1 : b) {
System.out.println(b1 + "........" + b1.getValue());
}
}
}

You could assign a value to the enum like so.
public enum LockUnlock {
LOCK(1), UNLOCK(3);
private final int value;
private LockUnlock(int value) {
this.value = value;
}
public int getValue() { return value; }
}

#eldix_ you can use enums when you know that some of the Constant data in your code can't be changed by the user.
For example.
if you want to show some data in a drop down on the screen like below
as shown in the example, where the drop down values are constants, which client has to select.
we can change this at one place use it any where, without data being changed.

Related

JavaFX: Binding a TextProperty (eg. Label) to a simple Integer

The general question: Is there any way to update a label when the value of a simple integer changes ?
I'm talking about simple int's and not stuff like ReadOnlyIntegerWrappers. I've tried the following according to Converting Integer to ObservableValue<Integer> in javafx
(I had to change the identifier (is that what it's called ?) of ObservableValue from Integer to String because I couldn't find a way to bind it to the TextProperty otherwise)
I've included my demo code below which somehow seems to result in a NullPointerException at label.textProperty().bind(m.getObsValue());. The application is written in a MVC-pattern.
Model:
public class Model {
private int value;
private ObservableValue<String> obsInt;
public Model(){
value = 5;
obsInt = new ReadOnlyObjectWrapper<>(value + "");
}
public int getValue(){
return value;
}
public void setValue(int value){
this.value = value;
}
public ObservableValue<String> getObsValue(){
return obsInt;
}
}
Controller:
public class Controller {
private Model m;
private View v;
public Controller(Model m, View v){
this.m = m;
this.v = v;
}
public void handleMouseclick(MouseEvent e){
m.setValue(m.getValue() + 5);
}
public void init(){
v.setOnMouseClicked(this::handleMouseclick);
}
}
View:
public class View extends Region{
private Model m;
private Label label;
public View(Model m)
{
this.m = m;
label.textProperty().bind(m.getObsValue());
label.setLayoutX(200);
label.setLayoutY(200);
paint();
}
public void paint(){
getChildren().clear();
getChildren().addAll(label);
}
#Override
public double computePrefHeight(double width){
return 800;
}
#Override
public double computePrefWidth(double height){
return 600;
}
}
As you might've noticed I'm currently still studying JavaFX. So I probably just missed something stupid. Any advice would be greatly appreciated !
Let's start from the end - the exception is because you never initialize label, so it is null - as simple as that. Using label = new Label(); should solve it.
And now for the bindings - you say you don't want to use IntegerProperty or ReadOnlyIntegerWrapper, but rather use a simple int - that means you have no convenient way of knowing when the value is changed! The label will always contain the initial value of your integer, so you may as well do something like:
label.setText(Integer.toString(m.getValue()));
Instead, I would advise you to do something like
public class Model {
private SimpleIntegerProperty value = new SimpleIntegerProperty(this, "value");
public Model() {
value.set(5);
}
public int getValue(){
return value.get();
}
public void setValue(int value){
this.value.set(value);
}
public IntegerProperty valueProperty(){
return value;
}
}
then you can bind the label's text property using Bindings.convert:
label.textProperty().bind(Bindings.convert(m.valueProperty()));
this way, whenever the model's value is changed, the label text would automatically reflect this.
As you can see, SimpleIntegerProperty is nothing to be afraid of! The arguments in the constructor are optional, but recommended - they are the object this property belongs to (this), and the name of the property ("value", in this case). You can also pass the initial value in the constructor, instead of explicitly setting it in your Model constructor.

Looking up enum label by value

I have the following enum in my java android application:
static enum PaymentType
{
Scheme(0), Topup(1), Normal(2), Free(3), Promotion(4), Discount(5), Partial(6),
Refund(7), NoShow(8), Prepay(9), Customer(10), Return(11), Change(12), PettyCash(13),
StateTax(14), LocalTax(15), Voucher(16), Membership(17), Gratuity(18), Overpayment(19),
PrepayTime(20), HandlingFee(21);
private int value;
private PaymentType(int i) {
value = i;
}
public int getValue() {
return value;
}
}
I use this enum alot to find out the integer value of one of these string labels, for example int i = Lookups.PaymentType.Voucher.getValue();.
How can I do this the other way around? I have an integer value from a database and I need to find which string that corresponds to.
You should do something like this (static-init block should be at the end! and in your case just replace "asc" and "desc" with numbers, or add any other field):
public enum SortOrder {
ASC("asc"),
DESC("desc");
private static final HashMap<String, SortOrder> MAP = new HashMap<String, SortOrder>();
private String value;
private SortOrder(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
public static SortOrder getByName(String name) {
return MAP.get(name);
}
static {
for (SortOrder field : SortOrder.values()) {
MAP.put(field.getValue(), field);
}
}
}
After that, just call:
SortOrder asc = SortOrder.getByName("asc");
To go from an ordinal() index value back to enum:
type = PaymentType.values()[index];
However, keep in mind that this is fragile when the ordinal is stored anywhere else, such as a database. If the index numbers ever change, you'll get invalid results.
For more reliable lookup table, use a Map.

Change the value of final Integer variable

A final object cannot be changed, but we can set its attributes:
final MyClass object = new MyClass();
object.setAttr("something"); //<-- OK
object = someOtherObject; //<-- NOT OK
Is it possible to do the same with a final Integer and change its int value?
I'm asking because I call a worker:
public SomeClass myFunction(final String val1, final Integer myInt) {
session.doWork(new Work() {
#Override
public void execute(...) {
//Use and change value of myInt here
//Using it requires it to be declared final (same reference)
}
}
And i need to set the value of myInt inside of it.
I can declare my int inside another class, and that would work. But I wonder if this is necessary.
No : an Integer is immutable, just like for example String.
But you can design your own class to embed an integer and use it instead of an Integer :
public class MutableInteger {
private int value;
public MutableInteger(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
You can't because it immutable by design.
You can set the value of an int[] or Integer[] or AtomicInteger
You cannot change the value of final integer once assigned.. However, you can delay the assignment., i.e. : - You can only assign a final integer once.. You can do it either at the time of declaration, or in initializer block, or in constructor..
You could wrap your Integer in another object that is final and then 'replace' the Integer inside that wrapper object by another.

In Java, how to iterate on the constants of an interface?

in an interface, I store constants in this way (I'd like to know what you think of this practice). This is just a dummy example.
interface HttpConstants {
/** 2XX: generally "OK" */
public static final int HTTP_OK = 200;
public static final int HTTP_CREATED = 201;
public static final int HTTP_ACCEPTED = 202;
public static final int HTTP_NOT_AUTHORITATIVE = 203;
public static final int HTTP_NO_CONTENT = 204;
public static final int HTTP_RESET = 205;
public static final int HTTP_PARTIAL = 206;
...
}
Is there a way I can iterate over all constants declared in this interface ?
Using reflection:
Field[] interfaceFields=HttpConstants.class.getFields();
for(Field f:interfaceFields) {
//do something
}
But anyway, if you can redesign your class, I would recomend you to handle a static enum constants construction. So, suposing your class will contain always an int value for every constant:
enum HttpConstants {
HTTP_OK(200), HTTP_CREATED(201), HTTP_ACCEPTED(202),
HTTP_NOT_AUTHORITATIVE(203),HTTP_NO_CONTENT(204),
HTTP_RESET(205), HTTP_PARTIAL(206) /* ... */;
private int value;
HttpConstants(int aValue) {
value=aValue;
}
public int getValue() {
return value;
}
}
Then, to loop on it:
for(HttpConstants val: HttpConstants.values()) {
int value=val.getValue();
//...
}
Thus, avoiding the access to the reflection API.
I would create these constants as an enumeration. Enums in Java can have their own fields and methods, which very convenient for your case. So I would do this the following way:
enum HttpConstant {
HTTP_OK(200),
HTTP_CREATED(201),
HTTP_ACCEPTED(202),
HTTP_NOT_AUTHORITATIVE(203),
HTTP_NO_CONTENT(204),
HTTP_RESET(205),
HTTP_PARTIAL(206);
private final int id;
HttpConstant(int id) {
this.id = id;
}
int getId() {
return id;
}
}
Now the iteration is easy:
for (HttpConstant constant : HttpConstant.values()) {
//Do something with the constant
}
This way it is also easy to add associate some new values with the constants, you just have to add new fields.
Right now you may use reflection:
Field[] interfaceFields = HttpConstants.class.getFields();
for (Field field : interfaceFields) {
int constant = field.getInt(null);
//Do something with the field
}
However, it is better to use the approach with enums because with reflection coding errors result in runtime exceptions instead of compile-time errors.
for(Field f : HttpConstants.class.getFields()){
int constant = f.getInt(null);
}
public enum HttpConstant {
/** 2XX: generally "OK" */
HTTP_OK(200).
HTTP_CREATED(201),
HTTP_ACCEPTED(202),
HTTP_NOT_AUTHORITATIVE(203),
HTTP_NO_CONTENT(204),
HTTP_RESET(205),
HTTP_PARTIAL(206);
private int code;
private HttpConstant(int code) {
this.code = code;
}
public int getCode() {
return code;
}
}
with HttpConstant.values().
Well usually when i have something like that i make a Map in the interface that has the keys - constant names with values constant - values.
And that's how i can iterate over them.
I'd like to know what you think of this practice
Consider using an enum instead of an interface with constants.
enum HttpResultCode {
HTTP_OK(200),
HTTP_CREATED(201),
HTTP_ACCEPTED(202),
HTTP_NOT_AUTHORITATIVE(203),
HTTP_NO_CONTENT(204),
HTTP_RESET(205),
HTTP_PARTIAL(206);
private final int code;
private HttpResultCode(int code) {
this.code = code;
}
public int getCode(int code) {
return code;
}
public static HttpResultCode forCode(int code) {
for (HttpResultCode e : HttpResultCode.values()) {
if (e.code == code) {
return e;
}
}
throw new IllegalArgumentException("Invalid code: " + code);
}
}

Design Issue | Enum to represent combo box options

I need to use an Enum with a combobox (values shown below).
YES (shown as YES on UI, stored in DB as Y)
NO (shown as NO on UI, stored in DB as N)
DEFAULT (shown as "" on UI, stored in DB as null)
The Enum has methods to perform the following -
toString() - to provide the custom String for UI. (showing the combo options)
OptionToDB (static) - Convert a selected option to db value (on save / update)
DBToOption (static)- Convert a DB value to selcted option (while loading the screen)
static enum EnumOption{
YES,NO,DEFAULT;
....
public static EnumOption DBToOption(String val){
if("Y".equals(val)){
return YES;
} else if("N".equals(val)){
return NO;
}else {
return DEFAULT;
}
}
....
}
It works pretty well, but the issue with above methods is that it uses if/else comparison to deduce which option / db value to be returned.
I thought of storing the dbValue as a field in enum but I was not able to reduce the if/else from DBToOption.
Can this if/else be avoided in any way using a better design??
If you store the dbValue as a field in the enum, you can remove the if/else and replace it with a for-loop, although I don't see anything wrong with those if/elses for this particular case:
static enum EnumOption {
YES("Y"),
NO("N"),
DEFAULT("");
private final String value;
private EnumOption(String value) {
this.value = value;
}
public static EnumOption DBToOption(String val) {
for (EnumOption opt : EnumOption.values()) {
if (opt.value.equals(val)) {
return opt;
}
}
return DEFAULT;
}
}
public enum EnumOption {
YES("Y"), NO("N"), DEFAULT("");
private final String value;
private final static Map<String, EnumOption> options;
static {
options = new HashMap<String, EnumOption>();
for (EnumOption opt : EnumOption.values()) {
options.put(opt.value, opt);
}
}
private EnumOption(String value) {
this.value = value;
}
public static EnumOption DBToOption(String val) {
return options.get(val) != null ? options.get(val) : DEFAULT;
}
}
And here is the test that proves it works.
public void testDBToOption() {
assertEquals(EnumOption.NO, EnumOption.DBToOption("N"));
assertEquals(EnumOption.YES, EnumOption.DBToOption("Y"));
assertEquals(EnumOption.DEFAULT, EnumOption.DBToOption(""));
assertEquals(EnumOption.DEFAULT, EnumOption.DBToOption(null));
assertEquals(EnumOption.DEFAULT, EnumOption.DBToOption("R"));
}
So you want to get rid of the remaining if/else ...Are you doing Object Calisthenics?
You could do the following, if you do not have compatibility issues:
public enum EnumOption {
Y("Y", "YES"),
N("N", "NO"),
D("D", "");
private final String dbValue;
private final String uiValue;
private EnumOption(String dbValue, String uiValue) {
this.dbValue = dbValue;
this.uiValue = uiValue;
}
public String getDbValue() {
return this.dbValue;
}
public String uiValue() {
return this.uiValue;
}
public static EnumOption getFromDb(String dbValue) {
return EnumOption.valueOf(dbValue);
}
}
Since each enum value can only occur once, this has at least the same performance as all the other implementations.
For details about the automatically generated valueOf(String) method in enum types, and James DW's solution, you can read up in Josh Bloch's Effective Java Item 30 (Use enums instead of int constants), page 154.

Categories

Resources