Change the value of final Integer variable - java

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.

Related

Can Java enum class set default value

Mycode is
public enum PartsOfSpeech2 {
n("noun"),
wp("标点"),
a("adjective"),
d("conjunction"),
...;
which I want
public enum PartsOfSpeech2 {
n("noun"),
wp("标点"),
a("adjective"),
d("conjunction"),
%("noun");
can I hava a default value which is not in it, can it be set as a default value?
because I have a type is "%", but enum is not support %, so I want a default value to solve it
The default for one who holds a reference to an enum without setting a value would be null (either automatically in case of a class field, or set by the user explicitly).
Unfortunately you cannot override the method valueOf for your own enum, as it is static.
But you can still create your methods:
public enum PartsOfSpeech2 {
n("noun"),
wp("标点"),
a("adjective"),
d("conjunction");
private String value;
PartsOfSpeech2(String value) {
this.value = value;
}
// declare your defaults with constant values
private final static PartsOfSpeech2 defaultValue = n;
private final static String defaultString = "%";
// `of` as a substitute for `valueOf` handling the default value
public static PartsOfSpeech2 of(String value) {
if(value.equals(defaultString)) return defaultValue;
return PartsOfSpeech2.valueOf(value);
}
// `defaultOr` for handling default value for null
public static PartsOfSpeech2 defaultOr(PartsOfSpeech2 value) {
return value != null ? value : defaultValue;
}
#Override
public String toString() { return value; }
}
From JLS 8.9. Enums
An enum type has no instances other than those defined by its enum constants. It is a compile-time error to attempt to explicitly instantiate an enum type (§15.9.1).
So you can't have any instance which is take default value.
You can create default constant and use that using some condition.
public enum PartsOfSpeech2 {
....
DEFAULT("DEFAULT");
}
And use condition to check if your string have constant, Ex "%" have enum or not. if not use default value:
PartsOfSpeech2 result = PartsOfSpeech2.valueOf("%"); //Your String EX: %
PartsOfSpeech2 resultNew = result==null?PartsOfSpeech2.DEFAULT: result;
The way I solved it was the following
public enum YourEnum{
ENUM1("stringToMatchWith"),
ENUM2("stringToMatchWith2"),
DEFAULTENUM("Default");
public final String label;
YourEnum(String label) {
this.label = label;
}
public static YourEnum resolveYourEnum(String stringToMatch) {
return Arrays.stream(YourEnum.values()).filter(aEnum -> aEnum.label.equals(stringToMatch)).findFirst().orElse(YourEnum.DEFAULTENUM);
}
That way you can do YourEnum.resolveYourEnum("aString") and return the specified enum or the default we set

How to make the value of a String variable not change after once assigned? [duplicate]

This question already has answers here:
Declare final variable, but set later
(7 answers)
Closed 5 years ago.
How can I make sure that the value of String variable doesnot change after being assigned once? Assignment is not at the time of declaration.
More clarity :-
String x = y; (y is another string)
Even if y changes x should not change. How to make sure this?
What I have tried :-
Created a custom class:-
public class MyDs {
private final String unitName;
public MyDs(String iUnitName){
unitName = iUnitName;
}
public String getUnitName(){
return unitName;
}
}
in the main method :-
String iName = "xyz";
MyDs MyDsObj = new MyDs(iName);
But even after this, the value changes when the variable changes.
How can I solve this issue?
Your class be should be design as mentioned in below code
public class TestingClas {
private String name;
public void setName(String name) {
if (this.name == null && name != null)
this.name = name;
}
public String getName() {
return name;
}
}
Now use below code for testing purpose
TestingClas testingClas = new TestingClas();
testingClas.setName("Abdul Waheed");
testingClas.setName("You cannot change me any more now");
String updatedString = testingClas.getName();
updatedString variable will be having old value
as far as I understand ,you should design your class in a way that your variable should be final . with this approach you set it in constructor and then nothing can make it changes. even the referance it is holding is changed the value remains the same I mean a new object is created in heap and value of your final variable is kept same. below is a kind of design which makes the variable x set once and never be able to changed afterwards. Of course this is in instance scope, for class scope you can make your class singelton etc.
public class Test {
private final String x;
private String y;
public Test(String x){
this.x=x;
}
public String getY() {
return y;
}
public void setY(String y) {
this.y = y;
}
public String getX() {
return x;
}
}
Change your MyDs class to a singleton class
Making this a singleton class ensures that the final String unitName is updated only once and then it will cannot be altered again.
public class MyDs {
private final String unitName;
private static MyDs myDs;
public static MyDs getMyDsObject(String iUnitName) {
if (myDs == null) {
myDs = new MyDs(iUnitName);
}
return myDs;
}
private MyDs(String iUnitName) {
unitName = iUnitName;
}
public String getUnitName() {
return unitName;
}
}
Here the values "xyz" is stored in unitName and doesnot get updated again when you change to "zxy".
MyDs MyDsObj = MyDs.getMyDsObject("xyz");
Log.i("value", "" + MyDsObj.getUnitName());
MyDs MyDsObj1 = MyDs.getMyDsObject("zxy");
Log.i("value",""+MyDsObj.getUnitName());
Well, you question is not really clear (and the comment section is really chaty...), but if you want to only be able to set a value once but not during the initialisation, setters are not a bad choice. Just add a constraint.
public class MyClass{
private static final String DEFAULT_VALUE = new String("");
private String value = DEFAULT_VALUE;
public final void setValue(String value){
if(this.value != DEFAULT_VALUE) //use the reference on purpose
throw new IllegalArgumentException("This value can't be changed anymore");
this.value = value;
}
// Don't return `DEFAULT_VALUE` to prevent someone to gain access to that instance
public final String getValue(){
return this.value == DEFAULT_VALUE ? null : this.value;
}
}
This will be done at runtime, but this would do the trick.
Now, this is an immutable instance, with some mutable instance you might want to do a copy of it to be sure it can't be modifier using the original reference.

How would I use enum on my project?

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.

How do i display an objects integer value in a text view from another class?

I have a String in a class that is separate from another class and in this string i want to get an integer from an object of the other class, this object is in a class of its own.
Class with string below
TextView2.setText(//I want the objects integer value displayed here);
Class with object below
testClass Object = new testClass();
Object.setIntegerValue(5);
Class of which object was created from below
int integerValue;
public int getIntegerValue()
{
return integerValue;
}
public void setIntegerValue(int i)
{
IntegerValue = i;
}
How do i display "Object"'s integer value in the TextView 2 without the app crashing?
TextView.setText(object.getIntegerValue().toString());
Use TextView2.setText(Integer.toString(Object.getIntegerValue()));.
If you use just TextView2.setText(Object.getIntegerValue()), the TextView will try to find a String in Resource which id is the value of Object.getIntegerValue().
Just use the getter from the testClass:
TextView2.setText(Integer.toString(Object.getIntegerValue()));
public int getIntegerValue()
{
return integerValue;
}
public void setIntegerValue(int i)
{
IntegerValue = i;
}
I see an error here, when you call the setIntegervalue() function, you're modifying the value of IntegerValue variable, but you return the value of integerValue(which is different from IntegerValue) when calling the getIntegerValue() funvtion . Java is case-sensitive, so you're modifying and returning a different variable each time. See if this is not you're problem.
This should do it.
public int getIntegerValue()
{
return this.integerValue;
}
public void setIntegerValue(int i)
{
this.integerValue = i;
}
and for your TextView
textView.setText(object.getIntegerValue() + "");

Get enum by its inner field

Have enum with inner fields, kind of map.
Now I need to get enum by its inner field.
Wrote this:
package test;
/**
* Test enum to test enum =)
*/
public enum TestEnum {
ONE(1), TWO(2), THREE(3);
private int number;
TestEnum(int number) {
this.number = number;
}
public TestEnum findByKey(int i) {
TestEnum[] testEnums = TestEnum.values();
for (TestEnum testEnum : testEnums) {
if (testEnum.number == i) {
return testEnum;
}
}
return null;
}
}
But it's not very efficient to look up through all enums each time I need to find appropriate instance.
Is there any other way to do the same?
You can use a static Map<Integer,TestEnum> with a static initializer that populates it with the TestEnum values keyed by their number fields.
Note that findByKey has been made static, and number has also been made final.
import java.util.*;
public enum TestEnum {
ONE(1), TWO(2), SIXTY_NINE(69);
private final int number;
TestEnum(int number) {
this.number = number;
}
private static final Map<Integer,TestEnum> map;
static {
map = new HashMap<Integer,TestEnum>();
for (TestEnum v : TestEnum.values()) {
map.put(v.number, v);
}
}
public static TestEnum findByKey(int i) {
return map.get(i);
}
public static void main(String[] args) {
System.out.println(TestEnum.findByKey(69)); // prints "SIXTY_NINE"
System.out.println(
TestEnum.values() == TestEnum.values()
); // prints "false"
}
}
You can now expect findByKey to be a O(1) operation.
References
JLS 8.7 Static initializers
JLS 8.9 Enums
Related questions
Static initalizer in Java
How to Initialise a static Map in Java
Note on values()
The second println statement in the main method is revealing: values() returns a newly allocated array with every invokation! The original O(N) solution could do a little better by only calling values() once and caching the array, but that solution would still be O(N) on average.
Although someone has suggested using Map<Integer, TestEnum> think twice about it.
Your original solution, especially for small enums, may be magnitudes faster than using HashMap.
HashMap will probably be not faster until your enum contains at least 30 to 40 elements.
This is one case of "If it ain't broken, don't fix it".
Here is the most convenient way to find enum value by its field:
public enum TestEnum {
A("EXAMPLE_1", "Qwerty", 1),
B("EXAMPLE_2", "Asdfgh", 2),
C("EXAMPLE_3", "Zxcvbn", 3);
private final String code;
private final String name;
private final Integer typeID;
TestEnum(String code, String name, Integer typeID) {
this.code = code;
this.name = name;
this.key = typeID;
}
public String getCode() {
return code;
}
public String getName() {
return name;
}
public Integer getKey() {
return key;
}
public static TestEnum findValueByTypeId(Integer key) {
return Arrays.stream(TestEnum.values()).filter(v ->
v.getKey().equals(key)).findFirst().orElseThrow(() ->
new Exception(String.format("Unknown TestEnum.key: '%s'", key)));
}
}
You should have a HashMap with the numbers as keys and the enum values as values.
This map can typically be in your repository. Then you can easily replace an int variable from the database with your preferred enum value.
If your keys (int values) are stored in a database, then I will say its bad design to carry those keys around in an enum on your business layer. If that's the case, I will recommend not to store the int value in the enum.
One solution is to add
public final Test[] TESTS = { null, ONE, TWO, THREE };
public static Test getByNumber(int i) {
return TESTS[i];
}
To the enum.
If the internal data is not an integer, you could have a Map which you populate in a static { ... } initializer. This map could later be used in the getByNumber method above.

Categories

Resources