This question already has answers here:
Best practice for passing many arguments to method?
(17 answers)
Closed 9 years ago.
Java 1.6
I have a method with many parameters. This is not a constructor but a normal method.
class A {
public void m (int a, int b, boolean c, List<>...) { }
}
How to replace a method to a better form ? As I understand the Builder design pattern is for contructors.
If I face a method that has too many parameters I do the following steps usually:
I try to identify an entity these parameters are related to and check if Preserve Whole Object refactoring can be used.
You are getting several values from an object and passing these values as parameters in a method call. Send the whole object instead.
If all these parameters are independent and I want to increase number of parameters I use another one common solution - Introduce Parameter Object refactoring.
You have a group of parameters that naturally go together. Replace them with an object.
In order to build that object other techniques and patterns can be used (e.g. Builder, Method chaining, Fluent interfaces).
If the parameters naturally go together they can be substituted with the Parameter Object. If you don't want a long list of parameters in the constructor of the Parameter Object you can use the Builder design pattern to construct it. Another somewhat relevant technique is Preserve Whole Object.
You are right with Builder, depends on whether those params are mandatory or not.
I would personally start with http://en.wikipedia.org/wiki/Single_responsibility_principle because method (and constructors or classes) with many parameters smells. I mean, are those parameters related, is the method logic related together? Does it make any sense?
If those params has some relations, they could fit into some kind of domain entity.
Builder pattern is used to construct a complex object step by step and the final step will return the object. The process of constructing an object should be generic so that it can be used to create different representations of the same object.
“Separate the construction of a complex object from its representation so that the same construction process can create different representations”
If number of parameters is dynamic, you can use double brace initialization:
public static void main(final String[] args) {
method(new HashMap<String, Object>(){{
put("p1", new Object());
put("p2", new Object());
}});
}
private static void method(Map<String, Object> params){
}
It has some drawbacks, but still viable approach. Be careful every call site will have it's own anonymous class. There also might be some problems with type safety. Instead of String-based keys, you can use enums. Instead of Map any custom type could be used, Map just is the most common. DBI is more useful then varargs in case of dynamic parameters length.
If you need a lot of parameters - something wrong...
method not static -> You can define some parameters as fields.
If you realy need do it like this, maybe better create class A.AMParameter(int a, int b, boolean c, List<>...), and pass it in m (A.AMParameter), or use Map...
Related
In my program I read a fixed length file, stored each string in a local variable, and then stored every value into a class type array list. For creating the object of an array list, I used argument constructor with all the variables. The below code demonstrates this.
String a = "text1";
String b = "text2";
SampleModel sm = new SampleModel(a,b);
ArrayList<SampleModel> sampleList = new ArrayList<>();
sampleList.add(sm);
I find this absolutely right but my colleague asked me to change it to a no arg constructor and call getters and setters instead. That would be like below.
SampleModel sm = new SampleModel();
ArrayList<SampleModel> sampleList = new ArrayList<>();
String a = "text1";
String b = "text2";
sm.setA(a);
sm.setB(b);
sampleList.add(sm);
Is there any reason to prefer a no arg constructor over argument constructor? (My program has around 15 variables)
It depends on how the class will be used.
For example, an immutable class will need a constructor that takes arguments, and no setters.
But a Java Bean will need a no-argument constructor, and setters.
Some things to consider:
Encapsulation can be valuable. Other than special cases like JavaBeans, usually the interface of the class can be designed based on the desired interactions, not on the current set of data members.
Methods have names. Java does not support named arguments. Method names communicate how an actual parameter is being used, in the calling code. If your class has more than a handful of parameters, passing them via methods can result in more readable calling code.
Immutable classes have value. If you're adding named setters directly in your class, it won't be immutable. The builder pattern allows you to accept construction parameters even for immutable classes.
Whether I use accessors and mutators for a class variable depends on two things:
Whether the variable is essential or optional to the object.
Whether it might ever change in the course of using the object, or whether it is final.
Variables that are necessary and final should be in the constructor, in my opinion, and should not have mutators. Variables that are optional should have accessors and mutators. Variables that are essential but might change are up to your discretion. I would probably put them in the constructor, but use a Builder design pattern to avoid having a long list of arguments for the constructor.
A constructor that takes arguments is essentially for convenience (although that's not always the case if the object requires arguments in order to be constructed properly, it is here without seeing anymore context); it's doing the exact same thing as the set methods are doing.
There is no reason to not have a constructor take arguments, as long as those arguments "make sense" in the context of the object. In other words, it's more of a semantics thing to consider than a correctness thing.
If the constructor is:
public SampleModel(String a, String b)
{
this.a = a;
this.b = b;
}
It probably doesn't make a difference.
It might just be that it's easier to see whats going on than having a large comma separated list. This might also be a nice place to use Double Brace Initialization:
String a = "text1";
String b = "text2";
SampleModel sm = new SampleModel() {{
setA(a);
setB(b);
}};
ArrayList<SampleModel> sampleList = new ArrayList<>() {{
add(sm);
}};
Quotation from Fowler and Beck book: "Refactoring"
Long Parameter List
In our early programming days we were taught to pass in as parameters everything needed by a routine. This was understandable because the alternative was global data, and global data is evil and usually painful. Objects change this situation because if you don't have something you need, you can always ask another object to get it for you. Thus with objects you don't pass in everything the method needs; instead you pass enough so that the method can get to everything it needs. A lot of what a method needs is available on the method's host class. In object-oriented programs parameter lists tend to be much smaller than in traditional programs. This is good because long parameter lists are hard to understand, because they become inconsistent and difficult to use, and because you are forever changing them as you need more data. Most changes are removed by passing objects because you are much more likely to need to make only a couple of requests to get at a new piece of data. Use Replace Parameter with Method when you can get the data in one parameter by making a request of an object you already know about. This object might be a field or it might be another parameter. Use Preserve Whole Object to take a bunch of data gleaned from an object and replace it with the object itself. If you have several data items with no logical object, use Introduce Parameter Object. There is one important exception to making these changes. This is when you explicitly do not want to create a dependency from the called object to the larger object. In those cases unpacking data and sending it along as parameters is reasonable, but pay attention to the pain involved. If the parameter list is too long or changes too often, you need to rethink your dependency structure.
When should I use a constructor and when should I use static method?
Can you explain above with small snippet? I skimmed through a few threads but I'm still not clear with this.
Joshua Bloch advises to favor static factory methods instead of constructors (which I think is a good practice). Couple of advantages and disadvantages :
Advantages of static factory methods :
unlike constructors, they have names
unlike constructors, they are not required to create a new object each time they're invoked (you can cache instances : e.g. Boolean.valueOf(..)
unlike constructors, they can return an object of any subtype of their return type (great flexibility)
Disadvantages of static factory methods :
They are not really distiguishable from other static methods (it's hard to find out how to initialize an object if you are not familiar with the API)
The main disadvantage (if you use only static factory methods, and make constructors private) is that you cannot subclass that class.
Use a public constructor when you only ever want to return a new object that type and you want simplicity.
A good example is StringBuilder as it's mutable and you are likely to want a new object each time.
public String toString() {
StringBuilder sb = new StringBuilder();
// append fields to the sb
return sb.toString();
}
Use a static factor method when you might want to re-use objects (esp if immutable), you might want to return a sub-class or you want descriptice construction. A good example is EnumSet which has a number of static factories which do different things even though some have the same arguments.
EnumSet.noneOf(RetentionPolicy.class);
// has the same arguments, but is not the same as
EnumSet.allOf(RetentionPolicy.class);
In this case, using a static factory makes it clear what the difference between these two ways of construction the set.
Also EnumSet can return two different implementations, one optimised for enums with a small number of values (<= 64) RegularEnumSet and another for many values called JumboEnumSet
Always use a constructor if your class has a state (even for a single instance; singleton pattern ).
Only use static for utility methods like in java.lang.Math
Example:
public static int max(int a, int b) {
return (a >= b) ? a : b;
}
Doesn't change any state (instance variables) of an object, thus it can be declared static.
Use constructor when you need an object and other stuffs like functions and variables having one copy for every object.
when you want to do something without creating object then use static method.
Example:
public class Test {
public int value;
public static int staticValue;
public int getValue() {
return ++value;
}
public static int getStaticValue() {
return ++staticValue;
}
}
public class TestClass {
public static void main(String[] args) {
Test obj = new Test();
Test obj1 = new Test();
S.o.p(obj.getValue());
S.o.p(obj1.getValue));
S.o.p(Test.getStaticValue());
S.o.p(Test.getStaticValue());
}
}
Static factory methods have names, constructors don't. Thus factory methods can carry natural documentation about what they do that constructors can't. For example, see the factory methods in the Guava Libraries, like ImmutableMap.copyOf(otherMap). While this might have little effect on behaviour of construction, it has a huge effect on readability of the code. Definitely consider this if you're publishing an API.
Also you can use a factory when you need to do any more complicated configuration of the object you're creating, especially if you need to publish to other threads (registering in pools, exposing as an MBean, all manner of other things...) to avoid racy publication. (See e.g. Java Concurrency In Practice section 3.2)
Static methods that do something (e.g. Math.min) are not really the same thing as static factories, which can be considered direct replacements for constructors, with added flexibility, evolvability and (often) clarity.
Whenever you need to create an instance of an object you will have to use the constructor.
So, if you want to create a Car object, then you will need a constructor for that.
The keyword static means, that your method can be called without creating an instance.
class Car
{
private int num_of_seats;
public Car(int number_of_seats)
{
this.num_of_seats = number_of_seats;
}
// You want to get the name of the class that has to do with
// this class, but it's not bounded with any data of the class
// itself. So you don't need any instance of the class, and
// you can declare it as static.
static String getClassName()
{
return "[Car]";
}
}
In general you will use static class with data that are not correlated with the instance of the object.
Another example is:
class Ring
{
private List nodes;
public Ring(List nodes)
{
this.nodes = nodes;
}
// You want to calculate the distance of two ids on the ring, but
// you don't care about the ring. You care only about the ids.
// However, this functionality logical falls into the notion of
// the ring, that's why you put it here and you can declare it
// as static. That way you don't have to manage the instance of
// ring.
static double calculateDistance(int id_1, int id_2)
{
return (id_1 - id_2)/383; // The divisor is just random just like the calculation.
}
}
As the posts above say, it's just a matter of what you want to do and how you want to do it. Also, don't try to understand everything rightaway, write some code then try different approaches of that code and try to understand what your code does. Examples are good, but you need to write and then understand what you did. I think it's the only way you will figure out
why you do staff the way you have to do.
Static methods do not have to instantiate new objects everytime. Since object instantiation is expensive it allows instances to be cached within the object. So, it can improve performance.
This is the explanation from the Effective Java :
This allows immutable classes (Item 15) to use preconstructed
instances, or to cache instances as they’re constructed, and dispense
them repeatedly to avoid creating unnecessary duplicate objects. The
Boolean.valueOf(boolean) method illustrates this technique: it never
creates an object. This technique is similar to the Flyweight pattern
[Gamma95, p. 195]. It can greatly improve performance if equivalent
objects are requested often, especially if they are expensive to
create.
i.e. if you want to use a singleton, which means that you have only one instance of the object, which might be shared with others, then you need a static method, which will internally will call the constructor. So, every time someone wants an instance of that object you will return always the same, thus you will consume memory only for one. You always need a constructor in object oriented programming, in every OO language. In java an in many other languages the default constructor of an object is implied, and built automatically. But you need some custom functionality you have to make your own.
Above you see a few good examples of the usage. However, if you have something specific in your mind, please let us know. I mean if you have a specific case where you are not sure if you should use a static method or a constructor. Anyhow, you will definitely need a constructor, but I am not sure about the static method.
I've been reviewing Java Regex Library, surprised by the fact the Pattern class does not have a public constructor which I've taken for granted for years.
One reason I suspect the static compile method is being used in favor of constructor could be that constructor would always return a new object while a static method might return a previously created (and cached) object provided that the pattern string is the same.
However, it is not the case as demonstrated by the following.
public class PatternCompiler {
public static void main(String[] args) {
Pattern first = Pattern.compile(".");
Pattern second = Pattern.compile(".");
if (first == second) {
System.out.println("The same object has been reused!");
} else {
System.out.println("Why not just use constructor?");
}
}
}
Any other strong rationales behind using static method over constructor?
Edit: I found a related question here. None of the answers there convinced me either. Reading through all answers, I get a feeling that a static method has quite a few advantages over a public constructor regarding creating an object but not the other way around. Is that true? If so, I'm gonna create such static methods for each one of my classes and safely assume that it's both more readable and flexible.
Generally, a class won't have a public constructor for one of three reasons:
The class is a utility class and there is no reason to instantiate it (for example, java.lang.Math).
Instantiation can fail, and a constructor can't return null.
A static method clarifies the meaning behind what happens during instantiation.
In the class of Pattern, the third case is applicable--the static compile method is used solely for clarity. Constructing a pattern via new Pattern(..) doesn't make sense from an explanatory point of view, because there's a sophisticated process which goes on to create a new Pattern. To explain this process, the static method is named compile, because the regex is essentially compiled to create the pattern.
In short, there is no programmatic purpose for making Pattern only constructable via a static method.
One possible reason is that this way, caching can later be added into the method.
Another possible reason is readability. Consider this (often cited) object:
class Point2d{
static Point2d fromCartesian(double x, double y);
static Point2d fromPolar(double abs, double arg);
}
Point2d.fromCartesian(1, 2) and Point2d.fromPolar(1, 2) are both perfectly readable and unambiguous (well... apart from the argument order).
Now, consider new Point2d(1, 2). Are the arguments cartesian coordinates, or polar coordinates? It's even worse if constructors with similar / compatible signatures have entirely different semantics (say, int, int is cartesian, double, double is polar).
This rationale applies to any object that can be constructed in multiple different ways that don't differ in just the argument type. While Pattern, currently, can only be compiled from a regex, different representations of a Pattern may come in the future (admittably, then, compile is a bad method name).
Another possible reason, mentioned by #Vulcan, is that a constructor should not fail.
If Pattern.compile encounters an invalid pattern it throws a PatternSyntaxException. Some people may consider it a bad practice to throw an exception from a constructor. Admittably, FileInputStream does exactly that. Similarly, if the design decision was to return null from the compile method, this would not be possible with a constructor.
In short, a constructor is not a good design choice if:
caching may take place, or
the constructor is semantically ambiguous, or
the creation may fail.
This is just a design decision. In this case there is no "real" advantage. However, this design allows optimisation (caching for instance) without changing the API. See http://gbracha.blogspot.nl/2007/06/constructors-considered-harmful.html
Factory methods have several advantages, some of which are already specified in other answers. The advice to consider factory methods instead of constructors is even the very first chapter in the great book "Effective Java" from Joshua Bloch (a must-read for every Java programmer).
One advantage is that you can have several factory methods which have the same parameter signatures but different names. This you can't achieve with constructors.
For example, one might want to create a Pattern from several input formats, all of which are just Strings:
class Pattern {
compile(String regexp) { ... }
compileFromJson(String json) { ... }
compileFromXML(String xml) { ... }
}
Even if you are not doing this when you create the class, factory methods give you the ability to add such methods latter without causing weirdness.
For example, I have seen classes where the need for a new constructor came later and a special meaning-less second parameter had to be added to the second constructor in order to allow overloading. Obviously, this is very ugly:
class Ugly {
Ugly(String str) { ... }
/* This constructor interpretes str in some other way.
* The second parameter is ignored completely. */
Ugly(String str, boolean ignored) { ... }
}
Unfortunately, I can't remember the name of such a class, but I think it even was in the Java API.
Another advantage which has not been mentioned before is that with factory methods in combination with package-private constructors you can prohibit sub-classing for others, but still use sub-classes yourself. In the case of Pattern, you might want to have private sub-classes like CompiledPattern, LazilyCompiledPattern, and InterpretedPattern, but still prohibit sub-classing to ensure immutability.
With a public constructor, you can either prohibit sub-classing for everybody, or not at all.
If you really want to take the deep dive, plunge into the archives of JSR 51.
Regular expressions have been introduced as part of JSR 51, that’s where you might still find the design decisions in their archives, http://jcp.org/en/jsr/detail?id=51
It has a private constructor.
/**
* This private constructor is used to create all Patterns. The pattern
* string and match flags are all that is needed to completely describe
* a Pattern. An empty pattern string results in an object tree with
* only a Start node and a LastNode node.
*/
private Pattern(String p, int f) {
and compile method calls into that.
public static Pattern compile(String regex) {
return new Pattern(regex, 0);
}
Since you are using == comparison which is for references it will not work
The only reason I can think of this behaviour is that the match flag will be defaulted to zero in the compile method which acts a factory method.
I have a String which can either be of Double or Integer type or some other type. I first need to create a Double or Integer object and then send it over to a overloaded method. Here's my code so far;
public void doStuff1(object obj, String dataType){
if ("Double".equalsIgnoreCase(dataType)) {
doStuff2(Double.valueOf(obj.toString()));
} else if ("Integer".equalsIgnoreCase(dataType)) {
doStuff2(Integer.valueOf(obj.toString()));
}
}
public void doStuff2(double d1){
//do some double related stuff here
}
public void doStuff2(int d1){
//do some int related stuff here
}
I'd like to do this without if/else, with something like this;
Class<?> theClass = Class.forName(dataType);
The problem is 'theClass' still can't be cast to either double or int. I would be gratefull for any ideas.
Thanks.
Found a related thread; Overloading in Java and multiple dispatch
This is not just a problem of dealing with primitive types.
Which method to call is decided in compile time, that is, if you want to be able to call different methods depending on the type of the arguments, you'll need several calls (i.e. you need the if-construct).
In other words, it wouldn't work even if doStuff2 took Integer and Double as arguments (your code is basically as good as it gets).
(In fancy words, this is due to the fact that Java has single dispatch. To emulate multiple dispatch you either need to use conditional statements or a visitor pattern.)
Since the method call is decided at compile time as the another answer told you, overloading won't work for you. I think that this problem can be solved with inheritance. So you write a base class with yourMethod() and override it in your derived classes.
As aioobe says, the choice between overloaded methods is made at compile time based on the static types of the arguments.
If you want to simulate overload choice at runtime, you will need to do some complicated runtime analysis of the different possible methods. It would go something like this:
get all declared methods of the class that declared doStuff2.
filter out the methods whose name is not doStuff2.
filter out the methods whose argument type cannot be assigned from the (dynamic) type of the argument value.
of the remaining methods, pick the one that is the best match ... taking care to deal with "ties" as ambiguous.
This will be tricky to code, and trickier if you also throw in handling of primitive types. It will also make the method calls expensive.
Frankly, some kind of hard-wired dispatching is much simpler. If you don't like if / else tests (or switching on a String in Java 7), then you could do something like this.
Map<String, Operation> map = ...
map.put("Double", new Operation(){
public void doIt(Object obj) {
doStuff2((Double) obj);
}});
map.put("Integer", new Operation(){
public void doIt(Object obj) {
doStuff2((Integer) obj);
}});
...
map.get(typeName).doIt(obj);
... which at least allows you to "plug in" support for new types dynamically.
If you resort to reflection, you'll only have to deal specially with primitive types. So your technique can work, but with the addition of a few explicit tests. If you need to reflectively find a method that accepts a primitive double, use double.class.
Am having some arguments say (String a, Treeset b, Set c)
and I try to get the class by arguments[i].getClass(); of the above arguments..
is Iit possible to get the class of the interface <Set>.
For example:
Class[] argumentTypes = new Class [arguments.length];
for (int i = 0 ; i < arguments.length ; i++)
{
argumentTypes[i] = arguments[i].getClass();
}
The code you've given will find the classes of the arguments (i.e. the values provided to the method) - but those can never be interfaces; they'll always be concrete implementations. (You can never pass "just a set" - always a reference to an object which is an instance of an implementation of the interface, or a null reference.)
It sounds like you want the types of the parameters - which you'd get via reflection if you absolutely had to, finding the Method and then getting the parameters from that with getParameterTypes. But given that you're within the method, you already know the parameter types, because they're at the top of the method... I'm not sure the best way of finding "the currently executing" method, if that's what you're after.
If you're just trying to get the class associated with Set, you can use Set.class of course. But again, it's not really clear what you're trying to do.
EDIT: Okay, judging from your comment, there are some logical problems with what you're trying to do. Going from the values of arguments to which method would be invoked is impossible in the general case, because you've lost information. Consider this, for example:
void foo(String x) {}
void foo(Object y) {}
foo("hello"); // Calls first method
foo((Object) "hello"); // Calls second method
Here the argument values are the same - but the expressions have a different type.
You can find all methods which would be valid for the argument values - modulo generic information lost by type erasure - using Class.isAssignableFrom. Does that help you enough?
Note that you'll also need to think carefully about how you handle null argument values, which would obviously be valid for any reference type parameter...
You can use http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#getInterfaces()
You will get the class what the caller provided.
I mean,in below class you will get HashSet.
Set set=new HashSet();
System.out.println(set.getClass());
You can do this in two ways given below
Set s = new //any class that implements it for example HashSet or TreeSet etc.;
s.getClass().getName(); //This will return the name of the subclass which is refered by s.
or if in other way can do it
Set s = null;
s.getClass();//This causes NullPointer Exception