I have a class the following class University.
public class University {
private List<Student> Students = null;
private List<Departments> department;
private CanteenName canteenName;
private LibraryName libraryName;
}
I have to write a logic where i need to check each variables in this class and if any variable name like in this case(CanteenName ,LibraryName) contains a text 'Name' in it , it should check if it is null or not, other variable it should ignore.
I thought of doing a null check using the getter property , but is there any dynamic way as the class contain any number of variable like (CanteenName).
You can achieve this by using reflection:
public static void checkObjectFieldForNull(Object obj, String... fieldNames) throws Exception {
if (obj == null) return;
//get all the fields in the object
for (Field f : obj.getClass().getDeclaredFields()) {
f.setAccessible(true); //set the fields to be accessible
for (String str : fieldNames) {
//loop through the fieldNames and see if they are null
if (f.getName().toLowerCase().contains(str.toLowerCase())) {
Obj val = f.get(obj);
//throw an exception if any of the required fields are null
if (val == null) throw new Exception(f.getName() + " cannot be null");
}
}
}
}
Then in your program:
public static void main(String[] args) {
University u = new University();
checkObjectFieldForNull(u, "name");
}
Related
We have a use case where there is a class that has more than 130 attributes. There is a method that populates all the attributes and it is just very long just because of large number of attributes. Just the setters would make the method very long.
Just to give context about the source for these attributes, these are populated by different datasources. Few of them are from different micro services and few of them are from a mysql tables.
Our current solution is to group them into different groups based on the source or some similar business trait and update them in different methods. This has made some of the setters in different methods and just makes it very hard to read.
I have read else where about the builder pattern. But most of these attributes need some transformation after fetching from source and assigning each of the attributes to a temp variables and using them in the builder doesn't help much.
"Is there a design pattern...?" Nope.
First and foremost, reconsider whether this object even needs that many fields. "Our current solution is to group them into different groups" this suggests it doesn't.
If it genuinely needs that many fields and if the fields are identically named on both the source and target objects, i.e. the main instance with 130 fields is basically a composite of all the others, then you could consider using reflection.
e.g. for the following value objects
class Main {
private String a;
private Number b;
private String c;
private String d;
}
class A {
private final String a;
A(String a) {
this.a = a;
}
}
class B {
private final Integer b;
B(Integer b) { this.b = b; }
}
class C {
private final String c;
C(String c) { this.c = c; }
}
A simple example would be
public static void main(String[] args) throws Exception {
Main main = new Main();
A a = new A("a1");
B b = new B(2);
C c = new C("c3");
// Get all values from all sources
Map<String, Object> fieldToValue = new HashMap<>();
Stream.of(a, b, c).forEach(obj -> {
Field[] fields = getFieldsForInstance(obj);
for (Field field : fields) {
try {
Object prevValue = fieldToValue.put(field.getName(), field.get(obj));
if (prevValue != null) {
throw new RuntimeException("Duplicate source field " + field.getName());
}
}
catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
});
// Set the values on main instance
Field[] mainFields = getFieldsForInstance(main);
for (Field field : mainFields) {
if (fieldToValue.containsKey(field.getName())) {
Object value = fieldToValue.get(field.getName());
if (value != null) {
if (field.getType().isAssignableFrom(value.getClass())) {
field.set(main, value);
}
else {
throw new RuntimeException("Incompatible types for field " + field.getName());
}
}
}
else {
System.out.println("warning: field " + field.getName() + " is unset on main");
}
}
}
private static Field[] getFieldsForInstance(Object obj) {
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
}
return fields;
}
I'd also consider whether you could use code generation at compile time, e.g. JavaPoet.
I have a constant interface file like so ->
public interface MyConstants {
String CONSTANT_ONE = "foo";
String CONSTANT_TWO = "hello";
}
How do I iterate over this to get the values of the constant? I saw a method using reflect where you can access it like this ->
Field[] interfaceFields = MyConstants.class.getFields();
for(Field f : interfaceFields) {
f.get(f.getName());
}
This returns an object but I want it to be of type String. I know I can typecast it but what's the correct way of doing this?
There are a couple of ways to make this safe, i.e. allow you to cast the Object values to Strings without getting a ClassCastException.
Use instanceOf to check the actual Class of the Object reference.
Check the type of the field before accessing it.
package org.example;
import java.lang.reflect.Field;
public class SO62746826 {
public interface MyConstants {
String CONSTANT_ONE = "foo";
String CONSTANT_TWO = "hello";
int CONSTANT_THREE = 1; // now we have this field casting each of the values will throw a ClassCastException on this one
}
public static void main(String... args) throws IllegalAccessException {
Field[] interfaceFields = MyConstants.class.getFields();
for(Field f : interfaceFields) {
Object o = f.get(null);
if (o instanceof String) {
String s = (String)o;
System.out.println(s);
}
// or
if (f.getType().equals(String.class)) {
String s = (String)f.get(null);
System.out.println(s);
}
}
}
}
The code is groovy but the answer can be both, Groovy or Java.
I have a Person class with this fields:
class Person(){
String name
String lasName
}
I have a method that returns two objects from the same class. One object with some fields and the other with the rest, in my example it would be like this:
person1 = "name : Jon"
person2 = "lastName : Snow"
What I need is to replace all the null fields of person1 with the person2 field if this is not null, in our example, the output would be:
person1.merge(person2)
person1= "name : Jon, lastName : Snow"
Is there any method on Java or Groovy to do something similar to this without writing all my fields(using some kind of loop)?
If there isn't any default method to use, how can I iterate through all the fields from a class?
Just tested using reflection. The desired output is
merged person:Person{name=John, lastName=Snow}
public static void testReflection() {
Person p1 = new Person("John", null);
Person p2 = new Person(null, "Snow");
Person merged = (Person) mergePersons(p1, p2);
System.out.println("merged person:" + merged);
}
public static Object mergePersons(Object obj1, Object obj2) throws Exception {
Field[] allFields = obj1.getClass().getDeclaredFields();
for (Field field : allFields) {
if (Modifier.isPublic(field.getModifiers()) && field.isAccessible() && field.get(obj1) == null && field.get(obj2) != null) {
field.set(obj1, field.get(obj2));
}
}
return obj1;
}
mergePersons accepts two Objects.
Then it go through all fields and validate if the first object has a null value.
If yes, then it verify if the second object is not nulled.
If this is true it assigns the value to the first Object.
Providing this solution you only access public data. If you want to access private data aswell, you need to remove the Modifier verification and set if accessible before like:
public static Object mergePersons(Object obj1, Object obj2) throws Exception {
Field[] allFields = obj1.getClass().getDeclaredFields();
for (Field field : allFields) {
if (!field.isAccessible() && Modifier.isPrivate(field.getModifiers()))
field.setAccessible(true);
if (field.get(obj1) == null && field.get(obj2) != null) {
field.set(obj1, field.get(obj2));
}
}
return obj1;
}
This is a quick (and presumptuous) approach that is basically the same as using reflection on the fields but instead uses:
Groovy's built-in getProperties() method on java.lang.Object, which provides us with a Map of its property names and values
Groovy's default Map constructor, which allows use to create instances of an Object given a Map of properties.
Given these two features, you can describe each object you want to merge as a Map of their properties, strip out the null-valued entries, combine the Maps together (and remove the pesky 'class' entry which is readonly), and use the merged Map to construct your merged instance.
class Person {
String first, last, middle
}
def p1 = new Person(first: 'bob')
def p2 = new Person(last: 'barker')
Person merged = (p1.properties.findAll { k, v -> v } // p1's non-null properties
+ p2.properties.findAll { k, v -> v }) // plus p2's non-null properties
.findAll { k, v -> k != 'class' } // excluding the 'class' property
assert merged.first == 'bob'
assert merged.last == 'barker'
assert merged.middle == null
Given Groovy fields are implemented as a getter/setter pair with a backing field you can probably do it this way in Groovy:
static <T> void merge(T from, T to) {
from.metaClass.properties.findAll { p ->
p.getProperty(to) == null &&
p.getProperty(from) != null &&
to.respondsTo(MetaProperty.getSetterName(p.name))
}
.each {
p -> p.setProperty(to, p.getProperty(from))
}
}
You're going to have to go the reflection route. I'm assuming you have a default constructor, otherwise the following won't work. Also, it needs two same types.
public static <T> T mergeObjects(T first, T second) throws IllegalAccessException, InstantiationException {
Class<?> clazz = first.getClass();
Field[] fields = clazz.getDeclaredFields();
Object returnValue = clazz.newInstance();
for (Field field : fields) {
field.setAccessible(true);
Object value1 = field.get(first);
Object value2 = field.get(second);
Object value = (value1 != null) ? value1 : value2;
field.set(returnValue, value);
}
return (T) returnValue;
}
Here is example
import java.lang.reflect.Field;
public class Merge2Obj {
private String name;
private String lasName;
public Merge2Obj() {
super();
}
public Merge2Obj(String name, String lasName) {
super();
this.name = name;
this.lasName = lasName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLasName() {
return lasName;
}
public void setLasName(String lasName) {
this.lasName = lasName;
}
public static <T> T mergeObjects(T first, T second) throws IllegalAccessException, InstantiationException {
Class<?> clazz = first.getClass();
Field[] fields = clazz.getDeclaredFields();
Object returnValue = clazz.newInstance();
for (Field field : fields) {
field.setAccessible(true);
Object value1 = field.get(first);
Object value2 = field.get(second);
Object value = (value1 != null) ? value1 : value2;
field.set(returnValue, value);
}
return (T) returnValue;
}
public static void main(String[] args) throws IllegalAccessException, InstantiationException {
Merge2Obj obj1 = new Merge2Obj("ABC", null);
Merge2Obj obj2 = new Merge2Obj("PQR", "LMN");
Merge2Obj obj3 = mergeObjects(obj1, obj2);
System.out.println(obj3.name);
System.out.println(obj3.lasName);
}
}
Assuming a mutable data class with getters and setters, Apache BeanUtils may suit your needs.
By default BeanUtilBeansBean.copyProperties(Object dest, Object orig) looks for pairs of T orig.get*() and dest.set*(T value), and calls the latter with the result of the former.
But you can inject a custom PropertyUtilsBean, so you could wrap the default one to prevent it from replacing non-null properties:
public NoClobberPropertyUtilsBean extends PropertyUtilsBean {
#Override
public void setSimpleProperty((Object bean,
String name,
Object value)
throws IllegalAccessException,
InvocationTargetException,
NoSuchMethodException {
if(getProperty(bean,name) == null) {
super.setSimpleProperty(bean,name,value);
}
}
}
Now you can merge with:
BeanUtilsBean beanUtils = new BeanUtilsBean(new ConvertUtilsBean(), new NoClobberPropertyUtilsBean());
Person merged = new Person();
beanUtils.copyProperties(person1);
beanUtils.copyProperties(person2);
If a property is non-null in both sources, the first copyProperties wins.
You could of course change the semantics, for example it would behave a different way if the guard was if(value != null).
At one level BeanUtils is just a wrapper around the kind of Reflection operations other answers suggest. It's up to you whether you want the extra level of abstraction. You may need to override more methods if you want to support map/list members, or BeanUtils' DynaBean class.
this below class in my database model on Relam object
public class ModelMarketBanners extends RealmObject {
#PrimaryKey
private String id;
private String marketId;
private String imageFileName;
private String title;
}
as far as i know i can get model fields data by class getter such as getId(), but i want to get filed name instead of class getter methods on loop clause, for example using for to show all class fields such as id or marketId, how can i do that?
i want to get all fileds data and if which one isn't empty attach layout with that data, instead of programing multi line to check and attaching that
for example:
for(int i=0; i> model.field_count; i++){
if (model.field.lenght() > 0) Log.v("data is: ", model.field);
}
instead of
SampleModel model = realm.where(SampleModel.class).findfirst();
if(model.getId().lenght() > 0)
Log.v("data is",model.getId());
if(model.getmarketId().lenght() > 0)
Log.v("data is",model.getmarketId());
if(model.getImageFileName().lenght() > 0)
Log.v("data is",model.getImageFileName());
There is a way, using reflection:
for (Field field : ModelMarketBanners.class.getDeclaredFields()) {
for (Method method : ModelMarketBanners.class.getMethods()) {
if ((method.getName().startsWith("get")) && (method.getName().length() == (field.getName().length() + 3))) {
if (method.getName().toLowerCase().endsWith(field.getName().toLowerCase())) {
try {
Object value = method.invoke(model);
if (!TextUtils.isEmpty(String.valueOf(value)) {
Log.v("data is: ", String.valueOf(value));
}
} catch (IllegalAccessException | InvocationTargetException e) {
}
}
}
}
}
I saw the other post, take a look at this using reflection...
public class SomeClass {
private String returnString;
private String id;
private String marketId;
private String imageFileName;
private String title;
// test
public static void main(String[] args) {
List<String> myFields = new ArrayList<>();
Field[] allFields = SomeClass.class.getDeclaredFields();
for (Field field : allFields) {
myFields.add(field.getName());
}
System.out.println(myFields);
}
}
the output will be the fields of the class
[returnString, id, marketId, imageFileName, title]
EDit:
if you need the data in the string variables please take a look at this question/ my answer....
Assuming I have an object and I took it fields:
Field[] fields = obj.getFields();
Now I'm iterating through each one and would like to print their members if it's some kind of class, otherwise just use field.get(obj) in case it's a string, int or anything that this command will print its value, not just the reference pointer.
How can I detect it?
You can get, without instantiation required, the Type of each field of a class like this:
public class GetFieldType {
public static void main (String [] args) {
Field [] fields = Hello.class.getFields();
for (Field field: fields) {
System.out.println(field.getGenericType());
}
}
public static class Hello {
public ByeBye bye;
public String message;
public Integer b;
...
}
}
You can use instanceof to tell the objects apart.
public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
Object[] objects = new Object[4];
objects[0] = new Integer(2);
objects[1] = "StringTest";
objects[2] = new BigDecimal(2.00d);
for (Object obj : objects) {
if (obj != null) {
if (obj instanceof BigDecimal) {
System.out.println("bigdecimal found " + obj);
} else if (obj instanceof String) {
System.out.println("String found " + obj);
} else {
System.out.println("Integer found " + obj);
}
}
else{
System.out.println("object is null");
}
}
}
If you need to test if an object is from your project, you can look at the package name and compare it to your project's package name.
You can either do this on the declared type of the field or on the runtime type of the field contents. The snippet below demonstrates the latter approach:
SomeClass foo = new SomeClass();
for (Field f : foo.getClass().getDeclaredFields()) {
boolean wasAccessible = f.isAccessible();
try {
f.setAccessible(true);
Object object = f.get(foo);
if (object != null) {
if (object.getClass().getPackage().getName()
.startsWith("your.project.package")) {
// one of yours
}
} else {
// handle a null value
}
} finally {
f.setAccessible(wasAccessible);
}
}
Do remember that obj.getFields(); only returns publicly-accessible fields. You may want to consider getDeclaredFields() as I've done above. If you stick with getFields(), you can omit the accessibility code in the above example.
With a bit of work, you could distinguish your classes by the classloader that loaded them. Take a look at this:
Find where java class is loaded from
Though this could help, it's not going to be the silver bullet for your problem, mainly because:
primitives (byte, short, char, int, long, float, double, and boolean) are not classes.
the architecture of classloaders is different in different app servers.
the same class could be loaded many times by different classloaders.
what I understood is you what to go recursive in object hierarchy and get values of primitives
public class ParentMostClass {
int a = 5;
OtherClass other = new OtherClass();
public static void main(String[] args) throws IllegalArgumentException,
IllegalAccessException {
ParentMostClass ref = new ParentMostClass();
printFiledValues(ref);
}
public static void printFiledValues(Object obj)
throws IllegalArgumentException, IllegalAccessException {
Class<? extends Object> calzz = obj.getClass();
Field[] fileds = obj.getClass().getDeclaredFields();
for (Field field : fileds) {
Object member = field.get(obj);
// you need to handle all primitive, they are few
if (member instanceof String || member instanceof Number) {
System.out.println(calzz + "->" + field.getName() + " : "
+ member);
} else {
printFiledValues(member);
}
}
}
}
public class OtherClass {
int b=10;
}
I got output as
class com.example.ParentMostClass->a : 5
class com.example.OtherClass->b : 10