Suppose the arguments given in the String array are:
String [] args = {"ABC","5", "4.4","true"};
Now I want to call the constructor that takes a String, integer, double and Boolean respectively by calling the method class.getConstructor(args).
I am trying to parse parameters the user passes to my program on the command line and want to configure my class accordingly.
How will I do this?
As a string like "5" can mean a String, an integer, or a double, it's impossible to go from the args array forward to the matching constructor. As #Sotirios commented, you have to look at all constructors of the class, try to parse the args elements with the appropriate functions, and if that succeeds, then the constructor is applicable.
Then calling the constructor will be the easiest part of that project.
The method getConstructor(Class<?>... parameterTypes) you mention belongs to the Reflection Framework. While reflection does have its merits and is sometimes the only way to solve a problem, you should avoid it, unless you have a good reason.
It is hard and tedious to get code right using reflection as the compiler can't detect most errors. For general use it's just a code smell.
The usual way to initialize a class is to just call the respective constructor directly, as #Ralf Kleberhoff describes: MyClass instance = new MyClass(stringParam, intParam, doubleParam, booleanParam);.
If most of the parameters are optional, you usually only pass the required parameters to the constructor. This avoids an abundance of different constructors (to be tested and documented). The constructor usually sets the optional parameters to reasonable default values. These optional parameters are then set using setters if they are available.
As you don't really describe, what you want to achieve (instead of your current problem), we can only guess...
My guess would be that you try to parse parameters the user passes to your program on the command line and want to configure your class accordingly.
My Answer to that would just be: Don't write that code! There are many good libraries out there. These are tested and offer many goodies and examples. If you insist on reinventing the wheel, these are a good starting point to see how this could be done.
Related
Ive been thinking about this and I've seen different examples on this. Usually I would chain constructors in a upward manner. So if I have 4 different constructors, starting with a default constructor, who calls the constructor where we need to pass in one argument, who calls the constructor where we need 2 arguments to pass in and so on, so we have usable objects, where all the fields hold data.
Is there a different approach to chaining constructor because I couldn't think of another case ? Why would I want my constructor, where I need 3 arguments to pass in, call my constructor where I only need to pass in 2 arguments ?
The Builder pattern works for this scenario. A rough demo could look like this:
Dog dog = new DogBuilder().setHeight(10).setWeight(40).setColor(Color.BROWN).build();
Each set method returns a reference to the DogBuilder instance, with that property set. Calling .build() calls a private/package private constructor with all values set.
This is a good article for reference:
https://dzone.com/articles/design-patterns-the-builder-pattern
I think "common sense" best practices are:
Minimize the number of constructors your class offers (for example by relying on the Builder pattern)
Yes, "upward chaining" where the n arg constructor calls an n+1 constructor (and provides a default argument) is probably the more common (and more useful) style.
But as the last sentence indicates: to a certain degree, this is about "personal" style. Or whatever "style" applies. When your team is used to do things in a different way, and you have hundreds of existing classes following that "special style", then you allow that "team internal" preference to guide your actions.
I'm writing something using JSoup, and this is something I've seen elsewhere, many of the methods take strings as arguments.
This sort of things bugs me, I'd much rather use an enum value as an argument. This'd be easy to set up using the HTML.Tag 'enum' and the .toString() method.
Then in my overloaded methods I'd translate the 'enum' to string and feed it into the original method.
So I'd go from calling:
Elements allDivs = bodyElem.getElementsByTag("DIV");
Which is prone to spelling mistakes and not knowning the right tag name, etc to calling:
Elements allDivs = bodyElem.getElementsByTag(HTML.Tag.DIV))
But I can't figure how to overload getElementsByTag to take a HTML.Tag argument.
I've tried this:
Element bodyElem = doc.body(){
Elements getElementsByTag(HTML.Tag tag){
return getElementsByTag(tag.toString());
}
};
But that doesn't work. Specifying this.getElementsByTag refers to the holding class (e.g. HTMLReader, which is one I wrote), and super.getElementsByTag refers to Object.
I'm worried that I just can't do this as Element might be final, like string in this question.
So how should I go about doing this?
JSoup's Element type is not final which means you can extend it, it looks like you are trying to extend it with an anonymous inner class, however you cannot use inner classes to extend an existing object (doc.body() returns an already instantiated Element, you can't modify it).
Your options all depend on what approach you want to take and what seems to have the best cost/complexity to benefit ratio.
1.) Extend the Element class directly and cast the result of doc.body() to your new type that contains your overloaded getElementsByTag method.
2.) Just remember to call the toString() method on your enum type every time you are passing it into the existing getElementsByTag method, it's more verbose but it's either that or cast every Element to something else.
Java eschews some tools from other languages like C#'s extension methods (which would let you do exactly what you want here) for readability and maintainability, unfortunately that sometimes leads to the edge case like this where not having them may make code a little ugly.
first of all I'm using java, even though it could be a question for any language
say I have a complicated system, now sometimes I end up building objects (setting all the parameters), then passing it over to a "target layer"(manager), which opens the object (getting the parameters).
if I were to pass all the parameters in one function, it would be considered poor design, because there's suppose to be a small amount of parameters per function
this seems like a waste, and in the past I also decided to set the parameters straight to the "target layer"
is there a design pattern that deals with this issue?
or something that books or experts in the subject recommend?
You might take a look on the Effective Java Book that will cover Design method signatures carefully
There will be three techniques for shortening long parameters :
break the method into multiple methods, each which require only a subset of the parameters
create helper classes to hold group of parameters (typically static member classes)
adapt the Builder
pattern from object construction to method invocation
Since you're asking the reference, I hope it can help solve your problem and don't forget to buy the book here
Since you were asking about book references, here is one from Clean Code, Chapter 3: Functions:
When a function seems to need more than two or three arguments, it is
likely that some of those arguments ought to be wrapped into a class
of their own. [...]
Reducing the number of arguments by creating objects out of them may
seem like cheating, but it’s not. When groups of variables are passed
together, [...] they are likely part
of a concept that deserves a name of its own.
So I guess it's ok to group a lot of method arguments into classes, as long as these classes represent some coherent concepts.
Personally if I do something like this, I like the wrapper class to be immutable and created by a dedicated builder. Which increases the number of additional classes twofold (wrapper and the builder), but enables the treatment of such a class as one atomic argument.
Extract the parameters into its own "Parameter-Object" (pattern name) and pass that object to the function.
If the Parameter-Object itself is complicated to construct, use the Builder-Pattern which simplifies the construction if the object can be constructed in different ways.
For Example:
function(param1, param2, param3, ...)
The parameters are then extracted into an Object:
class ParamObject {
param1;
param2;
param3;
}
with its corresponding setters and getters.
To construct the ParamObject use the BuilderPattern.
And finally, the invocation would look like this:
function(paramobject):
Inside the function the former arguments are then retreived from the object.
As siledh stated: Make sure to group arguments into classes that share a common concept, which means that it´s ok to create several classes out of the paramlist.
This sounds like a Data Transfer Object to me.
http://martinfowler.com/eaaCatalog/dataTransferObject.html
I want to check preconditions on a base class so that I know subtypes will always use constructor arguments that are valid.
Let's take as an example a constructor that:
takes 2 or more parameters
takes parameters of different types
for one parameter, it performs multiple checks (e.g. String is not null and not empty)
How would one best use the Guava preconditions approach in that case?
In a mock example like this: (this is contrived!)
protected AbstractException(String errorMessage, Throwable errorCause) {
super(errorMessage, errorCause);
checkNotNull(errorMessage,
ErrorMessage.MethodArgument.CANNOT_BE_NULL_CHECK, "errorMessage");
checkArgument(!errorMessage.isEmpty(),
ErrorMessage.MethodArgument.CANNOT_BE_EMPTY_STRING_CHECK,
"errorMessage");
checkNotNull(errorCause, ErrorMessage.MethodArgument.CANNOT_BE_NULL_CHECK,
"errorCause");
}
I end up calling super before checking the arguments because a call to super needs to be the first line of the method and, although I could do super(checkNoNull(errorMessage)), I cannot do the same wrapping using checkArgument because that returns void. So the dilemma is:
Where do I put the checks on all arguments? I don't want to create a Builder just for that
How do I "group" checks as in a fictitious checkStringNotNullAndNotEmpty()
Should I rather think about integration with matchers frameworks? (hamcrest, fest assertions...)
I use the odd-looking ErrorMessage.MethodArgument.CANNOT_BE_NULL_CHECK because the default throw does not include an error message so from the testing side I cannot recognise this as an argument validation failure rather than a "any" NPE?
Am I doing it all wrong?
This should have been a comment, but it's too long.
Calling super before the test is harmless provided that the super ctor doesn't do things which it shouldn't do anyway.
It could be prevented via a static builder method, you need no Builder. But it's not worth it.
I doubt that grouping tests is generally useful; if it was, then there would be a such method already. But if you need one such a concrete thing more than twice, then write your own; if it comes often, report it to the Guava team as an RFE.
I'm pretty sure, matchers are an overkill here as you're just creating an exception, i.e., something used only rarely (I hope). As your test is runtime only, it can't really help to catch errors. It would be nice, if you could statically ensure a "properly" constructed exception, but it's impossible in pure java.
More important: The exceptions you're throwing are probably inferior to the ones you'd get without all the checks. Imagine the user provides a cause and no message. That's bad, you think, but you replace it with an NPE lacking any cause. That's worse.
Look at Guava's Preconditions.format (package private). They could check the correct number of arguments first, but they do not. You can provide too few or too many, which is an error, but ignoring it is the best way to handle it.
I have a class named ActivityLog. This class holds a list of ActivityRecords. I want to return a list of ActivityRecords by these criterias: Environment and Condition. Should the method name include the "criteria"? See example:
activityLog.allRecords();
activityLog.allRecordsBy(Environment environment);
activityLog.allRecordsBy(Condition condition);
activityLog.allRecordsBy(Condition condition, Environment environment);
or
activityLog.allRecordsByEnvironment(Environment environment);
activityLog.allRecordsByCondtion(Condition condition);
I probably think the first is better because you will read the method name and you will understand from the parameter what it does, but I may be wrong? Which is the best, or are there even better alternatives?
I could have named the methods records(), recordsBy etc. too, but I want to have a consitency through my API where you always start writing all for lists of objects so you get help from for example Intelli Sense.
I like putting the criteria in the actual method name. So I would use:
activityLog.allRecordsByEnvironment(Environment environment);
To me proper method naming expresses a small summary of what the method does. Since the parameters are included in the method signature I would not consider the parameters to be part of the actual name, therefore not placing the criteria in the name gives the user of an api incomplete information about the methods functionality. (IMO)
I applaud your effort to practice self documenting code, great practice.
I like the overloaded variant (your first example), because it communicates that the methods are all related and provide largely the same functionality, aka, you are returning records, filtered by some criteria. You will see examples of this in many open source libraries and even the SDK itself.
I'd treat it the same as static factory methods, which are named constructors. And there not only parameter says what this method does, its name itself does it. So I'd choose 2nd option.
#Bob, about names being too long - even if you would put 2 parameters into its name, it still would be ok for me. Anyway you should avoid having methods with more than 3 parameters. Following this rule will prevent your methods' names from being enormous long.
I would take the first one.
If these methods are doing the same thing or providing the same functionality then they should have the same name. But be aware of Effective Java Item 41 and 42. You've to ensure that at least one corresponding param of overloaded method are having radically different types.
The 2nd approach becomes ugly very fast with every param added. I see this in often in Broker classes at work. There are people writing methods like findByFirstnameAndLastnameAndBirthdayOrderByUgliness(blablub). No comment.
Methods in OOP represent behavior, so I would name all of them getRecords() and made them overloaded.
In my opinion, specifying criteria in the name of method looks like naming heirarchy classes like this
Car -> BMW_Car -> X5_BMW_Car