Check if primitive has been set - java

Given a very simple class:
class MyClass {
int id;
double value;
MyClass(int id) {
this.id = id;
}
void setValue(double v) {
value = v;
}
boolean isValueUnassigned() {
return value == 0;
}
}
To check if value has not been assigned yet, is it OK if I just do return value == 0; since a double is 0 by default?

You should go for wrapper class for double which is Double. For Double data type default value would be null. So that there would not be any ambiguity. If value is null, then it's not assigned any value.

Well, yes primitive double is set to 0.0 by default. But if you simply do return value == 0; you can't be sure if someone called setValue(0) before, but it is a valid assignment too. If you want to be 100% sure if someone called the setValue() I would suggest something like this:
class MyClass {
private int id;
private double value;
private boolean valueSet; // is false by default
public MyClass(int id) {
this.id = id;
}
public void setValue(double v) {
value = v;
valueSet = true;
}
public boolean isValueSet() {
return valueSet;
}
}

Adding to what #Harshal has already said. Code for something like that would look like:
class MyClass {
private int id;
private Double value;
public MyClass(int id) {
this.id = id;
}
public void setValue(double v) {
value = v;
}
public double getValue() {
//Check for null pointer and return
if(value == null)
return <whatever you want>;
return value.doubleValue();;
}
public boolean isValueSet() {
return (value == null ? false : true);
}
}

You can use Double to reinitialize the double using following
class MyClass {
int id;
Double value;
MyClass(int id) {
this.id = id;
}
void setValue(Double v) {
value = v;
}
boolean isValueUnassigned() {
return value == null ? false : true;
}
}

Explanation
The main issue here is that, whatever double value you choose, e.g. 0 or -1, it could actually be a valid value set by the user. In which case your application would falsely return that it was not set yet, while it was.
What you need is called a sentinel value, i.e. a special value that indicates this case. Typically there are 3 approaches:
Flag
Introduce a simple boolean flag boolean isSet which you initialize to false and set to true once it was set.
This approach is good and really fast. But does not scale well if you, for example, start to introduce hundreds of such values for which you need to represent "not set yet".
double value;
boolean isValueSet = false;
void setValue(double value) {
this.value = value;
isValueSet = true;
}
boolean isValueUnassigned() {
return !isValueSet;
}
Object wrapper
Object variables can, additionally to their actual values/instances also refer to null. This can be used as sentinel to indicate the special case.
So you could go for having the value internally represented as Double instead of double, starting with null.
The disadvantage is that an object introduces quite some memory and performance overhead compared to a simple primitive. In this case it does not really matter but if you scale this up to a couple of thousands of them, you would definitely start to feel the impact.
Double value = null;
void setValue(double value) {
this.value = value; // auto-boxing
}
boolean isValueUnassigned() {
return value == null;
}
Sentinel value
If you application naturally allows that some values can never be used, you can use them as sentinel to indicate the case. A common example would be an age field for which you would not allow the user to set it to negative values. Then you can use, for example -1 to indicate it.
This approach is quite common and efficient. But it obviously is not always applicable and it is also not necessarily the most readable/maintainable approach.
double value = -1;
void setValue(double value) {
if (value < 0) {
throw new IllegalArgumentException("Negative values are not allowed");
}
this.value = value;
}
boolean isValueUnassigned() {
return value == -1;
}

The value is assigned when the object is created. You don't need a method to check if the value has been assigned because the answer is always yes.

Found the cleanest and clearest way to express it:
class MyClass {
int id;
Optional<Double> value;
MyClass(int id) {
this.id = id;
this.value = Optional.empty();
}
void setValue(double v) {
value = Optional.of(v);
}
double getValue() {
if (isValueUnassigned) {
throw new RuntimeException("Value has not been assigned");
}
return value.get();
}
boolean isValueUnassigned() {
return value.isEmpty();
}
}

a double value is 0 by default , but you can pass -1 to it .
double value = -1;
for check :
if (value!= -1) {
// To Do
}

Related

Create an empty constructor when wrong parameters

class classname {
private int value;
public classname(int value) {
if(value > 20 || value < 1) {
//make object null
}
else {
this.value = value;
}
}
}
Basically, when the parameter is not in the range I want to make an empty object.
something like:
classname newclass = new classname(100);
if(newclass == null) {
//this is what i want
}
Instead of initialising an object with null, you should throw an IllegalArgumentException, e.g.:
if(value > 20 || value < 1) {
throw new IllegalArgumentException("Value must be between 1 and 20");
}
This would prevent the initialisation and return correct error message to the user. Also, this is considered as best practice (e.g. try calling Integer.parseInt("abc");)
For this look at factory design. You should create a factory class and let that factory return the class instance. Inside factory implementation you can write the logic based on parameter.
Look at this post.
Create Instance of different Object Based on parameter passed to function using C#
You should create a factory method which either return instance if argument is valid or null and hide the constructor using private:
class YourClass {
private int value;
// Factory method
public static YourClass newYourClass(int value) {
if(value > 20 || value < 1)
return null;
else
return new YourClass(value);
}
private YourClass(int value) {
this.value = value;
}
}
You can make it in this way
public class MyClass {
private int value; // if -1 not in the range!
public MyClass(int value) {
if (value > 20 || value < 1) {
this.value = -1;
} else {
this.value = value;
}
} //end of constructor
} //end of the MyClass
you can do somthing like this
class classname {
private Integer value;
public classname(Integer value) {
this.value = value <1 || value>20 ? null : value;
}
}
public class CustomObjectFactory
{
private int value;
CustomObjectFactory(int value)
{
this.value = value;
}
public CustomObjectFactory getInstance()
{
System.out.print(value);
if(value<10)
{
System.out.print("if"+value);
return null;
}else
{
System.out.print("else"+value);
return new CustomObjectFactory(value);
}
}
}

Enum with negative/gap value in Java

I have a problem with enum in Java. I have an enum that starts from -1:
public enum AipType {
Unknown(-1),
None(0),
AipMod(1),
AipNoMod(2);
private final int id;
AipType(int id) {this.id = id;}
public int getValue() {return id;}
}
The problem is when I use this code to initialize a var of AipType
AipType at = AipType.getValues()[index];
where index is a number in the interval [-1,0,1,2] the -1 mess up the value.
i.e. 0 returns Unknown, 1 returns AipMod and 2 returns AipNoMod.
I used this implementation because I need to set manually the numeric value for each enum case. In other case I have a gap beetwen the values so I have the same problem: I cannot use values() and then access with [ ].
I tried to initialize in this way
AipType at = AipType(index);
but doesn't work.
Ideas ? Thanks...
We don't know what the getValues() method you're using exactly doing. Is it supposed to be values().
Anyway, you can always add a static method in your enum, which returns the correct enum instance for that value, and invoke it wherever you need it:
public enum AipType {
Unknown(-1),
None(0),
AipMod(1),
AipNoMod(2);
private final int id;
AipType(int id) {this.id = id;}
public int getValue() {return id;}
public static AipType fromValue(int id) {
for (AipType aip: values()) {
if (aip.getValue() == id) {
return aip;
}
}
return null;
}
}
If you're invoking fromValue() too often, you might also want to cache the array returned by values() inside the enum itself, and use it. Or even better, a map would be a better idea.
Enum.getValues() returns an array of the enums based on the definition order in the enum class.
getValues() doesn't know about the id field or the getValue() method you have added to your enum.
What you could do instead of calling getValues()[-1] (by the way, you'll never be able to index an array in Java with -1) is to add a static function like:
static AipType getAipType(int id) {
for (AipType a : getValues()) {
if (a.getId() == id) return a;
}
throw new IllegalArgumentException("id=" + id + " does not exist");
}
Just have a Map<Integer, AipType> instead of using values(), and expose access to it via a method:
public enum AipType {
UNKNOWN(-1),
NONE(0),
MOD(1),
NO_MOD(2);
private static final Map<Integer, AipType> VALUE_TO_ENUM_MAP;
private final int value;
static {
VALUE_TO_ENUM_MAP = new HashMap<>();
for (AipType type : EnumSet.allOf(AipType.class)) {
VALUE_TO_ENUM_MAP.put(type.value, type);
}
}
private AipType(int value) {
this.value = value;
}
public int getValue() {
return id;
}
public static AipType forValue(int value) {
return VALUE_TO_ENUM_MAP.get(value);
}
}
That will be completely flexible about values - or you could still use an array and just offset it appropriately.
Can you declare your enum like below?
public enum AipType {
Unknown(-1),None(0),AipMod(1),AipNoMod(2);
private int value;
private AipType(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
public static AipType fromValue(int value) {
for (AipType at: values()) {
if (at.getValue() == value) {
return at;
}
}
return null;
}
};
And instantiate like:
AipType at = AipType.fromValue(-1);
If the ids are completely custom, the only chance you'd have would be to create a map and store the id->AipType mapping there.
Example:
public enum AipType {
... //enum definitions here
static Map<Integer, AipType> map = new HashMap<>();
static {
for( AipType a : AipType.values() ) {
map.put(a.id, a);
}
}
public static AipType typeById( int id ) {
return map.get(id);
}
}
Then call it like AipType.typeById(-1);.

Java Return between a int or String(unknown return type)

My program loads information from a text file and creates an array of an object with the information whether it is a integer or a string.
I then want the object to return either a String or an Integer depending on whether the object is holding a integer value or a string value.
edit...
So here is my type class that holds either a int if the field in the text file is a number, or a string if the field is a word, and this is held in a Type array.
public class Type {
private String name;
private int value;
public Type(String name) {
this.name = name;
}
public Type(int value) {
this.value = value;
}
public String getName() {
return this.name;
}
public int getValue() {
return this.value;
}
public boolean isInt() {
boolean isInt = false;
if (this.value != 0) {
isInt = true;
return isInt;
}
return isInt;
}
}
So in my array could be either a Int or a String, i want to return the datatype without any long statements in my main class.
If you strictly want only to get the specific values, you could add a method to your Type class and get the values from this method, ugly but does what you want:
public <T> T getDynamicValue(Type t) {
if (isInt()) {
return (T) ((Integer) t.getValue());
} else {
return (T) t.getName();
}
}
use of it:
List<Type> dynamicList = Arrays.asList(new Type[]{new Type(1), new Type(2), new Type("dog")});
for (Type t : dynamicList) {
System.out.println("T -> " + t.getDynamicValue(t));
}
If you want to perform some manipulation with this data, you have to make an instanceof check and Cast it, for instance some splitting (or String methods) with the name value...
You can't choose the type of object to return at runtime. Your only option is to return an Object. You can check if it's a String or an int using this code, for example:
if(object instanceof String) {
//... it's a string
}
else {
//...otherwise it's an int
}
If you are reading all inputs into String instances, you will need to test the values against Integer.parseString(value) to find out if it is actually an Integer.
You could try to cast the object into an Integer and catch the ClassCastException:
try {
int i = (Integer) object;
}
catch (ClassCastException e){
String s = (String) object;
}
When I have this type of problem, I sometimes solve it by turning the problem around and using a callback-style solution.
For example:
for ( Type t : array ) {
t.process( callback );
}
Where the callback looks like this:
interface Callback {
public void processInt(....);
public void processString(....);
}
You can then either implement the process method either with an if (isInt()) callback.processInt() else callback.processString(), or if you change the definition of Type you can use the inheritance tree to do it for you.
For example:
interface Type {
public void process( Callback cb );
}
class IntType implements Type {
public void process( Callback cb ) {
cb.processInt(...);
}
}
class StringType implements Type {
public void process( Callback cb ) {
cb.processString(...);
}
}

Setting a value in a class is not working

I have a class called monetary
public class Monetary
{
double value;
String type;
public Monetary()
{
value = 0;
type = "";
}
public double getValue()
{
return value;
}
public void setValue(double x)
{
x = this.value;
}
and i was testing get and set methods so i made a testing class as the following
public class test
{
public static void main(String [] args)
{
double test = 5000;
Monetary testM = new Monetary();
testM.setValue(5000);
System.out.println(testM.getValue());
}
}
The problem is that the result java prints is not 5000.0, but 0. I don't get why this is happening. Aren't these methods correct?
The problem is in the setValue method:
public void setValue(double x) {
x = this.value;
}
You're assigning the parameter the current value of the attribute, it should be backwards:
public void setValue(double x) {
this.value = x;
}
Note that even doing this, you will get an output like 5000.0000000.... In order to fix the result you can use String#format or System.out.printf:
System.out.println(String.format("%.2f", testM.getValue()));
or
System.out.printf("%.2f\n", testM.getValue());
In your code you are assigning the value to parameter x, it should be opposite.
public void setValue(double x){
this.value = x;
}
try this:
public void setValue(double x)
{
this.value = x;
}
public void setValue(double x){
this.value = x;
}
You are assigning the parameter you've passed x with the default value of the value. You must be doing the exact opposite of that. Assign the value with the value passed x.
Hence, instead of this this.value = 5000, this is happening x = 0.
You are assigning the parameter (double x) the value of int value which does nothing because you are return value, so what you want to do is
public class Monetary
{
double value;
String type;
public Monetary()
{
value = 0;
type = "";
}
public double getValue()
{
return value;
}
public void setValue(double x)
{
value = x;//change this
}

Enum type conversion to int

i am trying to use the following code...
The Enum class i am using is
public enum AccountType {
kAccountTypeAsset(0x1000),
kAccountTypeAssetFixed(0x1010),
private int value;
private AccountType(int value)
{
this.value = value;
}
public int getValue()
{
return value;
}
}
public AccountType accountType = kAccountTypeAsset;
integerToDB(accountType);
...
/*************************/
public Object integerToDB (Integer i )
{
if(i == -1)
{
return null;
}
return i;
}
How can i use
accountType
as integer.
integerToDB(accountType.getValue()); ?
Since your enum has implemented a getValue method, you can use accountType.getValue() to get the integer value stored in accountType.

Categories

Resources