- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 Trade
带有以下代码的对象,它实现了 Serializable
接口(interface),但由于它包含 javafx 属性,我得到这个 java.io.NotSerializableException
因此未能正确执行 writeObject()
和 readObject()
.我的最终目标是能够使用 ObjectOutputStream
来写入 和读取 这个对象。和 ObjectInputStream
我阅读了 3 个链接:
NotSerializableException on SimpleListProperty
自从我的Trade
类正在运行 ScheduledService
要从 Google Finance 获取收盘价,我知道我需要调用 startService()
在 readObject()
内确保当readObject()
方法被调用并且对象被反序列化,线程将再次重新启动。
此外,我明白我需要在我的 Trade
中定义这两个私有(private)方法。类(class)。
private void writeObject(ObjectOutputStream out) throws IOException
{
out.defaultWriteObject();
// What else should I write in here?
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
{
// our "pseudo-constructor"
in.defaultReadObject();
// Not sure what else I need to write in here
// now we are a "live" object again, so let's run rebuild and start
startService();
}
问题:我已经阅读了上面的第 3 个链接,但我仍然对上面这两个私有(private)方法中还应该包含什么感到困惑?
因为我的贸易对象有相当多的属性,但都是它真正需要的只是buySell,transactionDate,symbol, double volume, double price
构造一个对象。我应该将其余属性设置为 transient
吗?那么呢?
public class Trade implements Serializable{
// properties
private Long creationTime;
private int counter;
private ObjectProperty<LocalDate> transactionDate;
private StringProperty symbol;
private StringProperty details;
private StringProperty buySell;
private DoubleProperty volume;
private DoubleProperty price;
private ReadOnlyDoubleWrapper transactionFee;
private final ReadOnlyDoubleWrapper closingPrice;
private final PauseTransition delay;
private ReadOnlyBooleanWrapper caution;
private final ScheduledService<webScraping> stockService = new ScheduledService<webScraping>() {
// web scrape google finance data
...
}
// constructor
public Trade(BuySell buySell, LocalDate transactionDate, String symbol, double volume, double price){
...
startService();
creationTime = Calendar.getInstance().getTimeInMillis();
}
// getters and setters and instance methods that return the properties themselves
public Long getCreationTime(){
return this.creationTime;
}
private Object writeReplace() {
return new TradeProxy(this);
}
private void readObject(ObjectInputStream stream)
throws InvalidObjectException {
throw new InvalidObjectException("Proxy required");
}
...
private static class TradeProxy implements Serializable{
private String buySell;
private LocalDate transactionDate;
private String stockTicker;
private double price;
private double volume;
private Long creationTime;
private TradeProxy(Trade trade){
this.buySell = trade.getBuySell();
this.transactionDate = trade.getTransactionDate();
this.stockTicker = trade.getStockTicker();
this.price = trade.getPrice();
this.volume = trade.getVolume();
this.creationTime = trade.getCreationTime();
}
private void writeObject(ObjectOutputStream s ) throws IOException{
s.defaultWriteObject();
}
private Object readResolve() throws ObjectStreamException{
return new Trade(this.buySell,this.transactionDate, this.symbol, this.volume, this.price);
}
}
}
更新:我更新了我的代码。但是因为 creationTime
不是 Trade
的参数的构造函数,在我的例子中我不知道如何序列化/反序列化它。更准确地说,如果我创建一个 Trade
对象在时间说 creationTime = 1443444301488
,我希望这个对象被序列化,当我读入对象并反序列化它时,我希望 creationTime 与它原来的完全相同(即 1443444301488) 我不知道如何为了达成这个。这就是我现在面临的问题。
最佳答案
我会避免序列化 javafx 对象。而是创建一个包含应该被序列化的状态的 javabean 对象。然后您可以让您的 Trade 对象从序列化的代理 javabean 构建它自己。
class TradeSerialProxy {
private String simpleBeanFields;
private int moreSimpleStateFields;
//getters and setters
}
然后
public Trade (TradeSerialProxy proxy) {
//build the Trade object using the proxy.
}
您会在 Effective Java 一书中看到与此类似的内容。尽管在那本书中他出于安全目的使用代理。我遵循的规则是只序列化简单的 javabean 对象,仅此而已。避免序列化复杂的对象。
另外,如果您使用常规的 Java 序列化,那么只要您的类实现发生变化,您就可能会遇到版本问题。有很多方法可以解决这个问题,比如使用 JSON 和 GSON 进行序列化。因为我使用的是纯标准 Java,没有外部库/jar,所以我必须使用 HashMap 来完成此操作……我只序列化 HashMap 并使用传递给它的 HashMap 构建真实对象。我必须这样做以避免出现常量串行版本不匹配异常并坚持使用纯标准的 vanilla Java。
编辑:这是一个使用序列化代理模式的对象。此方法来自 Effective Java 第 2 版第 78 项。
public class UserProfile implements Serializable {
///////////////////////////////////////////////////////////////////////////
//private variables
private String profileName = null;
private int version = 0;
private LeaderboardPermissions leaderboardState = LeaderboardPermissions.ASK;
private boolean upgradeWalkThrough = true;
private final Map<GameType, GameTypeStats> gameTypeStats;
private final String id;
private boolean offNet = true;
///////////////////////////////////////////////////////////////////////////
//serialization stuff
private static final long serialVersionUID = 7625672295622776890L;
private UserProfile(UserProfileProxy t) {
this.profileName = t.profileName;
this.version = t.version;
this.leaderboardState = t.leaderboardState;
this.upgradeWalkThrough = t.upgradeWalkThrough;
this.gameTypeStats = t.gameTypeStats;
this.id = t.id;
this.offNet = t.offNet;
}
private Object writeReplace() {
return new UserProfileProxy(this);
}
private void readObject(ObjectInputStream stream)
throws InvalidObjectException {
throw new InvalidObjectException("Proxy required");
}
///////////////////////////////
//serialization proxy
private static class UserProfileProxy implements Serializable {
private String profileName = null;
private int version = 0;
private final LeaderboardPermissions leaderboardState;
private boolean upgradeWalkThrough = true;
private final Map<GameType, GameTypeStats> gameTypeStats;
private String id;
private static final long serialVersionUID = 6985672045622776890L;
private boolean offNet;
private UserProfileProxy(UserProfile t) {
this.profileName = t.profileName;
this.version = t.version;
this.leaderboardState = t.leaderboardState;
this.upgradeWalkThrough = t.upgradeWalkThrough;
this.gameTypeStats = t.gameTypeStats;
this.id = t.id;
this.offNet = t.offNet;
}
private void writeObject(ObjectOutputStream s) throws IOException {
s.defaultWriteObject();
}
private Object readResolve() throws ObjectStreamException {
return new UserProfile(this);
}
}
这种方法被嵌入到 Java 对象序列化协议(protocol)中。我现在使用的另一种方法是使用 HashMap<String, Object>
作为代理。
这是界面。我必须让这个接口(interface)中的方法返回它们的散列,因为我广泛使用加密序列化对象的散列来防止篡改保存的文件。我不一定要推荐这个,而是展示序列化代理的可能性。
public interface MapSerializable {
public static String CLASS_KEY = "MapSerializable.CLASS_KEY";
/**
* Object will populate a HashMap of objects that it can use at some later
* point to reinitialize itself. Return the hash of the objects used to
* build itself.
*
* @param serial
* @return
* @throws IOException
*/
public int populateSerialMap(HashMap<String, Object> serial) throws IOException;
/**
* Object will initialize itself using the input HashMap. Returns the hash
* of the objects that were used to initialize itself from the Map.
*
* @param serial
* @return hash of the objects that were used to load yourself.
* @throws IOException
*/
public int initializeFromMap(HashMap<String, Object> serial) throws IOException;
}
这是一个使用它的对象的例子。
public class GameType implements MapSerializable {
////////////////////////////////////////////////////////////////////////////
//private variables
private String displayName = null;
////////////////////////////////////////////////////////////////////////////
//constrcutor
public GameType(String name) {
this.displayName = name;
}
GameType() {
}
////////////////////////////////////////////////////////////////////////////
//public methods
@Override
public int populateSerialMap(HashMap<String, Object> serial) throws IOException {
serial.put("displayName", displayName);
return 17 * Objects.hashCode(displayName);
}
@Override
public final int initializeFromMap(HashMap<String, Object> serial) throws IOException {
int hash = 0;
ObjectHashPair<String> ohp = model.utils.SerialUtils.getObjectFromMap(serial, "displayName", "");
displayName = ohp.obj;
hash += 17 * ohp.hash;
return hash;
}
}
EDIT2:对第一种方法的更深入的解释。
您需要先了解 Java 序列化的一些基础知识。 Java 为您完成了大部分繁重的工作,它实际上有一个 writeObject 和 readObject 在大多数情况下都可以正常工作。这对你来说是个好消息,因为你需要做的就是决定哪些字段需要进入代理只是你想要序列化的东西(状态)而不必担心实际进行序列化(添加/删除对象到溪流)。接下来,您需要能够使用代理初始化您的主类,反之亦然。因此,在您的主类中创建一个构造函数,该构造函数将代理对象作为输入,在该构造函数中初始化您的主类。对代理对象执行相同的操作。最后,Java 甚至让您能够使用代理通过 writeReplace 和 readResource 方法进行写入和读取。主类的 writeReplace 将返回一个代理实例,实质上告诉 Java 改为序列化该对象。另一方面,在代理中,您需要一个 readResolve 来在反序列化期间返回主对象的实例。
所以让我们通过项目符号列表中的步骤:
1) 决定哪些字段需要保存并创建你的代理类(我使用了一个内部嵌套类)来拥有这些字段。
2)在主类和代理类中创建构造函数。 Main(Proxy obj)
和 Proxy(Main obj)
.
3)分别在主类和代理类上实现writeReplace和readResolve。
希望对您有所帮助。
关于javafx:如何为此对象编写 writeObject() 和 readObject()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32770574/
我只想从客户端向服务器发送数组 adc_array=[w, x, y, z]。下面是客户端代码,而我的服务器是在只接受 json 的 python 中。编译代码时我没有收到任何错误,但收到 2 条警告
我是 lua 和 Node js 的新手,我正在尝试将我正在开发的移动应用程序连接到服务器。问题是它连接到服务器,但我尝试传递的数据丢失或无法到达服务器。对我正在做的事情有什么问题有什么想法吗? th
我在这个页面上工作 http://www.haskell.org/haskellwiki/99_questions/Solutions/4 我理解每个函数的含义,看到一个函数可以像这样以多种方式定义,
我目前正在尝试将数据写入 excel 以生成报告。我可以将数据写入 csv 文件,但它不会按照我想要的顺序出现在 excel 中。我需要数据在每列的最佳和最差适应性下打印,而不是全部打印在平均值下。这
所以,我正在做一个项目,现在我有一个问题,所以我想得到你的帮助:) 首先,我已经知道如何编写和读取 .txt 文件,但我想要的不仅仅是 x.hasNext()。 我想知道如何像 .ini 那样编写、读
我正在尝试编写一个函数,该函数将返回作为输入给出的任何数字的阶乘。现在,我的代码绝对是一团糟。请帮忙。 function factorialize(num) { for (var i=num, i
这个问题已经有答案了: Check variable equality against a list of values (16 个回答) 已关闭 4 年前。 有没有一种简洁或更好的方法来编写这个条件
我对 VR 完全陌生,正在 AFrame 中为一个类(class)项目开发 VR 太空射击游戏,并且想知道 AFrame 中是否有 TDD 的任何文档/标准。有人能指出我正确的方向吗? 最佳答案 几乎
我正在尝试创建一个 for 循环,它将重现以下功能代码块,但以一种更具吸引力的方式。这是与 Soundcould 小部件 API 实现一起使用的 here on stackoverflow $(doc
我有一个非常令人困惑的问题。我正在尝试更改属性文件中的属性,但它只是没有更改... 这是代码: package config; import java.io.FileNotFoundException
我对 VR 完全陌生,正在 AFrame 中为一个类(class)项目开发 VR 太空射击游戏,并且想知道 AFrame 中是否有 TDD 的任何文档/标准。有人能指出我正确的方向吗? 最佳答案 几乎
我正在开发一个用户模式(Ring3)代码级调试器。它还应支持.NET可执行文件的本机(x86)调试。基本上,我需要执行以下操作: 1).NET在隐身模式下加载某些模块,而没有LOAD_DLL_DEBU
我有一个列表,我知道有些项目是不必要打印的,我正在尝试通过 if 语句来做到这一点...但是它变得非常复杂,所以有没有什么方法可以在 if 语句中包含多个索引而无需打印重写整个声明。 看起来像这样的东
我很好奇以不同方式编写 if 语句是否会影响程序的速度和效率。所以,例如写一个这样的: bool isActive = true; bool isResponding = false; if (isA
我在搜索网站的源代码时找到了一种以另一种方式(我认为)编写 if 语句的方法。 代替: if(a)b; 或: a?b:''; 我读了: !a||b; 第三种方式和前两种方式一样吗?如果是,为什么我们要
我的数据采用以下格式(HashMap的列表) {TeamName=India, Name=Sachin, Score=170} {TeamName=India, Name=Sehwag, Score=
我目前正在完成 More JOIN operations sqlzoo 的教程,遇到了下面的代码作为#12 的答案: SELECT yr,COUNT(title) FROM movie JOIN ca
我正试图找到一种更好的方法来编写这段代码: def down_up(array, player) 7.downto(3).each do |row| 8.times do |col
出于某种原因,我的缓冲区中充满了乱码,我不确定为什么。我什至用十六进制编辑器检查了我的文件,以验证我的字符是否以 2 字节的 unicode 格式保存。我不确定出了什么问题。 [打开文件] fseek
阅读编码恐怖片时,我刚刚又遇到了 FizzBuzz。 原帖在这里:Coding Horror: Why Can't Programmers.. Program? 对于那些不知道的人:FizzBu
我是一名优秀的程序员,十分优秀!