Which methods and interfaces do you always implement in your classes?
Do you always override equals()? If you do, do you also do hashcode()? toString()? Do you make it a habit to implement the Comparable interface?
I've just written some code where I needed to implement compareTo() and override equals() to get my program to work in a sane manner; I now start seeing ways of using these everywhere...
What do y'all think?
I usually don't implement things in advance unless I need them.
If my class contains data members and I plan to store it somewhere, I will usually implement equals, hashCode, and comparable.
However, I found that most of my classes do not have this issue so there's no point to do it. For example, if your class revolves around functionality on other objects rather than data, why bother? If you have one instance or is organized hierarchically (e.g., a GUI widget or window), why bother?
Don't implement things you don't need, but always make sure to check whether they are needed or not because Java will generally not warn you.
Also, make sure to use your IDE or something like Apache commons to generate these functions. There is rarely a need to hand-code them.
As for toString, I rarely implement it until I find myself debugging and needing a better presentation in the Eclipse debugger (e.g., instead of object ID). I am afraid of implicit converts and never use toString when generating output.
(Almost) Always toString().
It is usually helpful for debugging purposes.
If you override equals, you (almost always) have to override hashCode. hashCode's contract is that two objects that are equals must have the same hash code. If you override equals such that equality is based on something besides the system identity hash code, the it's possible for two objects to be equal to each other but have different hash code.
I think you should never implement things you don't need, or are not sure you are going to need them or not. If it doesn't add value to your code, don't put it in. If you like to keep your (unit) tests in synch with your code, and use them to show use cases of your code, then you shouldn't have anything that is not covered by those tests. This includes equals(), hashCode(), compareTo() etc.
The problem I see, other than a possible waste of time, is that it would confuse someone who reads the code. "Why does this class have equals implemented? Is it some data value? Can it be a part of a collection? Does it even make sense to compare instances of this class?"
So I'd say only implement these when you actually need them. Therefore I can't say that I always implement this and that method. Perhaps toString() would be the method that I write the most, because it's usefulness appears a lot in debugging.
Almost always toString(), it's a pain to be debugging and read something about object Class#123456
equals() and hashCode() when needed, but always both or neither.
The Iterable interface is useful on collection-like classes, and will usually just return something like innerCollection.iterator(). Comparable can be useful too.
also, our company created some interfaces I use a lot, like Displayable (like toString, but gives more or another type of info, like for logging) and ParseLocatable (for stuff that comes from a file we parse, and we want to see in which file and on which line where for example a specific rule was defined (a little like stacktraces)
Effective Java has a chapter on how and when to implement toString, equals, hashCode, Comparable, etc. Highly recommended reading.
toString() is sometimes really helpful for testing purposes when you're too lazy to write Unit tests, also comes in handy for watches while debugging.
But I wouldn't recommend to implement Comparable in every object, it's nice sometimes, but use it wise or you'll end up with loads of code that you don't actually need.
Ditto for toString() and its variants in different languages and runtimes, but I'd also like to point you towards Ned Batchelder's article on stringification, which is a good read and is close to my reasoning for doing so.
For business CRUD applications, I always override ToString. This helps when binding a List(Of T) to a WinForm control. For example, overriding ToString in a Customer object to return _name will then automatically show the customer name value when binding a List(Of Customer) to a ListBox control. Comes in handy.
I usually implement the compareTo method as well as the toString method. Its generally good to know how one instance of the class compares to another instance for sorts and searches. Also an overrided toString method is great for debugging. You can see the content of the class (not just the memory location) presented in a way that makes sense for the class you have written.
On objects that are used primarily for holding data ("rocks"), I find toString and the equals/hashcode contract to be invaluable. This is because rocks are typically passed into and extracted out of collections all the time, most notably the Hash(Set/Map) collections, which require the equals and hashcode contract, and it is very easy to see these objects in a debugger if toString is implemented. When implementing toString, I always use Apache Common's ToStringBuilder class to display all of my properties - that way it is very easy to read the output. I am never concerned about "implicit conversion" - toString is not meant to be used as anything but a human readable string, that the toString can be used on Number subclasses to convert to and from is really just a quirk, etc. Production code should never rely on the toString method to convert the object to a string representation, because that's not what it's for - it's for a human readable string representation, so a different method should be defined if a non-human, but computer code useable string representation is desired.
For data value classes I have an AbstractPojo class which uses reflection to implement equals, hashCode, toString and asMap()
I extend this class for all my data value objects so I don't implement this each time.
I don't override ToString but I apply sometimes the DebuggerDisplay attribute which does the same for the debugging purposes and does not put overhead on the release version.
I also found myself overriding the ToString() method a lot. Especially during development. Although code generators help, it becomes quite annoying to have to change it every time you rename a class member.
Actually I got so annoyed, I tried to find a remedy, This is what I came up with:
Creates a string of this format: MemberType MemberName=MemberValue
Usage:
string testMember = "testing";
Console.WriteLine(Member.State(() => testMember));
Writes ' string testMember="testing" ' to the Console.
Here it is:
public static class Member
{
public static string State<T>(Func<T> expr)
{
var member = ExtractMemberFromLambdaExpression(expr);
Type memberType = GetTypeOfMember(member);
string contents = ExtractContentsFromLambdaExpression(expr);
return string.Format("{0} {1}={2}",memberType.Name, member.Name, contents);
}
static string ExtractContentsFromLambdaExpression<T>(Func<T> expr)
{
if (expr() == null) {
return "NULL";
}
string contents = string.Empty;
if (expr().GetType().IsArray) {
foreach (var item in (expr() as Array)) {
contents += item.ToStringNullSafe() + ", ";
}
contents = contents.Trim().TrimEnd(',');
} else {
contents = expr().ToString();
}
return contents;
}
static MemberInfo ExtractMemberFromLambdaExpression<T>(Func<T> expr)
{
// get IL code behind the delegate
var il = expr.Method.GetMethodBody().GetILAsByteArray();
// bytes 2-6 represent the member handle
var memberHandle = BitConverter.ToInt32(il, 2);
// resolve the handle
return expr.Target.GetType().Module.ResolveMember(memberHandle);
}
static Type GetTypeOfMember(MemberInfo member)
{
Type memberType;
if (member.MemberType == MemberTypes.Field) {
memberType = GetFieldType(member as FieldInfo);
}
else if (member.MemberType == MemberTypes.Property) {
memberType = GetPropertyType(member as PropertyInfo);
}
else {
memberType = typeof(object);
}
return memberType;
}
static Type GetFieldType(FieldInfo fieldInfo)
{
return fieldInfo.FieldType;
}
static Type GetPropertyType(PropertyInfo propertyInfo)
{
return propertyInfo.PropertyType;
}
}
A more thorough explanation and how to use it can be found on my blog about the:
Generic ToString() Method
Related
I was wondering, when constructing an object, is there any difference between a setter returning this:
public User withId(String name) {
this.name = name;
return this;
}
and a builder (for example one which is generated by Builder Generator plugin for IDEA)?
My first impression is that a setter returning this is much better:
it uses less code - no extra class for builder, no build() call at the end of object construction.
it reads better:
new User().withName("Some Name").withAge(30);
vs
User.UserBuilder.anUserBuilder().withName("Some Name").withAge(30).build();
Then why to use builder at all? Is there anything I am missing?
The crucial thing to understand is the concept of an immutable type.
Let's say I have this code:
public class UnitedStates {
private static final List<String> STATE_NAMES =
Arrays.asList("Washington", "Ohio", "Oregon", "... etc");
public static List<String> getStateNames() {
return STATE_NAMES:
}
}
Looks good, right?
Nope! This code is broken! See, I could do this, whilst twirling my moustache and wielding a monocle:
UnitedStates.getStateNames().set(0, "Turtlia"); // Haha, suck it washington!!
and that will work. Now for ALL callers, apparently there's some state called Turtlia. Washington? Wha? Nowhere to be found.
The problem is that Arrays.asList returns a mutable object: There are methods you can invoke on this object that change it.
Such objects cannot be shared with code you don't trust, and given that you don't remember every line you ever wrote, you can't trust yourself in a month or two, so, you basically can't trust anybody. If you want to write this code properly, all you had to do is use List.of instead of Arrays.asList, because List.of produces an immutable object. It has zero methods that change it. It seems like it has methods (it has a set method!), but try invoking it. It won't work, you'll get an exception, and crucially, the list does not change. It is in fact impossible to do so. Fortunately, String is also immutable.
Immutables are much easier to reason about, and can be shared freely with whatever you like without copying.
So, want your own immutable? Great - but apparently the only way to make one, is to have a constructor where all values are set and that's it - immutable types cannot have set methods, because that would mutate them.
If you have a lot of fields, especially if those fields have the same or similar types, this gets annoying fast. Quick!
new Bridge("Golden Gate", 1280, 1937, 2737);
when was it built? How long is it? What's the length of the largest span?
Uhhhhhhh..... how about this instead:
newBridge()
.name("Golden Gate")
.longestSpan(1280)
.built(1937)
.length(2737)
.build();
sweet. Names! builders also let you build over time (by passing the builder around to different bits of code, each responsible for setting up their bits). But a bridgebuilder isn't a bridge, and each invoke of build() will make a new one, so you keep the general rules about immutability (a BridgeBuilder is not immutable, but any Bridge objects made by the build() method are.
If we try to do this with setters, it doesn't work. Bridges can't have setters. you can have 'withers', where you have set-like methods that create entirely new objects, but, calling these 'set' is misleading, and you create both a ton of garbage (rarely relevant, the GC is very good at collecting short lived objects), and intermediate senseless bridges:
Bridge goldenGate = Bridge.create().withName("Golden Gate").withLength(2737);
somewhere in the middle of that operation you have a bridge named 'Golden Gate', with no length at all.
In fact, the builder can decide to not let you build() bridge with no length, by checking for that and throwing if you try. This process of invoking one method at a time can't do that. At best it can mark a bridge instance as 'invalid', and any attempt to interact with it, short of calling .withX() methods on it, results in an exception, but that's more effort, and leads to a less discoverable API (the with methods are mixed up with the rest, and all the other methods appear to throw some state exception that is normally never relevant.. that feels icky).
THAT is why you need builders.
NB: Project Lombok's #Builder annotation gives you builders for no effort at all. All you'd have to write is:
import lombok.Value;
import lombok.Builder;
#Value #Builder
public class Bridge {
String name;
int built;
int length;
int span;
}
and lombok automatically takes care of the rest. You can just Bridge.builder().name("Golden Gate").span(1280).built(1937).length(2737).build();.
Builders are design patterns and are used to bring a clear structure to the code. They are also often used to create immutable class variables. You can also define preconditions when calling the build() method.
I think your question is better formulated like:
Shall we create a separate Builder class when implementing the Builder Pattern or shall we just keep returning the same instance?
According to the Head First Design Patterns:
Use the Builder Pattern to encapsulate the construction of a product
and allow it to be constructed in steps.
Hence, the Encapsulation is important point.
Let's now see the difference in the approaches you have provided in your original question. The main difference is the Design, of how you implement the Builder Pattern, i.e. how you keep building the object:
In the ObjecBuilder separate class approach, you keep returning the Builder object, and you only(!) return the finalized/built Object, after you have finalized building, and that's what better encapsulates creation process, as it's more consistent and structurally well designed approach, because you have a clearly separated two distinct phases:
1.1) Building the object;
1.2) Finalizing the building, and returning the built instance (this may give you the facility to have immutable built objects, if you eliminate setters).
In the example of just returning this from the same type, you still can modify it, which probably will lead to inconsistent and insecure design of the class.
It depends on the nature of your class. If your fields are not final (i.e. if the class can be mutable), then doing this:
new User().setEmail("alalal#gmail.com").setPassword("abcde");
or doing this:
User.newBuilder().withEmail("alalal#gmail.com").withPassowrd("abcde").build();
... changes nothing.
However, if your fields are supposed to be final (which generally speaking is to be preferred, in order to avoid unwanted modifications of the fields, when of course it is not necessary for them to be mutable), then the builder pattern guarantees you that your object will not be constructed until when all fields are set.
Of course, you may reach the same result exposing a single constructor with all the parameters:
public User(String email, String password);
... but when you have a large number of parameters it becomes more convenient and more readable to be able to see each of the sets you do before building the object.
One advantage of a Builder is you can use it to create an object without knowing its precise class - similar to how you could use a Factory. Imagine a case where you want to create a database connection, but the connection class differs between MySQL, PostgreSQL, DB2 or whatever - the builder could then choose and instantiate the correct implementation class, and you do not need to actually worry about it.
A setter function, of course, can not do this, because it requires an object to already be instantiated.
The key point is whether the intermediate object is a valid instance.
If new User() is a valid User, and new User().withName("Some Name") is a valid User, and new User().withName("Some Name").withAge(30) is a valid user, then by all means use your pattern.
However, is a User really valid if you've not provided a name and an age? Perhaps, perhaps not: it could be if there is a sensible default value for these, but names and ages can't really have default values.
The thing about a User.Builder is the intermediate result isn't a User: you set multiple fields, and only then build a User.
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.
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.
class MyThing {
protected HashMap<String,Object> fields;
protected MyThing(HashMap<String,Object> newFields){
fields.putAll(newFields);
}
protected Object get(String key){
return fields.get(key);
}
}
Now a little background. I am using this class as a super class to a bunch of different classes which represent objects from an XML file. This is basically an implementation of an API wrapper and I am using this as an adapter between the parsed XML from an API and a database. Casting is delegated to the caller of the get method. If the subclasses need to do something when they are created or when they return a variable, they just call super and then manipulate what gets returned afterwards. eg.:
class Event extends MyThing {
public Event(HashMap<String,Object> newFields){
super(newFields);
// Removes anything after an # symbol in returned data
Pattern p = Pattern.compile("\\#.*$");
Matcher m = p.matcher((String)fields.get("id"));
boolean result = m.find();
if (result)
fields.put("id", m.replaceFirst(""));
}
}
public Object get(String key){
Object obj = super(key);
if (key.equals("name")){
return "Mr./Mrs. " + ((String)obj);
}
}
}
The reason I feel like I should do this is so I don't have to write getId, getName, getWhatever methods for every single subclass just because they have different attributes. It would save time and it is pretty self explanatory.
Now this is obviously "unJavalike" and more like a ducktyped language way of doing things, but is there a logical reason why I should absolutely not be doing this?
If you're going to this level of complexity and mucking up your object model just because you don't want to have getters and setters, do it in Groovy instead.
Groovy is a duck typed dynamic language on the JVM that accepts 98% of valid Java code, so you already know most of the language (you don't lose functionality)...there are "more idiomatic" ways of doing things, but you can pick those up with time. It also already has a built in XmlSlurper, which probably does most of what you're trying to do anyway.
As for the "reasons why you shouldn't", you're introducing all types of maintainability concerns.
New classes will always have to derive from the base class.
They will have to implement a constructor that always calls a base constructor
They will have to override get() [which you're basically using to encapsulate your getters and setters anyway, why not just add that method and delegate to those other methods] and write specific logic which is likely to degrade with time.
Why shouldn't you? It'll work, right? Sure. But it's poor engineering in that you're either creating a maintenance nightmare, or reinventing the wheel and likely to do it wrong.
Obviously, it's not type safe.
Future maintainers won't know what the types are supposed to be and will get generally confused as to why you're not using POJOs.
Instead of constant time, space complexity and performance you have the characteristics of a HashMap.
It become very difficult to write non-trivial getters/setters in future.
Most data binding systems are designed to work with POJOs/Beans (JAXB, JPA, Jackson, etc).
I'm sure there are more, but this will do. Try using some proper OXM libraries and you'll be much better off.
I'm in the middle of QA'ing a bunch of code and have found several instances where the developer has a DTO which implements Comparable. This DTO has 7 or 8 fields in it. The compareTo method has been implemented on just one field:
private DateMidnight field1; //from Joda date/time library
public int compareTo(SomeObject o) {
if (o == null) {
return -1;
}
return field1.compareTo(o.getField1());
}
Similarly the equals method is overridden and basically boils down to:
return field1.equals(o.getField1());
and finally the hashcode method implementation is:
return field1.hashCode;
field1 should never be null and will be unique across these objects (i.e. we shouldn't get two objects with the same field1).
So, the implementations are consistent which is good, but should I be concerned that only one field is used? Is this unusual? Is it likely to cause problems or confuse other developers? I'm thinking of the scenario where a list of these objects are passed around and another developer uses a Map or Set of somesort and gets unusual behaviour from these objects. Any thoughts appreciated. Thanks!
I suspect that this is a case of "first use wins" - someone needed to sort a collection of these objects or put them in a hash map, and they only cared about the date. The easiest way of implementing that was to override equals/hashCode and implement Comparable<T> in the way you've said.
For specialist sorting, a better approach would be to implement Comparator<T> in a different class... but Java doesn't have any equivalent class for equality testing, unfortunately. I consider it a major weakness in the Java collections, to be honest.
Assuming this really isn't "the one natural and obvious comparison", it certainly smells in terms of design... and should be very carefully document.
Strictly speaking, this violates the Comparable spec:
http://download.oracle.com/javase/6/docs/api/java/lang/Comparable.html
Note that null is not an instance of any class, and e.compareTo(null) should throw a NullPointerException even though e.equals(null) returns false.
Similarly, it looks like the equals method will throw NPE on equals(null) instead of returning false (unless of course you "boiled" out the null handling code).
Is it likely to cause problems or confuse other developers?
Possibly, possibly not. It really depends on how large your project is and how widespread/"reusable"/long-lived your object source code is expected to be used:
Small/short-lived/limited use == probably not a problem.
Large/long-lived/widespread use == counter-intuitive implementation may cause future problems
You shouldnt be concerned with it, if field1 is really unique. If it`s not, you may have problems. Anyway, my advise is to do some unit tests. They should show the truth.
I don't think you need to be concerned. The contract between the three methods is kept and it's consistent.
Whether it's correct from a business logic point of view is a different question.
If e.g. field1 maps to a primary key in the database it's perfectly valid. If field1 is the "firstname" of a person, I would be concerned