I'm a new java developer, and I want to develop my code with reflection.
I have a class call User:
I want to pass dynamic value to those 3 methods, so in java reflection I got some code but I don't understand why?
import .....
public class user
{
private int id;
private String name;
private Date dob;
public setID(int id)
{
this.id = id;
}
public setName(String name)
{
this.name = name;
}
public setDOB(Date dob)
{
this.dob = dob;
}
}
Class cls = Class.forName("user");
Method[] methods = cls.getDeclearedMethod();
for(Method m : methods)
{
Object[] args = new Object[1];
args[0] = .....
m.invoke(cls, args[0]);
}
I don't dare to ask why you wanna do this... this way but i hope this example helps you get the feeling of some of the capabilities of reflection provided by Java.
import java.lang.reflect.Method;
import java.util.Date;
public class Ref {
public static void main(String[] args) throws ClassNotFoundException,
InstantiationException, IllegalAccessException {
Class cls = Class.forName("User");
Object o = cls.newInstance();
Object[] fieldValues = { new Integer(1), "", new Date() };
Method[] methods = cls.getDeclaredMethods();
for (Method m : methods) {
Class[] paramTypes = m.getParameterTypes();
Object[] paramValues = new Object[1];
if (paramTypes.length == 0) {
continue;
}
if (paramTypes[0].equals(Date.class)) {
paramValues[0] = new Date();
} else if (paramTypes[0].equals(String.class)) {
paramValues[0] = "nice";
} else if (paramTypes[0].equals(Integer.TYPE)) {
paramValues[0] = 2;
}
if (paramValues[0] != null) {
try {
m.invoke(o, paramValues[0]);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} // end for
} // end for
System.out.println("o = " + o);
} // end method main
} // end class Ref
class User {
private int id;
private String name;
private Date dob;
public void setID(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setDOB(Date dob) {
this.dob = dob;
}
public String toString() {
return "[id = " + id + ", name = " + name + ", date = " + dob + "]";
}
}
Related
I need help passing a test, but can't seem to find the solution anywhere. I have a code for determining the bonus points for customers. I get my info from a text file and I need to give customers bonus points based on vairables. The catch is that the bonus points should only be added when used the save() method, which overwrites the text file. I have a CustomerRepository class:
public class CustomerRepository {
private static final String FILE_PATH = "src/poly/customer/data.txt";
public List<AbstractCustomer> customers;
public CustomerRepository() {
try {
this.customers = readFiles();
} catch (IOException e) {
e.printStackTrace();
}
}
private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
public List<AbstractCustomer> readFiles() throws IOException{
List<AbstractCustomer> result = new ArrayList<>();
List<String> lines = Files.readAllLines(Path.of(FILE_PATH));
for (String line : lines) {
String[] parts = line.split(";");
int points = Integer.parseInt(parts[3]);
if (parts[0].equals("REGULAR")) {
LocalDate date = LocalDate.parse(parts[4], formatter);
RegularCustomer customer = new RegularCustomer(parts[1], parts[2], points, date);
result.add(customer);
} else if (parts[0].equals("GOLD")) {
GoldCustomer customer = new GoldCustomer(parts[1], parts[2], points);
result.add(customer);
} else {
throw new IOException();
}
}
return result;
}
public void save(AbstractCustomer customer) {
if (!(customers.contains(customer))) {
customers.add(customer);
}
StringBuilder result = new StringBuilder();
for (AbstractCustomer client : customers) {
result.append(client.toString());
result.append("\n");
}
try{
File file = new File(FILE_PATH);
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(result.toString());
bw.close();
}catch(IOException e){
e.printStackTrace();
}
}
This class is working, but I don't know how to give customer objects points only when they are saved. I also have RegularCustomer and GoldCustomer classes which extend the AbstractCustomer class:
public abstract sealed class AbstractCustomer permits GoldCustomer, RegularCustomer {
protected String id;
protected String name;
protected int bonusPoints;
public AbstractCustomer(String id, String name, int bonusPoints) {
this.id = id;
this.name = name;
this.bonusPoints = bonusPoints;
}
public abstract void collectBonusPointsFrom(Order order);
public String getId() {
return id;
}
public String getName() {
return name;
}
public Integer getBonusPoints() {
return bonusPoints;
}
The code itself is working fine and does the intended things, but my only problem is passing this test:
#Test
public void customerIsChangedOnlyWhenSaved() {
String randomId = UUID.randomUUID().toString();
repository.save(new RegularCustomer(
randomId, "David", 0, LocalDate.now()));
AbstractCustomer customer = repository.getCustomerById(randomId).get();
assertThat(customer.getBonusPoints(), is(0));
customer.collectBonusPointsFrom(new Order(200, LocalDate.now()));
assertThat(customer.getBonusPoints(), is(not(0)));
AbstractCustomer loaded = repository.getCustomerById(randomId).get();
assertThat(loaded.getBonusPoints(), is(0));
}
This test creates a new customer and adds a order, but the customer bonuspoints should not change, because it is not saved. My code still adds the points and overwrites the file.
There is also a BonusCollector class, which collects bonus points from order, but this class shouldn't be modified.
This is the implementation for collectBonusPoints(Order order):
#Override
public void collectBonusPointsFrom(Order order) {
if (order.getTotal() >= 100) {
double points = order.getTotal();
if (isWithinAMonth(order.getDate())) {
this.bonusPoints += Math.toIntExact(Math.round(points * 1.5));
this.lastOrderDate = order.getDate();
} else {
this.bonusPoints += Math.toIntExact(Math.round(points));
this.lastOrderDate = order.getDate();
}
}
}
The gold customer implementation is a bit different.
The problem is with persisting state.In abstractcustomer class you need to have get method and from this method to return the clone of the object to be able to pass the test.
public class Customer {
protected String id;
protected String name;
protected int bonusPoints;
public Customer(String id, String name, int bonusPoints) {
this.id = id;
this.name = name;
this.bonusPoints = bonusPoints;
}
public void collectBonusPointsFrom(Order order) {
....
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public Integer getBonusPoints() {
return bonusPoints;
}
public Customer get(){
//if you don`t return new object you will work directly with the one from repo
return new Customer(id,name,bonusPoints);
}
}
The full code you can find -> https://drive.google.com/file/d/1FOeF68RO-qI4CO9mJ92rKlQ8MNigWbof/view?usp=sharing
I try to copy an object by reflection. I haven't difficulties with copy primitive types, but i dont understand how copy reference types.
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Set;
public class ReflMethod {
private static final Set<Class<?>> WRAPPER_TYPES = getWrapperTypes();
public Object CopyObject(Object object) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Class clazz = object.getClass();
Field[] fields = clazz.getDeclaredFields();
Object instance = object.getClass().newInstance();
for(Field field : fields) {
field.setAccessible(true);
Class newClass = Class.forName(field.get(object).getClass().getName());
if(isWrapperType(newClass)) {
field.set(instance, field.get(object));
}
else if(!isWrapperType(newClass)) {
//WEIRDNESS HERE
field.set(instance, CopyObject(field.get(object).getClass().getName()));
//WEIRDNESS HERE
}
}
return instance;
}
public static boolean isWrapperType(Class<?> clazz)
{
return WRAPPER_TYPES.contains(clazz);
}
public static Set<Class<?>> getWrapperTypes()
{
Set<Class<?>> ret = new HashSet<Class<?>>();
ret.add(Boolean.class);
ret.add(Character.class);
ret.add(Byte.class);
ret.add(Short.class);
ret.add(Integer.class);
ret.add(Long.class);
ret.add(Float.class);
ret.add(Double.class);
ret.add(Void.class);
return ret;
}
}
I want using recursion for copying reference types...Where do I think wrong?
public class Cat {
private Phone phone;
private int age;
public Cat() {
}
public Cat(int age, Phone phone) {
this.age = age;
this.phone = phone;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Phone getPhone() {
return phone;
}
public void setPhone(Phone phone) {
this.phone = phone;
}
}
public class Phone {
private String name;
public Phone() {
}
public Phone(String name) {
this.name = name;
}
public void SetName(String name) {
this.name = name;
}
public String GetName() {
return name;
}
}
And main class:
public class MainClass {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException {
ReflMethod reflMethod = new ReflMethod();
Phone phone1 = new Phone("IPhone");
Cat cat1 = new Cat(20, phone1);
Cat cat2 = (Cat)reflMethod.CopyObject(cat1);
System.out.println("cat1 : " + cat1.getAge() + " " + cat1.getPhone().GetName());
System.out.println("cat2 : " + cat2.getAge() + " " + cat2.getPhone().GetName());
cat1.setAge(100);
Phone phone = new Phone("Af");
cat1.setPhone(phone);
System.out.println("cat1 : " + cat1.getAge() + " " + cat1.getPhone().GetName());
System.out.println("cat2 : " + cat2.getAge() + " " + cat2.getPhone().GetName());
}
}
The code doesn't work because of the code marked as WEIRDNESS HERE.
The answer was found in the depths of Stackoverflow :D
But it doesn't work with collections :(
ReflMethod:
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class ReflMethod {
public static Object CopyObject(Object object)
{
try
{
Object clone = object.getClass().newInstance();
for(Field field : object.getClass().getDeclaredFields()) {
field.setAccessible(true);
if(field.get(object) == null || Modifier.isFinal(field.getModifiers()))
{
continue;
}
if(field.getType().isPrimitive()
|| field.getType().equals(String.class)
|| field.getType().getSuperclass().equals(Number.class)
|| field.getType().equals(Boolean.class))
{
field.set(clone, field.get(object));
}
else {
Object childObj = field.get(object);
if(childObj == object) {
field.set(clone,clone);
}
else {
field.set(clone,CopyObject(field.get(object)));
}
}
}
return clone;
}
catch (Exception e) {
return null;
}
}
}
I am calling a sonar webservice and getting below output in json format.
[
{
"id":10252,
"uuid":"ca49aeed-de29-41a1-b0e2-e2b7c7d1b6c5",
"key":"UTILITY",
"name":"UTILITY",
"scope":"PRJ",
"qualifier":"VW",
"date":"2012-05-02T05:07:04-0400",
"creationDate":"2009-03-12T09:03:35-0400",
"lname":"UTILITY",
"msr":[
{
"key":"ncloc",
"val":253603.0,
"frmt_val":"253,603"
},
{
"key":"test_success_density",
"val":85.5,
"frmt_val":"85.5%"
},
{
"key":"coverage",
"val":96.0,
"frmt_val":"96.0%"
}
]
}
]
Now I want to parse this output in java and fetch values of date, ncloc, test_success_density and coverage. How can I do it? I tried many java apis but having trouble while fetching values of above field.
Do likewise,
NOTE : include proper Jackson Jar(i used jackson-core-2.2.3.jar)
Your Main Class's Main Method Should be.....
public static void main(String[] args) {
ObjectMapper mapper = new ObjectMapper();
String jsonInString = "[ {\"id\":10252, \"uuid\":\"ca49aeed-de29-41a1-b0e2-e2b7c7d1b6c5\", \"key\":\"UTILITY\", \"name\":\"UTILITY\", \"scope\":\"PRJ\", \"qualifier\":\"VW\", \"date\":\"2012-05-02T05:07:04-0400\", \"creationDate\":\"2009-03-12T09:03:35-0400\", \"lname\":\"UTILITY\", \"msr\":[ {\"key\":\"ncloc\",\"val\":253603.0,\"frmt_val\":\"253,603\"}, {\"key\":\"test_success_density\",\"val\":85.5,\"frmt_val\":\"85.5%\"}, {\"key\":\"coverage\",\"val\":96.0,\"frmt_val\":\"96.0%\"} ] } ]";
//JSON from String to Object
try {
Bean[] objs = mapper.readValue(jsonInString, Bean[].class);
for(Bean b : objs){
//System.out.println(b); here you have Bean Object's Array and you can do whatever you want...
}
} catch (JsonParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JsonMappingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
And let's say Your Bean.java will be,
import java.util.Date;
import java.util.List;
public class Bean {
private long id;
private String uuid;
private String key;
private String name;
private String scope;
private String qualifier;
private Date date;
private Date creationDate;
private String lname;
private List<Msr> msr;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public String getQualifier() {
return qualifier;
}
public void setQualifier(String qualifier) {
this.qualifier = qualifier;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
public String getLname() {
return lname;
}
public void setLname(String lname) {
this.lname = lname;
}
public List<Msr> getMsr() {
return msr;
}
public void setMsr(List<Msr> msr) {
this.msr = msr;
}
#Override
public String toString() {
return this.id + " : " +
this.uuid + " : " +
this.key + " : " +
this.name + " : " +
this.scope + " : " +
this.qualifier + " : " +
this.date + " : " +
this.creationDate + " : " +
this.lname + " : " +
this.msr ;
}
}
class Msr{
private String key;
private String val;
private String frmt_val;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getVal() {
return val;
}
public void setVal(String val) {
this.val = val;
}
public String getFrmt_val() {
return frmt_val;
}
public void setFrmt_val(String frmt_val) {
this.frmt_val = frmt_val;
}
#Override
public String toString() {
return this.key + " : " + this.val + " : " + this.frmt_val;
}
}
Do the above thing, works perfectly...!!
I have some classes in my project and when I want to instantiate object from them using myClass.newInstance() to build SQL queries, it just creates the object with one field and I can't retrieve all class fields to complete my query. When I get size of my object it returns '1' instead of '3'.
Any idea what should I do?
Here-under you can find one class and my query builder.
#JupiterEntity
#TableName(name="tbl_person")
public class Person {
#PrimaryKey
#DbColumn(name = "clmn_id")
private int id;
#DbColumn(name="clmn_name", length = 1024)
private String name;
#DbColumn(name="clmn_family", length = 1024)
private String family;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFamily() {
return family;
}
public void setFamily(String family) {
this.family = family;
}
}
And here is when I want to instantiat an object from my class:
public MySQLEntityManager() {
StringBuilder stringBuilder = new StringBuilder();
if(ServiceLocator.getConfiguration().createDDL()) {
for(Class entityClass : ServiceLocator.getConfiguration().getEntities()) {
Object obj = new Object();
try {
obj = entityClass.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
stringBuilder.append("DROP TABLE ")
.append("'")
.append(ServiceLocator.getConfiguration().getDatabaseName())
.append("'.'")
.append(getTableName(obj)).append("' ");
System.out.println(stringBuilder.toString());
stringBuilder.setLength(0);
stringBuilder.append("CREATE TABLE")
.append("'")
.append(ServiceLocator.getConfiguration().getDatabaseName())
.append("'.'")
.append(getTableName(obj)).append("' ");
Map<Field, Object> fields = ReflectionHelper.getValuesOfFields(obj);
for(Field field : fields.keySet()) {
System.out.println(field.getName() + " -> " + fields.get(field));
}
String delimiter = "";
for (Field field : fields.keySet()) {
String columnName = field.getName();
if (field.isAnnotationPresent(DbColumn.class)) {
DbColumn dbColumn = field.getAnnotation(DbColumn.class);
columnName = dbColumn.name();
}
stringBuilder.append(delimiter).append(columnName);
delimiter = ", ";
}
System.out.println("*****" + stringBuilder.toString());
delimiter = "";
System.out.println(stringBuilder.toString());
}
}
}
So the problem is that ReflectionHelper.getValuesOfFields(obj) isn't returning what you want. You can debug that, or use obj.getClass().getDeclaredFields() instead of some NIH junk.
Im quite new to Rhino and trying to convert a javascript object to a java object but unable to do so. It doesnt seem to evaluate properly.
The javascript that I have is,
var myObject = new Object();
myObject.string1 = 'Hello';
myObject.string2 = 'World';
myObject.id = 1;
var parser = new Packages.com.MyParser();
var returnStr = parser.PrintObj(myObject);
And I have the following java class that I want to evaluate this to,
public class Person extends ScriptableObject {
private int id;
private String string1;
private String string2;
public Person() {}
public void jsConstructor() {
this.string1 = "";
this.string2 = "";
this.id = 0;
}
public int getID()
{
return this.id;
}
public void jsSet_id(int value)
{
this.id = value;
}
public int jsGet_id()
{
return this.id;
}
public String jsGet_string1()
{
return this.string1;
}
public void jsSet_string1(String value)
{
this.string1 = value;
}
public String jsGet_string2() {
return this.string2;
}
public void jsSet_string2(String value)
{
this.string2 = value;
}
#Override
public String toString() {
return id + " " + string1 + " " + string2;
}
#Override
public String getClassName() {
return "Person";
}
And the skeleton of my parser is,
public class MyParser {
public String PrintObj(ScriptableObject obj) {
// Need to convert to Person object here
// Obviously casting doesnt work here
return null;
}
}
Thanks
OK figured it out !
First of all i needed to define the class in javascript as. It was complaining at first it couldn't find the class without the namespace "com". Had to add that...
defineClass("com.Person")
var myObject = new Person();
myObject.string1 = 'Hello';
myObject.string2 = 'World';
myObject.id = 1;
var parser = new Packages.com.MyParser();
var returnStr = parser.PrintObj(myObject);
And then in the parser I added the following,
public String PrintObj(ScriptableObject obj) {
try {
Person pObj = (Person)Context.jsToJava(obj, Person.class);
System.out.println("Printing person: " + pObj);
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}