What is this type of passing constructor to a method called in Java
(the Class_name is an internal class)?
method_name(new Class_name(arguments));
How can we pass constructor without having an instance of the object?
Well, actually new Class_name(arguments) will create a new instance of the class. A construction might be useful - it is more concise than
Class_name instance = new Class_name(arguments);
method_name(instance);
but you would not be able to access instance later on.
As has been said, you are passing a new object.
If you want to pass just the information about this class, then your method would need to take a Class an an argument, for example...
public void method_name(Class clz) { ... do something... )
You would call it like this...
method_name( Class_name.class);
The other thing doing literally what you wanted would be to give the Constructor, which you can get, for example, by...
Constructor const = Class_name.class.getConstructor( ArgumentType.class, AnotherArgumentType.class, ...);
for example...
Constructor const = Class_name.class.getConstructor( String.class);
...if your constructor took one String argument.
And then call your method...
public void method_name(Constructor constructor) { ... do something... )
... with...
method_name( const );
The last way is very specific and I doubt that it's actually what you NEED, no matter what you think you might need.
new creates a object and this is passed to the function. You are not passing class you are passing "new" of that class which will create a object
You are not passing a constructor, an instance :
When you do :
MyClass myClass = new Myclass();
method_name(myClass);
You have an instance of MyClass into myClass. then you call method_name with myClass as an argument
So this can be shortened as :
method_name(new Myclass());
These types of use cases are very common for Decorator design pattern, where you do not require the intermediate objects.
Example:
FileReader fr = new FileReader(filename);
LineNumberReader lnr = new LineNumberReader(fr);
or
LineNumberReader lnr = new LineNumberReader(new FileReader(filename));
Take a look at I/O classes from nio framework for more understanding on these types of use cases.
Related
Ill try to make it short.
I want to iterate through the methods of a class via "getMethods()". Now when the method has a Parameter which is an instance of the "Event" class, it should be invoked.
Example Method:
private void onEvent(ExampleEvent event) {...]
"ExampleEvent" is an instance of the "Event" class.
Help is appreciated!
You want to use getParameterTypes() instead of getParameters(). If you want to match a parameter type to a parameter name, simply index the two arrays the same.
Something Like this, its been awhile since i wrote in java but This something like this should work
Method[] methods = Class.getMethods();
List<Method> methodsWithEvent = new List<Method>();
for(Method method : methods){
Class[] params = method.getParameterTypes();
for(Class class : params)
if(typeof(class) == typeof(ExampleEvent))
methodsWithEvents.add(method);
}
I learned two things:
The new-operator creates a new instance and then the stated connstructor is executed to initialise that new instance
A constructor call (this()) creates a new instance.
For my understanding these statements object each other.
For example wouldn't new Example() create two instances then, because the new-operator creates one and the constructor calls this() and creates another? Of course it doesn't but what exactly creates an instance now...?
class Example
{
private boolean _b;
public Example()
{
this(false);
}
public Beispiel(boolean b)
{
_b = b;
}
}
Your second point is incorrect: Invoking this() doesn't "create a new instance". Rather, it calls a (usually different) constructor than the one called by new.
Calling new is what creates the new instance.
You can use this inside a constructor to call constructors of the same class with different number of arguments for example:
class Example{
private boolean b;
public Example(){
this(false) // you now call public Example(boolean b) to save code istead of this.b=false
}
public Example(boolean b){
this.b = b;
}
}
By calling this(false) you do not create a new instance. You just call a constructor within a constructor(the one matching the number of the arguments you are passing), for which i cannot think of any efficient practical use right now, but nevertheless is perfectly valid. Note that, to chain constructors like that, you have to make a new constructor call in the first line of the "parent" constructor.If that makes sense.
Bottomline; you create one object.
Maybe adding print statements for each different constructor call can help you grasp this thing better.
Also, take a look here: How do I call one constructor from another in Java?
No. Invoking this doesn't create a new instance. Only invoking new creates a new instance of the object.
Your syntax this(argument) is explicit invocation of a different constructor within the same class.
Such invocation can be done , for instance, to initialize some variables in the object.
See from the Oracle Java tutorials Using the this keyword
I have some classes and for some reason I need a procedure that create some variables of that class dinamically...
Let's assume I have this code:
for (int i = 0 ; i < 5 ; i++)
{
....
POP tmp = new POP();
tmp = (POP) ast.convert(aso, POP.class);
}
I want that the POP class is set dinamically... I almost achieved what I want except for the casting from object to class, I do not know how to write it...
String className = "POP";
Class cl = Class.forName(className);
Class cl2 = POP.class;
cl = (??????) ast.convert(aso, cl2);
How can I solve it?
In your second code snippet, cl will actually be Class<POP> but cl2 is Class<String>, which I guess is not what you expect. Assuming you are coding in Java 5 or newer, you should not use the raw types (Class instead of Class<?>), this will make your code safer and easier to read.
Also note that you have to use the fully qualified class name, and not just the simple name of your classes. For example
Class.forName("String"); // Won't work
Class.forName("java.lang.String"); // Is what you need.
When you have a Class instance you can use reflection to create new instances dynamically:
Class<?> cl2 = ... ;
// If the class has a no-arg visible constructor
Object foo = cl2.newInstance();
// Or using an explicit constructor (here with an integer and a String as arguments)
Constructor<Class<?>> cons = cl2.getConstructor(Integer.class, String.class);
Object bar = cons.newInstance(1, "baz");
But maybe what you are trying to achieve could be done using the Abstract Factory pattern ? You provide an object that is able to create instances of the type that you want, and you can choose the factory to use based on the class name.
http://c2.com/cgi/wiki/wiki?AbstractFactoryPattern
I am working on a Configuration Loader class so that I can change the parameters of my program via an external text file (config.txt) rather than having to recompile my code with every change I make.
It has been suggested that I use Java's Reflection to do this, but I'm a little confused as to how I might actually implement this.
I have been able to successfully extract the class name and the arguments for its constructor from my text file, but how do I go from this to an instantiated object?
here's what I have of my method so far:
public void loadObject(String classString, HashMap hm)
{
String className = props.getProperty(classString);
Class c = Class.forName(className);
}
classString is a string containing the name of the class, and hm is a hashmap where the class' constructor parameters map to their intended values.
I.e., for class Foo (int xPos, float yPos), "xPos" would map to a string of the intended int, and "yPos" maps to a string of the intended float. I want to be able to return, new Foo(hm.get"xPos".toInt, hm.get"yPost".toFloat), but I'm unsure how to dynamically use a constructor like that (the issue is, there are multiple possible classes -- perhaps it's a bar instead of a foo, for instance).
I know that its possible to do an if/else based off the classString, and simply call the proper constructor after identifying it that way, but I am looking to create a more extensible code that doesn't have to be rewritten every time I add a new class to the program.
All of the possible objects inherit from a single parent object.
You would use Class.getConstructor(Class<?>... parameterTypes) to get a reference to the constructor followed by Constructor.newInstance(Object... initargs).
However I would suggest taking a look at a dependency injection framework such as Spring or Guice as it sounds like what you are creating is a basic version of what they do.
Upon request for expanding this answer:
Class c = Class.forName(name);
Constructor ctor = c.getConstructor(Integer.class, Integer.class);
Integer param1 = hm.get("xPos") ...;
Integer param2 = hm.get("yPos") ...;
Object instanceOfTheClass = ctor.newInstance(param1, param2);
Of course instead of param1 and param2 you would create an array of arguments based upon what was in the input file (the same goes for the arguments to getConstructor()), etc.
Here's an example of doing it from program arguments:
import java.lang.reflect.Constructor;
import java.util.*;
public class InstantiateWithReflectionIncludingArgs {
public static void main(String[] args) throws Exception {
String className = args[0];
List<Object> argList = new ArrayList<Object>();
if (args.length > 1) {
argList.addAll(Arrays.asList(args).subList(1, args.length));
}
Class c = Class.forName(className);
List<Class<?>> argTypes = new ArrayList<Class<?>>();
for (Object arg : argList) {
argTypes.add(arg.getClass());
}
Constructor constructor = c.getConstructor(
argTypes.toArray(new Class<?>[argTypes.size()]));
Object o = constructor.newInstance(
argList.toArray(new Object[argList.size()]));
System.out.println("Created a " + o.getClass() + ": " + o);
}
}
Naturally, the argList can only ever have Strings in this case because they're pulled from a String[], but you could add args of any type. Note that constructor args are positional, not named, so the names in the map won't do you much good. They need to be in the proper order.
Try running it and passing "java.util.Date" as an argument.
Class<?> clazz = MyClass.class;
Constructor<?> ctor = clazz.getConstructor( /* Array of Classes the constructor takes */);
ctor.newInstance( /* arguments the constructor takes */ );
I am newbie to java programming language.
My problem is:
I want to read sys.input for a class name from console. Upon reading the name of the class, I want to generate that class automatically and call its method if that class exists already.
my trial is here. Although I dont get any error, nothing happens.
my kind regards.
class s1{
public s1(){
System.out.println(""+ s1.class);
}
}
public class reflection {
public static void main(String[] args) throws IOException, ClassNotFoundException{
System.out.println("enter the class name : ");
BufferedReader reader= new BufferedReader(new InputStreamReader(System.in));
String line = "reflection_N3.";
line+=reader.readLine();
//System.out.println(line);
// "name" is the class name to load
Class clas = Class.forName(line);
clas.getClassLoader();
}
}
You are not creating an instance of the class. Try
Class clas = Class.forName(line);
Object obj = clas.newInstance();
However, the problem is, you can't do much with this object unless you know its exact type, and cast it to that type.
In this example, you could try casting it to your class type, e.g.
if (obj instanceof s1) {
s1 myS1 = (s1) obj;
myS1.s1();
}
However, this hardly works in real life, where you don't know the possible types in advance. The typical solution to this is to define an interface for a specific purpose, and require that the class implements that interface. Then you can downcast the class instance to that interface (throwing an exception if the cast fails), and call its interface methods, without needing to know its concrete type.
Or, as #helios noted, you can use reflection to obtain a method of the loaded class having a specific name.
Btw the Java convention is to start class names with uppercase, hence S1 and Reflection.
You're only obtaining the ClassLoader, you're never actually constructing an object of the specified class.
Use clas.newInstance() if you want to call the default constructor, or investigate Class.getConstructor(...) if you need to call a specific constructor.