Java | Get constructor reflectively - java

How I can get constructor reflectively, if its param is Object ... objects.
My constructor:
public MyClass ( Object ... objects )
{
if ( ! ( objects == null ) )
{
if ( objects.length > 0 && objects [ 0 ] instanceof Long )
{
setLatency ( ( Long ) objects [ 0 ] ) ;
}
}
}
How I get it now:
Class< ? > clazz = Class.forName ( "MyClass" ) ;
Constructor< ? > clazzConstructor = clazz.getConstructor ( Object [ ].class ) ;
What I try to do:
Long latency = 1000L ;
MyClass myInstance = ( MyClass ) clazzConstructor.newInstance ( latency ) ;
And I get
java.lang.IllegalArgumentException: argument type mismatch
If latency == null, everything works.

Your constructor is expecting an object array but you're passing a single Long to it.
Wrapping latency into an object array will work, although be careful as newInstance() itself is expecting Object ..., and if you pass it nothing but an Object[], it will interpret it as a list of arguments. So you'll have to do something like this:
MyClass myInstance = ( MyClass ) clazzConstructor.newInstance ( (Object)new Object[] { latency } ) ;
or
MyClass myInstance = ( MyClass ) clazzConstructor.newInstance ( new Object[] { new Object[] { latency } } ) ;
The first one "fools" the compiler into wrapping your object array into another, the second one does it explicitly instead.
(Passing null only worked because null is null, no matter what the declared type of the parameter is.)

Try it this way
MyClass myInstance = (MyClass) clazzConstructor
.newInstance(new Object[] { new Object[] { latency } });
newInstance(Object ... initargs) needs array of objects as arguments. Buy your fist argument in constructor is also array of object Object... o so you need to wrap it again in Object array.
I tested it with this code and in seems to work fine
class MyClass {
private Long latency;
public void setLatency(Long latency) {
this.latency = latency;
}
public Long getLatency() {
return latency;
}
public MyClass(Object... objects) {
if (!(objects == null)) {
if (objects.length > 0 && objects[0] instanceof Long) {
setLatency((Long) objects[0]);
}
}
}
public static void main(String[] args) throws Exception {
Class<?> clazz = MyClass.class;
Constructor<?> clazzConstructor = clazz.getConstructor(Object[].class);
System.out.println(clazzConstructor);
Long latency = 1000L ;
MyClass myInstance = (MyClass) clazzConstructor
.newInstance(new Object[] { new Object[] { latency } });
System.out.println(myInstance);
System.out.println(myInstance.getLatency());
}
}

Related

How to search for null values inside a java object?

I'm writing a JUnit test to assert that my algorithm's output object does not present any null value or empty strings.
For simplicity imagine 3 classes : Parent, Child, Car, where Parent is the object that I have to validate.
#Data
#AllArgsConstructor
#FieldDefaults(level = AccessLevel.PRIVATE)
#Builder
public class Child {
String name;
int age;
}
#Data
#AllArgsConstructor
#FieldDefaults(level = AccessLevel.PRIVATE)
#Builder
public class Car {
String brand;
String model;
}
#Data
#AllArgsConstructor
#FieldDefaults(level = AccessLevel.PRIVATE)
#Builder
public class Parent {
String name;
int age;
List<Child> children;
Car car;
}
what is the best and easy way to search for null values or empty strings?
I'm currently using the following method as a validator, checking field by field for null values and empty strings.
private boolean isValid(Parent parent) {
if(parent == null) return false;
boolean isObjectNull = Stream.of(parent.getName(), parent.getChildren(), parent.getCar()).anyMatch(Objects::isNull);
if(isObjectNull) return false;
isObjectNull = Stream.of(parent.getCar().getBrand(), parent.getCar().getModel()).anyMatch(Objects::isNull);
if(isObjectNull) return false;
for(Child child : parent.getChildren()){
isObjectNull = Stream.of(child.getName()).anyMatch(Objects::isNull);
if(isObjectNull) return false;
if(!isValidString(child.getName())) return false;
}
return isValidString(parent.getName(), parent.getCar().getBrand(), parent.getCar().getModel());
}
private boolean isValidString(String... values){
for(String s : values){
if(s.isEmpty())
}
}
But I would love something I can also use for other objects I will create in the future.
You can use reflection to obtain all the getters from your objects that do return a reference (instead of a primitive). Then iterate over that list (or array, your choice) and execute them; when the return value for any of these is null, return false or throw an appropriate exception.
A little bit like this:
public final void validateNonNull( final Object candidate ) throws ValidationException
{
if( isNull( candidate ) throw new ValidationException( "candidate is null" );
final var candidateClass = candidate.getClass();
final List<Method> getters = Arrays.stream( candidateClass.getMethods() ) // getters are always public!
.filter( m -> !m.getName().equals( "getClass" ) )
.filter( m -> m.getName().startsWith( "get" ) )
.filter( m -> m.getParameterCount() == 0 )
.filter( m -> !m.getReturnType().isPrimitive() )
.collect( Collectors.toList() );
for( var method : methods )
{
if( isNull( method.invoke( candidate ) ) throw new ValidationException( "candidate.%s() returned null".formatted( method.getName() ) );
}
}
ValidationException is a custom exception, and you need to declare the checked exceptions that are declared for Method::invoke.
To check for empty Strings, too, change the for loop like this:
…
for( var method : methods )
{
var retValue = method.invoke( candidate );
if( retValue instanceof String aString && aString.isEmpty() ) throw new ValidationException( "candidate.%s() returned the empty String".formatted( method.getName() ) );
if( isNull( retValue ) throw new ValidationException( "candidate.%s() returned null".formatted( method.getName() ) );
}

Writing a constructor of a class that extends an ArrayList

This is the signature of my class:
public class Constraint extends ArrayList<Interval> {
// ...
}
the other class Interval:
public class Interval {
// ...
}
has two ints, first and last
Constructor:
public Interval(int first, int last) {
this.first = first;
this.last = last;
}
A method that returns the union of two Intervals or more but should be of Constraint type:
public Constraint union(Interval interval) {
Interval a = new Interval(first, end);
int l = 0;
int max = 0;
// Interval result = new Interval(l, max);
l = (a.first < interval.end) ? a.first : interval.end;
max = (a.end > interval.end) ? a.end : interval.end;
return new Interval(l, max);
// the return here will return a new interval of type Interval but
// the method that I'm suppose to write should return something of
// type Constraint
}
My main issue is: how can I write the following constructor?
public Constraint(Collection<Interval> collection) throws NullPointerException {
// if the collection is empty, I have to write something like this:
if (collection == null) {
throw new NullPointerException("collection is empty");
}
// ...
}
Any help on how I should write the constructor of the class Constraint is really appreciated.
You have stumbled upon a deficiency of Java: the call to super() must be the first call in your constructor, so you are not allowed to precede it with code that checks against null. There is no good reason for this limitation, it is just the way java is. A flaw in the language. (If you learn Scala you will see that it totally did not have to be this way.)
So, the solution is to do the null-check in the same statement as the call to super. The following should accomplish this:
public Constraint( Collection<Interval> collection )
{
super( Objects.requireNonNull( collection ) );
}
If your version of java does not have Objects.requireNonNull() you can code a private static function yourself which checks the collection for nullity, throws if null, or returns the collection as-is if not null.

JPA/ Hibernate function in multiselect NPE

Using a function in a multiselect (or select(construct(...)) results in a NullPointerException (Hibernate 4+) with the following code:
criteriaQuery.select(criteriaBuilder.construct(OrderCriteria.class,
order.get(Order_.id),
criteriaBuilder.function("array_to_string", String.class,
criteriaBuilder.function("array_agg", String.class, employee.<String>get(Employee_.firstName)), criteriaBuilder.literal(",")),
));
The following exception is thrown:
java.lang.NullPointerException
org.hibernate.internal.util.ReflectHelper.getConstructor(ReflectHelper.java:354)
org.hibernate.hql.internal.ast.tree.ConstructorNode.resolveConstructor(ConstructorNode.java:185)
I have traced the exception back to Hibernate ConstructionNode::resolveConstructorArgumentTypes.
It appears that getDataType() does not exist on MethodeNode (criteriaBuilder.function creates a MethodNode) resulting in a NPE:
private Type[] resolveConstructorArgumentTypes() throws SemanticException {
SelectExpression[] argumentExpressions = collectSelectExpressions();
if ( argumentExpressions == null ) {
// return an empty Type array
return new Type[] {};
}
Type[] types = new Type[argumentExpressions.length];
for ( int x = 0; x < argumentExpressions.length; x++ ) {
types[x] = argumentExpressions[x].getDataType(); --> [types[x] == null with MethodNode]
}
return types;
}
Is there something wrong with the way the select is constructed?
After a few hours it became clear the using an non-registered function cannot be used in this way, resulting in this very unclear exception.
Solution:
public class ExtendedPostgreSQL9Dialect extends PostgreSQL9Dialect{
public ExtendedPostgreSQL9Dialect() {
super();
registerFunction("array_agg", new StandardSQLFunction("array_agg", StandardBasicTypes.STRING));
}
}

Recreating a method invocation (using reflection)

How do I recreate a method invocation? when all I've got is the list of methods, obtained by getDeclaredMethods(), and converted into a HashMap<String,Method> and a list of its parameters' Classes, obtained by getParameterTypes().
Suppose I get a string from the user and I want to invoke it:
"print(3,"Hello World!",true,2.4f)"
And the method print(int,String,boolean,float) is part of the getMethods() array. I'm having trouble to figure out how do I compose the invocation. So far this is what I got:
private static final Pattern functionCall = Pattern.compile(String.format("^%s\\(%s?\\)$", "(\\w+)", "(.*)"));
if( (m = functionCall.matcher(line)).find() ) {
String function = m.group(1); // in this example = "print"
String arguments = m.group(2); // in this example = "3,\\"Hello World!\\",true,2.4f"
if( methods.containsKey(function) ) {
Method method = methods.get(function);
Class<?>[] paramsExpected = method.getParameterTypes();
String [] paramsActual = arguments.split(",");
if( paramsExpected.length != paramsActual.length ) {
throw new IllegalArgumentException(function + ": bad number of arguments");
}
for( Class<?> param: paramsExpected) {
???????
}
method.invoke(context, ??????);
To be perfectly clear, I don't know in advance what string the user will input, I have to check it against the available methods and their parameters, and if I find it, then I have to invoke it with the parameters supplied by the user.
This what you need to do. One option is to use the ConverterUtils.convert method of BeanUtils to convert string to object of specific type. This will work for built in types.
Object[] args = new Object[paramsExpected.length];
int i = 0;
for( Class<?> param: paramsExpected) {
args[i] = convertStringToType(paramsActual[i], param);
i = i +1;
}
method.invoke(context, args);
Object convertStringToType(String input, Class<?> type) {
return ConverterUtils.convert(input,type);
}

How to convert from String to a primitive type or standard java Wrapper types

I have a java.lang.reflect.InvocationHandler and I need to implement the method invoke()
I have a value of type java.lang.String from my elaboration and I need to convert this value to the appropriate returnType expected by the method (it can be a primitive like int, boolean, double or wrapper classes like Boolean, Integer, Double, Float, etc).
Example:
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
String computedValue = compute(...);
return convert(method.getReturnType(), computedValue);
}
private Object convert(Class<?> returnType, String stringValue) {
return ...; // what's the simplest way?
}
I am not expecting to simply implement an automatic conversion between complex objects, but I expect a simple way to convert from String to the standard java types.
I've seen (too) many times stuff like this, but it doesn't seem appropriate to me:
public static Object toObject( Class clazz, String value ) {
if( Boolean.class.isAssignableFrom( clazz ) ) return Boolean.parseBoolean( value );
if( Byte.class.isAssignableFrom( clazz ) ) return Byte.parseByte( value );
if( Short.class.isAssignableFrom( clazz ) ) return Short.parseShort( value );
if( Integer.class.isAssignableFrom( clazz ) ) return Integer.parseInteger( value );
if( Long.class.isAssignableFrom( clazz ) ) return Long.parseLong( value );
if( Float.class.isAssignableFrom( clazz ) ) return Float.parseFloat( value );
if( Double.class.isAssignableFrom( clazz ) ) return Double.parseDouble( value );
return value;
}
and the above is not even the worse one I saw, so far :)
Does anybody have a secret trick here?
As far as I'm aware, there is no real alternative to the version you presented. You can simplify it a bit (since the wrapper types are all final), but you essentially need to use if or switch or hashing to switch on the class.
My advice is to code it like the above. Ugly code is only a problem per se if you have to look at it. So put it inside a utility method and don't look at it again.
FWIW - this is how I'd simplify the method:
public static Object toObject( Class clazz, String value ) {
if( Boolean.class == clazz ) return Boolean.parseBoolean( value );
if( Byte.class == clazz ) return Byte.parseByte( value );
if( Short.class == clazz ) return Short.parseShort( value );
if( Integer.class == clazz ) return Integer.parseInt( value );
if( Long.class == clazz ) return Long.parseLong( value );
if( Float.class == clazz ) return Float.parseFloat( value );
if( Double.class == clazz ) return Double.parseDouble( value );
return value;
}
This is simpler and more efficient. And it is equivalent to the original version because the classes are all final and because the specs state that equality for Class objects is object identity.
Arguably, we should be using the <wrapper>.valueOf(String) methods which return the wrapper objects directly.
I make no claim that this is less ugly ... but "beauty" is not a useful measure of code quality, because it is subjective and because it doesn't tell you whether the code is easy to understand and / or maintain.
UPDATE
To support primitive types as well, add the corresponding classes to the if conditions; e.g.
if (Boolean.class == clazz || Boolean.TYPE == clazz) {
return Boolean.parseBoolean(value);
}
It may now be getting to the point where doing a String switch on the type's name is more efficient, though there are some slightly knotty issues of type identity that need to be thought through. (In theory, you can have multiple types with the same full name that have been loaded by different classloaders. I think you'd need to "play fast and loose" in a classloader to do that with the primitive wrapper classes ... but I think it might still be possible.)
I think I found something
import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String returnValue = ...
return convert(method.getReturnType(), returnValue);
}
private Object convert(Class<?> targetType, String text) {
PropertyEditor editor = PropertyEditorManager.findEditor(targetType);
editor.setAsText(text);
return editor.getValue();
}
I think that those 3 lines of code are better than the multiple ifs, and I avoided to add external library dependencies, since java.beans package is inside the Java standard libraries (javadocs: PropertyEditorManager).
I find it quite acceptable; my only perplexity is that PropertyEditor is contained in java.beans package and I would have preferred something available in java.util or java.lang.reflect package, since this code has nothing to do with java.beans actually.
The code above has also the advantage that you can register additional PropertyEditor instances to translate complex objects, btw. That's not a bad thing to have though.
I think it's better than a list of ifs, in beauty, but also in quality.
Probably org.apache.commons.beanutils.ConvertUtils can help?
import org.apache.commons.beanutils.ConvertUtils;
// ...
final Object v = ConvertUtils.convert("42", Integer.class);
I propose this:
List<Class<?>> clsList = new ArrayList<Class<?>>();
clsList.add(Boolean.class);
clsList.add(Integer.class);
//etc.
for (Class<?> cls : clsList) {
if (cls.isAssignableFrom(clazz)) {
return cls.getMethod("valueOf", new Class[] { String.class }).invoke(null, new Object[] { value });
//Missing in this example: Handle a few exceptions
}
}
I'll leave it to you whether this looks cleaner or uglier.
There is a lightweight library that parses strings to java types which does what you want. It's called type-parser and you can find it on github here.
Your above code could then look something like this:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
TypeParser parser = TypeParser.newBuilder().build();
String computedValue = compute(...);
return parser.parseType(computedValue, method.getGenericReturnType());
}
in jdk8, you could now do something like so O(1) lookup time with no if statements...
A better version now that handles nulls correct is here
https://github.com/deanhiller/webpieces/blob/master/webserver/http-router/src/main/java/org/webpieces/router/impl/params/ObjectTranslator.java
private Map<Class<?>, Function<String, Object>> classToUnmarshaller = new HashMap<>();
private Map<Class<?>, Function<Object, String>> classToMarshaller = new HashMap<>();
public ObjectTranslator() {
classToUnmarshaller.put(Boolean.class, s -> s == null ? null : Boolean.parseBoolean(s));
classToUnmarshaller.put(Boolean.TYPE, s -> Boolean.parseBoolean(s));
classToUnmarshaller.put(Byte.class, s -> s == null ? null : Byte.parseByte(s));
classToUnmarshaller.put(Byte.TYPE, s -> Byte.parseByte(s));
classToUnmarshaller.put(Short.class, s -> s == null ? null : Short.parseShort(s));
classToUnmarshaller.put(Short.TYPE, s -> Short.parseShort(s));
classToUnmarshaller.put(Integer.class, s -> s == null ? null : Integer.parseInt(s));
classToUnmarshaller.put(Integer.TYPE, s -> Integer.parseInt(s));
classToUnmarshaller.put(Long.class, s -> s == null ? null : Long.parseLong(s));
classToUnmarshaller.put(Long.TYPE, s -> Long.parseLong(s));
classToUnmarshaller.put(Float.class, s -> s == null ? null : Float.parseFloat(s));
classToUnmarshaller.put(Float.TYPE, s -> Float.parseFloat(s));
classToUnmarshaller.put(Double.class, s -> s == null ? null : Double.parseDouble(s));
classToUnmarshaller.put(Double.TYPE, s -> Double.parseDouble(s));
classToUnmarshaller.put(String.class, s -> s);
classToMarshaller.put(Boolean.class, s -> s == null ? null : s.toString());
classToMarshaller.put(Boolean.TYPE, s -> s.toString());
classToMarshaller.put(Byte.class, s -> s == null ? null : s.toString());
classToMarshaller.put(Byte.TYPE, s -> s.toString());
classToMarshaller.put(Short.class, s -> s == null ? null : s.toString());
classToMarshaller.put(Short.TYPE, s -> s.toString());
classToMarshaller.put(Integer.class, s -> s == null ? null : s.toString());
classToMarshaller.put(Integer.TYPE, s -> s.toString());
classToMarshaller.put(Long.class, s -> s == null ? null : s.toString());
classToMarshaller.put(Long.TYPE, s -> s.toString());
classToMarshaller.put(Float.class, s -> s == null ? null : s.toString());
classToMarshaller.put(Float.TYPE, s -> s.toString());
classToMarshaller.put(Double.class, s -> s == null ? null : s.toString());
classToMarshaller.put(Double.TYPE, s -> s.toString());
classToMarshaller.put(String.class, s -> s == null ? null : s.toString());
}
public Function<String, Object> getUnmarshaller(Class<?> paramTypeToCreate) {
return classToUnmarshaller.get(paramTypeToCreate);
}
public Function<Object, String> getMarshaller(Class<?> type) {
return classToMarshaller.get(type);
}
such that you can then call
primitiveTranslator.getConverter(Integer.TYPE).apply(stringToConvert);

Categories

Resources