Question about inheritance in Java
I am writing a small bean manager and I was wondering if it is possible to extend Object class to make new methods apply to my beans without having each bean implement my extended class.
for example I have a fieldset copying method which scans source and target beans for similar fields and types and copies values from one bean to the other:
Code:
public static Object map(Object beanA, Object beanB) {
Class<?> classA = beanA.getClass();
Class<?> classB = beanB.getClass();
Field[] fieldsetA = classA.getDeclaredFields();
Field[] fieldsetB = classB.getDeclaredFields();
try {
for (Field fieldA : fieldsetA) {
for (Field fieldB : fieldsetB) {
if (fieldA.getName().equals(fieldB.getName()) && fieldA.getType() == fieldB.getType()) {
String setterName = "set" + capitalize(fieldB.getName());
String getterName = (fieldA.getType().getName().equals("boolean") ? "is" : "get") + capitalize(fieldA.getName());
Method getter = classA.getDeclaredMethod(getterName);
Method setter = classB.getDeclaredMethod(setterName, fieldB.getType());
setter.invoke(beanB, getter.invoke(beanA));
}
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace(System.out);
}
return beanB;
}
So later I use:
Code:
beanB = (BeanB)map(beanA,beanB);
It works. Still what I would like is to be able to apply map method to a bean2 object directly without needs of casting and mentioning bean2 twice. Something like this:Is it possible without implementing my extended class in every bean explicitly? Or have I recompile the JDK Object class and use my own JDK distro?
Re: Question about inheritance in Java
wow, talk about ugly solutions, "Recompiling the SDK", do you want all your users to do so too??
Often, answer is very simple:
Quote:
Excepting Object, which has no superclass, every class has one and only one direct superclass (single inheritance). In the absence of any other explicit superclass, every class is implicitly a subclass of Object.
http://java.sun.com/docs/books/tutor...ubclasses.html
Re: Question about inheritance in Java
You can generify the method to avoid the BeanB cast, but I don't see how you can avoid passing a beanB instance, because you need an instance of BeanB in the method and you can't create an instance of a parameterized type (beanB) inside the method.
Here's the generified version:
Code:
public static <A, B> B map(A beanA, B beanB) {
Class<A> classA = (Class<A>) beanA.getClass();
Class<B> classB = (Class<B>) beanB.getClass();
Field[] fieldsetA = classA.getDeclaredFields();
Field[] fieldsetB = classB.getDeclaredFields();
try {
for (Field fieldA : fieldsetA) {
for (Field fieldB : fieldsetB) {
if (fieldA.getName().equals(fieldB.getName()) && fieldA.getType() == fieldB.getType()) {
String setterName = "set" + capitalize(fieldB.getName());
String getterName = (fieldA.getType().getName().equals("boolean") ? "is" : "get") +
capitalize(fieldA.getName());
Method getter = classA.getDeclaredMethod(getterName);
Method setter = classB.getDeclaredMethod(setterName, fieldB.getType());
setter.invoke(beanB, getter.invoke(beanA));
}
}
}
}
catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace(System.out);
}
return beanB;
}
...
beanB = map(beanA, beanB);
Alternatively, if you have all your beans subclass a mapper class you can do what you wanted:
Code:
class Mapper {
public void map(Mapper beanA) {
Class classA = beanA.getClass();
Class classB = getClass();
Field[] fieldsetA = classA.getDeclaredFields();
Field[] fieldsetB = classB.getDeclaredFields();
try {
for (Field fieldA : fieldsetA) {
for (Field fieldB : fieldsetB) {
if (fieldA.getName().equals(fieldB.getName()) && fieldA.getType() == fieldB.getType()) {
String setterName = "set" + capitalize(fieldB.getName());
String getterName = (fieldA.getType().getName().equals("boolean") ? "is" : "get") +
capitalize(fieldA.getName());
Method getter = classA.getDeclaredMethod(getterName);
Method setter = classB.getDeclaredMethod(setterName, fieldB.getType());
setter.invoke(this, getter.invoke(beanA));
}
}
}
}
catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace(System.out);
}
}
}
...
class BeanA extends Mapper { ... }
class BeanB extends Mapper { ... }
...
beanB.map(beanA);
This does have the advantage of only allowing Mapper beans to participate.
As soon as we started programming, we found out to our surprise that it wasn't as easy to get programs right as we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large part of my life from then on was going to be spent in finding mistakes in my own programs...
M. Wilkes
Re: Question about inheritance in Java
Quote:
Originally Posted by
postmortem
wow, talk about ugly solutions, "Recompiling the SDK", do you want all your users to do so too??
Often, answer is very simple...
Knew this from the very first day I started coding in Java... That's why I was talking about Object extension. Also I am not crazy to recompile SDK :D. I just was asking if it's the only real solution for my "problem". And as I understand it is btw.
Btw theoretically speaking SDK recompilation is not insane solution in cases of a single enterprise web application. These are rarely if ever updated and it's applications server per app. So practically anything can be customized there. The real insanity applies in cases of applets and desktop applications only.
Quote:
Originally Posted by dlorde
Here's the generified version...
Thanks, really! I almost forgot you could do it this way (rarely use generics these days :p). As for the inheritance, well, nevermind... I just was hoping for some super-wonder modern technique to globally override classes or something... I wasn't sure such thing existed anyways. Just checking, you know... :D
Thanks guys, you clearly showed me the way out of the weed room.
Re: Question about inheritance in Java
Quote:
Originally Posted by
Xeel
I just was hoping for some super-wonder modern technique to globally override classes or something... I wasn't sure such thing existed anyways. Just checking, you know... :D
You might be able to get closer with AOP (Aspect Oriented Programming), but it's been a while since I looked at it, so you'd have to do some reading.
Never hesitate to ask a lesser person...
Confucius
Re: Question about inheritance in Java
A similar but more complicated one:
I am having real trouble writing a List copying method:
PHP Code:
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class BeanMapper {
public static <A, B> B map(A beanA, B beanB) {
Class<?> classA = beanA.getClass();
Class<?> classB = beanB.getClass();
Field[] fieldsetA = classA.getDeclaredFields();
Field[] fieldsetB = classB.getDeclaredFields();
try {
for (Field fieldA : fieldsetA) {
for (Field fieldB : fieldsetB) {
if (fieldA.getName().equals(fieldB.getName())
&& fieldA.getType() == fieldB.getType()) {
String setterName = "set" + capitalize(fieldB.getName());
String getterName = (fieldA.getType().getName().equals("boolean") ? "is" : "get") + capitalize(fieldA.getName());
Method getter = classA.getDeclaredMethod(getterName);
Method setter = classB.getDeclaredMethod(setterName, fieldB.getType());
setter.invoke(beanB, getter.invoke(beanA));
}
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace(System.out);
}
return beanB;
}
public static <A,B> ArrayList<B> mapList(List<A> listA, B itemB){
ArrayList<B> listB = new ArrayList<B>();
BeanMapper bm = new BeanMapper();
for(A itemA : listA){
ClassFactory<B> instance = bm.new ClassFactory<B>();
itemB = instance.get();
itemB = map(itemA,itemB);
listB.add(itemB);
}
return listB;
}
private static String capitalize(String word) {
return word.substring(0, 1).toUpperCase() + word.substring(1);
}
private class ClassFactory<T> {
private T instance;
public T get(){
return instance;
}
}
}
When I run it I get NullPointerException in line 22 (Class<?> classB = beanB.getClass();). Why instance.get() from ClassFactory<B> gives null?
Re: Question about inheritance in Java
Sorry, was stupid, corrected my mistake already =)
Re: Question about inheritance in Java
I don't know why you're using these techniques, but even with a modern JVM, reflection is relatively inefficient, and it's less clear to read and maintain.
Why not use OO techniques instead?
The hardest part of the software task is arriving at a complete and consistent specification, and much of the essence of building a program is in fact the debugging of the specification...
F. Brooks