I have a complex object hierarchy that has a couple of extends.
I am looking for a library that can reflectively insert default values on all fields.
For instance:
class Person {
String name;
Color color;
List<Clothes> clothes;
}
class Child extends Person {
Sibling sibling;
}
class Foo {
Person person;
Child child;
}
I would like a library that take an object as parameter, in this case the Foo class, and then reflectively insert default values (even better if I can define default values) on all fields. Also all maps,list,sets etc should get a new
I have looked at BeanUtils, but to my knowledge, it doesn't support exactly what I am looking for.
NB: These are just examples, and my objects are much more complex and big. They have many objects, and each object has many objects and so on. Both with maps, lists etc.
Is it maybe better to combine some libraries like BeanUtils and Google Guava and make it my own?
It should be fairly simple to do in one method provided you have the structure already built (in when case setting them as you build is a more logical approach)
If you know the default values in advance, why not just set them in the class? (i.e. default, default values ;)
Is there much value in setting a default name for a person (other than null) Can you give an example of where you would want to specify the default value dynamically?
Personally I would just try to use normal java constructors, and/or getters and setters etc. However from the question I'm guessing you want something that can work without knowing the exact structure of your classes.
So if you really have to do this, you could probably do something along the lines of the following:
public void setFields(Object myObject) {
Class<?> clazz = myObject.getClass();
Field[] fields = clazz.getFields();
for(Field field : fields) {
String name = field.getName();
if(name.equals("person")) {
field.set(myObject, new Person());
} else if (name.equals("color")) {
// etc...
}
}
}
Related
I'm working on an application which writes on a NoSQL database (Elasticsearch to be precise) and I have to manage more than a dozen (the number grows with time) different document classes, that is classes with numerous fields, their getters and setters and methods to convert the class to a JSONObject (each field is annotated with #JsonProperty(PROPERTY_NAME) and we use a JSON parser ).
All these classes have some fields and methods in common, which are all contained in a superclass (let us call it DocZero) but they all have their own custom fields, which brings me to the point.
It is true that these fields are custom, but some are shared between different classes in a non-linear way, that is I have my document classes Doc1, ... DocN and I have some sets of fields (around 10 as of right now) shared by them in a very wild way.
Some examples to best convey the situation:
Doc1 contains Set1 to Set5;
Doc2 contains Set1, Set2 and Set5 to Set8;
Doc3 contains Set6 and Set7;
Doc4 contains Set5 and Set7;
Doc5 contains Set1, Set2, Set5 and Set7 to Set10.
Given that I need to get and set these fields and, from time to time, manipulate a document with them, I made interfaces out of the Set#, each containing (abstract) setters and getters.
As such, when I declare a class
public class DocX implements SetA, SetB, SetC
I get reminded to implement the methods and hence add the required fields, but this means that all the classes implementing the same set will need to have the same parameters and the same methods which means that I need to write the same code many times (sometimes more than getter and setter methods).
Adding all the fields to DocZero foregoing the different Doc# classes is a solution which I am not keen on using, since I prefer to distinguish different document types and since this situation is present, in lower magnitude, in another section of the code, with AnotherDocZero, AnotherDoc# and AnotherSet# for which merging cannot be done due to other constraints and for which I would like a potential solution to work too.
I feel like this is one of those situation where multiple inheritance would solve the issue, but unfortunately Java doesn't allow it.
How could I avoid duplication in a situation like this? Have you got any advice to improve my handling of this issue?
If several kinds of fields are often grouped together, that suggests that grouping is a natural part of the domain of your program, and should be represented as such.
So, if you often find this in your classes
int xCoordinate;
int yCoordinate;
You should instead introduce
public final class Point ... {
private final int x;
private final int y;
Point(int x, int y) {
...
}
...
}
then instead of repeating x and y, write
Point position;
I strongly suggest to keep your data classes simple even if it does mean that you will need to repeat many fields definitions - POJOs are definitely easier to maintain and understand how the "result" data object looks like if you have all fields in one place - multilevel inheritance will quickly create a mess
For constraints of having proper getters you should use interfaces as you do. You can even create single interface for every getter and group them in another one like
public interface Set1To5 extends Set1, Set2, Set3, Set4, Set5 {}
For avoid duplication of getters/setters you can use some additional lib like lombok or consider not using getters/setters at all (just make all the fields in your data document classes public - but this one of course is not the option if you need to constraint classes with interfaces)
There is a pattern to explore. I don't know it already exists or there is a specific name for it.
Consider:
Java 8+ interfaces can have default methods. These methods can use other interface methods to define additional / default logic. The class implementing such an interface automatically get these methods, without having to implement them.
Also, a class can implement multiple interfaces.
The above two can be used to have "easy to compose" types in Java.
Example:
Create a base interface that can store/retrieve data. This can be as simple as:
public interface Document {
<T> T get(String key);
void set(String key, Object value);
}
This is the basic capability that will be used by all specific data objects.
Now, define two interfaces that contain nothing but specific field getter/setters using the above interface:
public interface Person extends Document {
default String getName(){
return get("name");
}
default void setName(String name){
set("name", name);
}
}
And another one:
public interface Salaried extends Document {
default double getSalary(){
return get("salary");
}
default void setSalary(double salary){
set("salary", salary);
}
}
Get the idea? This is a simple schema built upon the basic get/set capability. And you might want to define field names as constants in real applications.
But so far, it is all interfaces. It is not linked to something real, like a DB. Hence we must define an implementation to Document that uses a DB storage:
public class DBDoc implements Document {
private final Map<String,Object> data;
public DBDoc(HashMap<String, Object> data) {
this.data = new HashMap<>(data);
}
public DBDoc(){
this.data = new HashMap<>();
}
#Override
#SuppressWarnings("unchecked")
public <T> T get(String key) {
return (T) this.data.get(key);
}
#Override
public void set(String key, Object value) {
this.data.put(key, value);
}
}
We have used a simple map for storage, but it might as well be using a db connection or db specific document to get/set data. This is up to what DB or storage you are using.
Finally, we have the capability to compose types out of these interfaces:
public class Employee extends DBDoc implements Person, Salaried { }
And use them:
public static void main(String[] args) {
Employee employee = new Employee();
employee.setName("Joe");
employee.setSalary(1000.00);
System.out.println(employee.getName());
System.out.println(employee.getSalary());
}
I think default method is an option to go.
https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
i will discribe my problem with the following example:
public class Person{
private int age;
private String name;
public Person(int age, String name){
this.age = age;
this.name = name;
}
}
I ve a class with some Members (age and name in this case) but i don't know which and how much my class does have. Also i don't even care about the amount or the types. I wan't to get all members of only one class. like this:
private List<Object> getAll(Class searchedClass, Object from){
// This is where the magic happens
}
This method shall return a List with every not null object which is an instance of the Class "searchedClass" and is a member of the Object "from".
In my case i've classes called Property and PropertyContainerList and an interface called PropertyContainer. A PropertyContainerList can only contain objects which implements my interface PropertyContainer. So a class could've 10 Properties as members and another one cuold've 5 but objects of both can be added. A Property has the method addListener(...). I want, every time an object is added to my list, to add an listener to every "Property"-member of the object. so like this:
if(instance of PropertyContainer is added){
List<Property> properties = getAll(Property.class, propertyContainerObject);
for(Property property : properties)
property.addListener(new Listener());
}
I tried a few things but i've no idea how to realize the getAll(Class, Object) method. Please help :)
Thanks for answers
Field f = Class.getDeclaredField("fieldname");
Object o = f.get(ObjectToGetMemberFrom);
This did it for me :)
What you probably need is reflection. Read the reflection trail in the Java tutorial.
Reflection allows you to inspect at runtime what member variables and functions a class has, and to read from and write to the member variables.
I recomend you have a look at this post:
Java - Get a list of all Classes loaded in the JVM
on how to load all classes in a certain package or the entire JVM.
Once a List of all loaded/ known classes is available you will have to:
1.) Check per class in the list if it is implementing the desired Interface
2.) If so use Reflection methods to read desired "members" (fields and/or methods) according to http://docs.oracle.com/javase/tutorial/reflect/class/classMembers.html
Also note that with reflection (it worked with JDK 1.4 lol...) you are possibly still able to change private to public at runtime to read all of those fields as well.
NOTE: To get a list of "all" classes i will rely on this google library rather than doing it all from scratch:
http://code.google.com/p/reflections/downloads/detail?name=reflections-0.9.9-RC1-uberjar.jar&can=2&q=
Say I have the following class:
class Foo
{
public String bar;
public String baz;
}
And I have the following code, in another class:
Foo foo = new Foo();
String[] properties = {"bar", "baz"};
String[] values = {"barValue", "bazValue"};
Is it possible to iterate over the properties array and use that to set the values of Foo? E.g something like:
for (int i = 0; i < properties.length; i++)
{
foo[ properties[i] ] = values[i];
}
Is something like the above possible?
Is something like the above possible?
No.
With the properties as you have defined them, your only choices are:
writing or generating Java code (or bytecodes) to refer to the fields a foo.bar or foo.baz, or
use reflection.
If you want dynamic properties, use a Map object; e.g. a HashMap<String, String>.
As to your illustrative example, that won't / can't work because:
regular object fields cannot be indexed like an array, and
unlike C++, Python and other languages, Java doesn't support ad-hoc overloading of any of the core language constructs (apart from methods).
Java is not a dynamic language that supports this kind of thing. You need to learn to live with what it can offer you ... or use a different language.
You commented thus:
Reflection is supposed to be bad for performance.
Well yes, but it is relative. Accessing or updating a field reflectively is likely to be 10 to 100 times slower than accessing/updating it using normal Java code. However, if you are only doing this occasionally, the performance overhead may not be relevant. If it does turn out to be an issue, then your options include hand-writing, or generating the code. For example:
public class Foo
{
public String bar;
public String baz;
public void setNamedProperty(String name, String value) {
switch (name) {
case "bar":
bar = value;
break;
case "baz":
baz = value;
break;
default:
throw new IllegalArgumentException("Unknown property name");
}
}
}
For what it is worth, that code is going to be about as time efficient as setting a dynamic property in a language that supports dynamic properties. (And I suspect it will be more space efficient, given that dynamic properties are typically implemented using native coded hash tables.)
You can use Introspection, and it is much better a way when you face Java Beans.
Cons are:
It will call getter/setters if they are present, or will access fields directly if there are no getter/setters and fields are public.
You can iterate over properties, because it gives you an array of PropertyDescriptors.
It support BeanInfo classes,
so you can configure your bean properties
define accessor/mutators with different naming convention (not getter or setter)
You can use libraries like Apache Commons BeanUtils or Spring BeanWrapper API.
For more information look at java.beans.Introspector javadocs.
By the way as far as I know Interospection is built upon reflection, so it uses reflection itself.
I want to add new fields(variables) and encapsulating methods for a given class. For example: A class name Student has no any fields like below:
public class Student implements Serializable{
}
then in my application an instance is created;
Student s=new Student();
I want to add new methods which do not exist for student class at the run time.for example: I want to add a field called studentName, and getStudentName() and setStudentName() methods.
Then at the run time the student object will be like this;
public class Student implements Serializable{
private String studentName;
public void setStudentName(..){}
public String getStudentName(){return ...;}
}
In my application objects are written to a text file and all objects of same type do not have all variables. Therefore, I want to add only the required fields to save memory.
Any way is there a way to do this? Any sample code or link?
EDIT: or else can we create a class either and create instances which does not exists ?
EDIT 2: Thanks all of you answered and got many info and ideas. And changed the way to a better path from your suggestions as well
Why not just create a HashMap of values? Much more efficient, and has all the flexibility you're looking for.
public class Student
{
private HashMap<String, String> values;
public Student()
{
this.values = new HashMap<String, String>();
}
public void addValue(String name, String value)
{
values.put(name, value);
}
public String getValue(String name)
{
return values.get(name);
}
}
Why a HashMap?
You said that all objects may have differing values, and you'll be defining those new methods and attributes by a String. Well.. this will achieve that functionality without any horrible bytecode manipulation. For example:
String attrName = "name";
String attrValue = "jim";
Student stu = new Student();
stu.addValue(attrName, attrValue);
At the moment, you've only got the one value in your HashMap. The only overheard you have to face is the HashMap object itself, and two methods, which frankly is a fair trade off for a far tidier solution.
You can use bytecode instrumentation libraries like Javassist or ASM for this purpose. Here is an example of adding a field or method by using Javassist.
While it is possible with bytecode manipulation and such it wouldn't be wise, especially if you intend to do this to "save memory". It's unlikely that you would have so much data that it would make a difference, and if you did, you would store them in a database anyways.
Instead of writing your own HashMap based solution you can use DynaBean and DynaClass: support not only simple properties but also indexed (Array) and mapped (Map).
DynaBean can be introspected to get properties and values so you can dump to file BUT
with this solution you are only "simulating" a bean, your Student class doesn't really contains fields and accessors (you you call Student.getClass().getDeclaredField() you will get an empty array).
If you need to compose a "real" java java.lang.Class Javassist (my preferred choice, I used to resolve a solution similar to your question) or ASM (or CGLIB) are the best choiches.
I dont believe if this is possible in java but I'm sure it will only add to the memory because if you add them dynamically they must be set up beforehand + the code to add them dynamically.
Practically speaking, not in Java. In other languages like Javascript, this is possible.
Java is not a dynamic programming language and so I would not advice to follow that route even if some advance approaches may allow you to do so.
The Java idiom for that scenario would be to store the field values in a (hash) map instead. So you would have a couple of common accessors to set or get all attribute values and in the accessor you would need to indicate the name of the attribute you want to change.
However this solution won't save memory unless the maximum number of attributes is rather large and most object just have values for a small number of such attributes.
public class Entity {
// 5 is an estimate for the number attrs.
private Map<String,Object> attrs = new HashMap<>(5);
public Object getAttribute(String name) { return attrs.get(name); }
public void setAttribute(String name, Object obj) { attrs.put(name,obj); }
}
You could implement some runtime type-checking if you manage meta-data about possible attributes and their value types.
I am reading a Stream, which provides an identifier (a simple int). Depending on the int different data follows, which i need to turn into objects. So far i created classes for each object type, and each class provides a read(InputStream input)-method which reads whatever data there is to be read for that kind of object (all object classes inherit from a common base class).
However, there are numerous id's and thus numerous classes. What is the most elegant way to determine and create the instance of the class?
The most naive approach i tried first was to have a switch-case block to create the instances, but i find that it clutters the code (unreasonably). It also forces me to have every class available at compile time.
Second try was to create a map that maps each int to a class and use newInstance() to create the objects. There is still the problem that i need to initialize the map, which still requires that i have every class available at compile time. It more or less just moved the clutter from one place to another.
Removing the compile time dependencies is not required, it would just be a bonus if possible. The main goal is to avoid the boilerplate code.
Constraints: I don't want to add a library to solve this. Reflection is fine with me.
An alternative approach is to still use a Map but essentially use late-binding, if that's preferable. You could even store the config in a properties file like:
1=java.lang.String
2=my.class.Something
...etc...
You then do something like this:
Map<Integer,ObjectFactory> loader = ... // load from properties; fairly trivial
assuming:
public class ObjectFactory {
private Final String className;
private transient Class clazz;
public ObjectFactory(String className) {
this.className = className;
}
public Object createInstance() {
try {
if (clazz == null) {
clazz = Class.forName(className);
}
return clazz.newInstance();
} catch (Exception e) {
throw new IllegalStateExxception("Could not crate " + className, e);
}
}
}
I think your map solution sounds fine, but move the initial map setup out of of the Java code and into a config file. (Class.forName will help here)
You could have a registry with prototypes.
A prototype of each class you want to be able to create (at a point in time) could be added to your registry object at runtime, these prototypes would each have their own unique integer id.
When you want an object of id x, you just ask of your registry object to clone and return the prototype which id is x. (or null if no such prototype is currently registered).
Internally the registry could be a (hash)map for quick retrieval, but it could just as easily be a list of prototypes (Do make sure of course that all prototypes implement a common interface the registry can work with). Best thing is, no need for reflection!