Java enums vs constants for Strings - java

I've switched from using constants for Strings to using enums. Many times I need the String representation of the enum (for logging, to pass to an API that requires a String, etc).
With String constants, you can just pass the String value, but with enums you have to call toString(). Is there a way you can "default" to the String value when supplying the enum variable?
As many posters have commented, perhaps one shouldn't be using enums if you frequently need the String representation.

You should fully adopt enum and not use the String representation in the first place. Only use the toString() to generate messages, logs, etc, but internally you'd want to work with enum. Any Map, Set, etc operations should be done on the enum type, which guarantees proper serialization, singleton pattern, and everything else that enum types are supposed to have.
In your snippet:
Object o = map.get(Options.OPTION_1);
//This won't work as intended if the Map key is a String
Compile-time error aside, you should really question whether the map key should even be of type String in the first place. The way you're using it, it looks like it should be a Map<Options, Something>.

There are a lot of good reasons to use Enum in Java. But not if you only need a String.
For example, if you are representing a specific set of entities and don't want them to be type-equivalent with other kinds of things (like Strings), then an Enum would be appropriate. Moreso if you are going to be calling functions that operate them and differentiate based on the particular instance.
On the other hand, if you are only interested in the String value of something, then there is nothing wrong with a String constant.
From what you've posted, I can't tell what the use case is. Is there some reason you need to use Enum here?

Related

Avoid multiple castings of java properties (String) to Integer Double

I am looking for a way to reduce the castings of properties from java Properties to Numeric such as Integer, Double and if possible even a class that might casting directly for instance Integer[].
Say I have multiple properties and must pass for instantiation many times and I wish to use a class that parses and casts only once.
Properties mogaProps = parseProperties("mogabcpu/moga");
for (int i=0;i<10000;i++){
NSGA2Runner GA = new NSGA2Runner(Integer.valueOf(mogaProps.getProperty(
"NUMINITIALCHROMOSSOMES")), Integer.valueOf(mogaProps.getProperty(
"NUMCHROMOSOMES")),
Double.valueOf(mogaProps.getProperty(
"MUTATIONRATE")), Double.valueOf(mogaProps.getProperty(
"CROSSOVERRATE")),
parseStringTo1DArray(mogaProps.getProperty("NUMITERATIONS"))
}
Is there a better alternative avoiding the use of a custom class to specifically hold all potential different data types attributes?
I have found this However I could not find this Config Class dependency.
Thanks
I am looking for a way to reduce the castings of properties
You are parsing, not casting. The .valueOf calls are creating new values by interpreting the meaning held within text (parsing) rather than reshaping an existing value (casting). But not a useful distinction in the context of your Question, just FYI.
Say I have multiple properties and must pass for instantiation many times and I wish to use a class that parses and casts only once.
If the properties are not changing at runtime, just instantiate your configuration object (a NSGA2Runner object in your case, your GA) once. Pass that object around to the other methods and objects that need the information.
In your example code with the for loop, if your real code is processing the properties once and then using that data 10,000 times, move your GA = line to outside the loop.
By the way, if you are assigning an object once only, mark GA as final. That keyword obstructs any inadvertent attempt to make that variable point to any other object.
reduce the castings of properties from java Properties to Numeric such as Integer, Double
Your data is stored as text in a Properties. You need to work with that data as numbers, not text. So there is no getting around the chore of parsing that text into numbers.
I am not sure why you are concerned about this. Perhaps performance is your concern? Such parsing is quick and easy. Not a significant impact on performance unless you are often processing millions of such values. Do a bit of micro benchmarking to see for yourself.
Is there a better alternative avoiding the use of a custom class to specifically hold all potential different data types attributes?
Defining a class is the appropriate way to gather together related parts of information in an object-oriented language like Java.
If your data is read-only, then you might want to use the records feature in Java 16 and later. A record is a brief way to write a class whose main purpose is to communicate data transparently and immutably. You merely need to declare the type and name of each member field. The compiler implicitly creates the constructor, getters, equals & hashCode, and toString.
public record NSGA2Runner( int numberOfInitialChromosomes , int numberOfChromosomes , double mutationRate , double crossoverRate , int[] numberOfIterations ) {}

Is there anything similar to Java AutoValue in C#?

After working on a Java project for some time then coming back to C#, I've found myself really missing AutoValue. Specifically, I'd like the ability to:
Produce an immutable value class with minimal boilerplate.
Have things like equality and hash code automatically handled for me.
Ideally, have it automatically generate a builder to allow fluent construction and arbitrary validation like "if you give parameter A, you must also give B".
In the same vein, a toBuilder()-style function to make a deep copy of an existing instance while making some modifications.
All of that would have been really easy with AutoValue. Is there anything similar? I could, of course, implement all that functionality myself, but it's a lot of boilerplate, making it harder to maintain and more error-prone.
From what you've described, it seems that you will need to wait until C#9 record types in order to get what you've described of java's AutoValues, i.e. in C#9, you should be able to declare:
public data class Person
{
public string FirstName { get; init; }
public string LastName { get; init; }
}
You'll then get:
Immutable behaviour
The benefit of C#'s object initialiser syntax
An automatic default implementation of equality and hashcode
With expressions will allow the `copy most properties, but allowing some field values to be changed during the copy.
In the interim (C#8 and prior), you'll need to do some of this by hand, i.e.
Declare your class properties as get only
Initialise all properties via a constructor
Create your own static factory / builder methods
Use code generation tools in IDE's like to generate equality members
As an aside, if you have just switched from Java to C#, you may not be aware of structs as value types for trivial 'records', which from the docs:
Structs are best suited for very small data structures that contain primarily data that is not intended to be modified after the struct is created.
Although structs do have a default implementation of value equality, this can be unacceptable given that it is just the first field included in the hashcode, and that you'd need to provide an implementation of operator == if you want to use == for value equality.
That said, the use cases for structs must be carefully considered, and should generally be used only for trivial immutable records or for performance reasons when used in arrays.

When to use Enum class in java?

It may be very obvious questions, but is it good to use Enum class if you know that the list of values will keep increasing?
Let's say you define an Event Enum first it contains only [Poo, Too] then as we know we always have some new requirement it becomes [Poo, Too, App, Laa] and that keep changing again and again,
So what is the best approach in this case?
tl;dr
If the entire set of possible values is known at compile-time, use enum.
If values can be added or dropped while your system is in use (at runtime), then you cannot use an enum. Use a Set, List, or Map instead.
Known at compile-time
An enum is appropriate when the domain (set of all possible values) is known at compile-time.
If this year your company is offering two products ( Poo & Too ), then make an enum for those two elements.
public enum Product { POO , TOO }
Next year, your company decides to grow their product offerings by adding App & Laa. As part of a planned deployment, add two more objects to your enum.
public enum Product { POO , TOO , APP , LAA }
By the way, notice the naming conventions. The enum has a regular class name (initial cap). The objects being automatically instantiated are constants, and so are named in all-uppercase.
Also, be aware that the enum facility in Java is quite flexible and powerful, much more so than the usual naming-a-number enum scheme seen in most languages. You can have member variables and methods and constructors on a Java enum. For example, you can add a getDisplayName method to provide text more appropriate to a user-interface than the all-caps object name, as seen in DayOfWeek::getDisplayName. You can add quite a bit of functionality, such as ChronoUnit.between.
What you cannot do at runtime with an enum in Java is add or remove objects. Thus the requirement that you know your domain at compile-time. However, when working with a group of enum objects, you can use the highly-optimized EnumSet and EnumMap classes.
Known at runtime
If you cannot determine the domain at compile-time, if users can add or remove elements at runtime, then use a collection such as a List, Set, or Map rather than an enum.
Singleton
Though not originally intended as a purpose of Enum in Java, an enum happens to be the safest (and simplest) way to implement the Singleton design pattern.
This approach to a singleton is explained in the famous book Effective Java by Dr. Joshua Bloch, et al. Using an enum solves multiple obscure technical problems with other approaches to a singleton.
Your question is pretty generic and I'm pretty sure there is no single right answer. But judging based on spring* tags, I suppose you might be asking about enums in DTOs that being sent over your system in serialized form. If that's the case, I would recommend to choose String in DTO, while inside single app it's ok to use enum. Then you would just care about deserialization/conversion in a factory manner, having ability to handle unknown/missing constant gracefully by logging/providing fallback or meaningful error.
It depends on a case-by-case situation and your question doesn't have much context. However, I do recommend using ENUMs for many cases, including if you expect the list of ENUMs to increase.
Some reasons to use them are:
It creates a definite guide of ENUM elements that can be used throughout your code. It eliminates uncertainty over what something is named or what it is. For example ENUM that contains list of animals, or enum of "something".
Its easy to refactor later if you need to change anything.
I'm sure there are many more reasons, I find it like a table of contents sometimes. For many cases, you can completely avoid it and be fine but I think its better to use it in general if you're on the fence.

Represent email, telephonenumber and id's as POJO's instead of Strings

I have a typical business web application where the domain contains entities like accounts and users. My backend is Java, so they're represented by POJO's. During an early iteration, every attribute of those POJO's were just strings. This made sense because the html input was a string, and the way the data is persisted in the DB is also similar to a string.
Recently, we've been working on validating this kind of input and I found it helps if I switch over to an object notation for this kind attributes. For example, a TelephoneNumber class consists of:
(int) country calling code
(string) rest of number
(static char) the character to prefix the country calling code (in our case this is a +)
(static pattern) regular expression to match if phonenumber is sensical
methods to compare and validate telephone numbers.
This class has advantages and disadvantages:
not good: Additional object creation and conversion between string/object
good: OOP and all logic regarding telephone numbers is bundled in one class (high cohesion),
good: whenever a telephone number is needed as an argument for a method or constructor, java's strict typing makes it very clear we're not just dealing with a random string.
Compare the possible confusing double strings:
public User(String name, String telephoneNumber)
vs the clean OOP way:
public User(String name, TelephoneNumber telephoneNumber)
I think in this case the advantages outweight the disadvantges. My concern is now for the following two attributes:
-id's (like b3e99627-9754-4276-a527-0e9fb49d15bb)
-e-mailadresses
This "objects" are really just a single string. It seems overkill to turn them into objects. Especially the user.getMail.getMailString() kind of methods really bother me because I know the mailString is the only attribute of mail. However, if I don't turn them into an object, I lose some of the advantages.
So my question is: How do you deal with this concepts in a web application? Are there best practices or other concerns to take into account?
If you use Strings for everything you are essentially giving up type safety, and you have to "type check" with validation in any class or method where the string is used. Inevitably this validation code gets duplicated and makes other classes bloated, confusing, and potentially inconsistent because the validation isn't the same in all places. You can never really be sure what the string holds, so debugging becomes more difficult, maintenance gets ugly, and ultimately it wastes lots of developer time. Given the power of modern processors, you shouldn't worry about the performance cost of using lots of objects because it's not worth sacrificing programmer productivity (in most cases).
One other thing that I have found is that string variables tend to be more easily abused by future programmers who need to make a "quick fix", so they'll set new values for convenience just where they need them, instead of extending a type and making it clear what's going on.
My recommendation is to use meaningful types everywhere possible.
Maximizing the benefit of typing leads to the idea of "tiny types", which you can read about here: http://darrenhobbs.com/2007/04/11/tiny-types/
Essentially it means you make classes to represent everything. In your example with the User class, that would mean you would also make a Name class to represent the name. Inside that class you might also have two more classes, FirstName and LastName. This adds clarity to your code, and maximizes the number of logical errors the compiler stops you from making. In most cases you would never use a first name where you want a last name and vice versa.
One of the biggest advantages of objects is the fact that they can have methods. For example, all your data object (phone number, address, email etc.) can implement the same interface IValidatable with validate method, which does the obvious. In this case, it would make sense to wrap email in an object as well, since we do want to validate emails. Regarding ID - assuming it's assigned internally by your app, you probably don't need to wrap it.

Java toString for debugging or actual logical use

This might be a very basic question, apologies if this was already asked.
Should toString() in Java be used for actual program logic or is it only for debugging/human reading only. My basic question is should be using toString() or write a different method called asString() when I need to use the string representation in the actual program flow.
The reason I ask is I have a bunch of classes in a web service that rely on a toString() to work correctly, in my opinion something like asString() would have been safer.
Thanks
Except for a few specific cases, the toString should be used for debugging, not for the production flow of data.
The method has several limitations which make it less suitable for use in production data flow:
Taking no parameters, the method does not let you easily alter the string representation in response to the environment. In particular, it is difficult to format the string in a way that is sensitive to the current locale.
Being part of the java.Object class, this method is commonly overridden by subclasses. This may be harmful in situations when you depend on the particular representation, because the writers of the subclass may have no idea of your restrictions.
The obvious exceptions to this rule are toString methods of the StringBuilder and the StringBuffer classes, because these two methods simply make an immutable string from the mutable content of the corresponding object.
It is not just for debugging/human reading only, it really depends on the context in which the object is being used. For example, if you have a table which is displaying some object X, then you may want the table to display a readable textual representation of X in which case you would usually implement the toString() method. This of course is a basic example but there are many uses in which case implementing toString() would be a good idea.

Categories