I have a piece of code, it's always used but it looked very redundant , and what can I do for sidestepping redundancy.
if(CommonUtil.isNull(second.getProvince())) {
second.setProvince(first.getProvince());
}
if(CommonUtil.isNull(second.getCity())) {
second.setCity(first.getCity());
}
if(CommonUtil.isNull(second.getDistrict())) {
second.setDistrict(first.getDistrict());
}
if(CommonUtil.isNull(second.getAddress())) {
second.setAddress(first.getAddress());
}
........
You can write this method in your data classes and do null control of all fields with one line of code. My code advice is like below:
public boolean copyIfNull(Object o)
{
Class<?> clazz = this.getClass();
Field[] fields = clazz.getDeclaredFields();
for(Field field : fields)
{
try {
Object fieldValue = field.get(this);
if (fieldValue == null)
{
field.set(this, field.get(o));
return false;
}
}
catch (Exception e) {
System.err.println("Field value could not be obtained");
e.printStackTrace();
return false;
}
}
return true;
}
And you will call this method in main like that:
second.copyIfNull(first)
As your objects look like beans from afar, you might have a look at java.beans.Introspector and BeanInfo.
Roughly along the lines of:
BeanInfo bi = Introspector.getBeanInfo(MyObjectClass.class);
for(PropertyDescriptor p : bi.getPropertyDescriptors()) {
// perform null-check
// invoke read on source object via read method delivered by p.getReadMethod()
// write to target via method delivered by p.getWriteMethod()
}
Related
I'm using the method below to get the names of all getter methods of a class:
private static Map<String, Object> fetchGetterMethods(Object object) {
Map<String, Object> result = new HashMap<String, Object>();
BeanInfo info;
try {
info = Introspector.getBeanInfo(object.getClass());
for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
Method reader = pd.getReadMethod();
if (reader != null) {
String name = pd.getName();
if (!"class".equals(name)) {
try {
Object value = reader.invoke(object);
result.put(name, value);
} catch (Exception e) {
}
}
}
}
} catch (IntrospectionException e) {
} finally {
return result;
}
}
I would like to skip the getter methods annotated with #Transient. How can I implement this?
#Transient
public boolean isValid() {
}
All you need is reader.getAnnotation(Transient.class) - if that returns something (it'll be an instance of Transient), it had the annotation. If it returns null, it did not. You can only do this to annotations whose definition is explicitly annotated with retentionlevel runtime, but assuming you're talking about JPA's #Transient, it is.
Note that writing a return statement in a finally block is absolutely not something you want to do.
You should use the Method#isAnnotationPresent method.
if (!reader.isAnnotationPresent(Transient.class)) {
// do work
}
This is a convenience method for the solution suggested by #rzwitserloot, and is the equivalent to:
if (reader.getAnnotation(Transient.class) == null) {
I'm rewriting a framework originally done in C# into Java and this has me stumped. It's a method using reflection to return any property in a class that implements a particular interface using LINQ:
public List<TInterface> GetElementsOfType<TInterface>()
{
return GetType().GetProperties()
.Where(x => typeof(TInterface).IsAssignableFrom(x.PropertyType))
.Select(x => x.GetValue(this, null)).OfType<TInterface>()
.ToList();
}
I am trying to recreate in Java and so far have this. Not too sure if it's right though?:
public <T> List<?> GetElementsOfType(Class<T> klazz) {
Class<?> props = this.getClass();
List<T> elementsOfType = new ArrayList<>();
try {
Field fieldlist[] = props.getDeclaredFields();
for (Field aFieldlist : fieldlist) {
if (aFieldlist.getType().isAssignableFrom(klazz)){
elementsOfType.add((T)aFieldlist);
}
}
} catch (Exception e) {
return null;
}
return elementsOfType;
}
Update: Thanks everyone for your help. This seems to work for me although the unchecked cast causes a warning I had to suppress:
#SuppressWarnings("unchecked")
public <T> List<T> GetElementsOfType(Class<T> klazz) {
Class<?> props = this.getClass();
List<T> elementsOfType = new ArrayList<>();
try {
Field fieldlist[] = props.getDeclaredFields();
for (Field aFieldlist : fieldlist) {
if (klazz.isAssignableFrom(aFieldlist.getType())){
elementsOfType.add((T) aFieldlist.get(this));
}
}
} catch (Exception e) {
return elementsOfType;
}
return elementsOfType;
}
}
In Java, a property is not a field. A property is defined as a public non-static read method and, if it’s not a read-only property, a public non-static write method. An instance of a class with one or more such properties is known as a Java bean.
You can examine properties using the java.beans package, starting with Introspector:
try {
BeanInfo beanInfo = Introspector.getBeanInfo(props, Object.class);
for (PropertyDescriptor prop : beanInfo.getPropertyDescriptors()) {
if (klazz.isAssignableFrom(prop.getPropertyType())) {
elementsOfType.add(klazz.cast(prop.getReadMethod().invoke(this)));
}
}
} catch (IntrospectionException | ReflectiveOperationException e) {
throw new RuntimeException(e);
}
Because Java uses checked exceptions, you can’t easily use Streams to write LINQ-like code in this case. It’s possible, but unwieldy. And not worth the bother, considering the above code is fairly succinct.
(The reason for the Object.class in Introspector.getBeanInfo(klazz, Object.class) is that we don’t want properties of Object, namely the read-only class property of Object defined by Object.getClass().)
I want tranfers attributes values from a object that came from my Entity manager to a new object.
The return Object is always null
public class ReflectionUtil {
public static Object copyAttributesFromTo(Object a, Object b) throws IllegalArgumentException, IllegalAccessException {
Field[] fieldsFromFirstClass = a.getClass().getDeclaredFields();
Field[] fieldsFromSecondClass = b.getClass().getDeclaredFields();
for (Field currentFieldFromTheFirstClass : fieldsFromFirstClass) {
for (Field currentFieldFromTheSecondClass : fieldsFromSecondClass) {
String nameOfTheFirstField = currentFieldFromTheFirstClass.getName();
String nameOfTheSecondField = currentFieldFromTheSecondClass.getName();
if (!Modifier.isFinal(currentFieldFromTheFirstClass.getModifiers())) {//Dispensa os Final
if (!currentFieldFromTheFirstClass.isAnnotationPresent(Id.class)) {//Não sobescreve campo id
if (nameOfTheFirstField.equals(nameOfTheSecondField)) {
currentFieldFromTheFirstClass.setAccessible(true);
currentFieldFromTheSecondClass.setAccessible(true);
currentFieldFromTheSecondClass.get(b));
currentFieldFromTheFirstClass.set(a, currentFieldFromTheSecondClass.get(b));
}
}
}
}
}
return a;
}
}
In the Facade call I always have to put all the attribute values to new object
public void update(Profile object) {
dao.beginTransaction();
Profile persistedObject = dao.find(object.getId());
persistedObject.setName(object.getName());
dao.commitAndCloseTransaction();
}
So I think to create some like that
public void update(Profile object) {
dao.beginTransaction();
Profile persistedObject = dao.find(object.getId());
ReflectionUtil.copyAttributesFromTo(persistedObject , object);
dao.commitAndCloseTransaction();
}
really miss understood why u are using 2 loop? .. if the classes are same . u dont need to do it .. just do it in 1 loop .. and use fields get for obj which is holding data .. and use set for to set .. here is the more better way .. if the same object is required u can use generics .. and same object type will be required ( request return type )
public static <T> T copyAttributesFromTo(T value, T dataHolder) throws IllegalArgumentException, IllegalAccessException {
if (value == null || dataHolder == null) {
throw new IllegalArgumentException();
}
final Field[] fields = value.getClass().getDeclaredFields();
for (Field field : fields) {
if (!Modifier.isFinal(field.getModifiers())) {
field.setAccessible(true);
field.set(value, field.get(dataHolder));
}
}
return value;
}
The return Object is always null
It is impossible for the return object (i.e. whatever a contains when you return) to be null.
It is easy to see that the code does not change the reference a. There are no assignments to it in the method, so it cannot change.
The other possibility was that you called the method with a null value for a. But if you did that, the first line of the method calls a.getClass() and that will throw an NPE if a is null.
TL;DR - it is impossible.
So what does this mean?
Here are the most likely explanations:
You are mistaken that null is being returned. Perhaps the method is not being called? Perhaps, it is not returning?
Maybe you have misinterpreted the evidence in some other way. It is hard to know without seeing the code ... and the evidence.
Maybe you don't mean that the method is returning Object; i.e. I misunderstood the question. (Your problem description is pretty unambiguous though ...)
I make a change in the code and works to update for me
public static Object copyAttributesFromTo(Object a, Object b) throws IllegalArgumentException, IllegalAccessException {
Field[] fieldsFromFirstClass = a.getClass().getDeclaredFields();
Field[] fieldsFromSecondClass = b.getClass().getDeclaredFields();
//JSFMessageUtil.addMsgLog(JSFMessageUtil.matricula, ReflectionUtil.class.getCanonicalName(), "ReflectionUtil: Aqui");
for (Field currentFieldFromTheFirstClass : fieldsFromFirstClass) {
for (Field currentFieldFromTheSecondClass : fieldsFromSecondClass) {
Object nameOfTheFirstField = currentFieldFromTheFirstClass.getName();
Object nameOfTheSecondField = currentFieldFromTheSecondClass.getName();
if (!Modifier.isFinal(currentFieldFromTheFirstClass.getModifiers())) {//Dispensa os Final
//if (!currentFieldFromTheFirstClass.isAnnotationPresent(Id.class)) {//Não sobescreve campo id
if (nameOfTheFirstField.equals(nameOfTheSecondField)) {
currentFieldFromTheFirstClass.setAccessible(true);
currentFieldFromTheSecondClass.setAccessible(true);
//JSFMessageUtil.addMsgLog(JSFMessageUtil.matricula, ReflectionUtil.class.getCanonicalName(), "ReflectionUtil: " + currentFieldFromTheSecondClass.get(b));
currentFieldFromTheFirstClass.set(a, currentFieldFromTheSecondClass.get(b));
}
//}
}
}
}
return a;
}
The call
public void update(Aluno a) {
try {
Aluno aluno = new Aluno();//(Aluno) em.find(Aluno.class, a.getId());
em.getTransaction().begin();
//aluno.setNome(a.getNome());
ReflectionUtil.copyAttributesFromTo(aluno, a);
em.merge(aluno);
em.getTransaction().commit();
} catch (Exception e) {
System.out.println("Error " + e.getLocalizedMessage());
JOptionPane.showMessageDialog(null, e.getLocalizedMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
} finally {
em.close();
}
}
Say I have the following code...
#FunctionalInterface
static interface MessageFunction<T> {
void send(T obj);
}
static #interface Message {
Class<?> value();
}
static class Foo {
#Message(String.class)
MessageFunction<String> bass = (string) -> {
// Do Stuff
};
}
static class MessageManager {
Map<Class<?>, MessageFunction<?>> messages = new HashMap<>();
public void register(Object obj) {
for (Field field : obj.getClass().getDeclaredFields()) {
Message message = field.getAnnotation(Message.class);
if (message != null) {
MessageFunction<?> function;
try {
function = (MessageFunction<?>) field.get(obj);
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
return;
}
Method sendMethod;
try {
// Will this work?
sendMethod = function.getClass().getDeclaredMethod("send", Object.class);
} catch (NoSuchMethodException | SecurityException e) {
e.printStackTrace();
return;
}
// How do I do something like this?
/*if (sendMethod.testParamaters(message.value())) {
this.messages.put(message.value(), function);
}*/
}
}
}
}
public static void main(String[] args) {
MessageManager manager = new MessageManager();
manager.register(new Foo());
}
I am reflecting a field that references an #FunctionalInterface of a generic type. Because the method parameter is also generic I have no way of knowing what parameters it accepts, Thus I must pass it along through other means (the annotation).
The issue is that there is the annotation value and the generic type do not have to match and there seems to be no way to check. I wan't it to fail in registration if the type listed in the annotation would not be accepted into the send method.
How would I go about thing this without actually calling the method. Is there a way? Better yet although I know its most likely impossible, is there a way to know what the parameter type is without the annotation?
The following is just a suggestion, I have used it in my project. But it is not a perfect solution for the question. May be you can download the source of GenericHibernateDao framework and see the sourcecode of method "getTypeArguments". I think it is so cool!.
// get a class object for your entity
Class clazz = ...
Type type = clazz.getGenericSuperclass();
if (type instanceof ParameterizedType) {
Type trueType = ((ParameterizedType)type).getActualTypeArguments()[0];
Class modelClass = (Class) trueType;
// Now you can creat an Instance in you generic parameterType
Object entity = modelClass.forInstance();
}
I do something similar in some of my code Here is a snippet.
Method[] meths = actionClass.getMethods();
for (Method meth : meths) {
Class<?>[] pTypes = meth.getParameterTypes();
/*
* Filter out all methods that do not meet correct
* signature. The correct signature for an action method
* is: String actionName(HttpServletRequest request)
*/
//...check for the correct number of params and the correct param type
if (pTypes.length != 1 || !HttpServletRequest.class.toString().equals(pTypes[0].toString())) {
continue;
} else {
//...check for return type
if (!String.class.toString().equals(meth.getReturnType().toString())) {
continue;
}
}
//If you make it here than that means the method
//meets the requirements to be a full fledged action.
//...
}
I use this method to remove Html code from my Strings in classes:
public void filterStrings() {
Field[] fields = this.getClass().getDeclaredFields();
if (fields == null) {
return;
}
for (Field f : fields) {
if (f.getType() == java.lang.String.class) {
try {
String value = (String) f.get(this);
f.set(this, methodToRemoveHtml(value));
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
Works fine. Since I caught myself putting this method in many classes I use, I thought I'd let all those classes inherit from a BaseClass and implement the method only there.
But when I do this, I get a: java.lang.IllegalAccessException: access to field not allowed on every try.
Why is this happening and
How can I fix this?
I guess the fields are private, so they can only be accessed from code inside the class that contains them, and not a superclass.
You have to make them accessible by calling setAccessible(true); on them or making them public or protected.
for (Field f : fields) {
if (f.getType() == java.lang.String.class) {
try {
f.setAccessible(true); // make field accessible.
String value = (String) f.get(this);
// ...
May be you need to call:
f.setAccessible(true);