Java: Creating a subclass object from a parent object - java

Newbie Java question. Say I have:
public class Car{
...
}
public class Truck extends Car{
...
}
Suppose I already have a Car object, how do I create a new Truck object from this Car object, so that all the values of the Car object is copied into my new Truck object?
Ideally I could do something like this:
Car c = new Car();
/* ... c gets populated */
Truck t = new Truck(c);
/* would like t to have all of c's values */
Would I have to write my own copy constructor? This would have to be updated everytime Car gets a new field...

Yes, just add a constructor to Truck. You will probably want to add a constructor to Car also, though not necessarily public:
public class Car {
protected Car(Car orig) {
...
}
public class Truck extends Car {
public Truck(Car orig) {
super(orig);
}
...
}
As a rule it's generally best to make classes either leaf (and you might want to mark those final) or abstract.
It looks as if you want a Car object, and then have the same instance turn into a Truck. A better way of doing this is to delegate behaviour to another object within Car (Vehicle). So:
public final class Vehicle {
private VehicleBehaviour behaviour = VehicleBehaviour.CAR;
public void becomeTruck() {
this.behaviour = VehicleBehaviour.TRUCK;
}
...
}
If you implement Cloneable then you can "automatically" copy an object to a instance of the same class. However there are a number of problems with that, including having to copy each field of mutable objects which is error-prone and prohibits the use of final.

If you are using Spring in your project you may use ReflectionUtils.

Yes, you have to do this manually. You'll also need to decide how "deeply" to copy things. For instance, suppose the Car has a collection of tyres - you could do a shallow copy of the collection (such that if the original object changes the contents of its collection, the new object would see the change too) or you could do a deep copy which created a new collection.
(This is where immutable types like String often come in handy - there's no need to clone them; you can just copy the reference and know that the contents of the object won't change.)

Would I have to write my own copy constructor? This would have to be
updated everytime Car gets a new field...
Not at all!
Try this way:
public class Car{
...
}
public class Truck extends Car{
...
public Truck(Car car){
copyFields(car, this);
}
}
public static void copyFields(Object source, Object target) {
Field[] fieldsSource = source.getClass().getFields();
Field[] fieldsTarget = target.getClass().getFields();
for (Field fieldTarget : fieldsTarget)
{
for (Field fieldSource : fieldsSource)
{
if (fieldTarget.getName().equals(fieldSource.getName()))
{
try
{
fieldTarget.set(target, fieldSource.get(source));
}
catch (SecurityException e)
{
}
catch (IllegalArgumentException e)
{
}
catch (IllegalAccessException e)
{
}
break;
}
}
}
}

you can use reflection i do it and work fine for me:
public Child(Parent parent){
for (Method getMethod : parent.getClass().getMethods()) {
if (getMethod.getName().startsWith("get")) {
try {
Method setMethod = this.getClass().getMethod(getMethod.getName().replace("get", "set"), getMethod.getReturnType());
setMethod.invoke(this, getMethod.invoke(parent, (Object[]) null));
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
//not found set
}
}
}
}

Would I have to write my own copy constructor? This would have to be updated everytime Car gets a new field...
Essentially, yes - you can't just convert an object in Java.
Fortunately you don't have to write all the code yourself - look into commons-beanutils, specifically methods like cloneBean. This has the added advantage that you don't have to update it every time it gets a new field!

You could always use a mapping Framework such as Dozer. By default (without further configuration), it maps all fields of the same name from one object to another using the getter and setter methods.
Dependency:
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer</artifactId>
<version>5.5.1</version>
</dependency>
Code:
import org.dozer.DozerBeanMapper;
import org.dozer.Mapper;
// ...
Car c = new Car();
/* ... c gets populated */
Truck t = new Truck();
Mapper mapper = new DozerBeanMapper();
mapper.map(c, t);
/* would like t to have all of c's values */

You will need a copy constructor, but your copy constructor can use reflection to find the common fields between the two objects, get their values from the "prototype" object, and set them on the child object.

You could use the reflection API to loop through each of the Car fields and assign the value to the equivalent Truck fields. This can be done within truck. Further it is the only way to access the private fields of Car - at least in an automatic sense, providing that a security manager is not in place and restricting access to private field.

The solutions presented above have limitations you should be aware of. Here's a short summary of algorithms for copying fields from one class to another.
Tom Hawtin: Use this if your superclass has a copy constructor. If it does not you will need a different solution.
Christian: Use this if the superclass does not extend any other class. This method does not copy fields recursively upwards.
Sean Patrick Floyd: This is a generic solution for copying all fields recursively upwards. Be sure to read #jett's comment that a single line must be added to prevent an endless loop.
I reproduce Sean Patrick Floyd's analyze function with the missing statement:
private static Map<String, Field> analyze(Object object) {
if (object == null) throw new NullPointerException();
Map<String, Field> map = new TreeMap<String, Field>();
Class<?> current = object.getClass();
while (current != Object.class) {
Field[] declaredFields = current.getDeclaredFields();
for (Field field : declaredFields) {
if (!Modifier.isStatic(field.getModifiers())) {
if (!map.containsKey(field.getName())) {
map.put(field.getName(), field);
}
}
}
current = current.getSuperclass(); /* The missing statement */
}
return map;
}

I know this is an OLD question, but I hate to leave out dated answers when things have improved.
Using JSON is much easier. Convert it to JSON and back again as child.
Here is an Android Kotlin Example.
val gson = Gson()
val childClass = gson.fromJson(
gson.toJson(parentObject),
object: TypeToken<ChildObject>(){}.type
) as ChildObject
I think in Java it would be basically.
Gson gson = new Gson()
ChildObject child = (ChildObject) gson.fromJson(
gson.toJson(parentObject),
TypeToken<ChildObject>(){}.getType()
)
And you're done, no messiness, just simple json in, json out.
If you don't have gson, I'm sure you have other json options available to you.
It's a WHOLE lot cleaner and faster than doing reflection and all that craziness.

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);
}

factory pattern dynamic approach

I am trying to understand factory pattern.If there are many implementation then my factory pattern will have lot of if else or switch cases. And also every time I introduce a new implementation i should change my factory code
Like in below examples if lets assume dog duck are implementing Pet interface like tomorrow if many animals implement pet interface my factory frows long with lot of if else else if code or switch case. Is there any way to solve this with bringing more dynamic approach?
package com.javapapers.sample.designpattern.factorymethod;
//Factory method pattern implementation that instantiates objects based on logic
public class PetFactory {
public Pet getPet(String petType) {
Pet pet = null;
// based on logic factory instantiates an object
if ("bark".equals(petType))
pet = new Dog();
else if ("quack".equals(petType))
pet = new Duck();
return pet;
}
If the animals grows
if ("bark".equals(petType))
pet = new Dog();
else if ("quack".equals(petType))
pet = new Duck();
else if ("mno".equals(petType))
pet = new MNO();
else if ("jkl".equals(petType))
pet = new JKL();
else if ("ghi".equals(petType))
pet = new GHI();
else if ("def".equals(petType))
pet = new DEF();
......
else if ("abc".equals(petType))
pet = new ABC();
return pet
I think there is a dynamic approach:
In your factory you need a Map<String, Class<? extends Pet>>
In static constructor of every class, which extends Pet, register it with such map.
Than creating a class will be just map.get(pet).newInstance ( you'd have to check for nulls, of course)
The idea behind the factory pattern is to let you dynamically instantiate objects whose types you don't necessarily know about at design time.
Having a big if block defeats that purpose.
The effective way to implement this pattern is to also have a factory for each type, which implements a base factory interface and has the ability to instantiate a new object of that type (by the way, in Java, the built-in Class is an example of such a factory).
Then you register a map of names/ids/etc. to instances of these individual factories at runtime. When it's time to instantiate one of the types, you look up the factory in the map by name and use that to instantiate a new object of that type.
How you register individual factories in the map is totally up in the air. You could register some explicitly, you could scan a configuration file, etc.
Essentially you want to replace your if block with a map that is dynamically created at runtime.
You don't even need to solely use a preregistered "map" - sometimes it may be appropriate to figure out how to create an object with a given name on the fly, or a combination of the two (e.g. Class.forName() searches the class path if it can't find the class already loaded). The point is the translation of the name to the class type can take place without the base factory actually knowing what the class type is.
It's worth noting that Java reflection provides a very workable factory implementation already via Class.forName() and/or Class.newInstance(), so consider using that instead of reinventing the wheel if it makes sense.
use reflection
public Pet getPet(String petType)
{
Pet _pet = (Pet)Class.forName(petType).newInstance();
return _pet;
}
you need to change your arguments from 'bark','quack' to 'Dog' and 'Duck' etc
I've been banging my head a little on this since I had a similar problem, and finally I came with a solution based on Reflections Library (pay attention to the final S in Reflections!)
It can be applied to your problem IF all your pet subclasses have an attribute that can be used to discriminate them, for example
public String petType;
The method of your factory could be the following:
public static Pet getPet(String _petType) {
String packageName = "your.package.with.pet.classes";
Reflections reflections = new Reflections(packageName);
Set<Class<? extends Pet>> allPets = reflections
.getSubTypesOf(Pet.class);
Iterator<Class<? extends Pet>> it = allPets.iterator();
while (it.hasNext()) {
try {
Pet pet = it.next().newInstance();
if (pet.petType.equals(_petType))
return pet;
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Pet " + _petType
+ " not yet implemented in package " + packageName);
return null;
}
This method would remain unaffected if new Pets were defined.
Pros:
It doesn't need further modification to Pet subclasses, neither any sort of initialization/registration on a Map structure maintained by the Factory
It's more general than the solution based on Java Reflection API because you can discriminate Pet subclasses upon some attributes instead of the class name
Cons:
It creates local instances of all Pet sub-classes to find the appropriate one. On this side, I'm confident that this approach can be improved.
In Java8, there's a Supplier interface that supports this quite well. Reflections and manual invocations can be avoided and a cleaner approach can be used.
Something like this for Factory:
public class DynamicSupplierTierFactory {
public static final Map<String, Supplier<? extends Tier>> registeredSuppliers = new HashMap<>();
static {
registeredSuppliers.put("blue", new BlueSupplier());
registeredSuppliers.put("silver", new SilverSupplier());
registeredSuppliers.put("golden", new GoldenSupplier());
}
public static void registerSupplier(String type, Supplier<? extends Tier> supplier){
registeredSuppliers.put(type, supplier);
}
public static Tier getTier(String type){
Supplier<? extends Tier> supplier = registeredSuppliers.get(type);
return supplier != null ? supplier.get():null;
}
}
Suppliers will be like:
public class BlueSupplier implements Supplier<Tier> {
#Override
public Tier get() {
return new Blue();
}
}
This can be seen here in more detail: https://medium.com/#mhd.durrah/factory-pattern-the-dynamic-way-with-java-8-3ca5ab48a9cf

Java reflection unclarity

I am trying to get a list of objects from the Database based on a target object through reflection.
I don't have much experience with reflection so this doesn't work.
Is it even possible to achieve my goal?
public static List<Object> getObjectsFromDataBase(Object targetObj) {
....................
ResultSet rs = stat.executeQuery(queryToExecute);
while (rs.next()) {
Object obj = new Object();
for (Field property : targetObj.getClass().getFields()) {
property.set(obj, rs.getString(property.getName()));
}
objListToReturn.add(obj);
}
.....................
return objListToReturn;
}
If the fields in the target object's class are not public they won't show up in getFields(). Try this:
import java.lang.reflect.Field;
public class Test
{
public static class A
{
public String field1;
public String field2;
}
public static void main(String[] args) throws Exception
{
A a = new A();
Object b = a;
for (Field f : b.getClass().getFields())
{
System.out.println(f.getName());
}
}
}
If you remove public, getFields() returns an empty array.
The short answer is yes, this is possible, but not with the code you provided. This concept is called Object Relational Mapping and things like Hibernate or XStream do this for you. If you're just learning about reflection that's great too. You'll probably need a way to map the fields to the properties of the object, whether that's done with convention (matched names), straight code, annotations, or a mapping input file is up to you.
I can see two problems:
You are creating obj as type Object. the first argument of Field.set() needs to be the same type (or a subtype) as the class the containing the field. You need to use reflection to create an object of the same type as targetObj, by using obj = targetObj.getClass().newInstance() (assuming a default constructor is available)
Also your problem might be that the getFields() method only returns the public fields of the class.
targetObj.getClass().getFields()
If you want to get all the fields of the class, you will need to use the getDeclaredFields() method.

How to use Cloneable type as parameter to Java generic class

I have a generic class that needs to be able to clone objects of the parameter type. A very simple example is below. The compiler claims clone() from the type Object is not visible.
public class GenericTest<T extends Cloneable>
{
T obj;
GenericTest(T t)
{
obj = t;
}
T getClone()
{
// "The method clone() from the type Object is not visible."
return (T) obj.clone();
}
}
I'd prefer not to have the caller do the cloning since there are other things that have to happen to maintain the integrity of the object. The code above is just an illustration of the problem without the noise of the other data I have to maintain related to the cloned object.
Is there a way around this or is this another one of those cases where the designers of Java consider rationalizing its shortcomings the equivalent of having none?
Because the method is marked as protected on the Object class, you cannot in general call this method on arbitrary objects. Personally I didn't think this would be a problem at first (hey, I'm a subclass of Object, so I should be able to call its protected methods, right?), but the compiler needs to know that you're a subclass of the target object's class (or in its package) in order to call protected methods, neither of which apply here.
The idea behind the clone() method is that classes which supported it would override the method, declaring it as public.
The only real solution here that preserves full functionality is to use reflection to access the method and get around the access modifiers. An alternative would be to write your own MyCloneable interface which has a public clone() method declared on it; this might work if you'll only ever be passing your own domain classes in, but means that you couldn't use it on external classes (such as java.util.String or java.util.ArrayList) since you can't force them to implement your interface.
As per answers to the linked question, this is a very dubious design.
A mistake on Java's part. Reflection is the right way to go
static Method clone = Object.class.getMethod("clone");
static public <T extends Cloneable>
T clone(T obj)
return (T) clone.invoke(obj);
I needed to clone a POJO with fields in it. What did work was the following:
public static Object clone(Object o)
{
Object clone = null;
try
{
clone = o.getClass().newInstance();
}
catch (InstantiationException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
// Walk up the superclass hierarchy
for (Class obj = o.getClass();
!obj.equals(Object.class);
obj = obj.getSuperclass())
{
Field[] fields = obj.getDeclaredFields();
for (int i = 0; i < fields.length; i++)
{
fields[i].setAccessible(true);
try
{
// for each class/suerclass, copy all fields
// from this object to the clone
fields[i].set(clone, fields[i].get(o));
}
catch (IllegalArgumentException e){}
catch (IllegalAccessException e){}
}
}
return clone;
}

Categories