I am considering a design in Java where I want a string object but with more 'type-safety' than just being of class String. This because I have a number of 'POJO' objects for Hibernate, representing my database tables. Each of these classes has a large number of public static fields representing the properties of the class, I.e.:
public class PersistantBean {
public static String PROP_FIELD_COLUMN_ONE="columnOne";
public static String PROP_FIELD_COLUMN_TWO="columnTwo";
// [...]
These properties are used when we need to access a property in a generic way, e.g. for code I am currently writing .parseAndSet(PROP_FIELD_PRICE,"£3.00").
I would like to be able to add a stronger type to the PROP_FIELD_... fields so that I could write
public class PersistantBean {
public static PropertyName PROP_FIELD_COLUMN_ONE="columnOne";
public static PropertyName PROP_FIELD_COLUMN_TWO="columnTwo";
// [...]
with minimal changes to other parts of the project,
so that parseAndSet would look like:
public void parseAndSet(PropertyName prop, String priceToParse)
Essentially, I would like PropertyName to be a type that is like String in everyway apart from the compiler would error if I tried to put a String where a PropertyName was expected, is any design pattern like this possible.
(I am shying away from Enums, although now I mention it, Enums may be the way to go.)
For Java 1.5 and above, just use an enum type.
For Java 1.4 and below, use the typesafe enum pattern. E.g.
public class Suit {
private final String name;
public static final Suit CLUBS =new Suit("clubs");
public static final Suit DIAMONDS =new Suit("diamonds");
public static final Suit HEARTS =new Suit("hearts");
public static final Suit SPADES =new Suit("spades");
private Suit(String name){
this.name =name;
}
public String toString(){
return name;
}
}
enum(enumeration) is a better idea, which above mentioned scenario.
eg:
enum PROP_FIELD_COLUMN {
columnOne, columnTwo,etc
}
I'd use an Enum. That way you get compile-time checking.
If your Strings really have a good fairly standard naming convention, like "column" + "One", "Two", etc. as in your example, you could save a lot of work by combining an enum for the prefix with an int for the suffix. So, create a class or utility method that takes an enum for the prefix, e.g. COLUMN, and combines it with an int, say 2, to yield "columnTwo".
An alternative might be be for your code, like parseAndSet, to validate the passed in String against an array or Collection of legal Strings, or maybe a regex, and throw an IllegalArgumentException. You'd get runtime checking and if you have good unit tests this could work.
EDIT ADDED
#sethupathi.t had a nice idea in his answer - In some cases it may be preferable to make the 2nd argument (for which I used an int) also an enum.
As far as I can tell, there are two reasonable ways to do what you want to do.
The first way (and probably best way, if it works for you) is to use an enum, as mentioned in another answer.
The second way, which may be necessary if you do not know all of your PropertyName's at runtime, would be to use a PropertyNameFactory along the lines of:
public class PropertyNameFactory
{
public static PropertyName getPropertyName(String propertyName)
{
// Check validity of the propertyName against what ever rules we
// have defined (maybe valid propertyNames are read from a DB at
// startup, etc).
if (isValid(propertyName))
{
// Ideally get from a cache, but for the sake of the example
// we will create a new one...
return new PropertyName(propertyName);
}
throw new IllegalArgumentException("Invalid property name: " + propertyName);
}
}
This is not ideal in that it does not provide true type safety of your property names, but it does ensure their validity.
I have to second the Enum answers.
However, a more literal answer to your question is that Java provides an interface for String-like objects, java.lang.CharSequence, and many parts of the standard Java libraries have been updated to accept CharSequence where appropriate. This will not however give you the behavior that you want, which is to have your class behave as a subtype of String.
Related
Whats the use of fields or classes inside annotations?
public #interface Test {
public String val = "hello"; // WHY??
public static class MyClass {// WHY??
public static void main(String[] args) {
System.out.println(val);
}
}
String value();
}
Fields: because you can define fields in any interface. They're always implicitly public, static and final: in other words, to define constants in the namespace of the interface.
The answer is essentially the same for classes: it's a public, static (but not final) class. it's just a namespace in which to define the class.
To turn the question around: why shouldn't you be able to do this?
There are all sorts of syntactically valid things you can do that you might think are ill-advised. For example:
String String = "String"; String: break String;
is valid, but useless, and confusing. There are 3 different meanings of String here, 4 if you count the literal. This is far less useful than annotation members, but also allowed.
Sometimes it's effort to stop you doing things: it adds complexity to the language, and the compiler to enforce; and in the effort to prevent the odd piece of madness, you might accidentally remove useful expressivity.
All:
I am on first day reading team's code(the one wrote this left...):
There is one enum definition confused me so much:
/**
* Enum defines the processing stages and the order
*
*/
public enum ProcessStage {
/*
* Individual stages in the process.
* Order of processing is based on the order of listing.
*/
EXTRACT("Extraction", "EXTRACTED", "EXTRACTION_FAILED"),
ROUTE("Routing", "ROUTED", "ROUTE_FAILED"),
PUBLISH("Publishing", "PUBLISHED", "PUBLISH_FAILED");
private String detailedName;
private String successState;
private String failedState;
private ProcessStage(String detailedName, String successState, String failedState) {
this.detailedName = detailedName;
this.successState = successState;
this.failedState = failedState;
}
public String getSuccessState() {
return successState;
}
public String getFailedState() {
return failedState;
}
/**
* Factory method to provide the ProcessStage from its success or failed state value stored in DB.
* #param state
* #return ProcessStage
*/
public static ProcessStage getProcessStage(String state) {
for(ProcessStage ps: ProcessStage.values()) {
if(ps.getSuccessState().equals(state) || ps.getFailedState().equals(state)) {
return ps;
}
}
return null;
}
public String toString() {
return detailedName;
}
}
I wonder if anyone give me some simple introduction about how to read this(like what kinda syntax it uses)? The most confused part is:
EXTRACT("Extraction", "EXTRACTED", "EXTRACTION_FAILED"),
ROUTE("Routing", "ROUTED", "ROUTE_FAILED"),
PUBLISH("Publishing", "PUBLISHED", "PUBLISH_FAILED");
I do not quite understand what this means and how to use this.
And why there are a lot of methods defined inside it and how to use method with a enum variable?
Thanks
Enum
The enum declaration defines a class (called an enum type). The enum
class body can include methods and other fields. The compiler
automatically adds some special methods when it creates an enum.
enums are special type of class. Instead of creating singleton pattern using regular class or to create constants, like WeekDays, we can use enum in such places. Here
EXTRACT("Extraction", "EXTRACTED", "EXTRACTION_FAILED"),
Here EXTRACT is an enum constant meaning it is an instance of the classProcessStage and also all other enum constants(ROUTE, PUBLISH). All costants of enum are unique objects, meaning they are singleton instance created in the jvm and enum makes sure the instances are unique. You need not to put additional effort to create singleton pattern.
The above code is not only declaration, it is also calling the constructor with three String parameters to create the instance.
private ProcessStage(String detailedName, String successState, String failedState) {
this.detailedName = detailedName;
this.successState = successState;
this.failedState = failedState;
}
why there are a lot of methods defined inside it?
Since it is also a class, it can have methods like any other classes. But the restriction is, it cannot be inherited, because internally enum extens the class Enum<E extends Enum<E>> class.
how to use method with a enum variable?
EXTRACT.getFailedState() //returns "EXTRACTION_FAILED"
Keep in mind, without seeing more of the code, I can't be exactly sure what this particular enum is being used for.
So, Let's say we have a method somewhere, where a process is passed through.
public void doSomething(Process process) {}
Now, let's assume that the purpose of this method is to check the status of the process and then do some logic based upon that result. This would entail doing something like the following
public void doSomething(Process process) {
if(ProcessStage.EXTRACT.equals(process.getStage()) {
//do something here...you will have access to the methods within
//the enum
}
}
Without knowing more, this is all I can give you. I hope this gives you a slightly better understanding of what that enum is doing
I'm trying to figure out the best way to create a class whose sole purpose is to be a container for global static variables. Here's some pseudocode for a simple example of what I mean...
public class Symbols {
public static final String ALPHA = "alpha";
public static final String BETA = "beta";
/* ...and so on for a bunch of these */
}
I don't need constructors or methods. I just need to be able to access these "symbols" from everywhere simply by calling: Symbols.ALPHA;
I DO need the actual value of the String, so I can't use an enum type. What would be the best way to accomplish this?
Well, it's not clear what else you need beyond the code you've already given - other than maybe making the class final and giving it a private constructor.
However, in order to avoid accidentally using an inappropriate value, I suspect you would be better off making this an enum, like this:
public enum Symbol {
ALPHA("alpha"),
BETA("beta");
private final String value;
private Symbol(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
That way:
You can't accidentally use Symbol.ALPHA where you're really just expecting a string
You can't accidentally use a string where you're really expecting a symbol
You can still easily get the string value associated with a symbol
You can switch on the different symbol values if you need to
You can do that using an interface. No need to construct, values are public, static and final, and can obviously be strings. Such an interface would look similar to your class:
public interface Symbols {
public static final String ALPHA = "alpha";
public static final String BETA = "beta";
/* and so on */
}
You can access the fields directly from everywhere in your code (given it's public) as Symbols.ALPHA etc.
Or, you can use an enum even though you want strings - ALPHA.toString() will return "ALPHA" (and if you want a slightly different string, you can override toString())
Are these configuration parameters or simply "constants" which don't change no matter what? For the former, I'd rather create a configuration class and instantiate it with different values for each environment. Then simply use dependency injection to inject these configurations in different classes. If your requirement is the latter or you are not using DI (Spring/Guice), static classes/interfaces are good to go.
I am absolute clueless why the following code keeps throwing NullpointerExceptions. I was not able to understand or debug this (its stripped down code from a larger class)...
The code is based on the "Enum Pattern" and I want to keep a List/Map of all "Constants" that are contained in the class (I might be using Reflection for this but using a List/Map is much easier...)
public class Country {
public static final Country SWITZERLAND = new Country("SWITZERLAND");
private static ArrayList<Country> countries = new ArrayList<Country>();
private Country(String constname) {
//constname is currently not used (I will use it for a Key in a Map)
System.out.println(constname);
System.out.println("Ref debug:"+this);
//Ad this to the Countries
Country.countries.add(this);
}
}
Help would be very much appreciated. What am I missing here?
SWITZERLAND, being static, is potentially initialized before countries, which is also static. Therefore, countries is still null in the constructor call of SWITZERLAND.
To force a well-defined order of initialization, use a static block:
public class Country {
public static final Country SWITZERLAND;
private static ArrayList<Country> countries;
static {
countries = new ArrayList<Country>();
SWITZERLAND = new Country("SWITZERLAND");
}
}
To expand on what Konrad said, the static variable initializers are executed in textual order (as specified in JLS section 8.7). If you put the ArrayList first, it will work:
public class Country {
private static ArrayList<Country> countries = new ArrayList<Country>();
public static final Country SWITZERLAND = new Country("SWITZERLAND");
...
Konrad's suggestion of using a static constructor to keep the order clearly specified is a good one though.
Are you using Java "pre 1.5"? If not, use a straight enum...
Because I think this deserves more than the cursory mention Jon gave it:
The "typesafe enum pattern" is obsolete!
Unless you are forced to use an ancient Java version (pre 1.5, which isn't even supported anymore by Sun), you should use Java's real Enums, which save you a lot of work and hassles (because old-style typesafe enums are very hard to get right) and are just all around awesome.
'Country' constructor call to initialize SWITZERLAND static field happens before initialization of countries list. If you change order of static field definition it will work better.
I think code bellow may work .Constructor of class have to define as public method not private.
Country(String constname) {
//constname is currently not used (I will use it for a Key in a Map)
System.out.println(constname);
System.out.println("Ref debug:"+this);
//Ad this to the Countries
Country.countries.add(this);
}
Motivation
Recently I searched for a way to initialize a complex object without passing a lot of parameter to the constructor. I tried it with the builder pattern, but I don't like the fact, that I'm not able to check at compile time if I really set all needed values.
Traditional builder pattern
When I use the builder pattern to create my Complex object, the creation is more "typesafe", because it's easier to see what an argument is used for:
new ComplexBuilder()
.setFirst( "first" )
.setSecond( "second" )
.setThird( "third" )
...
.build();
But now I have the problem, that I can easily miss an important parameter. I can check for it inside the build() method, but that is only at runtime. At compile time there is nothing that warns me, if I missed something.
Enhanced builder pattern
Now my idea was to create a builder, that "reminds" me if I missed a needed parameter. My first try looks like this:
public class Complex {
private String m_first;
private String m_second;
private String m_third;
private Complex() {}
public static class ComplexBuilder {
private Complex m_complex;
public ComplexBuilder() {
m_complex = new Complex();
}
public Builder2 setFirst( String first ) {
m_complex.m_first = first;
return new Builder2();
}
public class Builder2 {
private Builder2() {}
Builder3 setSecond( String second ) {
m_complex.m_second = second;
return new Builder3();
}
}
public class Builder3 {
private Builder3() {}
Builder4 setThird( String third ) {
m_complex.m_third = third;
return new Builder4();
}
}
public class Builder4 {
private Builder4() {}
Complex build() {
return m_complex;
}
}
}
}
As you can see, each setter of the builder class returns a different internal builder class. Each internal builder class provides exactly one setter method and the last one provides only a build() method.
Now the construction of an object again looks like this:
new ComplexBuilder()
.setFirst( "first" )
.setSecond( "second" )
.setThird( "third" )
.build();
...but there is no way to forget a needed parameter. The compiler wouldn't accept it.
Optional parameters
If I had optional parameters, I would use the last internal builder class Builder4 to set them like a "traditional" builder does, returning itself.
Questions
Is this a well known pattern? Does it have a special name?
Do you see any pitfalls?
Do you have any ideas to improve the implementation - in the sense of fewer lines of code?
The traditional builder pattern already handles this: simply take the mandatory parameters in the constructor. Of course, nothing prevents a caller from passing null, but neither does your method.
The big problem I see with your method is that you either have a combinatorical explosion of classes with the number of mandatory parameters, or force the user to set the parameters in one particular sqeuence, which is annoying.
Also, it is a lot of additional work.
public class Complex {
private final String first;
private final String second;
private final String third;
public static class False {}
public static class True {}
public static class Builder<Has1,Has2,Has3> {
private String first;
private String second;
private String third;
private Builder() {}
public static Builder<False,False,False> create() {
return new Builder<>();
}
public Builder<True,Has2,Has3> setFirst(String first) {
this.first = first;
return (Builder<True,Has2,Has3>)this;
}
public Builder<Has1,True,Has3> setSecond(String second) {
this.second = second;
return (Builder<Has1,True,Has3>)this;
}
public Builder<Has1,Has2,True> setThird(String third) {
this.third = third;
return (Builder<Has1,Has2,True>)this;
}
}
public Complex(Builder<True,True,True> builder) {
first = builder.first;
second = builder.second;
third = builder.third;
}
public static void test() {
// Compile Error!
Complex c1 = new Complex(Complex.Builder.create().setFirst("1").setSecond("2"));
// Compile Error!
Complex c2 = new Complex(Complex.Builder.create().setFirst("1").setThird("3"));
// Works!, all params supplied.
Complex c3 = new Complex(Complex.Builder.create().setFirst("1").setSecond("2").setThird("3"));
}
}
No, it's not new. What you're actually doing there is creating a sort of a DSL by extending the standard builder pattern to support branches which is among other things an excellent way to make sure the builder doesn't produce a set of conflicting settings to the actual object.
Personally I think this is a great extension to builder pattern and you can do all sorts of interesting things with it, for example at work we have DSL builders for some of our data integrity tests which allow us to do things like assertMachine().usesElectricity().and().makesGrindingNoises().whenTurnedOn();. OK, maybe not the best possible example but I think you get the point.
Why don't you put "needed" parameters in the builders constructor?
public class Complex
{
....
public static class ComplexBuilder
{
// Required parameters
private final int required;
// Optional parameters
private int optional = 0;
public ComplexBuilder( int required )
{
this.required = required;
}
public Builder setOptional(int optional)
{
this.optional = optional;
}
}
...
}
This pattern is outlined in Effective Java.
Instead of using multiple classes I would just use one class and multiple interfaces. It enforces your syntax without requiring as much typing. It also allows you to see all related code close together which makes it easier to understand what is going on with your code at a larger level.
IMHO, this seems bloated. If you have to have all the parameters, pass them in the constructor.
I've seen/used this:
new ComplexBuilder(requiredvarA, requiedVarB).optional(foo).optional(bar).build();
Then pass these to your object that requires them.
The Builder Pattern is generally used when you have a lot of optional parameters. If you find you need many required parameters, consider these options first:
Your class might be doing too much. Double check that it doesn't violate Single Responsibility Principle. Ask yourself why you need a class with so many required instance variables.
You constructor might be doing too much. The job of a constructor is to construct. (They didn't get very creative when they named it ;D ) Just like classes, methods have a Single Responsibility Principle. If your constructor is doing more than just field assignment, you need a good reason to justify that. You might find you need a Factory Method rather than a Builder.
Your parameters might be doing too little. Ask yourself if your parameters can be grouped into a small struct (or struct-like object in the case of Java). Don't be afraid to make small classes. If you do find you need to make a struct or small class, don't forget to refactor out functionality that belongs in the struct rather than your larger class.
For more information on when to use the Builder Pattern and its advantages you should check out my post for another similar question here
Question 1: Regarding the name of the pattern, I like the name "Step Builder":
http://rdafbn.blogspot.com/2012/07/step-builder-pattern_28.html
http://www.javacodegeeks.com/2013/05/building-smart-builders.html
Question 2/3: Regarding pitfalls and recommendations, this feels over complicated for most situations.
You are enforcing a sequence in how you use your builder which is unusual in my experience. I could see how this would be important in some cases but I've never needed it. For example, I don't see the need to force a sequence here:
Person.builder().firstName("John").lastName("Doe").build()
Person.builder().lastName("Doe").firstName("John").build()
However, many times the builder needed to enforce some constraints to prevent bogus objects from being built. Maybe you want to ensure that all required fields are provided or that combinations of fields are valid. I'm guessing this is the real reason you want to introduce sequencing into the building.
In this case, I like recommendation of Joshua Bloch to do the validation in the build() method. This helps with cross field validation because everything is available at this point. See this answer: https://softwareengineering.stackexchange.com/a/241320
In summary, I wouldn't add any complication to the code just because you are worried about "missing" a call to a builder method. In practice, this is easily caught with a test case. Maybe start with a vanilla Builder and then introduce this if you keep getting bitten by missing method calls.