Create Objects Dynamically in Java - java

Is there a (better) way to dynamically create Objects?
Right now I'm using a simple 'factory pattern' solution as following:
String classType = generalObject.getClass().toString();
if(classType.equals("class be.testApp.UserObject")) {
return UserObject.fromByteArray(data);
//return new UserObject();
}
else if(classType.equals("class.be.testApp.NewsObject")) {
return NewsObject.fromByteArray(data);
//return new NewsObject();
}

This code is not a factory pattern and no object is created. You evaluate the class name and call a static method on a class.
Now it looks like you have an object (generalObject) and want to create a new instance of the very same type. If all possible types have a public default constructor (convention!), then you can use this to create a new instance based on the given object:
Object newObject = generalObject.getClass().newInstance();
(but maybe I still didn't get your idea...)

You could use reflection here, something like
final Class<?> clazz = generalObject.getClass();
final Method method = clazz.getMethod("fromByteArray", data.getClass());
return method.invoke(null, data);
should do.

String classType = generalObject.getClass().toString();
if(classType.equals("class be.testApp.UserObject")) {
return UserObject.fromByteArray(data);
}else if(classType.equals("class.be.testApp.NewsObject")) {
return NewsObject.fromByteArray(data);
}
This is very complicated. Since apparently both classes are on your compile classpath, just use the class objects, not their string representations:
Class<?> classType = generalObject.getClass();
if(UserObject.class.equals(classType)) {
return UserObject.fromByteArray(data);
}else if(NewsObject.class.equals(classType)) {
return NewsObject.fromByteArray(data);
}

Related

How to null check and return a value in a generic way

I have a long list of object mapping to do from classes auto generated by JAXB.
customer.setCustomerId(rentalCustomer.getCustomerid().getValue()));
customer.setCustomerName(rentalCustomer.getTradingname().getValue());
customer.setVatNumber(rentalSearchCustomer.getVatNumber().getValue());
....
....
Basically I need to make a null check for ALL fields:
getValue(RentalCustomerIDType idType){
if(idType != null){
return idType.getValue();
}
else {
return "";
}
}
Problem is there are too many of these and they all have different types: RentalCustomerIDType, TradingType, VatNumberType..etc
Is there an elegant way to this by creating a GENERIC method that makes null check and return proper values for ALL maybe using Functional Libraries for Java?
Perhaps use reflection on the class when it's generated and eliminate all nulls by assigning non-null values to the fields?
Check an replace null values in multiple variables java
They say (the guy who answered) that they strongly disagree with using reflection for this purpose... but... meh. I've done it and it works.
You could use a generic method to declare the getValueFromAllObjects method and then use reflection to invoke the getValue method
public static <T> String getValueFromAllObjects(T t) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
if(t != null){
return (String) t.getClass().getDeclaredMethod("getValue").invoke(t);
}
else {
return "";
}
}
Refer to https://stackoverflow.com/a/54883454/442256 for reflection alternatives. I've just inlined an example in your code above
From what I understand, you do not want to be changing existing auto-generated classes. What you can do is create a CustomerWrapper class that wraps Customer and inserts defaults when a null is set to a field. This is the idea in code:
public class CustomerWrapper() {
private final Customer customer;
public CustomerWrapper(Customer customer) {
this.customer = customer;
}
public void setCustomerId(String id) {
this.customer.setCustomerId(id == null ? "" : id);
}
// Insert other methods here.
}
maybe a case for Aspect Oriented Programming, if its use is an option:
using an Advice in AspectJ (see around advice)
or (I have not checked this) Spring AOP How to change the return value by spring aop (closed, but has one answer)
I guess you want to use something like. here I have taken ResponseUserDto as my Pojo Class for null checks of it's properties.
private ResponseUserDto getValidNotNullPropertyObject(Object source) {
final BeanWrapper src = new BeanWrapperImpl(source);
Map < String, Object > result = new HashMap<>();
for (PropertyDescriptor property: src.getPropertyDescriptors()) {
if (src.getPropertyValue(property.getName()) == null) {
/* if(property.getPropertyType() == ?) {
//maybe do somethig here
}*/
result.put(property.getName(), ""); // this is start
} else {
result.put(property.getName(), src.getPropertyValue(property.getName()));
}
}
final ObjectMapper mapper = new ObjectMapper(); // Jackson's ObjectMapper
final ResponseUserDto finalResult = mapper.convertValue(result, ResponseUserDto.class);
return finalResult;
}
and to use this, you can call it like this
return this.getValidNotNullPropertyObject(responseUserDto);
This does what you want. But there is a caveat. Each type must implement the same interface that provides the getValue() method. Otherwise, you will probably need reflection to get the method as you suspected. But here is a solution for posterity.
setType(rentalSearchCustomer::getCustomerid,
customer::setCustomerId);
setType(rentalSearchCustomer::getTradingname,
customer::setCustomerName);
setType(rentalSearchCustomer::getVatNumber,
customer::setVatNumber);
System.out.println(customer);
public static <T extends GetValue> void setType(Supplier<T> sup,
Consumer<String> con) {
if (sup.get() == null) {
con.accept("");
} else {
con.accept(sup.get().getValue());
}
}
interface GetValue {
public String getValue();
}

Is it okay to pass an object to a new object constructor and not use it inside?

Is it okay to pass an object type, or simply a type of any kind into the constructor of a new object then not use it inside of the constructor?
The purpose is to have the new object be created based on what parent class it resides in (it is aggregated) so it generates different variables for itself based on that fact.
Or is there a better way to do this?
public class ObjectA {
private MalleableObject obj;
public void createObject(){
obj = new MalleableObject(this);
}
}
public class ObjectB {
private MalleableObject obj;
public void createObject(){
obj = new MalleableObject(this);
}
}
public class MalleableObject{
private boolean doIBelongToA;
public MalleableObject(ObjectB obj){
doIBelongToA = false;
}
public MalleableObject(ObjectA obj){
doIBelongToA = true;
}
}
The approach you are taking will definitely work, But the question is whether it is a good idea or not, The answer is depends on the use case that you are trying to tackle.
You asked about taking a object as parameter in constructor and not using it
If you are not using the property of passed parameter then why to take that in parameter, for that we have empty constructor , even when you don't specify it is by default injected
public MalleableObject(ObjectB obj){
doIBelongToA = false; // if you are directly setting the value without
//using obj b then use default constructor.
}
public MalleableObject(ObjectA obj){
doIBelongToA = true;
}
/*If you are interested in setting the value based on the reference only there
is no problem with your approach as well, One alternative you can take to
combine both of them in single constructor and check the reference and set
the value accordingly*/
If you use the property of the object for creating new object then certainly it's a good idea,
Copy constructor if you are using same object as parameter, Prototype design pattern if you are creating your object with similiar object already created
The example that you gave is a very basic example which does not highlight any use case and hence the approach you have taken will not be suggested
The simpler approach would be just adding the boolean variable in the constructor of MalleableObject.
public class ObjectA {
private MalleableObject obj;
public void createObject(){
obj = new MalleableObject(true);
}
}
public class ObjectB {
private MalleableObject obj;
public void createObject(){
obj = new MalleableObject(false);
}
}
public class MalleableObject{
private boolean doIBelongToA;
public MalleableObject(boolean doIBelongToA){
this.doIBelongToA = doIBelongToA;
}
}
This would easily assure that the object made from class A has value true for doIBelongToA.
Also, you will not have to add different constructors for further classes, if added, ensuring extensibility
While you aren't using it directly, you are definitely using information from the parameter. Personally, I'd save the reference, or at least its type, for later use in case you need it and implement doIBelongToA as a method, but there's nothing technically wrong with your approach:
public class MalleableObject{
private Class ownerType;
public MalleableObject(Class ownerType) {
this.ownerType = ownerType;
}
public boolean doBelongToA() {
return ownerType.equals(ObjectA.class);
}
}
The above approach works but it's not a best practice and hence has some limitations. I would suggest you use builder pattern where you can create use of a builder to create an object and then have a method that defines the behavior. You will be able to extend this to add variables/business logic in the future.
I think the Factory pattern is also good
thing to look at

Instantiating an Object using Java Reflection

I am testing a private method using JUnit and I am invoking it using Reflection. The error I am getting is java.lang.InstantiationException. I know it is not creating an instance of Class but I am not sure what I am doing wrong. Object object = clazz.newInstance(); is the line that throws Exception.
Method under test
private int _getType(String type) {
if ("DATE".equalsIgnoreCase(type)) return Types.DATE;
if ("STRING".equalsIgnoreCase(type)) return Types.VARCHAR;
if ("INT".equalsIgnoreCase(type)) return Types.INTEGER;
if ("TIMESTAMP".equalsIgnoreCase(type)) return Types.TIMESTAMP;
return Types.NULL;
}
JUnit test
#Test
public void testGetType() throws Exception {
String type1 = "DATE";
String type2 = "STRING";
String type3 = "INT";
String type4 = "TIMESTAMP";
Class clazz = SpringStoredProcImpl.class;
Object object = clazz.newInstance();
Method method = object.getClass().getDeclaredMethod("getType", String.class);
method.setAccessible(true);
method.invoke(object, type1);
I don't have my asserts yet so please ignore it.
Thanks in advance.
You try to create an instance with a no argument constructor which does exist in your case.
As the constructors are public you should first create your object normally using the new keyword, then execute the rest of your code starting from Method method...
FYI, if you wanted to create your object by reflection it would be something like clazz.getConstructor(DataSource.class, String.class, ArrayList.class).newInstance(dataSource, sprocName, params) instead of simply clazz.newInstance()
Different answer: don't do that.
Why do you think you need to make this method private? It looks like the responsibility of this method is to "lookup" an enum type, based on string input. I think it would make much more sense to simply make this method package protected and avoid the reflection overhead/hassle.

Question about java generics

I am writing this query service that's suppose to work with couple predefined classes. However, it seems to me to be redundant that, when using this service class, I need to pass both the Type of the class and a class object it self. For example, to query "Contact" object, I'll need to provide both and Contact.class, like the following:
lookupService = new MyLookupServiceImpl<Contact>(Contact.class);
In this case, is there a way to initialize Class without passing in "Contact.class"?
The service class look like the following:
public class MyLookupServiceImpl<T> {
private Class<T> cls;
public MyLookupServiceImpl(Class<T> clz){
this.cls = clz;
}
public T queryObject(String sql) {
try {
QueryResult result = ConnectionFactory.getConnection().query(sql);
if(result.getSize()>0){
T obj=null;
MyObject sObj = result.getRecords()[0];
MyObjectBuilder<T> ob = new MyObjectBuilder<T>(cls);
obj = ob.buildORMObject(sObj);
return obj;
}
} catch (ConnectionException e) {
logger.warn(e.toString());
}
return null;
}
}
Any suggestion would be appreciated.
Thank you,
The answer is NO. In java, because of type erasure, there is no other way infer/get this info at runtime other that passing in the type info as a Class<?> instance.
This is most likely necessary because it is not possible to create a new instance of an arbitrary class indicated by a type parameter; in other words, you cannot do:
T obj = new T();
because of the way Java generics are implemented (with type erasure).
Note that in your code, cls is passed to MyObjectBuilder<T> which is most likely an object that creates new instances of T. MyObjectBuilder<T> uses reflection to create a new instance of T, with a statement like this:
T obj = cls.newInstance();
See also: Create new instance of T in Java
Bala is correct (+1) unfortunately. However, if you use a Dependency Injection framework like Guice you could ask Guice to pass you a TypeLiteral which is the type you're interested in. You could do something like this:
public class MyLookupServiceImpl<T> {
private Class<T> cls;
#Inject
public MyLookupServiceImpl(TypeLiteral<T> type){
this.cls = (Class<T>)type.getRawType();
}
}
Then use the Guice Injector to pass you instances of MyLookupServiceImpl. Just an idea! :)

How can I handle a POJO like a bean?

How can I access a simple java object as a bean?
For example:
class Simple {
private String foo;
String getFoo() {
return foo;
}
private void setFoo( String foo ) {
this.foo = foo;
}
}
Now I want to use this object like this:
Simple simple = new Simple();
simple.setFoo( "hello" );
checkSettings( simple );
So I'm looking for the implementation of the method checkSettings( Object obj ):
public boolean checkSettings( Object obj ) {
// pseudocode here
Bean bean = new Bean( obj );
if( "hello".equals( bean.getAttribute( "foo" ) ) {
return true;
}
return false;
}
The java language contains a package called java.beans which sounds like it could help me. But I don't find a good starting point.
Any hints?
I think the functionality you're looking for resembles the one from the BeanUtils class of apache-commons:
http://commons.apache.org/beanutils/
Take a look at the getProperty() method of BeanUtils.
java.beans.Introspector.getBeanInfo yields an object implementing java.beans.BeanInfo, which in turn can be used to get PropertyDescriptors and MethodDescriptors (via its getPropertyDescriptors- and getMethodDescriptors-methods), which in turn can be used to get the information you actually want.
It is not really less effort than using reflection.
As stated in the question comments above I'm still not sure what you want, but it sort of sounds like you want to wrap an object gets & sets to an interface with a getAttribute. This is not what I think of as a "bean".
So you have an interface:
interface Thingie {
Object getAttribute(String attribute);
}
You would have to write an implementation of that that uses reflection.
class Thingie {
Object wrapped;
public Object getAttribute(String attribute) throws Exception {
Method[] methods = wrapped.getClass().getMethods();
for(Method m : methods) {
if (m.getName().equalsIgnoreCase("get"+attribute)) {
return m.invoke(wrapped);
}
}
}
}

Categories

Resources