Prev: Initializing a Map in an Interface?
Next: Urgent Opening for Senior .Net Engineer position with our direct client in Milpitas, CA
From: Rhino on 15 Mar 2010 16:50 This question is completely unrelated to the one I just asked about initializing a Map.... -- I have a class named StringUtils containing several utility methods. The class is stored in a package called "common" because it could potentially be utilitized by lots of other classes. The methods in this class include count(), which determines the number of occurrences of a character in a string, and blanks(), which creates a String containing the number of blanks specified in the input parameters (for example, blanks(4) generates a String containing 4 blanks). I'm trying to figure out if this utility class should be defined final and have all of its methods defined as static, just the way things work with the Math class, so that my classes could be referenced statically. For example, if the methods were static, I would write my code like this: int num = StringUtils.count("a", "foo"); System.out.println(StringUtils.blanks(4) + "Hello world"); Or would it be better to have a StringUtils NOT be final and NOT make its methods static? In that case, I'd have to instantiate StringUtils, then use the reference to the instance to use the methods, like this: StringUtils myUtils = new StringUtils(); int num = myUtils.count("a", "foo"); System.out.println(myUtils.blanks(4) + "Hello world"); Either way will work but which is the better design and why? And no, this is not a homework question. It's just one of many gaps in my own understanding ;-) -- Rhino --- news://freenews.netfront.net/ - complaints: news(a)netfront.net ---
From: Lew on 15 Mar 2010 17:00 Rhino wrote: > I have a class named StringUtils containing several utility methods. The > class is stored in a package called "common" because it could potentially > be utilitized by lots of other classes. The methods in this class include > count(), which determines the number of occurrences of a character in a > string, and blanks(), which creates a String containing the number of > blanks specified in the input parameters (for example, blanks(4) > generates a String containing 4 blanks). > > I'm trying to figure out if this utility class should be defined final > and have all of its methods defined as static, just the way things work No. Not declared as final, but with a private constructor. > with the Math class, so that my classes could be referenced statically. > For example, if the methods were static, I would write my code like this: > > int num = StringUtils.count("a", "foo"); > System.out.println(StringUtils.blanks(4) + "Hello world"); > > Or would it be better to have a StringUtils NOT be final and NOT make its > methods static? In that case, I'd have to instantiate StringUtils, then No. Not final, and yes static. > use the reference to the instance to use the methods, like this: > > StringUtils myUtils = new StringUtils(); > int num = myUtils.count("a", "foo"); > System.out.println(myUtils.blanks(4) + "Hello world"); > > Either way will work but which is the better design and why? Neither way. Have the class be non-final with a private constructor and all static methods. A class who will never have instances with their own state, whose sole purpose is to provide utility methods for other classes, whose entire operation depends only on data in the argument lists of those methods, and ultimately, for whom it really never adds value to have an instance, is called a "utility class" and likely should have instantiation prevented and all its members static. Declaring a class final does not prevent its instantiation. Declaring its constructor private does, and also prevents subclassing, making the 'final' declaration redundant, so don't bother with it. -- Lew
From: Eric Sosman on 15 Mar 2010 17:21 On 3/15/2010 4:50 PM, Rhino wrote: > This question is completely unrelated to the one I just asked about > initializing a Map.... > > -- > > I have a class named StringUtils containing several utility methods. The > class is stored in a package called "common" because it could potentially > be utilitized by lots of other classes. The methods in this class include > count(), which determines the number of occurrences of a character in a > string, and blanks(), which creates a String containing the number of > blanks specified in the input parameters (for example, blanks(4) > generates a String containing 4 blanks). > > I'm trying to figure out if this utility class should be defined final > and have all of its methods defined as static, just the way things work > with the Math class, so that my classes could be referenced statically. > For example, if the methods were static, I would write my code like this: > > int num = StringUtils.count("a", "foo"); > System.out.println(StringUtils.blanks(4) + "Hello world"); > > Or would it be better to have a StringUtils NOT be final and NOT make its > methods static? In that case, I'd have to instantiate StringUtils, then > use the reference to the instance to use the methods, like this: > > StringUtils myUtils = new StringUtils(); > int num = myUtils.count("a", "foo"); > System.out.println(myUtils.blanks(4) + "Hello world"); > > Either way will work but which is the better design and why? The methods as you describe them sound like they ought to be static. There's no state associated with a StringUtils instance that wouldn't also be associated with every other StringUtils instance, so one asks: What value does an instance bring to the party? That is, in StringUtils ut1 = new StringUtils(); int num1 = ut1.count("a", "foo"); StringUtils ut2 = new StringUtils(); int num2 = ut2.count("a", "foo"); .... why bother with ut2 when ut1 would do exactly the same thing, exactly as well? Even if blanks() maintains a cache of already-generated Strings that it can recycle to satisfy future requests, I'd say the cache belongs to the class and not to an instance. If ut1.blanks(4) caches a String, shouldn't ut2.blanks(4) be able to re-use that same String instead of caching its own? The question of whether to make StringUtils final is another matter, and seems independent of whether these methods are static. -- Eric Sosman esosman(a)ieee-dot-org.invalid
From: markspace on 15 Mar 2010 18:00 Rhino wrote: > I have a class named StringUtils containing several utility methods. I asked a question like this here long ago. What I think now is that you almost certainly should make the class final, and all the methods static. If you do need to keep state, make a new class, don't reuse the StringUtils, except as a factory. And as Lew says, the best way to make such a class final is to make the constructor private. That kills two birds with one stone. First the class is final because subclasses can't call the constructor, and second other classes can make instances of your utility class either. One last idea, I have a string utility class that is declared something like this: package mypackage.common.stringutils; public class StringUtils { ... In other words, the package name is stringutils, and so is the class name. This allows me to easily add classes to the stringutils package, without trying to overload StringUtils to hold state. For example, if RepeatedString is a class that tries to be faster than blanks(), but requires a max length: package mypackage.common.stringutils; public class RepeatedString { final private String repeated; public RepeatedString( String s, int dups ) { StringBuilder sb = new StringBuilder( s.length() * dups ); for( int i = 0; i < dups; i++ ) { sb.append( s ); } repeated = sb.toString(); } public String subStr( int count ) { return repeated.substring( 0, count ); } } This just allows me to have a nicer place to put RepeatedString (under stringutils) rather than have to find a place to shoe-horn it in somewhere else.
From: Lew on 15 Mar 2010 18:10
Rhino wrote: >> I have a class named StringUtils containing several utility methods. markspace wrote: > I asked a question like this here long ago. What I think now is that > you almost certainly should make the class final, and all the methods > static. > > If you do need to keep state, make a new class, don't reuse the > StringUtils, except as a factory. > > And as Lew says, the best way to make such a class final is to make the > constructor private. That kills two birds with one stone. First the When one speaks of making a class "final" in Java, one is referring to use of the 'final' keyword. Using "final" to mean something different is confusing here. -- Lew |