Is there any way to format the enum variables when they are called? I mean, If I have the next enum:
public enum Error{
IS_NULL("The variable {NAME_OF_VARIABLE} cannot be null.")
}
So, when I call it I want to replace {NAME_OF_VARIABLE} with the variable which is null. Ex: "The variable {phone_number} is null."
Now I use the next construction:
enum Error{
IS_NULL("The variable {%s} cannot be null.")
public String errorMsg;
}
public String validatePhoneNumber(String phoneNumber){
if(phoneNumber == null){
return String.format(Error.IS_NULL.errorMsg, "phoneNumber")}
return "OK"}
}
}
It works fine, but it looks a bit messy.
Thank you!
Firstly your code doesn't compile and you can make use of a ternary operator to check if the phoneNumber is null or not.
Given the enum :
enum Error {
IS_NULL("The variable {%s} cannot be null.");
public String errorMsg;
private Error(String errorMsg) {
this.errorMsg = errorMsg;
}
}
Validation method can be simplified to
public static String validatePhoneNumber(String phoneNumber) {
return phoneNumber == null ? String.format(Error.IS_NULL.errorMsg, "phoneNumber") : "OK";
}
Using Optional a little cleaner way of doing that could be:
public String validatePhoneNumber(String phoneNumber) {
return Optional.ofNullable(phoneNumber)
.map(a -> String.format(Error.IS_NULL.getErrorMsg(), "phoneNumber"))
.orElse("OK");
}
Related
So I have this enum that doesn't work as I expected and need some modifications:
public enum MyEnum {
CODE000("text description comes here"),
private final String value;
private static final Map<String, MyEnum> LOOKUP = Maps.uniqueIndex(
Arrays.asList(MyEnum.values()),
MyEnum::getValue
);
MyEnum(final String value) {
this.value = value;
}
public String getValue() {
return value;
}
public static MyEnum fromStatus(String status) {
return LOOKUP.get(status);
}
}
The way it works now is:
MyEnum.fromStatus("text description comes here") and of course I want the other way around:
MyEnum.fromStatus("CODE000") to return me "text description comes here"
Can someone suggest how I can change this ?
What you need is a literal lookup, which you get by calling valueOf:
MyEnum code000 = MyEnum.valueOf("CODE000");
And then:
String val = code000.getValue();
Please note that an exception will be raised if the string passed to valueOf doesn't resolve to an enum literal in MyEnum.
Your key function (MyEnum::getValue) is wrong as it returns the value.
It must be MyEnum::name
This will return the enum and not the text description as the value of the map is of type MyEnum. You can get the text value by calling getValue on the enum OR you can store the value in the map instead of the enum
If you want to get an enum value by enum name you can use this function :
public static String fromStatus(String status) {
MyEnum myEnum = valueOf(status);
return myEnum.getValue();
}
The answers so far are using the method valueOf. This method will return the enum constant as long as you provide a name of an enum constant. Otherwise an IllegalArgumentException will be thrown.
In your question you're using a lookup map. The Map (it looks like as it's created by Guava Maps) will return for non-enum-constant-names null. It will not throw a IllegalArgumentException in such cases. So it is a different behaviour.
In addition you say: "and of course I want the other way around"
This means you want to get the enum by status and the status by an enums name.
Therefore you would need to have two lookup methods:
status -> enum
name -> status
But you would get a compile time error if you define the two methods you mentioned:
public static MyEnum fromStatus(String status) { ... }
public static String fromStatus(String name) { ... }
The compiler could not distinguish the methods by name and parameter. But even though you wrote MyEnum.fromStatus("CODE000") actually it's the enum constant name you are using as parameter. So let's resolve the naming conflict by calling the second method fromName. The code for MyEnum could look like this:
public enum MyEnum {
CODE000("text description comes here");
private final String value;
private static final Map<String, MyEnum> LOOKUP_ENUM = Maps.uniqueIndex(Arrays.asList(MyEnum.values()), MyEnum::getValue);
private static final Map<String, String> LOOKUP_STATUS = Arrays.stream(MyEnum.values()).collect(Collectors.toMap(MyEnum::name, MyEnum::getValue));
MyEnum(final String value) {
this.value = value;
}
public String getValue() {
return value;
}
public static MyEnum fromStatus(String status) {
return LOOKUP_ENUM.get(status);
}
public static String fromName(String name) {
return LOOKUP_STATUS.get(name);
}
}
If you want to lookup the enum constants by it's names in the same manner (no exception on non-enum-constant-names), you need a third map and a third lookup method:
private static final Map<String, MyEnum> LOOKUP = Maps.uniqueIndex(Arrays.asList(MyEnum.values()), MyEnum::name);
public static MyEnum byName(String name) {
return LOOKUP.get(name);
}
This would work as follows:
System.out.println(MyEnum.fromStatus("text description comes here")); // CODE000
System.out.println(MyEnum.fromStatus("invalid")); // null - no exception
System.out.println(MyEnum.fromStatus(null)); // null - no exception
System.out.println(MyEnum.fromName("CODE000")); // "text description comes here"
System.out.println(MyEnum.fromName("invalid")); // null - no exception
System.out.println(MyEnum.fromName(null)); // null - no exception
System.out.println(MyEnum.byName("CODE000")); // CODE000
System.out.println(MyEnum.byName("invalid")); // null - no exception
System.out.println(MyEnum.byName(null)); // null - no exception
If you need the byName method I would suggest to rename the methodfromName to something like statusByName to keep them comprehensible apart.
Finally one more suggestion:
Since the lookup methods may return null we could return Optional<String> / Optional<MyEnum> as result. This would allow to immediately continue processing the result.
public static Optional<MyEnum> fromStatus(String status) { ... }
public static Optional<String> statusByName(String name) { ... }
public static Optional<MyEnum> byName(String name) { ... }
I have written a code for Person class and in that class create a constructor Person and argument name. Now I have to create an instance of this class will offer a getter for the person's name and also create an instance of this class will respond to a greet method that accepts one argument: message.
When the message is "Hello", greet must return:
Hi, I'm {{name}}
When the message is "Goodbye", greet must return:
Bye
When the message is anything else, greet will return the message that it was provided. I have a tested case code but I am stuck with assertEquals() function and getter function. Now I am facing error with assertfunction. Can anybody please tell me how does assertfucntion and getter works? I have implemented getter in my code, I'm but not sure whether I did it right.
Here's my code:
class Person
{
private String name;
Person(String n)
{
n = name;
}
String GetName()
{
return this.name;
}
public void greet(String t)
{
if (t == "Hello")
{
System.out.println("Hi my name is "+name);
}
else if (t == "Goodbye")
{
System.out.println("bye");
}
else
System.out.println("Hi, my name is"+name);
}
}
Test code:
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.Before;
public class TestPerson {
private Person jeff;
private Person susy;
#Before
public void setup() {
jeff = new Person("Jeff");
susy = new Person("Susy");
}
#Test
public void testGetName() {
assertEquals("Jeff", jeff.GetName());
}
#Test
public void testGreetHelloJeff() {
assertEquals("Hi, I'm Jeff", jeff.greet("Hello"));
}
#Test
public void testGreetHelloSusy() {
assertEquals("Hi, I'm Susy", susy.greet("Hello"));
}
#Test
public void testGreetGoodbye() {
assertEquals("Bye", jeff.greet("Goodbye"));
}
#Test
public void testGreetOther() {
assertEquals("Yo", jeff.greet("Yo"));
}
}
You cannot compare a String and the return value of a method that returns void.
Your Person class is odd. You have it too closely tied to System.out, which is not useful.
Your code has a lot of problems for such a small sample size. Here's what I might suggest:
public class Person {
private String name;
Person(String n) {
this.name = n;
}
String getName() {
return this.name;
}
public String greet(String t) {
if ("Hello".equals(t)) {
return String.format("Hi my name is %s", name);
} else if ("Goodbye".equals(t)) {
return "bye";
} else {
return String.format("Hi, my name is %s", name);
}
}
}
See your method returns void:
public void greet(String t)
How do you expect to get and assert a values of void?
Change void to String and do return a message string.
Also do not use == rather .equals(..)
"Hello" case seems does the same as default. Better do:
public class Person {
private String name;
Person(String name) {
this.name = name;
}
String getName() {
return this.name;
}
public String greet(String m) {
if ("Goodbye".equals(m)) {
return "bye";
} else {
return String.format("Hi, my name is %s", name);
}
}
}
By calling assertEquals("Bye", jeff.greet("Goodbye")); you're comparing the String "Bye" to void since .greet returns void.
Change greet to this:
public String greet(String t){
if(t.equals("Hello"))
return "Hi my name is " + name;
else if(t.equals("Goodbye"))
return "bye";
else
return "Hi, my name is" + name;
}
And then you can use the assertEquals(String, String) like:
assertEquals("bye", jeff.greet("Goodbye"));
In Java when comparing Strings use .equals() instead of ==. So 'if(t=="Hello")"' would be 'if(t.equals("Hello"))'
Method names should start with a lower case letter.
Also String comparison is case sensitive so make sure you are using the correct case when comparing your Strings.
It doesn't make sense to test the greet(String) method using assertEquals, since the method doesn't return anything. The assertEquals is used to assert whether the actual result returned from a tested method is equal to an expected value that you provide, just like the testGetName above.
It seems more appropriate to change void greet(String) to String greet(String) which returns a greeting message according to the t argument to make your code more testable.
Moreover, you should use aStr.equals(bStr) instead of aStr == bStr to compare two String. == just compare the reference of the two String object rather than their values.
enum generalInformation {
NAME {
#Override
public String toString() {
return "Name";
}
},
EDUCATION {
#Override
public String toString() {
return "Education";
}
},
EMAIL {
#Override
public String toString() {
return "Email";
}
},
PROFESSION {
#Override
public String toString() {
return "Profession";
}
},
PHONE {
#Override
public String toString() {
return "Phone";
}
}
}
I have that information are avaiable in enum.
How to print all enum values like: print.generalInformation?
That outputs:
Name
Education
Email
Phone
How to pass that enum generalInformation as an arg in another function?
System.out.println(java.util.Arrays.asList(generalInformation.values()));
Your second part... Just the same as an interface or a class
Firstly, I would refactor your enum to pass the string representation in a constructor parameter. That code is at the bottom.
Now, to print all enum values you'd just use something like:
// Note: enum name changed to comply with Java naming conventions
for (GeneralInformation info : EnumSet.allOf(GeneralInformation.class)) {
System.out.println(info);
}
An alternative to using EnumSet would be to use GeneralInformation.values(), but that means you have to create a new array each time you call it, which feels wasteful to me. Admittedly calling EnumSet.allOf requires a new object each time too... if you're doing this a lot and are concerned about the performance, you could always cache it somewhere.
You can use GeneralInformation just like any other type when it comes to parameters:
public void doSomething(GeneralInformation info) {
// Whatever
}
Called with a value, e.g.
doSomething(GeneralInformation.PHONE);
Refactoring using a constructor parameter
public enum GeneralInformation {
NAME("Name"),
EDUCATION("Education"),
EMAIL("Email"),
PROFESSION("Profession"),
PHONE("Phone");
private final String textRepresentation;
private GeneralInformation(String textRepresentation) {
this.textRepresentation = textRepresentation;
}
#Override public String toString() {
return textRepresentation;
}
}
With your current values, you could actually just convert the name to title case automatically - but that wouldn't be very flexible for the long term, and I think this explicit version is simpler.
Since Java 8 I would suggest the following solution:
public static String printAll() {
return Stream.of(GeneralInformation.values()).
map(GeneralInformation::name).
collect(Collectors.joining(", "));
}
In applications, it's good practice to separate data from presentation. It allows the data to be used in different user interfaces, it makes the data objects more lightweight, and it allows for the future possibility of internationalization.
With that in mind, it's good to avoid strongly coupling the display name to the enum constant. Fortunately, there is a class which makes this easy: EnumMap.
public class ApplicationUI {
private final Map<GeneralInformation, String> names;
public ApplicationUI() {
names = new EnumMap<>(GeneralInformation.class);
names.put(GeneralInformation.NAME, "Name");
names.put(GeneralInformation.EDUCATION, "Education");
names.put(GeneralInformation.EMAIL, "Email");
names.put(GeneralInformation.PROFESSION, "Profession");
names.put(GeneralInformation.PHONE, "Phone");
assert names.keySet().containsAll(
EnumSet.allOf(GeneralInformation.class)) :
"Forgot to add one or more GeneralInformation names";
}
public String getNameFor(GeneralInformation info) {
return names.get(info);
}
}
If you are still on Java 1.7 this is what worked for me:
String genInfoValues = "";
boolean firstRun = true;
for (generalInformation info : generalInformation.values()){
if (firstRun) {
firstRun = false;
genInfoValues += info.name();
} else {
genInfoValues += ", " + info.name();
}
}
values() on the enum returns an array. So, it would be simple to do the following to:
System.out.println(Arrays.toString(generalInformation.values()));
This would mean that the class was initialized, but the variables were not set.
A sample Class:
public class User {
String id = null;
String name = null;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
The actual class is huge that I prefer not to check if(xyz == null) for each of the variables.
Another non-reflective solution for Java 8, in the line of paxdiabo's answer but without using a series of if's, would be to stream all fields and check for nullness:
return Stream.of(id, name)
.allMatch(Objects::isNull);
This remains quite easy to maintain while avoiding the reflection hammer.
Try something like this:
public boolean checkNull() throws IllegalAccessException {
for (Field f : getClass().getDeclaredFields())
if (f.get(this) != null)
return false;
return true;
}
Although it would probably be better to check each variable if at all feasible.
This can be done fairly easily using a Lombok generated equals and a static EMPTY object:
import lombok.Data;
public class EmptyCheck {
public static void main(String[] args) {
User user1 = new User();
User user2 = new User();
user2.setName("name");
System.out.println(user1.isEmpty()); // prints true
System.out.println(user2.isEmpty()); // prints false
}
#Data
public static class User {
private static final User EMPTY = new User();
private String id;
private String name;
private int age;
public boolean isEmpty() {
return this.equals(EMPTY);
}
}
}
Prerequisites:
Default constructor should not be implemented with custom behavior as that is used to create the EMPTY object
All fields of the class should have an implemented equals (built-in Java types are usually not a problem, in case of custom types you can use Lombok)
Advantages:
No reflection involved
As new fields added to the class, this does not require any maintenance as due to Lombok they will be automatically checked in the equals implementation
Unlike some other answers this works not just for null checks but also for primitive types which have a non-null default value (e.g. if field is int it checks for 0, in case of boolean for false, etc.)
If you want this for unit testing I just use the hasNoNullFieldsOrProperties() method from assertj
assertThat(myObj).hasNoNullFieldsOrProperties();
How about streams?
public boolean checkFieldsIsNull(Object instance, List<String> fieldNames) {
return fieldNames.stream().allMatch(field -> {
try {
return Objects.isNull(instance.getClass().getDeclaredField(field).get(instance));
} catch (IllegalAccessException | NoSuchFieldException e) {
return true;//You can throw RuntimeException if need.
}
});
}
"Best" is such a subjective term :-)
I would just use the method of checking each individual variable. If your class already has a lot of these, the increase in size is not going to be that much if you do something like:
public Boolean anyUnset() {
if ( id == null) return true;
if (name == null) return true;
return false;
}
Provided you keep everything in the same order, code changes (and automated checking with a script if you're paranoid) will be relatively painless.
Alternatively (assuming they're all strings), you could basically put these values into a map of some sort (eg, HashMap) and just keep a list of the key names for that list. That way, you could iterate through the list of keys, checking that the values are set correctly.
I think this is a solution that solves your problem easily: (return true if any of the parameters is not null)
public boolean isUserEmpty(){
boolean isEmpty;
isEmpty = isEmpty = Stream.of(id,
name)
.anyMatch(userParameter -> userParameter != null);
return isEmpty;}
Another solution to the same task is:(you can change it to if(isEmpty==0) checks if all the parameters are null.
public boolean isUserEmpty(){
long isEmpty;
isEmpty = Stream.of(id,
name)
.filter(userParameter -> userParameter != null).count();
return isEmpty > 0
}
The best way in my opinion is Reflection as others have recommended. Here's a sample that evaluates each local field for null. If it finds one that is not null, method will return false.
public class User {
String id = null;
String name = null;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isNull() {
Field fields[] = this.getClass().getDeclaredFields();
for (Field f : fields) {
try {
Object value = f.get(this);
if (value != null) {
return false;
}
}
catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return true;
}
public static void main(String args[]) {
System.out.println(new User().isNull());
}
}
Field[] field = model.getClass().getDeclaredFields();
for(int j=0 ; j<field.length ; j++){
String name = field[j].getName();
name = name.substring(0,1).toUpperCase()+name.substring(1);
String type = field[j].getGenericType().toString();
if(type.equals("class java.lang.String")){
Method m = model.getClass().getMethod("get"+name);
String value = (String) m.invoke(model);
if(value == null){
... something to do...
}
}
Best for me is
Stream.of(getClass().getDeclaredMethods()).allMatch(Objects::isNull);
It can be used in a custom annotation + annotation processor to automagically define a boolean isNull() method on the annotated classes.
Based on Irkwz's answer, but a different approach:
public class SomeClass{
private String field1;
private String field2;
private ComplexField field3;
private String field4;
private Integer field15;
public boolean isNullAllFields() {
return Stream.of(this.getClass().getDeclaredFields()).anyMatch(element -> (element != null));
}
}
And the end of the day u invoke isNullAllFields method to figure out wheter the object fields are empty.
If you want to do the opposite i.e check if some/all members of class are non-non, the check this answer.
In order to make sure that certain members of the class are always non-null, we can use lombok #NonNull annotation on the individual fields of the class.
import lombok.Data;
import lombok.NonNull;
#Data
public class DataClass {
#NonNull
private String data1;
private int data2;
#NonNull
private String data3;
#NonNull
private String data4;
#NonNull
private String data5;
private String data6;
DataClass(String data1,...) {
// constructor
}
}
Easiest way is to convert the class to a map and get its keys and with stream check if any or all key's values are null or not, you can take input from user as well whether they want to check for specific set of keys only!
Below is the code to check whether any of the key's value has null, you can change stream config to all match or any match as per your requirement
Just replace isNullOrEmpty method i have used with proper null or empty check condition for that particular collection
public boolean checkIfAnyFieldIsNull(Object instance, Set<String> fields){
try {
Map<String, Object> instanceMap = new Gson().fromJson(new GsonBuilder().serializeNulls().create().toJson(instance), Map.class);
if(!isNullorEmpty(instanceMap)) {
fields = isNullorEmpty(fields) ? instanceMap.keySet() : fields;
return fields.stream().anyMatch(curField -> isNull(instanceMap.get(curField)));
}else{
return false;
}
}catch (Exception e){
return false;
}
}
}
Try this method once, its works for me!!
private fun checkIfAnyDataIsNull(model: YourModelCass): Boolean {
return Stream.of<Any>(
model.date,
model.merchantName,
model.payment,
).allMatch(Objects::isNull)
}
You can use the simple solution:
if(user.equals(new User()){
//your processing goes here
}
What's the best way to store this data in a Java enum?
<select>
<option></option>
<option>Recommend eDelivery</option>
<option>Require eDelivery</option>
<option>Require eDelivery unless justification provided</option>
</select>
I'm new to java and have tried things like
public enum Paperless {
"None" = null,
"Recommend eDelivery" = "Recommend eDelivery",
"Require eDelivery" = "Require eDelivery",
"Require eDelivery unless justification provided" = "Require eDelivery w/out justification"
}
But this doesn't work. I'm considering the possibility of storing a text value that summarizes the option that the user sees on this web page.
Take a look at the enum tutorial, more specifically the Planet example. You can do the same, e.g.
public enum Paperless{
NONE( null ),
RECOMMENDED_DELIVERY( "Recommended delivery" ),
...//put here the other values
REQUIRED_DELIVERY( "Required delivery" );
private String name;
Paperless( String name ){
this.name = name;
}
public String getName(){
return this.name;
}
}
Something like this can work for your case:
public enum PaperLess {
NONE("none"),
RECOMMEND("Recommend eDelivery"),
REQUIRE("Require eDelivery"),
REQUIRE_JUSTIFIED("Require eDelivery unless justification provided");
private String value;
private PaperLess(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
You can't assign strings to enum values in Java in the way that you are trying.
The way to do it would be:
public enum Paperless {
None(null),
RecommendedDelivery("Recommended Delivery"),
RequireEDelivery("Require eDelivery"),
RequireEDeliveryUnlessJustification("Require eDelivery unless justification provided");
private final String value;
Paperless(String value) {
this.value = value;
}
private String enumValue() { return value; }
public static void main(String[] args) {
for (Paperless p : Paperless.values())
System.out.println("Enum:" + p + "; Value:" + p.enumValue());
}
}
You can't have spaces in the names of members and you can't assign enum values, they are objects, not constants.
The name of the enum must be an identifier (e.g. one-word, not a string)
public enum Paperless {
None,
RecommendEDelivery,
...
}
You can associate string values with them if you want (although you can get the default too that equals to the identifier name, usign the name() method) by associating a String member with the enum type and providing a custom constructor.
public enum Paperless {
None("None"),
RecommendEDelivery("Recommend eDelivery"),
...;
private String myValue;
private Paperless(String name) {myValue=name;)
}
To access that associated string, you need to provide a public accessor method as well.
Java enums aren't constructed in that way. Check out
Java Tutorials: Enum Types
Java - Convert String to enum: #2
Yours might look something like this:
public enum Paperless {
NONE(""),
RECOMMEND("Recommend eDelivery"),
REQUIRE("Require eDelivery"),
REQUIRE_UNLESS("Require eDelivery unless justification provided");
private String text;
Paperless(String text) {
this.text = text;
}
public String getText() {
return this.text;
}
}
public enum Paperless {
NONE("None"),
RECOMMEND("Recommend eDelivery"),
REQUIRE("Require eDelivery"),
REQUIRE_UNLESS("Require eDelivery unless justification provided"),;
private String value;
private Paperless(String value){
this.value=value;
}
public String getValue(){
return this.value;
}
}