JavaFX保存扩展类变量

JavaFX保存扩展类变量,javafx,Javafx,在我的evergrowing应用程序中,我有一个大约有50个变量的基类。还有10个从基类扩展而来的类。原因是这10个类有许多共同的变量,但也有一些是类本身独有的。现在我试图保存每个扩展类,所以我必须将基类变量与ClassX变量组合起来。这是一张照片: 在每个ClassX中,我都可以这样做: super.saveData(); saveLocalData(); 这意味着我只需要在基类中提供一个saveData,但实际上需要多次重复saveLocalData-10 在每个类中,我只需使用以下命令即

在我的evergrowing应用程序中,我有一个大约有50个变量的基类。还有10个从基类扩展而来的类。原因是这10个类有许多共同的变量,但也有一些是类本身独有的。现在我试图保存每个扩展类,所以我必须将基类变量与ClassX变量组合起来。这是一张照片:

在每个ClassX中,我都可以这样做:

super.saveData();
saveLocalData();
这意味着我只需要在基类中提供一个saveData,但实际上需要多次重复saveLocalData-10

在每个类中,我只需使用以下命令即可获得变量列表:

Field[] vars = DisplayField.class.getDeclaredFields();
我可以这样写变量名和值:

bw.write(f.getName() + "=" + f.get(this) + "\n");
我可以对所有ClassX类执行相同的操作,并构建这样的文本文件

然后我突然想到,如果我可以从FileIOClass获得每个ClassX的基类,那么我就可以得到一个由两部分组成的单个saveData。我可以做到:

for (DisplayField field : fieldList) // Iterate all the CLassX's
field.getClass().getSuperclass().getDeclaredMethod("saveDisplayField").invoke(bw);

然后我陷入了可怕的困境。有人能“解开”我吗?或者我只是找错地方了吗?

你认为现在只需要基本类型,这是在限制自己,使你的应用程序无法扩展

你的问题有多种解决方案。你可以用e。G用于保存分层数据结构,它已经随Java提供

下面是一个简单的例子:

BaseClass.java

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({
    Class1.class,
    Class2.class
})
@XmlRootElement(name = "Base")
public class BaseClass {

    @XmlAttribute(name = "var1", required = true)
    protected int var1;
    @XmlAttribute(name = "var2", required = true)
    protected int var2;
    @XmlAttribute(name = "var3", required = true)
    protected int var3;

    public String toString() {
        return "var1=" + var1 + ", " + "var2=" + var2 + ", " + "var3=" + var3;
    }
}
public class BaseClass {

    @Persist
    Integer var1;

    @Persist
    Integer var2;

    @Persist
    Integer var3;

}
Class1.java

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Class1")
public class Class1 extends BaseClass {

    @XmlAttribute(name = "varX", required = false)
    protected int varX;
    @XmlAttribute(name = "varY", required = false)
    protected int varY;

    public String toString() {
        return "var1=" + var1 + ", " + "var2=" + var2 + ", " + "var3=" + var3 + ", varX=" + varX + ", varY=" + varY;
    }

}
public class Class1 extends BaseClass {

    @Persist
    Integer varX;

    @Persist
    Integer varY;

}
Class2.java

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Class2")
public class Class2 extends BaseClass {

    @XmlAttribute(name = "varA", required = false)
    protected int varA;
    @XmlAttribute(name = "varB", required = false)
    protected int varB;

    public String toString() {
        return "var1=" + var1 + ", " + "var2=" + var2 + ", " + "var3=" + var3 + ", varA=" + varA + ", varB=" + varB;
    }

}
public class Class2 extends BaseClass {

    @Persist
    Integer varA;

    @Persist
    Integer varB;

}
Main.java

import java.io.StringReader;
import java.io.StringWriter;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class XmlExample {
    public static void main(String[] args) {

        // marshal base
        BaseClass base = new BaseClass();
        base.var1=1;
        base.var2=2;
        base.var3=3;

        String baseXml = marshal( base);

        // marshal class1
        Class1 class1 = new Class1();
        class1.var1=1;
        class1.var2=2;
        class1.var3=3;
        class1.varX=10;
        class1.varY=20;

        String class1Xml = marshal( class1);

        // marshal class2
        Class2 class2 = new Class2();
        class2.var1=1;
        class2.var2=2;
        class2.var3=3;
        class2.varA=40;
        class2.varB=50;

        String class2Xml = marshal( class2);

        // unmarshal base
        unmarshal(baseXml);

        // unmarshal class1
        unmarshal(class1Xml);

        // unmarshal class2
        unmarshal(class2Xml);

        System.exit(0);
    }

    public static String marshal( BaseClass base) {

        try {

            JAXBContext jaxbContext = JAXBContext.newInstance(BaseClass.class);

            Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
            jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

            StringWriter stringWriter = new StringWriter();
            jaxbMarshaller.marshal(base, stringWriter);
            String xml = stringWriter.toString();

            System.out.println("XML:\n" + xml);

            return xml;

        } catch (Exception e) {
            throw new RuntimeException( e);
        }

    }

    public static void unmarshal( String xml) {

        try {

            JAXBContext jaxbContext = JAXBContext.newInstance(BaseClass.class);

            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            StringReader stringReader = new StringReader(xml);

            Object clazz = (Object) jaxbUnmarshaller.unmarshal(stringReader);

            // create/cast here whatever class you need
            if( clazz.getClass().isAssignableFrom( BaseClass.class)) {
                System.out.println( "BaseClass:");
            }
            else if( clazz.getClass().isAssignableFrom( Class1.class)) {
                System.out.println( "Class1:");
            }
            else if( clazz.getClass().isAssignableFrom( Class2.class)) {
                System.out.println( "Class2:");
            }

            System.out.println( clazz + "\n");

        } catch (Exception e) {
            throw new RuntimeException( e);
        }

    }
}
控制台输出:

XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Base var1="1" var2="2" var3="3"/>

XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Class1 varX="10" varY="20" var1="1" var2="2" var3="3"/>

XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Class2 varA="40" varB="50" var1="1" var2="2" var3="3"/>

BaseClass:
var1=1, var2=2, var3=3

Class1:
var1=1, var2=2, var3=3, varX=10, varY=20

Class2:
var1=1, var2=2, var3=3, varA=40, varB=50
Class: BaseClass
var1 = 1
var2 = 2
var3 = 3

Class: Class1
var1 = 4
var2 = 5
var3 = 6
varX = 10
varY = 20

Class: Class2
var1 = 7
var2 = 8
var3 = 9
varA = 30
varB = 40
您可以非常方便地序列化任何类型的对象,甚至是需要对象(如日期对象)的列表和格式


即使你不打算这样做,我也不会用反射来满足这种需求。而是在每个类中实现某种serializeToFile接口。

除了我的第一个答案之外,这里还有另一种不同的解决方案,可以根据需要使用反射,因为这是您的问题。但正如我在另一个答案中所说的,你是在限制自己

我将创建一个自定义注释,这样您仍然可以在bean中执行您喜欢的任何操作

注释:Persist.java

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.METHOD})  
public @interface Persist {
}
BaseClass.java

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({
    Class1.class,
    Class2.class
})
@XmlRootElement(name = "Base")
public class BaseClass {

    @XmlAttribute(name = "var1", required = true)
    protected int var1;
    @XmlAttribute(name = "var2", required = true)
    protected int var2;
    @XmlAttribute(name = "var3", required = true)
    protected int var3;

    public String toString() {
        return "var1=" + var1 + ", " + "var2=" + var2 + ", " + "var3=" + var3;
    }
}
public class BaseClass {

    @Persist
    Integer var1;

    @Persist
    Integer var2;

    @Persist
    Integer var3;

}
Class1.java

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Class1")
public class Class1 extends BaseClass {

    @XmlAttribute(name = "varX", required = false)
    protected int varX;
    @XmlAttribute(name = "varY", required = false)
    protected int varY;

    public String toString() {
        return "var1=" + var1 + ", " + "var2=" + var2 + ", " + "var3=" + var3 + ", varX=" + varX + ", varY=" + varY;
    }

}
public class Class1 extends BaseClass {

    @Persist
    Integer varX;

    @Persist
    Integer varY;

}
Class2.java

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Class2")
public class Class2 extends BaseClass {

    @XmlAttribute(name = "varA", required = false)
    protected int varA;
    @XmlAttribute(name = "varB", required = false)
    protected int varB;

    public String toString() {
        return "var1=" + var1 + ", " + "var2=" + var2 + ", " + "var3=" + var3 + ", varA=" + varA + ", varB=" + varB;
    }

}
public class Class2 extends BaseClass {

    @Persist
    Integer varA;

    @Persist
    Integer varB;

}
这就是如何使用类并序列化它们的值:

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

public class MainApp {

    public static void log(BaseClass base) {

        System.out.println( "\nClass: " + base.getClass().getName());

        Class parent = base.getClass().getSuperclass();
        while( parent != null) {
            logFields( base, parent);
            parent = parent.getSuperclass();
        }

        logFields( base, base.getClass());
    }

    public static void logFields(BaseClass obj, Class clazz) {

        try {

            for (Field field : clazz.getDeclaredFields()) {

                if (field.isAnnotationPresent(Persist.class)) {

                    Annotation annotation = field.getAnnotation(Persist.class);
                    Persist test = (Persist) annotation;

                    System.out.println(field.getName() + " = " + field.get(obj));

                }

            }

        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }

    }

    public static void main(String[] args) throws Exception {

        BaseClass base = new BaseClass();
        base.var1 = 1;
        base.var2 = 2;
        base.var3 = 3;
        log(base);

        Class1 class1 = new Class1();
        class1.var1 = 4;
        class1.var2 = 5;
        class1.var3 = 6;
        class1.varX = 10;
        class1.varY = 20;
        log(class1);

        Class2 class2 = new Class2();
        class2.var1 = 7;
        class2.var2 = 8;
        class2.var3 = 9;
        class2.varA = 30;
        class2.varB = 40;
        log(class2);

        System.exit(0);
    }
}
控制台输出:

XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Base var1="1" var2="2" var3="3"/>

XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Class1 varX="10" varY="20" var1="1" var2="2" var3="3"/>

XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Class2 varA="40" varB="50" var1="1" var2="2" var3="3"/>

BaseClass:
var1=1, var2=2, var3=3

Class1:
var1=1, var2=2, var3=3, varX=10, varY=20

Class2:
var1=1, var2=2, var3=3, varA=40, varB=50
Class: BaseClass
var1 = 1
var2 = 2
var3 = 3

Class: Class1
var1 = 4
var2 = 5
var3 = 6
varX = 10
varY = 20

Class: Class2
var1 = 7
var2 = 8
var3 = 9
varA = 30
varB = 40

然后将数据序列化到您喜欢的任何类的文件中。

这些变量是什么类型的?如果你需要保存e。G一份清单,你可能会犯严重的错误。关于你的要求没有足够的信息。从外观上看,我更愿意使用像e这样的注释框架。G保存数据。变量都是基本类型,例如double、int、boolean等。在我需要存储dropshadow参数的地方,我只存储“设置”,而不是dropshadow类-同样,只存储基本类型。所以没有什么棘手的存储。但不管变量的类型如何,基本问题仍然存在。哇,这对我来说是一个全新的世界。给我几小时,几天?消化所有这些,就像他们说的那样,我会随时通知你-谢谢你提供了如此详尽的例子。这是我欣赏StackOverflow的一件事——人们如何不遗余力地提供帮助。