How to accept Class return in reflection? - java

take the following as an example:
public class Person {
private String name;
private Achievements achievements;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Achievements getAchievments() {
return achievements;
}
}
and the achievements class:
public class Achievements {
public int amount() {
...
}
}
if i would be using the class regularly, i would go like :
Person p = new Person("John");
p.getAchievements().amount();
however, if i want to use the reflection API, how would i go about reaching to the amount(); step?
i know how to reach to the getAchievements();
however i'm blocked from the rest.
thanks

If I correctly understand you might need something like this:
Person obj = new Person("qew");
Method methodGetAchievements = obj.getClass().getMethod("getAchievments");
Object achievements = methodGetAchievements.invoke(obj);
Method methodAmount = achievements.getClass().getMethod("amount");
int amount = (int) methodAmount.invoke(achievements);

Related

How to invoke method on a specific definition of a class using reflection?

I am trying to pull a field via reflection that is an array of the below class.
package com.api.Person
public class Person {
private String name;
private int age;
public Person() {
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.client.Client
public class Client{
...
People[] peoples;
...
}
I know how to get the field I am looking for and declare my methods. So below, obj would be my People[] and methodgetAge and methodsetAge are two methods I have defined that act on a Person class. How do I take my obj and loop through it to get individual People and call methodgetAge on each person?
Class<?> mainClass = cl.loadClass("com.client.Client");
Class<?> peopleClass = cl.loadClass("com.api.Person");
Field allPersons = mainClass.getDeclaredField("peoples");
allPersons.setAccessible(true);
Object obj = allPersons.get(mainClass);
Method methodgetAge = peopleClass .getDeclaredMethod("getAge");
Method methodsetAge = peopleClass .getDeclaredMethod("setAge", int.class);

Java - Multiple constructors using same data type

How can we create constructor, to set different values that are from same data type?
Its impossible two create two identical constructors:
public User(int age, String name){
}
public User(int age, String surname){
}
User user1 = new User(33, Jack);
User user2 = new User(33, Sparrow);
Since both name and surname are from same data type, its impossible to know which value the user has meant to set.
We can create a constructor that has all the properties and then pass null for unset arguments.
public User(int age, String name, String surname){
}
User user1 = new User(33, Jack);
User user2 = new User(33, null, Sparrow);
There is a way to make it, using HashMap imitating the javascript object literal.
package javaapplication;
import java.awt.Color;
import java.util.HashMap;
public class JavaApplication {
public static class User {
public int age;
public String name;
public String surname;
public Color hairColor;
public User(HashMap<String, Object> arguments) {
if (arguments.containsKey("hairColor")) {
this.hairColor = (Color) arguments.get("hairColor");
}
if (arguments.containsKey("name")) {
this.name = (String) arguments.get("name");
}
if (arguments.containsKey("surname")) {
this.surname = (String) arguments.get("surname");
}
if (arguments.containsKey("age")) {
this.age = (int) arguments.get("age");
}
}
}
public static void main(String[] args) {
User jack1 = new User(new HashMap<String, Object>() {
{
put("hairColor", Color.RED);
put("name", "Jack");
put("age", 33);
}
});
System.out.println(jack1.hairColor); // java.awt.Color[r=255,g=0,b=0]
System.out.println(jack1.surname); // null
System.out.println(jack1.name); // Jack
System.out.println(jack1.age); // 33
User jack2 = new User(new HashMap<String, Object>() {
{
put("hairColor", Color.RED);
put("surname", "Sparrow");
put("age", 33);
}
});
System.out.println(jack2.hairColor); // java.awt.Color[r=255,g=0,b=0]
System.out.println(jack2.surname); // Sparrow
System.out.println(jack2.name); // null
System.out.println(jack2.age); // 33
}
}
Is there a more elegant way to do it?
The typical ways of doing this are with static creation methods or a builder object.
Static creation methods are the way to go if there are distinctive patterns of usage. For your example (where this perhaps isn't the case).
public static User ageName(int age, String name) {
...
}
public static User ageSurname(int age, String surname) {
...
}
...
In general it's a good idea to avoid any overloading. With constructors Java rather forces you into it, but sometimes you have to break free.
Builder may go something like:
public class UserBuilder { // This could be made a nested class of User
private int age = -1;
private String name;
private String surname;
private Color hairColor;
public UserBuilder age(int age) {
this.age = age;
return this;
}
// ... other properties ...
public User build() {
// Or return new User(this)
return new User(age, name, surname, hairColor);
}
}
This uses the typical Java dirty hack of returning this in a builder so you can build a train wreck.
User user1 = new UserBuilder().age(33).name("Jack").build();
You really need real examples of usage to see how it should fit in.
You are over-complicating things by using a HashMap here. Instead you could make use of the Builder Pattern for the same.
class User {
// required parameters
private int age;
// optional parameters
private String name;
private String surname;
public int getAge() {
return age;
}
public String getName() {
return name;
}
public String getSurname() {
return surname;
}
private User(UserBuilder userBuilder) {
this.age = userBuilder.age;
this.name = userBuilder.name;
this.surname = userBuilder.surname;
}
public static class UserBuilder {
// required parameters
private int age;
// optional parameters
private String name;
private String surname;
public UserBuilder setName(String name) {
this.name = name;
return this;
}
public UserBuilder setSurname(String surname) {
this.surname = surname;
return this;
}
public UserBuilder(int age) {
this.age = age;
}
public User build() {
return new User(this);
}
}
}
Now you can use it :
User user1 = new User.UserBuilder(12).setName("Jack").build();
User user2 = new User.UserBuilder(12).setSurname("Sparrow").build();
This assumes that age is a mandatory field, name and surname are optional fields for creating an object of User. You can tweak it as per your requirement accordingly.

Calling an object arraylist from another class and iteration through it

I have a problem accessing the arraylist I created in a class. I tried going through the answers of questions similar to mine but unfortunately I was unable to solve the problem.
So I have two classes Student and Person and I want to iterate through the arraylist of Person in the class Student. (The code doesn't really make sense, I know. I just want to understand).
I tried two approaches :
1) creating a variable of type Person in Student class and calling the get method from person class.
2) creating a get method in the class person that returns arraylist.
Both are not working properly when i tried to call the isHere method in the main method.(false was printed instead of true)
I think my two approaches intialise a new array of type Person and not call the arraylist to which elements are already added. How can solve this?
import java.util.ArrayList;
public class Student {
private Person p;
private String name;
private int age;
private String address;
public Student() {
}
public Student(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
public boolean isHere(String name) {
p = new Person();
// I also tried for(Person per : p.getList)
for (Person per : this.getL()) {
if (per.getName().equals(name)) {
System.out.println("hi");
return true;
}
}
return false;
}
public ArrayList<Person> getL() {
return p.getList();
}
public Person getP() {
return p;
}
public void setP(Person p) {
this.p = p;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
The Person class:
import java.util.ArrayList;
public class Person {
private String name;
private ArrayList<Person> list = new ArrayList<Person>();
Person() {
}
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ArrayList<Person> getList() {
return list;
}
public void setList(ArrayList<Person> list) {
this.list = list;
}
public void add(String name) {
list.add(new Person(name));
}
}
The statement p = new Person() in your isHere(..) method is creating a new Person object. When that Person object is created, the name in object p will be null and the list will be empty. So the for loop is never executed as the list is empty and hence it returns false.
If you ever want your code to run, you should not create the Person object and then immediately iterate through it because it will have nothing. You have to either add something to it or use a Person object which you believe will be populated before you run the isHere(..) method

Using Object class Reference variable, accessing different class members.

I am trying to access class members of different class i.e.,getDetails() from student as well as customer class using Object class Reference variable. But it looks like its not working. Please look into this easy code and help me out how to access the getDetails() using Object class ob[0] and ob[1]
class Customer
{
int custId;
String name;
Customer(String name, int custId)
{
this.custId = custId;
this.name = name;
}
public void getDetails()
{
System.out.println(this.custId+" : "+this.name);
}
}
class Student
{
int roll;
String name;
Student(String name, int roll)
{
this.name = name;
this.roll = roll;
}
public void getDetails()
{
System.out.println(this.roll+" : "+this.name);
}
public static void main(String []args)
{
Object[] ob = new Object[2];
ob[0] = new Student("Vishal", 041);
ob[1] = new Customer("Xyz" , 061);
ob[0].getDetails();
ob[1].getDetails();
}
}
Try creating a common interface that declares the method getDetails. Something like this:
public interface Person {
public void getDetails();
}
Let Student and Customer implement the interface. Then declare the array like this:
Person ent[] ob = new Person[2];
....

How to set / get a name to "ford" - instance of class Car I have created in main method of class Vehicle?

As you can see I am stuck in part where I should set a name an owner of ford... Thanks for help.
public class Vehicle {
Person owner;
long motorSerialNo;
String registerNo;
public static void main(String[] args) {
//an example, create an object instance of class Car
Car ford = new Car();
ford.model = "Focus";
ford.motorSerialNo = 123456;
ford.registerNo = "CA-126-65";
//and here is a problem
ford.owner.setName("John Croul");
}
}
class Car extends Vehicle {
String model;
}
class Person {
public Person(String name){
this.name = name;
}
String name;
String lastname;
String address;
String getName() {
return name;
}
void setName() {
this.name = name;
}
}
Firstly, your setter should look like
public void setName(String name) {
this.name = name;
}
Then you have to initialize the instance variable person before calling its method setName(), otherwise you will get the NullPoiterException.
Person owner = new Person();
or in the main method, as you did for other variables
ford.owner = new Person();

Categories

Resources