JAVA New istante of a copied object - java

Hello everyone I'm writing a Java program where I need to copy the values of an old object into a new one (the two must be separated, if I chance one, the other must not be affected);
Once the copy is done the data should be displayed on Jtable, however the 2 object created seems to be linked(if I try to change one the other get modified too)
I suspect the problem is this method :
public void CopiatoreDiArea(Area nuova, Area daCopiare){
nuova.setNome(daCopiare.getNome());
nuova.setInter(daCopiare.getInter());
nuova.setRischioInerente(daCopiare.getRischioInerente());
nuova.setRischioResiduo(daCopiare.getRischioResiduo());
nuova.setControlli(daCopiare.getChecklists());
nuova.setStrategicita(daCopiare.getStrategicita());
nuova.setRischiosita(daCopiare.getRischiosita());
nuova.setMediaHpReato(daCopiare.getMediaHpReato());
nuova.setProbabilitaInerente(daCopiare.getProbabilitaInerente());
nuova.setEsposta(daCopiare.isEsposta());
nuova.setStrumentale(daCopiare.isStrumentale());
nuova.setCommento(daCopiare.getCommento());
nuova.setCondivisa(daCopiare.isCondivisa());
if (daCopiare.getNomeCompleto() != null){
nuova.setNomeCompleto(daCopiare.getNomeCompleto());
}
else{
nuova.setNomeCompleto(daCopiare.getNome());
}
if (daCopiare.getInterCompany() != null){
nuova.setInterCompany(daCopiare.getInterCompany());
}
if (daCopiare.getArticoli() != null || daCopiare.getArticoli().size() != 0){
nuova.setArticoli(daCopiare.getArticoli());
}
}
If this is the wrong way, how can I accomplish that?

How do you create the new instance of nuova object?
You have to make a new instance of it, if you created the new object with the reference of the oldest they will be linked and every change in the one will be reflected in other.

If you call the method as following:
CopiatoreDiArea(new Area(), oldArea)
Your code should work as the new 'Area' has all the attributes the other object has without any references being made to the new Area.

Try this:
public Area CopiatoreDiArea(Area daCopiare){
Area nuova = new Area();
nuova.setNome(daCopiare.getNome());
nuova.setInter(daCopiare.getInter());
nuova.setRischioInerente(daCopiare.getRischioInerente());
nuova.setRischioResiduo(daCopiare.getRischioResiduo());
nuova.setControlli(daCopiare.getChecklists());
nuova.setStrategicita(daCopiare.getStrategicita());
nuova.setRischiosita(daCopiare.getRischiosita());
nuova.setMediaHpReato(daCopiare.getMediaHpReato());
nuova.setProbabilitaInerente(daCopiare.getProbabilitaInerente());
nuova.setEsposta(daCopiare.isEsposta());
nuova.setStrumentale(daCopiare.isStrumentale());
nuova.setCommento(daCopiare.getCommento());
nuova.setCondivisa(daCopiare.isCondivisa());
if (daCopiare.getNomeCompleto() != null){
nuova.setNomeCompleto(daCopiare.getNomeCompleto());
}
else{
nuova.setNomeCompleto(daCopiare.getNome());
}
if (daCopiare.getInterCompany() != null){
nuova.setInterCompany(daCopiare.getInterCompany());
}
if (daCopiare.getArticoli() != null || daCopiare.getArticoli().size() != 0){
nuova.setArticoli(daCopiare.getArticoli());
}
}
And then in your call:
Area nuova = CopiatoreDiArea(daCopiare);

If you copy primitives (or the special primitive wrapper classes) in Java, the runtime will always do a deep copy of the values. To illustrate this, I show a few examples.
See http://jdoodle.com/a/3TL for an online runnable version of the code below:
public class MyClass {
public static void main(String[] args) {
int a = 10;
int b = a;
b = 20;
System.out.println(a + " != " + b);
// We did not change a when changing b.
Integer c = 10;
Integer d = c;
d = 20;
System.out.println(c + " != " + d);
// We did not change c when we changed d, even though they are class instances.
// This shows that primitive wrappers are handled differently due to
// autoboxing.
// See https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
MyInteger e = new MyInteger(10);
MyInteger f = e;
f.value = 20;
System.out.println(e + " == " + f);
// Changing the data contained within f also affected e. The two variables now point to the same instance.
MyInteger g = new MyInteger(10);
MyInteger h = new MyInteger(g);
h.value = 20;
System.out.println(g + " != " + h);
// We prove that we have two instances, initially containing
// the same value but changing their internal values does not
// affect each other.
}
private static class MyInteger {
public int value;
public MyInteger(int value) {
this.value = value;
}
public MyInteger(MyInteger other) {
this.value = other.value;
}
public String toString() {
return Integer.toString(this.value);
}
}
}
From your example, it seems you might be trying to copy complex classes, even lists maybe, and these will always copy a reference only when you use simple assignment.
There are a few options that you could take, for instance the copy constructor that I use above, or alternatively rely on some form of reflection or serialization that does the hard work for you.
Apache Commons Lang has a SerializationUtils class that will run through all internal data in your classes, serialize them into byte format and then try to re-instantiate new versions of the same classes with the serialized data.
The Cloner library makes use of reflection and some special performance cases for known types such as collections and calendars, with some great debugging options.

Declare a copy constructor for deep cloning your object
public class Area {
public Area() { // constructor }
public Area(Area objectToCopy) {
setNome(objectToCopy.getNome());
setInter(objectToCopy.getInter());
setRischioInerente(objectToCopy.getRischioInerente());
setRischioResiduo(objectToCopy.getRischioResiduo());
setControlli(objectToCopy.getChecklists());
setStrategicita(objectToCopy.getStrategicita());
setRischiosita(objectToCopy.getRischiosita());
setMediaHpReato(objectToCopy.getMediaHpReato());
setProbabilitaInerente(objectToCopy.getProbabilitaInerente());
setEsposta(objectToCopy.isEsposta());
setStrumentale(objectToCopy.isStrumentale());
setCommento(objectToCopy.getCommento());
setCondivisa(objectToCopy.isCondivisa());
if (objectToCopy.getNomeCompleto() != null)
setNomeCompleto(objectToCopy.getNomeCompleto());
else
setNomeCompleto(objectToCopy.getNome());
if (objectToCopy.getInterCompany() != null)
setInterCompany(objectToCopy.getInterCompany());
if (objectToCopy.getArticoli() != null || objectToCopy.getArticoli().size() != 0)
setArticoli(objectToCopy.getArticoli());
}
}
and then do it calling
Area newArea = new Area(oldArea);

Related

java.lang.InstantiationError when creating instance of static inner class with Objenesis

I am trying to create a utility method that should be able to deep-clone any object.
(Object.clone() only works on Object implementing Cloneable and I heard it's flawed anyways.)
I am using Objenesis to create new instances of objects without the use of constructors.
However, when trying to clone a JFrame I get the following Exception:
(using this class because I think it should be a good and complex test)
java.lang.InstantiationError: [Ljava.util.concurrent.ConcurrentHashMap$Node;
at sun.reflect.GeneratedSerializationConstructorAccessor12.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:48)
at org.objenesis.ObjenesisBase.newInstance(ObjenesisBase.java:73)
I am open to any solution, not necessarily limited to Objenesis.
My Code:
private static ObjenesisStd OBJENESIS = new ObjenesisStd();
#SuppressWarnings("unchecked")
public static <T> T clone(T object, boolean deep){
if(object == null){
return null;
}else{
try {
T clone = (T) OBJENESIS.newInstance(object.getClass());
List<Field> fields = ReflectionUtil.getAllFieldsInHierarchy(object.getClass());
for(Field field : fields){
boolean isAccessible = field.isAccessible();
boolean isFinal = ReflectionUtil.isFinal(field);
field.setAccessible(true);
ReflectionUtil.setFinal(field, false);
Class<?> type = field.getType();
if(!deep || type.isPrimitive() || type == String.class){
field.set(clone, field.get(object));
}else{
field.set(clone, clone(field.get(object), true));
}
field.setAccessible(isAccessible);
ReflectionUtil.setFinal(field, isFinal);
}
return clone;
} catch (Throwable e) {
e.printStackTrace();
//throw new RuntimeException("Failed to clone object of type " + object.getClass(), e);
return null;
}
}
}
public static void main(String[] args) {
GetterSetterAccess access = new GetterSetterAccess(JFrame.class);
JFrame frame = new JFrame("Test Frame");
for(String attr : access.getAttributes()){
System.out.println(attr + " " + access.getValue(frame, attr));
}
System.out.println("----------------------------------------------");
frame = clone(frame, true);
for(String attr : access.getAttributes()){
System.out.println(attr + " " + access.getValue(frame, attr));
}
}
EDIT: Got it to work with the accepted answer and a few more fixes:
Avoided cloning Wrappers of Primitive Types (Integer.class etc.)
Avoided cloning Classes (Objects of the class Class.class)
Stored the cloned objects in a Map and reused them, so if Object A has a reference to Object B and Object B one to Object A it doesn't get stuck in an infinite loop. I also used a Map that checks for exact equality (==) instead of using equals().
Created a custom exception class which would just be passed on instead of throwing a new exception on every level (causing a huge caused-by-depth).
I finally figured it out. Your code doesn't handle arrays. So it fails with instantiating "[Ljava.util.concurrent.ConcurrentHashMap$Node;" which is an array of Nodes.
However, I will advocate that indeed, you should not do that. You will end up with fairly complicated code. Depending on what you want to do, you could use Jackson or XStream to do a marshall / unmarshall to perform the copy.
If you really want to continue that path, you will need something like this after the null check of your clone method.
if(object.getClass().isArray()) {
int length = Array.getLength(object);
Object array = Array.newInstance(object.getClass().getComponentType(), length);
for (int i = 0; i < length; i++) {
Array.set(array, i, clone(Array.get(object, i), true));
}
return (T) array;
}

Nicely written check for numbers that can be null in java

I have an application where I need to handle a lot of numbers (Integers or Longs) comming from external sources.
The numbers can be null. In case they are null I always need to convert them to 0.
The problem seems trivial, but I don't want to write hundreds of times:
if (someNumber == null) {
someNumber = 0;
}
I don't like it for two reasons:
I don't like to write three lines of code for such simple task, especially because I need to do it many times
I don't like to to "mutate" someNumber (assign new value to someNumber variable)
I tried some other ways which can be seen here:
public static void main(String[] args) {
Integer zeroOrNull = new Random().nextBoolean() ? 0 : null;
// version1: this is nasty (I already mentioned why)
if (zeroOrNull == null) {
zeroOrNull = 0;
}
// version2: this seems to much for so simple task...
zeroOrNull = Optional.ofNullable(zeroOrNull).orElseGet(() -> 0);
// version3: creating an util might be considerable. Is there already such predefined util ?
zeroOrNull = MyUtil.getValueOrZero(zeroOrNull); // returns value or )
System.out.println(zeroOrNull); // I want 0 here in case of null
}
What is the preffered and nice way to do such "test for null/conversion to 0" ? Any chance to do this conversion implicitly?
Use i = (i==null)?0:i;
one line check
no method call
plain and simple
no additional dependency (unlike some other proposed solutions)
Place this check as close to your numbers source as possible, to avoid unnecessary duplications.
By creating overloaded versions of Null Checker
public static void main(String args[]) {
Integer intObj = null;
System.out.println("intObj : " + checkNull(intObj));
intObj = 1122222;
System.out.println("intObj : " + checkNull(intObj));
Long longObj = null;
System.out.println("longObj : " + checkNull(longObj));
longObj = 666555556L;
System.out.println("longObj : " + checkNull(longObj));
System.out.println("*********With default value***********");
intObj = null;
System.out.println("intObj : " + checkNull(intObj, 1));
intObj = 1122222;
System.out.println("intObj : " + checkNull(intObj, 1));
longObj = null;
System.out.println("longObj : " + checkNull(longObj, 0L));
longObj = 666555556L;
System.out.println("longObj : " + checkNull(longObj, 0L));
}
static Integer checkNull(Integer obj) {
if (obj == null)
return 0;
return obj;
}
static Long checkNull(Long obj) {
if (obj == null)
return 0L;
return obj;
}
static Integer checkNull(Integer obj, int i) {
if (obj == null)
return i;
return obj;
}
static Long checkNull(Long obj, long l) {
if (obj == null)
return l;
return obj;
}
A simple solution would be to write a utility method like below:
public static Integer checkNullNumber(Integer i){
if(i == null)
return 0;
return i;
}
Now you can use this method wherever you want like:
zeroOrNull = checkNullNumber(zeroOrNull);
I don't like to write three lines of code for such simple task,
especially because I need to do it many times
if (zeroOrNull == null) zeroOrNull = 0;
I don't like to to "mutate" someNumber (assign new value to someNumber
variable)
there is no way to change the null-value into a "0" without constructing a new Integer object that holds this "0" and this single line of code does just that
Use java8 java.util.Optional class is very efficient, but don't use
explicit null values, use empty Optional
This is my original answer, if "efficient" was intended only by "performance" I've wronged word, sorry.
The mean is that all coding process is better, develop and execution are more safe.
http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html

Java/Weka - Need to create unique instances

I wonder if there is a method that checks whether my new instance has been already created and added to my instances in Java...
Like ;
Instance instance = new Instance(i, vals);
if(instances.contains(instance) == false) { //or hasInstance maybe
instances.add(instance);
}
I understand, that you want for two objects x1 and x2 with x1.equals(x2) that x1 is the same instance (x1 == x2).
One needs to do something like this:
private Map<Instance, Instance> identityMap = new HashMap<>();
public Instance unique(Instance instance) {
Instance first = identityMap.get(instance);
if (first == null) {
first = instance;
identityMap.put(instance, instance);
}
return first;
}
Instance instance = new Instance(i, vals);
instance = unique(instance);
The reason is, that you want to maintain the first instance, to be used by all.
By the way - for other purposes:
Set<Instance> instances = ...;
Instead of
if (!instances.contains(instance)) { // if not instances contains
one could use code like
if (instances.add(instance)) {
// Added, hence new...
} else {
// Not added, hence already existing...
}

java.reflection.Method.invoke(...) Not re-casting args

I am trying out Java Reflection API. I am just fetching the Method objects of any given class into a JComboBox, and on it's itemSelected, creating an interface for the parameters (and of course, a calling object.)
This works fine, no issued.
But on the invokeButton's action, I am trying to invke the selected method with given params.
Initially it said that the param count differed. I was guided by one of my friend saying that the paramVals array has references to actual values, which might be causing problem, may be due to scope. I then started creating new objects of class Object and then assigning them the values. This worked for param count. But now the problem is that the parameters are not type cast properly. Even a String typecast to Object (as it has to be an array of Objects) is not being cast back to String.
The doc says that the invoke method will cast them on it's own and if cast fails, will throw an IllegalArgumentException.
I am not getting what is causing the call of invoke method fails...
Here is the code for the frame:
package nttraining.abhay.reflectiondemo;
//imports go here
public class ReflectionFrame
extends JFrame
implements ActionListener, ItemListener{
JComboBox methods;
JButton invokeButton;
public ReflectionFrame(String title) throws HeadlessException {
super(title);
//Layout components
//adding methods of class String to a combo
Class<String> c = String.class;
Method ml[] = c.getMethods();
for(Method m : ml){
methods.addItem(m);
}
invokeButton.addActionListener(this);
methods.addItemListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource().equals(invokeButton)){
Method selected = (Method) methods.getSelectedItem();
Class paramtypes[] = selected.getParameterTypes();
Object paramVals[] = new Object[paramtypes.length];
System.out.println("Method : " + selected.toString());
for(int i=0; i<paramtypes.length; i++){
Object obj = new Object();
obj = paramtypes[i].cast(params[i].getText());
paramVals[i] = obj;
System.out.println("Added " + paramtypes[i].cast(params[i].getText()).toString() + " to params");
}
try {
result.setText(selected.invoke(object.getText(), params).toString());
} catch (Exception ex) {
System.out.println(ex.getClass().getName() + ": " + ex.getMessage());
}
}
}
#Override
public void itemStateChanged(ItemEvent e) {
Method selected = (Method) methods.getSelectedItem();
if(selected==null)
return;
Class paramtypes[] = selected.getParameterTypes();
int paramCount = paramtypes.length;
object = new JTextField();
paramNames = new JLabel[paramCount];
params = new JTextField[paramCount];
panel.removeAll();
panel.setLayout(new GridLayout(paramCount+1, 2));
panel.add(new JLabel("Calling object"));
panel.add(object);
for(int i=0; i<paramCount; i++){
paramNames[i] = (JLabel) panel.add(new JLabel(paramtypes[i].getName()));
params[i] = (JTextField) panel.add(new JTextField());
}
invalidate();
validate();
}
}
A problem I found is in this line:
obj = paramtypes[i].cast(params[i].getText());
cast does not convert objects, it only verfies that the given object is of a certain class. Since you always provide a String.class as parameter (via .getText()), this will fail for anything other then a String type parameter. Even Integer.class to primitive int will fail.
Below a piece of code that demonstrates the cast problem.
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
public class Q21642768 {
public static void main(String[] args) {
try {
// Calls String.indexOf(str, fromIndex) via reflection.
callStringMethod("Hello reflection world", "reflection", 1);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void callStringMethod(String s, String subString, int startIndex) throws Exception {
Class<String> c = String.class;
Method ma[] = c.getMethods();
Method indexOfSub = null;
Class<?>[] indexOfSubPTypes = null;
List<Method> stringMethods = new ArrayList<Method>();
List<Type[]> stringMethodsPTypes = new ArrayList<Type[]>();
for (Method m: ma) {
stringMethods.add(m);
System.out.print(m.getName() + ": ");
Class<?>[] mptypes = m.getParameterTypes();
stringMethodsPTypes.add(mptypes);
boolean first = true;
for (Type t : mptypes) {
if (first) {
first = false;
} else {
System.out.print(", ");
}
System.out.print(t.toString());
}
if ("indexOf".equals(m.getName())
&& mptypes.length == 2
&& mptypes[0].equals(String.class)
&& mptypes[1].equals(int.class)) {
indexOfSub = m;
indexOfSubPTypes = mptypes;
System.out.println(" <-- ");
} else {
System.out.println();
}
}
if (indexOfSub == null) {
System.out.println("target method not found");
return;
}
Object[] pValues = new Object[2];
pValues[0] = indexOfSubPTypes[0].cast(subString);
// Fails:
// pValues[1] = indexOfSubPTypes[1].cast(startIndex);
// pValues[1] = indexOfSubPTypes[1].cast(startIndex + "");
pValues[1] = startIndex;
Object result = indexOfSub.invoke(s, pValues);
System.out.println("Result: " + result);
}
}
The problem is that all your parameter values are String objects, since you get them with JTextField.getText(). String is the runtime type of these values, whereas the type of the method parameters will generally be different, and this is what matters.
To successfully invoke the method, you will first need to convert each value to the proper type specified in the paramTypes array. Neither cast() nor invoke() are going to do that for you. This means you must find a way to do the conversion from a String, basically deserializing from a String value into an object of the proper class, and that may not always be possible or too complex to do. At this point, I think you can start to imagine the complexity of what you are trying to do. This is very far from trivial. Remember that each parameter value will generally not be a simple value, but rather a full object graph, that's where the complexity is.
For example, if the type of a method parameter is an interface, how will you know which concrete implementation to instantiate? If you do find a concrete class implementing it - and that may not always be possible - how will you create instances of that class? Here you're entering a domain covered by serialization frameworks in Java. There are quite a few of these frameworks that are open source and you might want to take a look at some of them. You will find a comprenhesive list of such fraleworks here.
A few years ago, I worked on a related project, where I had to provide a Swing GUI to enable end-users to create objects of arbitrary types, used as input for a rule engine. What I came up with was a JTree with multiple roots, associated with a property sheet (i.e. a JTable with 2 columns), where the tree leaves were either simple types (primitives, primitive wrappers, Date, etc.) or object references. Each reference would point to a specific tree root representing the actual object to be later instantiated. I don't remember exactly how long it took, just that it took several months to get it tested and working.
So, I don't want to crush your hopes, but you should be aware that it's going to take a huge amount of work to do this.

Java: What scenarios call for the use of reflection?

So from reading some of the articles, the message i got out of it was being able to modify fields and set values to classes in real time without recompiling.
so is it possible to do this to 3rd party java library created classes which no source code is available / is it possible to use reflection to modify class instances on run time?
in what other scenarios is reflection commonly used?
I am trying to understand how reflection can be applicable.
Any time you're dealing with a string at runtime and want to treat part of that string as an identifier in the language.
Remote procedure calling -- treat part of a message received over the network as a method name.
Serialization and deserialization -- convert field names to string so you can write the object's fields to a stream and later convert it back into an object.
Object-relational mappings -- maintain a relationship between fields in an object and columns in a database.
Interfaces with dynamically typed scripting languages -- turn a string value produced by a scripting language into a reference to a field or method on an object.
It can also be used to allow language features to be emulated in the language.
Consider the command line java com.example.MyClass which turns a string into a class name. This doesn't require reflection, because the java executable can turn a .class file into code, but without reflection it would not be able to write java com.example.Wrapper com.example.MyClass where Wrapper delegates to its argument as in:
class Wrapper {
public static void main(String... argv) throws Exception {
// Do some initialization or other work.
Class<?> delegate = Class.forName(argv[0]);
Method main = delegate.getMethod("main", String[].class);
main.apply(null, Arrays.asList(argv).subList(1, argv.length).toArray(argv));
}
}
One other case developing IDEs like eclipse/netbeans etc., to determine which methods in an abstract class need to be implemented by a child class, and automatically write the missing method calls for you (one example).
Injection frameworks like Guice or Spring use reflection to help you build instances of objects at runtime.
Reflection is also useful in cases where configuration is required to string things together. For example, in an application I wrote I have a #Report("debits") annotation that is simply added to methods that generate reports. Then, in the XML configuration a user can simply add:
<requiredReports="debits,blah,another"/>
This minimizes boiler plate code from mapping the XML code to the actual method, since reflection can discover the report methods and make it available directly.
I was asked to create a solution for the below statement.
"1) A diff service that:
• can calculate the differences between two objects and return the resulting
"diff"
• can apply a previously created "diff" against an original object, so that
the returned object matches the modified object that was used to calculate
the diff. "
This would have been very difficult without using reflection. Using reflection I could list all the unknown object's Class elements, properties and methods. I could use these to get the values contained in the object. I could compare the original and modified objects values, create "diff" object reflecting changes between the two objects.
Using Java reflection I could then read the instructions in the "diff" object and apply these to the original object. Java reflection gave me the tools needed to change the values on the unknown properties of the original object. I could invoke setter methods and instantiate types where needed if the original property was null to set the modified value on the original object.
The "diff" app works on any two objects of the same type, but they could be any type, both objects just have to be of the same type.
Reflection is very powerful and allow us to create true generic polymorphic methods, functions, libraries and system, where the passed object type does not need to be known at compile time. This applies when using Java Reflection and Generics together, a very powerful combination.
To end of, I have also used Java Reflection to create a generic sort function, that could sort any list of any Class Type, using any property of the Class as the sort key.As long as the calling method passed the list and the property name to use, the method would return a sorted list.
Here are some cases to use reflection in
public class Main {
public static void main(String[] args) {
displayProperties(Stage.class);
}
public static void displayProperties(Class class) {
boolean hasParam = false;
boolean hasReturn = false;
ArrayList<Method> propMethods = new ArrayList<>();
Method[] methods = clazz.getMethods();
for (Method m: methods) {
Parameter[] paraType = m.getParameters();
if(m.getParameterCount()<2) {
if ((m.getReturnType() == void.class && paraType.length == 1) || (m.getReturnType() != void.class && paraType.length == 0)) {
//Get the properties alone
propMethods.add(m);
}
}
}
for (int i = 0; i < propMethods.size(); i++) {
if (propMethods.get(i).getName().startsWith("get") || propMethods.get(i).getName().startsWith("set")) {
System.out.println(readWrite(propMethods.get(i), propMethods) + " " + propMethods.get(i).getName().substring(3)+"( "+propMethods.get(i).getReturnType().getTypeName()+" )");
} else
System.out.println(readWrite(propMethods.get(i), propMethods) + " " + propMethods.get(i).getName() + "( "+propMethods.get(i).getReturnType().getTypeName()+" )");
}
}
public static String readWrite(Method method, ArrayList<Method> propMeths) {
ArrayList<Method> temp;
temp = propMeths;
boolean readIn = false;
boolean writeIn = false;
String onlyName = method.getName().substring(3);
for (int i = 0; i < temp.size(); i++) {
//use the substring--
if (temp.get(i).getName().startsWith("get") && temp.get(i).getName().endsWith(onlyName)) {
readIn = true;
}
if (temp.get(i).getName().startsWith("set") && temp.get(i).getName().endsWith(onlyName)) {
writeIn = true;
}
}
if (readIn == true && writeIn == true)
return "rw ";
else if (readIn == true && writeIn == false)
return "r ";
else
return "w ";
}
}
Another case with the String class
public static void main(String[] args)
{
displayProperties(String.class);
}
public static void displayProperties(Class class){
clazz.getDeclaredFields();
Method[] methods = clazz.getDeclaredMethods();
for(int ii = 0; ii<methods.length; ii++){
System.out.println("Method Name: "+methods[ii].getName());
System.out.println("Method Type: "+methods[ii].getReturnType());
System.out.println("Method Pa: "+methods[ii].getParameterCount());
System.out.println("Method Type: "+methods[ii].getReturnType());
}
}
Loading from XML with reflection
public static Object loadFromXml(String filePath) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
File newFile = new File(filePath);
Document doc = builder.parse(newFile);
Node root = doc.getFirstChild();
return loadObjectElement(root);
}
/**
* This method loads from an xml file and returns all the contents of the file as an object
* #param root The node passed in to the method from which the "tree" gets a new level
* #return all the contents of the xml file as an object
* #throws Exception
*/
public static Object loadObjectElement(Node root) throws Exception {
//loads the root
String studentClass = root.getAttributes().getNamedItem("class").getTextContent();
Object newStudentObject = Class.forName(studentClass).newInstance();
//gets the children nodes (may have text elements like \n)
NodeList studentFieldList = root.getChildNodes();
//iterates through the children nodes
for (int i = 0; i < studentFieldList.getLength(); i++) {
//checks to make sure the child node is not a text node
if (studentFieldList.item(i).getNodeType() != Node.TEXT_NODE) {
//checks if the current node does not have children
if (studentFieldList.item(i).getChildNodes().getLength() == 0) {
//receives data of the current node
String nameField = studentFieldList.item(i).getAttributes().getNamedItem("name").getTextContent();
String valueField = studentFieldList.item(i).getAttributes().getNamedItem("value").getTextContent();
Field declaredFieldInClass = newStudentObject.getClass().getDeclaredField(nameField);
//makes the field accessible
declaredFieldInClass.setAccessible(true);
//checks the field type
switch (declaredFieldInClass.getType().getSimpleName().toLowerCase()) {
case "integer":
case "int":
declaredFieldInClass.set(newStudentObject, Integer.valueOf(valueField));
break;
case "float":
declaredFieldInClass.set(newStudentObject, Float.valueOf(valueField));
break;
case "boolean":
declaredFieldInClass.set(newStudentObject, Boolean.valueOf(valueField));
break;
default:
declaredFieldInClass.set(newStudentObject, valueField);
}
declaredFieldInClass.setAccessible(false);
} else {
//there are children in the current node
NodeList modulesObjectList = studentFieldList.item(i).getChildNodes();
String nameField = studentFieldList.item(i).getAttributes().getNamedItem("name").getTextContent();
Field declaredFieldInClass = newStudentObject.getClass().getDeclaredField(nameField);
List<Object> modules = new ArrayList<>();
//adds the modules into the array
for (int j = 0; j < modulesObjectList.getLength(); j++) {
if (modulesObjectList.item(j).getNodeType() != Node.TEXT_NODE) {
//recursively calls the the loadObjectElement method for any sub lists
modules.add(loadObjectElement(modulesObjectList.item(j)));
}
}
//sets the modules of the specific student that the method is working with
declaredFieldInClass.set(newStudentObject, modules);
}
}
}
return newStudentObject;
}

Categories

Resources