简体   繁体   中英

Java casting an object passed to method to its original type

I have a list called itemsData of object of class EtcStruct, but the class can differ depending on the file i want to use (the class is full of variables setters and getters):

ObservableList<EtcStruct> itemsData =  FXCollections.observableArrayList();

Im passing it to the method thats supposed to work for any object type i choose and run invoked method from the file.

public static void parseToFile(ObservableList itemsData){
    EtcStruct itemObject = (EtcStruct) itemsData.get(0);
    System.out.print((int)reflectedmethod.invoke(itemObject);
}

Code above works , but what i want to achieve is make the method work without editing it's object type to make it more flexible for whatever structclass i plan to use.

I tried something with passing Struct Class name and .getClass() it returns the original type but i dont know what to do with it to make the new object of itemsData original type and cast the itemsData object.

public static void parseToFile(ObservableList itemsData,Class c){
    Object itemObject = c.newInstance();
    Object newobject = curClass.newInstance();
    newobject = c.cast(itemsList.get(0));
}

Above seemed dumb to me and obviously didnt work.

After reading your comment I understand better why one would use reflection in your case. A GUI builder/editor is an example where reflection is used to provide an interface to set/get the values of components. Still, IMHO, reflection isn't a tool you would design for when you own the classes and are the primary designer. If possible you should strive for something more like this:

interface Parsable {
    default int parse() {
        System.out.println("Here I do something basic");
        return 0;
    }
}

class BasicStruct implements Parsable { }

class EtcStruct implements Parsable {

    @Override
    public int parse() {
        System.out.println("Here I do something specific to an EtcStruct");
        return 1;
    }
}

// If some structs have a parent-child relationship
// you can alternatively `extend EtcStruct` for example.
class OtherStruct extends EtcStruct {

    @Override
    public int parse() {
        super.parse();
        System.out.println("Here I do something specific to an OtherStruct");
        return 2;
    }
}

void parseToFile(Parsable parsable) {
    System.out.println(parsable.parse());
}

// If you use a generic with a specific class you don't
// have to guess or care which kind it is!
void parseToFile(ObservableList<Parsable> parsables) {
    for (Parsable p : parsables) {
        parseToFile(p);
    }
}


public static void main(String[] args) {
    ObservableList<Parsable> parsables = FXCollections.observableArrayList();
    parsables.add(new BasicStruct());
    parsables.add(new EtcStruct());
    parsables.add(new OtherStruct());
    parseToFile(parsables);
}


Output:

Here I do something basic
0
Here I do something specific to an EtcStruct
1
Here I do something specific to an EtcStruct
Here I do something specific to an OtherStruct
2

Of course, this is just an example that needs to be altered to meet your needs.

But what I still don't get is if you're able to parse from a file why you can't parse to one. Nonetheless, I slapped some code together to show you how I might parse an object to a file, manually, when dealing with Object s only.

The idea is to satisfy a bean-like contract. That is, each structure should provide a parameter-less constructor, all fields you want managed by reflection will follow Java naming convention and will have both a public setter and getter.

Don't get caught up in the file writing; that will be determined by your needs. Just notice that by following this convention I can treat any Object as a parsable structure. A less refined version here for reference:

public void parseToFile(Object object) throws IOException, InvocationTargetException, IllegalAccessException {
    fos = new FileOutputStream("example" + object.getClass().getSimpleName());
    List<Method> getters = Arrays.stream(object.getClass().getMethods())
            .filter(method -> method.getName().startsWith("get") && !method.getName().endsWith("Class"))
            .collect(Collectors.toList());
    for (Method getter : getters) {
        String methodName = getter.getName();
        String key = String.valueOf(Character.toLowerCase(methodName.charAt(3))) +
                methodName.substring(4, methodName.length());
        fos.write((key + " : " + String.valueOf(getter.invoke(object)) + "\n").getBytes());
    }
    fos.close();
}

I think that you can just still use Generics to keep static objects typing. Try to parametrize your function parseToFile. Here is an example:

public static void parseToFile(ObservableList<EtcStruct> itemsData){
  EtcStruct itemObject = itemsData.get(0);
  System.out.print((int)reflectedmethod.invoke(itemObject);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM