I am trying pass class as value in hashmap. I need to get the class(value) using particular key and instantiate an object for the retrieved class. but in order to create object, i need to pass parameters.
My flow goes here, when i call the getExpo method from another class passing the key value. using the key value, i need to get the correct class and using that class need to instantiate the object and need to return the object. Inorder to create object, i need to pass the arguments since the class doesnot have default constructors.
The purpose of this procedure is in future, i need to add another key ,pair value, i shouldnot do any change........the implementation is same for all class ie creating the object
My class goes here
public class ExampleFactory {
static {
HashMap<String,Class<?>> hmap = new HashMap<String,Class<?>>();
hmap.put("jxpath", JXPathExpression.class);
hmap.put("spel", SpelExpression.class);
}
public Predicate getExpo(String key,String expression) {
// Need to get the class using key value and instantiate the object for the class
// but i need to pass parameters in order to create the object.something like this
//JXPathExpression object = new JXPathExpression(expression);
return null;
}
}
Try
Class aClass = hmap.get(key);
Constructor constructor = aClass.getConstructor(new Class[]{String.class});
return (Predicate) constructor.newInstance(expression);
Related
I have scenario where i want to access another class method which is returning something.
The method in another class is expecting parameter
Example:
public class Class1()
{
public Response postResponse(String getURL,DataTable dataTable)
{
/*..
my post request code here
..*/
return postData;
}
}
public class Class2()
{
public void readPostResponse()
{
/*..
here i want to access Class1.postResponse method and I don't want to pass the
parameter..
..*/
}
}
Please let me know how to achieve this.
You have three choices:
pass parameters. This is preferred way. Because parameters of method contains some info that can be used in method
mock or stub your parameters if it is possible. It looks like you are using Selenium, but Selenium starts a real browser
pass null parameters.It is not really preferred way because your method can work incorrectly without necessary data
I started to write this before #StepUp posted his answer. I am going to cover the way I think it should be done based on what I understood by "I don't want to pass the parameter"
It sounds you want to create a default case. This example is arbitrary since your code is not really specific. In general terms, when talking about functions, a default case for a function is a method with the same name, with no parameter list. For example,
public class Class1
{
/**
* Default case
*/
public Response postResponse()
{
// Some code here
}
/**
* Specific case (the ellipsis means some parameter list)
*/
public Response postResponse(...)
{
// Some code here
}
}
In your case, you may want to create a default step definition that you can invoke independently in a specific scenario, or you may want to call it from the same scenario with or without parameters specified in your data table. You can still take the same approach. I want to mention that having a default case, doesn't mean that you absolutely need to pass null parameters. 99% of the time, this is a bad idea. All you need to do is to pass some default values.
public class Class1
{
/**
* Default case
*/
public Response postResponse()
{
String url = "..."; // maybe a base URL here?
Object col1 = ...;
Object col2 = ...;
handlePostResponse(url, col1, col2);
// Do other stuff?
return response;
}
/**
* Specific case
*/
public Response postResponse(String url, DataTable dataTable)
{
// Iterate through data table and call handlePostResponse for each row
return response;
}
// This method wraps how to handle post response. The ellipsis might be the elements of the data table
private void handlePostResponse(String url, Object col1, Object col2)
{
// Do something
}
}
Now that you have this, you can call your method in Class 2 that needs to invoke the default case in Class 1.
public class Class2
{
public void readPostResponse()
{
Class1 clazz1 = new Class1();
Response resp = clazz1.postResponse(); // calling no parameters (default) case (you may not need to get the response object (ignore it altogether)
// Do more stuff?
}
}
Remember that every time you pass null to a function or return null from a function, you may have to do some sort of input or output validation to ensure the object about to be used to invoke other methods is not null. Not doing so will result in Null Pointer Exceptions.
One last note: I am using Object merely for illustration. In your case, it will be whatever type of object each column represent. Most likely, it will be String, but it could also be a number wrapper (i.e. Integer) or some custom data type you might've created for your scenario(s).
I have two generic classes
class Value<T>{...}
class Parameter<T>{...}
And i want to call a method from another class (Params)
public <T> void put(Parameter<T> key, Value<T> value) {
parameters.put(key, value);
}
And from my main class i want to call it with two objects Value and Parameter but with the Type in this way:
Value<Integer> v1 = new Value<Integer>(2);
Parameter<Integer> p1 = new Parameter<Integer>(3);
Params params = new Params();
params.put(p1,v1);
And i receive this error from Eclipse:
The method put(Parameter<T>, Value<T>) in the type Parameters is not applicable for the arguments (Parameter<Integer>, Value<Integer>)
Any hint of how can i call this method without having this error? This classes were not developed by me, so I'm trying to call them without success.
The compiler cannot derive what your class is, so you have to give it a hint:
params.<Integer>put(p1,v1);
Wouldn't it make sense to make the Params class generic?
To make a immutable class , Effective Java has one last condition.
To make a class immutable, follow these five rules:
5- Ensure exclusive access to any mutable components. If your class has any fields that refer to mutable objects, ensure that clients of the class cannot obtain references to these objects. Never initialize such a field to a client-provided object reference nor return the object reference from an accessor. Make defensive copies (Item 24) in contructors, accessors, and readObject methods
public final class ImmutableClass {
private MutableObject mutableObject;
// If I should not provide getter for this object. Then what is the use of this variable after I have
//initalised in the constructor
}
Can somebody explain me this point?
It's actually reasonably simple.
Basically, it's saying to not...
1- Make available any reference to any mutable object that your object might contain.
So if your Class contained a java.util.List as one of it's fields, there should be no way for any client using your Class to gain a reference directly to the List field, either via public deceleration or getter of some kind.
For example...
public class BadImmutableExample {
public List<String> myStrings; // This can not be referenced by the client
/*...*/
}
Would be bad, because the field myStrings is accessible to any body to make modifications to...
In the case you had to return the values in the List you would either be required to return a copy of the List (not a reference to it) or return an array of the values, for example.
For example...
public class BadImmutableExample {
private List<String> myStrings; // This can not be referenced by the client
/*...*/
public List<String> getMyStrings() {
return myStrings;
}
}
Would expose the List myStrings to any clients, which would allow them to modify it.
In this case, you could also use Collections.unmodifiableList(myStrings) to make the list unmodifiable, or return new ArrayList<String>(myStrings) or return an array of String instead...
2- Never initialise such a field to a client provided object...
Basically this means that if your Class requires the client to seed it with some kind of value or values, you should never maintain a reference directly them, instead, again, make a copy for you own reference...
For example...
public class BadImmutableExample {
private List<String> myStrings; // This can not be referenced by the client
public ImmutableExample(List<String> clientStrings) {
myStrings = clientStrings;
}
}
Would break this rule, as any changes to clientStrings would be immediately reflected within you class.
Instead, you could do something like...
public class BetterImmutableExample {
private List<String> myStrings; // This can not be referenced by the client
public ImmutableExample(List<String> clientStrings) {
myStrings = new ArrayList<String>(clientStrings);
}
}
Instead, which will make a copy of the client supplied list, but which will no longer reflect changes made to it (the client supplied list)
this is really basic I know, but I just can't see what the problem is... all I want to do is set the value of a variable from one class into an "intermediary" class and retrieve it in a third class (because filterArray will get called from other classes as well, and I want them all to read the same data). But if I do:
b =new GetSet()
b.setBdl(extras);
JSONArray arr= getData.filterArray();
using
class GetSet {
private Bundle params;
public GetSet() {
}
public Bundle getBdl() {
return this.params;
}
public void setBdl(Bundle bdl) {
params = bdl;
}
}
then in the filterArray method, if I try
Bundle params = new GetSet().getBdl();
I get all sorts of run time errors, and if I try
Bundle params = GetSet.getBdl();
it tells me I can't make a static reference to a non-static method.
Where am I going wrong?
The errors are because you are using it in a wrong way
look at your signature of getBdl its a public Bundle method its a non static method so can't be accessed by the classname.
it should be accessed through the bean object that is b,
second error is also related,
you wrote/set the property of the bean with the object b but when you access it , you are again creating a new GetSet().getBdl so it says Null pointer exception
so do like this
GetSet b=new GetSet();
b.setBdl(bundle object);
so now b contains the value
pass the b...
so get the bundle through b,,if you need to access it from another class pass b into its constructor and get it their
SomeClass class=new SomeClass(b);
now in that class you can get the bundle via b
hope it all helps you.
You should pass b to filterArray method.
First change filterArray to get one parameter of type GetSet:
public JSONArray filterArray(GetSet b)
Then, call it like:
getData.filterArray(b);
And inside filterArray just use:
Bundle params = b.getBdl();
The problem is that you create an object and sets a value, then you need to get the value from the same object.
When working with objects, you can create a new object of whatever class you want, set its internal value and when you access the same object from different places, the internal value will be the same (Im talking here both on GetSet and getData.
Another option is to use static value (and static getters and setters), if the value is same for all objects of the class. This usually not needed and may be used due to bad design. In your case you don't really need it, but it will work.
I know that I can dynamically determine the return type of a method by passing in a class and then declaring that class as the return type, as in the following example:
public static <returnType> returnClass dynamicConstructor (Class<returnType> returnClass){
//Dynamically construct an object using a zero parameter constructor
return (returnClass) object;
}
The code that would be called would be:
DynamicConstructor.construct(constructedClass);
This code is nice because when you're calling the method in code, it's simple and encapsulated. However, I would like to take it one step further and make the parameter a string containing the full class name, then have the method determine the type of the object via Class.forName(className). The trouble with this is that I can't figure out how to return the type as determined later on. Using method overloading, the code I have is:
public static ?????? dynamicConstructor (String className){
try {
return dynamicConstructor(Class.forName(className));
} catch (ClassNotFoundException e) {
System.out.println("Could not find class at path " + classPath);
e.printStackTrace();
return null;
}
}
The problem is that I have no idea what to put in the part labeled ??????. I want to be able to somehow reference the class determined by Class.forName(className). Is this possible?
It's certainly possible to create an instance of the class from the class name (as long as you have a zero-arg constructor), but if the only place the class name is stored is in a String, then there's no way to determine the type to return. So your method signature would be
public static Object dynamicConstructor(String)
which is probably not very useful or what you want.
So the short answer is, no, this is not possible.