Java - reflection - how to call copy constructor? - java

I have this code:
Class I want to copy:
public class NormalChair extends AbstractChair {
protected int height;
protected String name;
public NormalChair() {
super();
}
public NormalChair(String name, int height) {
super(name, height);
}
// Copy constructor - getName() and getHeight() are defined in parent class.
public NormalChair(NormalChair chair) {
this(chair.getName(), chair.getHeight());
}
}
Create some class
public Object createObj(String cls_name, String param1, int param2){
return Class.forName(cls_name).getConstructor(String.class, Integer.class).newInstance(param1, param2);
}
Then I try to copy object of that class using this:
Object obj_to_copy = createObj("Classname", "name", 10);
String cls_name = obj_to_copy.getClass().getName();
Class.forName(cls_name).getConstructor(Object.class).newInstance(obj_to_copy);
And I get this error:
Exception in thread "main" java.lang.NoSuchMethodException: test.NormalChair.<init>(java.lang.Object)
at java.lang.Class.getConstructor0(Class.java:2800)
at java.lang.Class.getConstructor(Class.java:1708)
at test.ProductTrader.create(ProductTrader.java:57)
at test.Test.main(Test.java:23)
So I suppose I need to call copy constructor somehow differently than showing it's type as Object?
P.S. Also I gave this example as simplistic. But in reality I would not know which class needs to be copied before runtime, so using copy constructor should not depend only on NormalChair class.
Update:
I updated my question, to make it more clear that when I copy object, before, runtime, I won't know what class it will need to copy.

Java reflection for some reason matches classes and method signatures strictly. So in order to find a matching constructor, you would need to enumerate available constructors with Class.getDeclaredConstructors() and find a matching one.
I have written a small library to simplify the task, here is a method matching class from it: HavingMethodSignature.
If you're interested, here is how you create a new instance with this lib:
Object o = OpenBean.newInstance(Class.forName(cls_name));

Why bother with a copy constructor in Java ? There is a standard way to copy an object in Java : simply clone it. If default cloning is not relevant, override the clone() method.
You simply need to write obj.clone() to get a copy.
see Java documentation of clone() for details.

If you can assume that a copy constructor accepts an object of the same class, you can do something like:
class ObjectCopier {
public static Object copy(Object orig) {
Class<?> cls = orig.getClass();
Constructor<?> con = cls.getDeclaredConstructor(cls);
return ((con == null) ? null : con.newInstance(orig);
}
}
(untested, so treat it as such)

Related

Creating child objects on basis created parent object in java

I'm learning java design patterns and I wonder if I can apply some with following problem. I have class Solider and some child classes, for example: General and Sergeant. I'm creating Solider object and in runtime I want to change this object to General or Sergeant object, or create new Sergeant or General object using created earlier Solider object:
Solider s = new Solider(...);
.....
if (generalCondition) {
General g = createGeneralFromSolider(s);
//or better:
//General g = promoteSoliderToGeneral(s);
} else if (sergeantCondition) {
Sergeant sr = createSergeantFromSolider(s);
//or better:
//Sergeant sr = promoteSoliderToSergeant(s);
}
Firstly I decided to create additional constructor in General/Sergeant Class:
Class General extends Solider {
General(Solider s, Map<String, String> generalSpecificParams) {
//first we are going to copy all solider params to general params (bad idea if we have a lot of params)
this.setParamX(s.getParamX());
....
//then we can assign the rest of general-specific params
this.setGeneralSpecificParams(generalSpecificParams);
}
}
and use it in methods createGeneralFromSolider but I'm not sure if it is elegant way. Main disadvantage is that I create new object, so after calling createGeneralFromSolider I have 2 object in memory. I would rather have one object in memory: General/Sergeant promoted from Solider (object General/Sergeant which earlier was the Solider object). I wonder if I can use some design patter to resolve it. I remember that in C++ there has been something like copying constructors which copying all params from one object to another by assigning all params, one after another. In Java I didn't hear about anything similar.
You would probably need to use a Factory pattern for this kind of situation.
For example:
public class SoldierFactory {
//use getSoldier method to get object of type Soldier
public Soldier getSoldier(String soldierType){
if(soldierType == null){
return null;
}
if(soldierType.equals("case1")){
return new General();
} else if(soldierType.equals("case2")){
return new Sergeant();
} else if(.....
}
return null;
}
}
public class FactoryPatternDemo {
public static void main(String[] args) {
SoldierFactory soldierFactory = new SoldierFactory();
Soldier s1 = soldierFactory.getsoldier("case1");
}
}
I think its better to not create the Soldier ahead of calling Soldier factory. You're going to change it regardless during run-time right?
First of all, when constructing child classes, use super as the first statement of the constructor like so:
class Soldier {
private String rank; // e.g. Pvt, PFC, etc.
private int yearsOfService;
// ... (Standard constructor)
public Soldier(Soldier s) {
this.rank = s.rank; this.yearsOfService = s.yearsOfService;
}
// ... (Getters and Setters)
}
class Sergeant extends Soldier {
private int subordinates;
public Sergeant(Soldier s) {
super(s)
this.rank = "Sergeant"; // overwrites this Sergeant's rank
this.subordinates = 0;
}
}
You could easily encapsulate this in a promoteSoldierToSergeant method. However, this can lead to telescoping constructors if classes with many attributes are designed naively, or necessitate your map-based workaround. To resolve this, I'm personally a big fan of the Builder pattern, but you can also consider the Factory pattern.
Your question regarding "copying constructors" is perhaps best addressed by reading up on the Clonable interface, but be aware of the differences between shallow and deep copies, and the implications for your classes and data structures.
I think your approach is totally acceptable. If you have an object X, that you want to turn into Y, you can do it in Y constructor, copying all necessary fields.
You could as well use a builder, or static factory methods, but either way you'll have to copy fields, as there's no automatic copy constructor in java (except if you use some dedicated library such as lombok, which can provide full-args constructors from annotations)
You worry about having 2 objects in memory. But if you remove every reference of the original Soldier, the garbage collector will destroy it.
Last thing, as mentionned by #tsolakp , is it a good design to have General inheriting from Soldier? Couldn't it be just a "grade" variable, or something like that, to reflect this state? It's a common mistake to overuse inheritance where composition would be sufficient, and would cause less troubles.
What you want could be achieved using Reflections.
That way you can automatically copy fields from the instance of parent to child class.
Your code would look something like this:
public static void copyObject(Object src, Object dest)
throws IllegalArgumentException, IllegalAccessException,
NoSuchFieldException, SecurityException {
for (Field field : src.getClass().getFields()) {
dest.getClass().getField(field.getName()).set(dest, field.get(src));
}
}
public static General createGeneral (Solider solider, String devision) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
General general = new General();
copyObject(solider, general);
general.setDevision(devision);
return general;
}
The Field import is java.lang.reflect.Field;
========================================================================
Another way would be to use the Apache Bean Utils.
Than, you can use it's cloneBean(Object Bean) method like this:
General general = cloneBean(solider);
to copy the fields from solider to general and after that all the fields that are specific to child class (General).
========================================================================
EDIT: It would also be wise to introduce another child class that would be used for "ordinary" soliders if you intended to use the parent class Solider for "ordinary" soliders (which I suppose you do according to your commented method name promoteSoliderToGeneral(Solider s).
So, for example you would have a parent class called MilitaryMan and 3 child classes that extend it: Solider, General and Sergeant.
This way, you can uniformly handle all of the MilitaryMan. And, you can check if the MilitaryMan is a Solider, General or Sergeant with:
if (militaryMan instanceOf Solider) {
// do solider specific processing
...
} else if (militaryMan instanceof General) {
...
} else if (militaryMan instanceof Sergeant) {
...
}
I think it would be cleaner this way.

Java casting an object passed to method to its original type

I have a list called itemsData of object of class EtcStruct, but the class can differ depending on the file i want to use (the class is full of variables setters and getters):
ObservableList<EtcStruct> itemsData = FXCollections.observableArrayList();
Im passing it to the method thats supposed to work for any object type i choose and run invoked method from the file.
public static void parseToFile(ObservableList itemsData){
EtcStruct itemObject = (EtcStruct) itemsData.get(0);
System.out.print((int)reflectedmethod.invoke(itemObject);
}
Code above works , but what i want to achieve is make the method work without editing it's object type to make it more flexible for whatever structclass i plan to use.
I tried something with passing Struct Class name and .getClass() it returns the original type but i dont know what to do with it to make the new object of itemsData original type and cast the itemsData object.
public static void parseToFile(ObservableList itemsData,Class c){
Object itemObject = c.newInstance();
Object newobject = curClass.newInstance();
newobject = c.cast(itemsList.get(0));
}
Above seemed dumb to me and obviously didnt work.
After reading your comment I understand better why one would use reflection in your case. A GUI builder/editor is an example where reflection is used to provide an interface to set/get the values of components. Still, IMHO, reflection isn't a tool you would design for when you own the classes and are the primary designer. If possible you should strive for something more like this:
interface Parsable {
default int parse() {
System.out.println("Here I do something basic");
return 0;
}
}
class BasicStruct implements Parsable { }
class EtcStruct implements Parsable {
#Override
public int parse() {
System.out.println("Here I do something specific to an EtcStruct");
return 1;
}
}
// If some structs have a parent-child relationship
// you can alternatively `extend EtcStruct` for example.
class OtherStruct extends EtcStruct {
#Override
public int parse() {
super.parse();
System.out.println("Here I do something specific to an OtherStruct");
return 2;
}
}
void parseToFile(Parsable parsable) {
System.out.println(parsable.parse());
}
// If you use a generic with a specific class you don't
// have to guess or care which kind it is!
void parseToFile(ObservableList<Parsable> parsables) {
for (Parsable p : parsables) {
parseToFile(p);
}
}
public static void main(String[] args) {
ObservableList<Parsable> parsables = FXCollections.observableArrayList();
parsables.add(new BasicStruct());
parsables.add(new EtcStruct());
parsables.add(new OtherStruct());
parseToFile(parsables);
}
Output:
Here I do something basic
0
Here I do something specific to an EtcStruct
1
Here I do something specific to an EtcStruct
Here I do something specific to an OtherStruct
2
Of course, this is just an example that needs to be altered to meet your needs.
But what I still don't get is if you're able to parse from a file why you can't parse to one. Nonetheless, I slapped some code together to show you how I might parse an object to a file, manually, when dealing with Objects only.
The idea is to satisfy a bean-like contract. That is, each structure should provide a parameter-less constructor, all fields you want managed by reflection will follow Java naming convention and will have both a public setter and getter.
Don't get caught up in the file writing; that will be determined by your needs. Just notice that by following this convention I can treat any Object as a parsable structure. A less refined version here for reference:
public void parseToFile(Object object) throws IOException, InvocationTargetException, IllegalAccessException {
fos = new FileOutputStream("example" + object.getClass().getSimpleName());
List<Method> getters = Arrays.stream(object.getClass().getMethods())
.filter(method -> method.getName().startsWith("get") && !method.getName().endsWith("Class"))
.collect(Collectors.toList());
for (Method getter : getters) {
String methodName = getter.getName();
String key = String.valueOf(Character.toLowerCase(methodName.charAt(3))) +
methodName.substring(4, methodName.length());
fos.write((key + " : " + String.valueOf(getter.invoke(object)) + "\n").getBytes());
}
fos.close();
}
I think that you can just still use Generics to keep static objects typing. Try to parametrize your function parseToFile. Here is an example:
public static void parseToFile(ObservableList<EtcStruct> itemsData){
EtcStruct itemObject = itemsData.get(0);
System.out.print((int)reflectedmethod.invoke(itemObject);
}

Type cast Java Object to my class

Developing application in C# .Net 4.5 using Xamarin, targeting Android. I have a custom class that has some properties in it. I am trying to use a built in component that does comparison using Java.Util.IComparator and Java.Lang.Object. Because it is a built in component, I don't have much flexibility into changing those two items.
My custom class is named recBatch and inside of it, I have some properties of integers and strings.
This is where the component gets initialized. It basically calls a method each time the user clicks on the header for column 0.
tableView.SetColumnComparator(0, GetBatchIdComparator());
This is the method that gets called by the component
public Java.Util.IComparator GetBatchIdComparator()
{
return new BatchIdComparator();
}
And finally, here is the class that is returned by the call.
public class BatchIdComparator : Java.Lang.Object, Java.Util.IComparator
{
public int Compare(Java.Lang.Object lhs, Java.Lang.Object rhs)
{
var leftID = (recBatch)lhs;
var rightID = (recBatch)rhs;
return leftID.Batch.CompareTo(rightID.Batch);
}
}
The first thing I tried to do above by just casting gives me an error as seen here. I did try what Visual Studio is suggesting but could not get it working either.
The next thing I tried was to create a new class like this one and change the cast from recBatch, my actual class to this new class to do the casting:
public class BatchIdComparator : Java.Lang.Object, Java.Util.IComparator
{
public int Compare(Java.Lang.Object lhs, Java.Lang.Object rhs)
{
var leftID = (castClass)lhs;
var rightID = (castClass)rhs;
return leftID.BatchData.Batch.CompareTo(rightID.BatchData.Batch);
}
}
public class castClass : Java.Lang.Object
{
public castClass(recBatch batchData)
{
batchData = BatchData;
}
public recBatch BatchData { get; private set; }
}
With this, I don't have errors and can compile but the problem is I am getting a cast exception when I run. The code does compile and because I am casting, I do have access to one of the properties in recBatch (Batch or recBatch.Batch). However, again, I get a cast exception. The exact error is:
So basically, I just need to cast the Java.Lang.Object into recBatch but I guess I am doing it wrong. Everything is "wired up" properly because if I put a break point at the Compare method, it does hit and the lhs, rhs arguments that are passed in have my class data in them (ie Batch) even though they are Java.Lang.Object types.
Any help is appreciated!
Thanks!
All, for those who may be interested, I have a solution to this that is in place and working quite well. It took another day of searching after some hints in my comments and some other clues.
Basically, I created another class that is solely responsible for casting my Java object. May not have needed to do this in a class but oh well. Here is the class and method contained inside:
public class CastJavaObject
{
public static T Cast<T>(Java.Lang.Object obj) where T : recBatch
{
var propInfo = obj.GetType().GetProperty("Instance");
return propInfo == null ? null : propInfo.GetValue(obj, null) as T;
}
}
Then, all I had to do was call it and pass in the Java object and just like that, the lhsCopy and rhsCopy were of my class, recBatch and not the Java Object and therefore, I could access all of the properties. I don't get any exceptions or notice any performance issues. However, if somebody has some comments on this approach, please feel free.
Here is how I called it:
public int Compare(Java.Lang.Object lhs, Java.Lang.Object rhs)
{
var lhsCopy = CastJavaObject.Cast<recBatch>(lhs);
var rhsCopy = CastJavaObject.Cast<recBatch>(rhs);
Thanks!
Mike

Why do we need this special type of constructor?

public MyConstructor(MyConstructor mc){
this.setId(mc.getId());
this.setName(mc.getName());
}
Here why do we need to set the value in constructor by getting its getter method. Is there any special purpose behind this ?
As already pointed out in the other answers, this sort of constructor mainly is intended for cloning objects, and is sometimes referred to as copy constructor
As Joshua Bloch suggests in his Book "Effective Java", Item 11, such a constructor should usually be preferred over implementing the clone() method, because the clone() method has some issues (see the book or corresponding stackoverflow questions for details).
There is no striking reason to implement it exactly like that - thus, one does not really need it in exactly this form. As mentioned in the comments, one could (most likely) alternatively write it as
public MyConstructor(MyConstructor mc){
this.id = mc.getId();
this.name = mc.getName();
}
or
public MyConstructor(MyConstructor mc){
this.setId(mc.id);
this.setName(mc.name);
}
or
public MyConstructor(MyConstructor mc){
this.id = mc.id;
this.name = mc.name;
}
The author here chose to use the nested set(mc.get()) approach. It has the potential advantage that it solely relies on the interface that is defined in terms of get/set methods, and thus may be more robust against changes.
One could argue about whether this is a good practice in general, but I think that for a copy constructor, it nicely and clearly states: "This object is initialized here, solely based on (and exactly like) the given object".
Side note: Cloning an object and giving the clone the same ID most likely defeats the purpouse of an ID - but there might be cases where this is appropriate
Consider cloning objects for a moment, but this is not cloning. If you come across a situation where you have a MyConstructor(type) object in your hand and you need to create another new object with the same object type MyConstructor. So, in your MyConstructor class, you need a constructor like above.
There you take the object what you had in your hand and take the id of that object, when you create your brand new second object
The purpose behind a constructor like that, is mostly for cloning.
Suppose you need to assign the value of one object to another and not the reference, this will work just fine.
Is already discussed here:
How do I copy an object in Java?
This is important to consider particularly if your class will be derived by a (sub) class.
public class Child extends Parent {
private int id;
private String name = "Child";
...
// getter and setters...
}
public class Parent {
private int id;
private String name = "Parent";
public Parent(Parent parent) {
this.setId(parent.getId());
// option#1
this.setName(parent.getName());
// option#2
// this.name = parent.name;
}
...
// getter and setters...
}
Sample main:
public class Main {
public static void main(String ...strings ) {
Parent parent = new Parent();
Child child = new Child();
Parent parent2 = new Parent(child);
System.out.println(parent2.getName());
}
}
Output:
Child
But if we use the Option#2 this.name = parent.name instead the output will be
Parent

How to get string name of a method in java?

How can I find out through reflection what is the string name of the method?
For example given:
class Car{
public void getFoo(){
}
}
I want to get the string "getFoo", something like the following:
Car.getFoo.toString() == "getFoo" // TRUE
You can get the String like this:
Car.class.getDeclaredMethods()[0].getName();
This is for the case of a single method in your class. If you want to iterate through all the declared methods, you'll have to iterate through the array returned by Car.class.getDeclaredMethods():
for (Method method : Car.class.getDeclaredMethods()) {
String name = method.getName();
}
You should use getDeclaredMethods() if you want to view all of them, getMethods() will return only public methods.
And finally, if you want to see the name of the method, which is executing at the moment, you should use this code:
Thread.currentThread().getStackTrace()[1].getMethodName();
This will get a stack trace for the current thread and return the name of the method on its top.
Since methods aren't objects themselves, they don't have direct properties (like you would expect with first-class functions in languages like JavaScript).
The closest you can do is call Car.class.getMethods()
Car.class is a Class object which you can use to invoke any of the reflection methods.
However, as far as I know, a method is not able to identify itself.
So, you want to get the name of the currently executing method? Here's a somewhat ugly way to do that:
Exception e = new Exception();
e.fillInStackTrace();
String methodName = e.getStackTrace()[0].getMethodName();
Look into this thread:
Getting the name of the currently executing method
It offers some more solutions - for example:
String name = new Object(){}.getClass().getEnclosingMethod().getName();
With Java 8, you can do this with a few lines of code (almost) without any additional libraries. The key is to convert your method into a serialisable lambda expression. Therefore, you can just define a simple interface like this:
#FunctionalInterface
public interface SerializableFunction<I, O> extends Function<I, O>, Serializable {
// Combined interface for Function and Serializable
}
Now, we need to convert our lambda expression into a SerializedLambda object. Apparently, Oracle does not really want us to do that, so take this with a grain of salt... As the required method is private, we need to invoke it using reflections:
private static final <T> String nameOf(SerializableFunction<T, ?> lambda) {
Method findMethod = ReflectionUtils.findMethod(lambda.getClass(), "writeReplace");
findMethod.setAccessible(true);
SerializedLambda invokeMethod = (SerializedLambda) ReflectionUtils.invokeMethod(findMethod, lambda);
return invokeMethod.getImplMethodName();
}
I'm using Springs ReflectionUtils class here for simplicity, but you can of course replace this by manually looping through all superclasses and use getDeclaredMethod to find the writeReplace method.
And this is it already, now you can use it like this:
#Test
public void testNameOf() throws Throwable {
assertEquals("getName", nameOf(MyClassTest::getName));
}
I haven't checked this with Java 9s module system, so as a little disclaimer it might be more tricky to do this with more recent Java versions...
try this,
import java.lang.reflect.*;
public class DumpMethods {
public static void main(String args[]) {
try {
Class c = Class.forName(args[0]);
Method m[] = c.getDeclaredMethods();
for (int i = 0; i < m.length; i++)
System.out.println(m[i].toString());
} catch (Throwable e) {
System.err.println(e);
}
}
}
Wait, since you already know the method name, can't you just type it as a string?
Instead of (pseudo) Class.methodName.toString(), just use "methodName".
Otherwise you can use Class#getDeclaredMethods() to get all the methods in a class

Categories