I have several pojos whose instance variables need to be converted to Object arrays. I am trying to find a way that this can be handled dynamically instead of adding a toObjectArray() method in each pojo.
Here is a sample class with the toObjectArray() method that I would like to get rid of:
public class Contact {
private String lastName;
private String firstName;
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public Object[] toObjectArray() {
return new Object[] {
this.getLastName(),
this.getFirstName(),
};
}
}
The instance variables do not have to be returned in order. I have a custom annotation which allows me to reflect proper order for the object array. I'm simply wondering if it is possible to dynamically iterate the instance variables and values of an object in order to create an object array.
Something like this...
public static Object[] toObjectArray(Object obj) {
/// cast Object to ?
/// iterate instance variables of Contact
/// create and return Object[]
}
public static void main(String[] args) {
Contact contact = new Contact();
contact.setLastName("Garcia");
contact.setFirstName("Jerry");
Object[] obj = toObjectArray(contact);
}
Any help would be greatly appreciated. Please let me know if I need to be more clear.
Thank you!
One possible way could be using reflection.
static <T> Object[] getFieldValues(final Class<T> type, final T instance) {
final Field[] fields = type.getDeclaredFields(); // includes private fields
final Object[] values = new Object[fields.length];
for (int i = 0; i < fields.length; i++) {
if (!fields[i].isAccessible()) {
fields[i].setAccessible(true); // enables private field accessing.
}
try {
values[i] = fields[i].get(instance);
} catch (IllegalAccessException iae) {
// ##?
}
}
return values;
}
//Creating dyanamic class object[dynamic array] size for Object.
//Defining Testclass for creatring menu buttons
public class TestClass extends AbstractAction{
boolean literal;
public TestClass(String literal) {
super(literal);
}
public void actionPerformed(ActionEvent e) {
}
}
ArrayList<TestClass> ObjectArray= new ArrayList<TestClass>();
//Here ObjectArray is defined as dynamic array class object.
//Insert new Class objects to the ObjectArray
ObjectArray.add( new TestClass("Button1")) ;
ObjectArray.add( new TestClass("Button2")) ;
ObjectArray.add( new TestClass("Button3")) ;
//Converting ArrayList object to ClassObject array
TestClass testclassObject[]=ObjectArray.toArray(new [ObjectArray.size()])
//Using of Class object array
for (TestClass subAction : testclassObject) {
if(subAction != null){
JButton subButton = new JButton ((String)subAction.getValue(Action.NAME), null);
subButton.addActionListener(subAction);
//Adding buttons to JPanel
JPanel buttonpanel= new JPanel();
buttonpanel.add(subButton);
}
}
Related
As the tittle says i want to save each new created object of Person's name in a list:
This is my code so far
package javaapplication4;
import java.util.*;
public class Person {
private String namePerson;
static List personList = new ArrayList();
{
personList.add(getPersonName());
}
public Person(String namePerson){
this.namePerson = namePerson;
}
public void setPersonName(String namePerson){
this.namePerson = namePerson;
}
public String getPersonName(){
return namePerson;
}
public void setPersonList(List personList){
this.personList= personList;
}
public static List getPersonList(){
return personList;
}
each time i am creating a person object its gets added as a 'null' spot in the list (when i use println).
how i change that to the name of the new object Person
like
Person Guy = new Person("NameOfGuy"); then list must be [NameOfGuy].
{
personList.add(getPersonName());
}
The above is called an instance initializer. It is executed before the constructor is executed. At that time, getPersonName will return null as you haven't yet set the value of namePerson.
Move that inside the constructor
public Person(String namePerson){
this.namePerson = namePerson;
this.personList.add(namePerson);
}
Sidenote: It is a bad practice to use raw types. You are using a raw List. It must be as
List<String> personList = new ArrayList<>();
What is a raw type and why shouldn't we use it?
As pointed out by #user7, you are adding the name into the list at the wrong place. What you should be doing is, adding person's name into list while you are creating person's object, i.e. inside your constructor. Replace your constructor with this :
public Person(String namePerson){
this.namePerson = namePerson;
personList.add(namePerson);
}
You can do the job Doing below changes to the Person class:
import java.util.*;
public class Person {
private String namePerson;
static List<String> personList = new ArrayList<>();
public Person(String namePerson) {
this.namePerson = namePerson;
personList.add(this.namePerson);
}
public void setPersonName(String namePerson) {
this.namePerson = namePerson;
}
public String getPersonName() {
return namePerson;
}
public void setPersonList(List personList) {
this.personList = personList;
}
public static List getPersonList() {
return personList;
}
}
I would like to make a generic method to get a List from the parameter object.
The problem is because I have a declared object with a instance of the other class that extends the declared class.
I don't want to use the instanceof solution because the number of classes that extends LimitedValue can be big.
I thought to use reflection for a solution, but I don't know how to use that with an instance of object, in this part of the code:
Class cls = Class.forName(limitedValue.getClass().getName());
Object obj = cls.newInstance();
//This is wrong, I don't want a new instance.
Method[] methods = cls.getDeclaredMethods();
for(int x= 0; x < methods.length; x++) {
Method method = methods[x];
if ("java.util.List".equals(method.getReturnType().getName())) {
//How to get the value of this method from limitedValue instance ?
}
}
This is my full code:
public class CalculatorLimitedValue {
public static void main(String[] args) throws Exception {
StoreItem storeItem = new StoreItem(1L, "Name of StoreItem", 50L);
List listOfStoreItems = new ArrayList();
listOfStoreItems.add(storeItem);
LimitedValue limitedValue0 = new Store(listOfStoreItems);
List firstList = calculator(limitedValue0);
//do something with the list
SupermarketItem supermarketItem = new SupermarketItem(1L, "Name of SupermarketItem", 21L);
List listOfSupermarketItems = new ArrayList();
listOfSupermarketItems.add(supermarketItem);
LimitedValue limitedValue1 = new Supermarket(listOfSupermarketItems);
List secondList = calculator(limitedValue1);
//do something with the list
}
/** This is the method that I'd like to make generic to return a List */
private static List calculator(LimitedValue limitedValue) throws Exception{
Class cls = Class.forName(limitedValue.getClass().getName());
Object obj = cls.newInstance();
//This is wrong, I don't want a new instance.
Method[] methods = cls.getDeclaredMethods();
for(int x= 0; x < methods.length; x++) {
Method method = methods[x];
if ("java.util.List".equals(method.getReturnType().getName())) {
//How to get the value of this method from limitedValue instance ?
}
}
/* I don't want to use this one way, because my classes that extends LimitedValue
can be big. I would like to made a generic way to get de list of classes. */
if (limitedValue instanceof Store) {
System.out.println("This is a store");
return ((Store) limitedValue).getStoreItems();
} else if (limitedValue instanceof Supermarket) {
System.out.println("This is a supermarket");
return ((Supermarket) limitedValue).getSupermarketItems();
}
return null;
}
}
If it help, these are my other classes:
LimitedValue.class
public class LimitedValue { }
StoreItem.class
public class StoreItem {
private Long id;
private String nameOfStoreItem;
private Long valueOfStoreItem;
public StoreItem(Long id, String nameOfStoreItem, Long valueOfStoreItem){
this.id = id;
this.nameOfStoreItem = nameOfStoreItem;
this.valueOfStoreItem = valueOfStoreItem;
}
//getters and setters...
}
SupermarketItem.class
public class SupermarketItem {
private Long id;
private String nameOfSupermarketItem;
private Long valueOfSupermarketItem;
public SupermarketItem() {
}
public SupermarketItem(Long id, String nameOfSupermarketItem, Long valueOfSupermarketItem) {
this.id = id;
this.nameOfSupermarketItem = nameOfSupermarketItem;
this.valueOfSupermarketItem = valueOfSupermarketItem;
}
//getters and setters...
}
Store.class
public class Store extends LimitedValue {
private List<StoreItem> storeItems;
public Store(List<StoreItem> storeItems) {
this.storeItems = storeItems;
}
//getters and setters
}
Supermarket.class
public class Supermarket extends LimitedValue {
private List<SupermarketItem> supermarketItems;
public Supermarket(List<SupermarketItem> supermarketItems) {
this.supermarketItems = supermarketItems;
}
//getters and setters
}
You could try to use reflection here to try to achieve what you want, but it would be better to reconsider your overall design and try to use a better object oriented design that solves the problem at hand.
In particular, lets say we consider adding a method called getItems to the LimitedValue class that returns a List of items, which may be SupermarketItems or may be StoreItems. If it is structured correctly, you won't need to know the actual type because the code will be abstracted over it polymorphically.
public abstract class LimitedValue {
List<? extends Item> getItems();
}
We've now defined a new method on LimitedValue, but we also have to consider that we've introduced this new Item thing. I note that the SupermarketItem and StoreItem all share similiar attributes, name, id and value, so it seems that it might be possible to use a single class to represent them all.
public abstract class Item {
final Long id;
final String name;
final Long value;
public Item(final Long id, final Long name, final Long value) {
this.id = id;
this.name = name;
this.value = value;
}
String getName() {
return name;
}
// other getters and setters
}
public class SupermarketItem extends Item {
public SupermarketItem(final Long id, final Long name, final Long value) {
super(id, name, value);
}
}
public class StoreItem extends Item {
public StoreItem(final Long id, final Long name, final Long value) {
super(id, name, value);
}
}
Now we've completely abstracted away the need for any reflection when accessing these objects - you can simply call item.getValue() as you will know that every item in the list is of type Item.
Of course, you'll also need to refactor the Store and SuperMarket classes, for example:
public class Supermarket extends LimitedValue {
private List<SupermarketItem> supermarketItems;
public Supermarket(List<SupermarketItem> supermarketItems) {
this.supermarketItems = supermarketItems;
}
public List<? extends Item> getItems() {
return supermarketItems;
}
}
and because you are only returning a List<Item> you always know what is in it, and you can change your main code to work with this.
This is a much cleaner long term solution.
To get the List value, use Method#invoke:
List list = method.invoke(limitedValue);
You don't need Object obj = cls.newInstance(); - you're not using it at all in the method.
In any case, you're making it very difficult for yourself. You could also define an interface
public interface HasList<E> {
List<E> getList();
}
and have all classes implement this.
I have an example class below and I want to return all class fields of certain type, in this example of type Image.
public class Contact {
private String surname, lastname, address;
private int age, floor;
private Image contactPhoto, companyPhoto;
private boolean isEmployed;
public String[] getAllImages() {
String images[] = // missing code
return images;
// in this case, I want to return {"contactPhoto","companyPhoto"}
}
}
I need a help here. How can I find all class fields of certain type. I will be calling this method in another class ofc.
Use reflection to access the fields declared on the class. Then iterate through the fields and check to see if their type matches Image.
You could also create a more useful method by accepting two parameters a target Class and a searchType Class. The method would then searches for fields with the target of the type searchType.
I would also recommend making this method static, since it really doesn't depend on any of the classes state.
Example
public class Contact {
private String surname, lastname, address;
private int age, floor;
private Image contactPhoto, companyPhoto;
private boolean isEmployed;
public static String[] getFieldsOfType(Class<?> target, Class<?> searchType) {
Field[] fields = target.getDeclaredFields();
List<String> results = new LinkedList<String>();
for(Field f:fields){
if(f.getType().equals(searchType)){
results.add(f.getName());
}
}
return results.toArray(new String[results.size()]);
}
public static String[] getAllImages(){
return getFieldsOfType(Contact.class, Image.class);
}
public static void main(String[] args) {
String[] fieldNames = getAllImages();
for(String name:fieldNames){
System.out.println(name);
}
}
}
A simpler alternative to using reflection would be to use a map as the primary data type for the field you are interested in:
public class Contact {
private static final String CONTACT_PHOTO = "contactPhoto";
private static final String COMPANY_PHOTO = "companyPhoto";
private String surname, lastname, address;
private int age, floor;
private HashMap<String, Image> images;
private boolean isEmployed;
public Contact() {
images = new HashMap<String, Image>();
images.put(CONTACT_PHOTO, null);
images.put(COMPANY_PHOTO, null);
}
public String[] getAllImages() {
Set<String> imageNames = images.keySet();
return imageNames.toArray(new String[imageNames.size()]);
}
public void setContactPhoto(Image img) {
images.put(CONTACT_PHOTO, img);
}
public Image getContactPhoto() {
return images.get(CONTACT_PHOTO);
}
public void setCompanyPhoto(Image img) {
images.put(COMPANY_PHOTO, img);
}
public Image getCompanyPhoto() {
return images.get(COMPANY_PHOTO);
}
}
Using field names as values can cause headaches.
If you need to identify individual images with strings, you could create a HashMap.
Use your current field names as keys and Image objects as values.
https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html
You can retrieve all key values (in your case,the names) via the method keySet()
Edit: Here's a working example class, derived from yours, but only with the relevant fields:
import java.awt.Image;
import java.util.HashMap;
import java.util.Set;
public class Contact
{
private HashMap<String, Image> images;
public Contact ()
{
images = new HashMap<String, Image>();
images.put( "contactPhoto", null);
images.put( "companyPhoto", null);
}
public Set<String> getAllImages()
{
return images.keySet();
}
public static void main(String[] args)
{
System.out.println(new Contact().getAllImages());
}
}
use:
Field[] fields=this.getClass().getFields();
...
for (...){
if ( fields[i].getType() == ?? ){
...
}
}
I want do declare a Subclass of an HTMLPanel.
In its constructor I want to give it a few paramters to construct the containing html.
Because I have to call the super-constructor as first statement, I have to change the html later in the constructor.
How can I do this?
public class MyHTMLPanel extends HTMLPanel
{
public MyHTMLPanel(String id, int anotherParameter)
{ super("");
String html=""
// ... some code th construct the html
//??? this.setHtml(html);
}
}
You can find below an example I used and worked well for me.
I don't remember why I don't sub-class HTMLPanel, whether a good reason or not.
You will notice a mechanism to randomize the html ids in case you include several objects of the same type in a single page.
public abstract class HtmlPanelBase extends Composite
{
private String _dynPostfix = "";
protected final String id(final String staticId) { return staticId + _dynPostfix; }
private final String wrapId(final String id) { return "id=\"" + id + "\""; }
private final String wrapDynId(final String refId) { return wrapId(id(refId)); }
private String _htmlAsText = null;
public String getHtmlAsText() { return _htmlAsText; }
abstract protected String htmlPanelBundleHtmlText();
abstract protected List<String> idList();
protected HTMLPanel _holder = null;
private HTMLPanel createHtmlPanel(final boolean defineGloballyUniqueIds)
{
// Referent HTML panel text containing the reference id's.
_htmlAsText = htmlPanelBundleHtmlText();
if (defineGloballyUniqueIds)
{
// List of id's in the HTML Panel reference page to replace with dynamic/unique id's.
final List<String> refIdList = idList();
// Replace the reference id's with dynamic/unique id's.
for (String refId : refIdList)
_htmlAsText = _htmlAsText.replace(wrapId(refId), wrapDynId(refId));
}
// Return the HTMLPanel containing the globally unique id's.
return new HTMLPanel(_htmlAsText);
}
public HtmlPanelBase(final boolean defineGloballyUniqueIds)
{
setup(defineGloballyUniqueIds);
initWidget(_holder);
}
private void setup(final boolean defineGloballyUniqueIds)
{
if (defineGloballyUniqueIds)
_dynPostfix = "_" + UUID.uuid().replace("-", "_");
_holder = createHtmlPanel(defineGloballyUniqueIds);
}
}
And now how you could sub-class from the above base:
public class HtmlPanelTemplate extends HtmlPanelBase
{
private final static boolean _defineGloballyUniqueIds = false;
private final static int _numIdCapacity = 40;
public HtmlPanelTemplate()
{
super(_defineGloballyUniqueIds);
setup();
}
#Override
protected String htmlPanelBundleHtmlText()
{
return YourClientBundle.INSTANCE.getYourFileHtml().getText();
}
#Override
protected List<String> idList()
{
final List<String> idList = new ArrayList<String>(_numIdCapacity);
return idList;
}
private void setup()
{
}
}
You don't need to subclass HTMLPanel. You can create a simple Composite widget:
public class myPanel extends Composite {
private HTMLPanel panel = new HTMLPanel();
public myPanel(String id, int anotherParameter) {
// set HTML to panel based on your parameters
initWidget(panel);
}
}
htmlPanel.getElement().setInnerHTML(...)
Don't know whether this works in derived class' constructor. But setting up a class for specific content text isn't really a good solution.
I have a class called Flight
The Flight class when instantiated, instantiates another class called SeatingChart, and SeatingChart also instantiates another class and so on and so forth.
public class Flight implements Serializable
{
SeatingChart sc = new SeatingChart(); seating
//WaitingList wl = new WaitingList();
}
public class SeatingChart extends ListAndChart implements PassengerList, Serializable
{
public static final int NOT_FOUND = 42;
Passenger [] pass = new Passenger[40];
}
public class Passenger implements Serializable
{
private String firstName, lastName, fullName;
public String getName()
{
fullName = firstName + " " + lastName;
return fullName;
}
public void setFirstName(String firstName)
{
this.firstName = firstName;
}
public void setLastName(String lastName)
{
this.lastName = lastName;
}
}
I have another method in another class that deserializes the object saved in the disk
public void actionPerformed(ActionEvent evt)
{
Serialization.deserialize(sw101); <--- sw101 is a Flight object
.
.
.
}
//code for deserialization
public static void deserialize(Flight sw101)
{
String filename = "serialized.ser";
sw101 = null;
FileInputStream fis = null;
ObjectInputStream in = null;
try
{
fis = new FileInputStream(filename);
in = new ObjectInputStream(fis);
sw101 = (Flight)in.readObject();
System.out.println("sw101" + sw101.toString());
in.close();
}
catch(IOException ex)
{
ex.printStackTrace();
}
catch(ClassNotFoundException ex)
{
ex.printStackTrace();
}
}
my question is when I assign sw101 the serialized object, everything sw101 instantiated in the beginning like the SeatingChart sc object also get whatever is saved in the file without me doing anything as long as those objects all implement the Serializable interface? If so why is my code not working? what am I doing wrong?
It looks like you're trying to return through a reference parameter (C/C++ background?)
That never works in Java. All parameters (including references) are passed by value. Once you do
sw101=null;
you lose the reference to the object that was passed in.
Your deserialize function should return the flight object instead.
(Technically there is a way to simulate returning through the arguments in Java by using an array, but it leads to unnecessarily complicated code)
In java, all parameters are passed as values.. so the answer to your last question is no. sw101 is a reference to a copy.
As said, you have to return your deserialized object to make it work.
check this article: parameter passing in java