Create Fields and methods dynamically - java

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.

Related

Avoid duplicate code with numerous Java classes sharing fields

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

Why is it bad practice to allow to set a collection?

Let's say we have a class with a simple collection (a list for instance). The class contains a constructor, getters and setters.
I've been told that it is a bad practice to set the collection directly.
class Example{
private String id;
private List<String> names;
public Example(String id, List<String> names){
this.id = id;
this.names = names;
}
public String getId(){
return id;
}
public List<String> getNames(){
return names;
}
public void setId(String id){
this.id = id;
}
public void setNames(List<String> names){
this.names = names;
}
}
Can anyone point the disadvantages of writing the method setNames()?
The logic behind set and get operations is to allow validation or replacing of inner representation, if you let an external class set the specific implementation, you lose control over the insertion logic (allows duplicates? is ordered?, is mutable?), and you make you object harder to use, as the users of it have to decide that, when is very probable that they don't care.
Since the private variable names is owned by your class you can ensure that you have control over its contents within the class. If you change the reference of that variable to a list that gets passed in then you no longer are certain that your instance won't be changed externally since both your class AND the class that passed the new list instance will both have a reference/access to it. Same is true with getNames() - any class that calls that method now has full access to change the contents of the list externally from the class.
That would give you two ways of changing the contents (getNames().add(...) vs. setNames(Arrays.asList(...))).
This is confusing.
You should pick a single option and make the other option impossible.
A lot of the builtin collections are mutable, so storing such a value may allow an external class to modify the internal state of your Example is a way you did not plan. Consider the following snippet:
List<Stirng> names = new ArrayList<>();
names.add("Stack");
names.add("Overflow");
Example example = new Example();
example.setNames(names);
// example.getNames() returns ["Stack", "Overflow"]
names.add("Exchange");
// example.getNames now returns ["Stack", "Overflow", "Exchange"]!
A safer approach could be to copy the contents of the passed list:
public void setNames(List<String> names){
this.names = new ArrayList<>(names);
}
A slightly different answer to those here already is that setters are a bad practice (*), whether you're setting a collection property or some other type.
To quote Effective Java 2nd Ed Item 15: "Minimize mutability":
There are many good reasons for [making classes immutable]: Immutable classes
are easier to design, implement, and use than mutable classes. They are less prone
to error and are more secure.
There is also a description of immutable classes in the Oracle tutorial.
(*) That's not to say that you should never use them; just that you should design classes to be immutable as a default position, and only make them mutable in the few occasions where it is actually required - and that's less often than you might imagine. To quote the same item in Effective Java:
Classes should be immutable unless there’s a very good reason to make them
mutable
Using get and set methods allows you to perform verification and validation on the input before it can cause problems. It can also be used to transform info going into and out of your system for the convenience of the program and user.
Edit
Just to be clear defensive measures are part of the verification and validation I was talking about.

Get Member/Fields of an existing Object

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=

Is it possible to return the name of an Object in Java?

Suppose you create an object:
class newClass{
public static void main(String[] args){
Object o = new Object();
}
}
Is it possible to return the name as a string, "o", or in anyform, of the given object?
No, this is not possible. If you really want this, you are probably using the wrong design. Note that objects do not have a name. Variables do have a name.
Is it possible to return the name of an Object in Java?
If you write something like this:
String name = obj.toString();
It will return string representation of object but this is not very human-readable. if you want to do it you need to create custom object and override toString() method:
public class MyObject {
private String name;
public String toString() {
return name;
}
}
Now when you write:
String name = myObj.toString();
It will return name in human-readable form. But this depends of your requirements if you want to create custom objects. In this way it's very simple and it works well.
No. The object does not know what the outside world calls it, i.e what reference(s) it has.
This is not possible.
You could use a Map<String, Object> to store a mapping from object name to object value and then return the key.
In reality the "name" of your object is a compile time constant. I.e. it doesn't change once you have compiled the code so
Object o = new Object();
return "o";
Would literally do what you want. Which begs the question, why would you want to do that?
This is not possible using java reflection. However, the information is stored in java class file if compiled with debugging information on. You may use bytecode engineering library like ASM to dig that.
Note: I just read sajmon's answer and he has the more elegant way of doing it to a certain extent
First of all the guys' answers are correct
but
if you really need it
I would extend Object class with something like MyObject
public class MyObject {
private String objectName;
public MyObject(){
}
public MyObject(String name){
setObjectName(name);
}
public getObjectName(){
return this.objectName;
}
public setObjectName(String name){
this.objectName = name;
}
}
but then each time you create an Object use MyObject instance instead and add your object name as a constructor parameter
MyObject mine = new MyObject("mine");
Having said that, it's still an open question as to why you might need it? :)
Since Java supports aliasing this really isn't sensible or possible.
Aliasing means there's no garuantee that an object is referenced by only one variable.
scoping just makes the whole problem even harder, since only references in the current scope would be of any use at that point. and there may be more than one.
it would help if you explained what you're trying to achieve with this code.
In addition to the previous answers, there may be several different variables, with different identifiers, that all reference the same object. A variable may refer to different objects at different times.
If you need a mapping from an object to a String, I suggest a Map<Object,String>.

Populate default values through reflection in java

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...
}
}
}

Categories