This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Use string in place of variable name
Is there any way in Java that allows an object to be created using a string?
Let's say, i have a class called "Toyata", is there anyway i can create an object of Toyata
using the string variable s in class Car?
public class Car{
String s = "Toyota";
}
public class Toyota{
int speed;
public Toyota(int speed){
this.speed=speed;
}
}
You can use reflection, but you need a fully qualified classname:
https://stackoverflow.com/a/4030634/1217408
EDIT:
Hovercraft Full Of Eels's comment about using a map lookup is probably far more appropriate in this situation.
You need to query for class (assuming it's in the default package this should work) via the value of s. Then you have to lookup the proper constructor via your class' getConstructor() method. Since Toyota does not contain a default constructor, you need to query for one that matches your expected parameters. In this case, it's an int. int is represented in Class form by Integer.TYPE. Finally after that is all said and done, you can call newInstance() on the constructor with the desired speed passed in and you should have a new instance ready to use. Of course there will be a few checked exceptions to handle.
Class<?> clazz = Class.forName(s);
Constructor constructor = clazz.getConstructor(new Class[] {Integer.TYPE});
Toyota toyota = (Toyota) constructor.newInstance(new Object[] {90});
Related
This question already has answers here:
Why do we need a default no argument constructor in Java?
(7 answers)
Closed 5 years ago.
Why would anyone want to define a zero argument constructor when a default parameterless constructor is created during compile time anyway? Are there any benefits to doing so? are there any cases where it is better to define a zero argument constructor within a class for the sole purpose of preventing the default from being created during compile time?
Simple: you define it when you need it.
For example to call another constructor with some default values which are then used by the other constructor to initialize fields of the class.
When you write down an "empty" constructor that does nothing besides calling the super constructor then sure - you wrote useless code that should go away.
A default constructor is added by java internally if user does not define any parametrised constructor. It initialises any uninitialised fields to their default values.
Like int to 0
string to null
object to null
It's needed if you want to execute an init-function as soon as a new object of the class is created. For Example:
public class Example {
public Example() {
init();
}
public void init() {
//do some Stuff
}
}
But Just defining it without doing anything is not sensefull.
This question already has answers here:
Why might one also use a blank constructor?
(10 answers)
Java entity - why do I need an empty constructor?
(8 answers)
Why Default constructor need to declare in POJO file which has Parameterized Constructor while instantiating Object?
(5 answers)
Default constructor does not initialize the instance members of the class?
(7 answers)
Closed 5 years ago.
Is it okay to use an empty constructor in Java? For example, when loading the data from a MySQL database, I want to do something like:
ResultSet set = statement.executeQuery();
while (set.next()) {
Faction faction = new Faction();
faction.setId(UUID.fromString(set.getString("id")));
faction.setName(set.getString("name"));
}
Because I already have a constructor for the faction class,
public Faction(Player player, UUID uuid) {}
I was wondering if I can have a plain constructor and just set the values as and when.
Otherwise I could create a constructor using parameters that match the mySQL data (public Faction(String name, UUID uuid, String announcement..etc), to load in.. Not sure what is best practice?
If the object state should not change when the Faction class is instantiated, provide a constructor with args and removing setter is better.
In this way, you avoid undesirable behavior.
Now, according to your saying, you probably need to set many String parameters.
Doing it with a constructor is very error prone as you may do a mistake in the parameter order when you use it.
To achieve your need, you have two main ways :
using an empty constructor and then setters as you propose (desirable if the object is mutable)
if your object is immutable, you could use the Builder pattern to construct an immutable object (You write something like : Faction faction = new Faction.Builder().name(name).uuid(uuid).announcement(announcement).build();
It depends on your use case. If you dont want the class variables to change once you set them then in that case declare those variables as final and use the parametised constructor. If you want the variables to change once you set them, then use the default constructor with setters and getters.Both the options are perfectly fine.
This question already has an answer here:
IllegalArgumentException with constructing class using reflection and array arguments
(1 answer)
Closed 6 years ago.
I am dumping CSV via jackson. I have a couple of mapping classes and want to pass the mapping class to the CSV export method.
I have an abstract class, extended it to each of the csv column formats. I pass the name of the class to the export function then want to map the data via the constructor for the class and dump it as CSV.
All fine until I get to creating the class that does the mapping and is to be exported.
Invocation exception/Invalid number of parameters exception.
protected String mapTransactionsToCSV(List<Object[]> results, String rowClassName)
Class rowClass = Class.forName(rowClassName);
for (Object[] component : results)
VehicleAbstract vehicle = (VehicleAbstract) rowClass.getDeclaredConstructor(Object[].class).newInstance(component);
csv.append(mapper.writer(schema).writeValueAsString(vehicle));
}
}
My specific class (and abstract class, which I just copied to try). has 2 constructors
public Bus() {}
public Bus(Object[] component) {}
See Problem with constructing class using reflection and array arguments
The problem is that newInstance already takes an array of objects. You need to wrap your object array in another array. Something like this:
component = {component}; // Wrap in a new object array
VehicleAbstract vehicle = (VehicleAbstract) rowClass.getDeclaredConstructor(Object[].class).newInstance(component);
This is the reason that you're getting an invalid number of parameters - you're passing each item in that object array as a separate parameter, instead of one parameter (the array of objects).
This question already has answers here:
Casting to a Class which is determined at run-time
(2 answers)
Closed 9 years ago.
I'm trying to use custom Class as a value in a Map<String, Class<?>>. Following are relevant parts of code:
Following is declaration and initialization of Map in main():
public static Map<String, Class<?>> mapQuery2ResponseType = new HashMap<String, Class<?>>();
static {
mapQuery2ResponseType.put("string1", CustomClass1.class);
mapQuery2ResponseType.put("string2", CustomClass2.class);
mapQuery2ResponseType.put("string3", CustomClass3.class);
}
Now I'm using this map to typecast an object to one of these classes: (assume that all classes contain a method getName() which return a String)
String name = (
(
mapQuery2ResponseType.get("string1")
)obj1
).getName();
where, obj1 is of generic type T,
but it's not allowing me to do so and says: Syntax error on token "obj1", delete this token.
Please help me to understand where am I doing wrong?
Edit:
When I use following code, it worked perfectly giving me the expected result,
String name = (
(
CustomClass1
)obj1
).getName();
and obj1 is of the same type as returned by mapQuery2ResponseType.put("string1", CustomClass1.class);.
Here I can see 1 thing... if I use use it directly, i use it as "CustomClass1", whereas if I get it from map by mapQuery2ResponseType.get("string1"), it returns "CustomClass1.class". I'm not sure if there is any difference in these two approaches? If there is, what is it?
So actually there wont be any conversion, it's just that I'm using it for large number of classes, and so trying to use a generalized approach.
Edit2:
as given in this question: Java: difference between “CustomClass1” and “CustomClass1.class”?, I think, reflection is the only solution for this task. But can anybody explain how to do it using reflection?
Simply put, this is syntactically invalid code. Not coincidentally, the compiler is telling you exactly what the problem is.
Remove ob1. I don't know what it is, or what you think it's supposed to do, but it does not make any sense there. To explain this, I'm going to twiddle your code just a bit:
The original code:
String name = ((mapQuery2ResponseType.get("string1"))obj1).getName();
Now with a local variable:
Class<?> clazz = mapQuery2ResponseType.get("string1");
String name = ((clazz) obj1).getName();
Okay, so now I think I see: you're trying to use a Class instance to cast an object. You can't do this – Java's syntax simply does not permit it. Here's how a cast might normally look:
Object foo = "bar";
String baz = (String) foo;
Note how the token for the cast expression is String, not String.class.
Class#cast() might look like a useful alternative, but that's not going to be of any use here, since you've only got Class<?>, and not Class<T>.
Forget about the Map. I suggest you restructure your code entirely such that the getName() method is defined on an interface which obj1 and all similar objects implement (assuming that the various objects have heterogenous types).
For example:
interface MyCommonInterface {
String getName();
}
class MyClass implements MyCommonInterface {
public String getName() {
// snip
}
}
// ...
MyClass obj1 = /* ... */
String name = obj1.getName();
No casting, no fancy Maps or Class instances. Just proper, simple use of the right parts of the language.
I think its better to use JAVA Reflection to do that.
Typecast needs the Type syntax befor the object to be cast, so you can do like this (CustomClass1.class)obj1, but you can't do it like (mapQuery2ResponseType.get("string1"))obj1 cause compiler can't take the cast in runtime environment.
When compile your code, you map value is considered as a value not a valid type, so you can't make cast like you have showed.
The motivation for using Static Factory methods staes as:
The most obvious motivation for Replace Constructor with Factory
Method comes with replacing a type code with subclassing.
You have an object that often is created with a type code but now
needs subclasses. The exact subclass is based on the type code.
However, constructors can only return an instance of the object that
is asked for. So you need to replace the constructor with a factory
method.
Can anyone please explain this with code? And what does this type code mean?
A second advantage that a factory method has over a bare constructor is that it can return an existing object. The Integer.valueOf(int) method makes good use of this. By contrast, new always creates a new object.
Finally, if we broaden the discussion slightly, a non-static factory method (e.g. in the form of a factory object) allow you use polymorphism to implement different object creation strategies.
And what does this type code mean?
You need to read this in the context of the page that you got this from. What the page is talking about is a single class that represents different "types" of thing. (In the example given, it is different types of employee represented by one Employee class.) The "type code" is simply the attribute of the class that discriminates the different types.
Imagine we have a Person class with a field called type to indicate if that person is a teacher or a student. This will be the type code.
Now imagine we replace this type field with an object hierarchy: Person class with 2 subclasses Teacher and Student.
If I use the constructors then I can only create a specific type of person i.e. new Teacher() or new Student()
but if I want a method that creates a different kind of person based on some logic then I can do:
public static Person newPerson() {
// can return either a Teacher or a Student
}
A constructor can only return one implementation, however a static factory method can return any number of implementations, often a sub-class of the class referred to. Static factory methods also have the advantage of being named so you can have different behaviour for the same arguments.
e.g. These two methods return a sub-class of EnumSet (based on the number of elements in the enum) with different values based on the name (even though the arguements are the same)
EnumSet<MemoryType> memoryTypes = EnumSet.noneOf(MemoryType.class);
EnumSet<MemoryType> memoryTypes2 = EnumSet.allOf(MemoryType.class);
From the source
public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
Enum[] universe = getUniverse(elementType);
if (universe == null)
throw new ClassCastException(elementType + " not an enum");
if (universe.length <= 64)
return new RegularEnumSet<>(elementType, universe);
else
return new JumboEnumSet<>(elementType, universe);
}
You can see it has one implementation for smaller enum sets and another for larger ones.