I have a simple singleton:
class Test1 implements Serializable {
private static Test1 instance;
public String a = "a";
public String b = "b";
public String c = null;
public String d = null;
public String e;
public String f;
private Test1() {
e = "e";
}
public static Test1 getInstance() {
if (instance == null) {
instance = new Test1();
}
return instance;
}
// http://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-with-examples
protected Object readResolve() {
return getInstance();
}
public String toString() {
return String.format("Test1{ a:%s, b:%s, c:%s, d:%s, e:%s, f:%s}", a, b, c, d, e, f);
}
}
My main():
if ((new File("t1.obj").exists() == false)) {
Test1 t1 = Test1.getInstance();
t1.b = "bb";
t1.d = "dd";
t1.f = "ff";
serialize("t1.obj", t1);
}
else {
Test1 t2 = deserialize("t1.obj");
}
First run looks well
Serialized hu.fehergeri13.abptc.server.Test1 object to t1.obj file.
Test1{ a:a, b:bb, c:null, d:dd, e:e, f:ff}
after second run:
Deserialized hu.fehergeri13.abptc.server.Test1 object from t1.obj file.
Test1{ a:a, b:b, c:null, d:null, e:e, f:null}
My serialize/deserialize:
public static void serialize(String filePath, Object o) {
try {
FileOutputStream fos = new FileOutputStream(filePath);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(o);
System.out.println(String.format("Serialized %s object to %s file.", o.getClass().getName(), filePath));
oos.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static <T> T deserialize(String filePath) {
try {
FileInputStream is = new FileInputStream(filePath);
ObjectInputStream ois = new ObjectInputStream(is);
T o = (T) ois.readObject();
System.out.println(String.format("Deserialized %s object from %s file.", o.getClass().getName(), filePath));
ois.close();
is.close();
return o;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
Why are the values keep default and not bb,dd,ff?
My serializable singleton:
public class MySingleton implements Serializable {
private static final long serialVersionUID = -5909418239300111453L;
private static MySingleton instance = null;
protected MySingleton() {
}
public static MySingleton getInstance() {
if (instance == null) {
instance = new MySingleton();
}
return instance;
}
protected Object readResolve() {
return getInstance();
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
instance = this;
}
private String attr;
public String getAttr() {
return attr;
}
public void setAttr(String attr) {
this.attr = attr;
}
}
Related
import java.io.*;
import java.util.ArrayList;
public class Main {
static ArrayList<test> testArrey = new ArrayList<test>();
public static void main(String[] args) {
output(new test(18, "aren"));
output(new test(22, "ahmad"));
input();
read();
}
public static void read() {
for (test a : testArrey) {
System.out.println(a.age);
}
}
public static void input() {
try {
FileInputStream fileInput = new FileInputStream("open.ses");
ObjectInputStream ObjectInput = new ObjectInputStream(fileInput);
Object a1 = ObjectInput.readObject();
test b1 = (test) a1;
testArrey.add(b1);
Object a2 = ObjectInput.readObject();
test b2 = (test) a2;
testArrey.add(b2);
ObjectInput.close();
} catch (Exception ex) {
System.out.println("input error");
ex.printStackTrace();
}
}
public static void output(test a) {
try {
FileOutputStream fileOut = new FileOutputStream("open.ses");
ObjectOutputStream objectOut = new ObjectOutputStream(fileOut);
objectOut.writeObject(a);
objectOut.close();
} catch (Exception ex) {
System.out.println("output error");
ex.printStackTrace();
}
}
public static class test implements Serializable {
int age ;
String name ;
public test(int age , String name ) {
this.age = age;
this.name = name;
}
}
}
as you can see a called output() method two time with new to object of (test)as argument ,and it must write two object on (open.ses)file but when i want to call (.readobject)two times it gives me an error that says one object is saved ............
how to write more than one object with the help of method like the one i wrote ??
I have been struggling to create a serializing method that serializes all my already existing objects. This is what I have done:
my class:
public class Test implements Serializable{
ArrayList<TheOtherClass> obj = new ArrayList<>();
public static void main(String[] args) {
Test test = new Test();
test.addTest("This", "Is", "Some");
test.addTest("Text", "As", "Example");
test.saveAllArrays();
}
// omitted code down here.
public void addTest(String some, String random, String text) {
obj.add(new TheOtherClass(some, random, text));
}
public void saveTest(Object obj) throws IOException{
ObjectOutputStream save = new ObjectOutputStream(new FileOutputStream("SaveFile.bin"));
save.writeObject(obj);
}
public void saveAllArrays(){
for(TheOtherClass all : obj){
try {
saveTest(all);
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}
my object class:
public class TheOtherClass implements Serializable{
private String some;
private String random;
private String savedText;
Getter and setter methods are omitted.
Here is a complete example. Hopefully it will get you moving.
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class Test implements Serializable {
private static final String FILE = "SaveFile.bin";
private List<Item> itemList = new ArrayList<>();
public class Item implements Serializable {
private String first;
private String second;
private String last;
public Item(String first, String second, String last) {
this.first = first;
this.second = second;
this.last = last;
}
#Override
public String toString() {
return first + ", " + second + ", " + last;
}
}
public static void main(String args[]) {
Test test = new Test();
if(args.length > 0) {
try {
test.loadItemList();
System.out.println("loaded");
test.printList();
} catch (IOException | ClassNotFoundException e) {
System.out.println(e.getMessage());
}
} else {
test.addItem("1", "2", "done");
test.addItem("Text", "As", "Example");
try {
test.saveItemList();
System.out.println("saved");
test.printList();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
private void printList() {
itemList.forEach(System.out::println);
}
private void addItem(String first, String second, String last) {
itemList.add(new Item(first, second, last));
}
private void loadItemList() throws IOException, ClassNotFoundException {
InputStream inputStream = new FileInputStream(FILE);
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
itemList = (List<Item>) objectInputStream.readObject();
}
private void saveItemList() throws IOException {
OutputStream outputStream = new FileOutputStream(FILE);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(itemList);
}
}
At present you're creating a new file per serialized object, so you lose all but the last one. There is no need to serialize multiple objects at all, or iterate over the array list. Just save it directly, and deserialize it directly too.
I have successfully serialized my custom object but when I deserialize it this happens:
-Custom object is NOT NULL
-All fields are NULL
I know that I have successfully serialized my custom object because I have read the serialization file and it look fine.
Here is my code:
public class Preferences implements Serializable {
private static Preferences instance;
public static final long serialVersionUID = 3358037972944864859L;
public String accessToken;
protected Object readResolve() {
return getInstance();
}
private Preferences() {
}
private synchronized static void synchronize() {
if(instance == null) {
instance = new Preferences();
}
}
public static Preferences getInstance() {
if(instance == null) {
Preferences.synchronize();
}
return instance;
}
public void save(File file) {
try {
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream out = new ObjectOutputStream(fos);
Preferences tempInstance = Preferences.getInstance();
out.writeObject(tempInstance);
out.close();
fos.close();
}catch(IOException e) {
e.printStackTrace();
}
}
public void load(File file) {
try {
FileInputStream fis = new FileInputStream(file);
ObjectInputStream in = new ObjectInputStream(fis);
if(file.length() > 0) {
Preferences tempInstance = (Preferences) in.readObject();
Log.e("", String.valueOf(tempInstance == null)); //prints FALSE
Log.e("", String.valueOf(tempInstance.accessToken == null)); //prints TRUE
}
in.close();
fis.close();
}catch(IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Here is my testing code:
public class CustomActivity extends AppCompatActivity {
private File dir = new File(Environment.getExternalStorageDirectory(), ".app");
private File backup = new File(dir, "backup.ser");
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
Log.e("APPLICATION", "START");
super.onCreate(savedInstanceState);
if(this instanceof ActivityLogin) {
if(!dir.exists()) {
dir.mkdirs();
}
Preferences.getInstance().load(backup);
}
}
#Override
protected void onUserLeaveHint() {
super.onUserLeaveHint();
try {
backup.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
Preferences.getInstance().save(backup);
Log.e("APPLICATION", "STOP");
}
}
Any thoughts on what might be a problem?
You have this method in your class:
protected Object readResolve() {
return getInstance();
}
This tells the serialization mechanism: whenever you deserialize a Preferences instance, replace it by the one returned by getInstance(). So, if youc call load() and the instance of your Preferences has a null accessToken, then the deserialized preferences will have a null accessToken too, since they are the same object.
Add
System.out.println(tempInstance == this);
to your logging statements (or whatever you use in android to log), and you'll see.
Run the main function in File2 , the problem is : threads stuck at "rval=MVEL.executeExpression(compiledExpression, vars);" , 10 threads run in sequential order, not parallel , I wanna know why this happened.
PS: I'm using MVEL 2.2 , the latest version
File1:MVELHelper.java
public class MVELHelper {
private static ParserContext _ctx = new ParserContext(false);
//public static Object execute(String expression, Map<String, Object> vars, Databus databus) throws Exception {
public static Object execute(String expression, Map<String, Object> vars) throws Exception {
Object rval = null;
try {
if(vars == null) {
rval = MVEL.eval(expression, new HashMap<String,Object>());
}
else {
rval = MVEL.eval(expression, vars);
}
return rval;
}
catch(Exception e) {
throw new Exception("MVEL FAILED:"+expression,e);
}
}
public static Serializable compile(String text, ParserContext ctx)
throws Exception {
if(ctx == null) {
//ctx = _ctx;
ctx=new ParserContext(false);
}
Serializable exp = null;
try {
exp = MVEL.compileExpression(text, ctx);
//exp = MVEL.compileExpression(text);
}
catch (Exception e) {
throw new Exception("failed to compile expression.", e);
}
return exp;
}
public static Object compileAndExecute(String expression, Map<String, Object> vars) throws Exception {
Object rval = null;
try {
Serializable compiledExpression=compile(expression,null);
System.out.println("[COMPILE OVER, Thread Id="+Thread.currentThread().getId()+"] ");
if(vars == null) {
rval=MVEL.executeExpression(compiledExpression, new HashMap<String,Object>());
//rval = MVEL.eval(exp, new HashMap<String,Object>());
}
else {
//rval=MVEL.executeExpression(compiledExpression, vars,(VariableResolverFactory)null);
rval=MVEL.executeExpression(compiledExpression, vars);
//rval = MVEL.eval(expression, vars);
}
return rval;
}
catch(Exception e) {
throw new Exception("MVEL FAILED:"+expression,e);
}
}
}
File2:ExecThread3.java
public class ExecThread3 implements Runnable{
Map dataMap=null;
public Map getDataMap() {
return dataMap;
}
public void setDataMap(Map dataMap) {
this.dataMap = dataMap;
}
#Override
public void run() {
Map varsMap = new HashMap();
Map dataMap=new HashMap();
dataMap.put("count",100);
varsMap.put("dataMap", dataMap);
String expression="System.out.println(\"[BEFORE Thread Id=\"+Thread.currentThread().getId()+\"] \"+dataMap.get(\"count\"));"+
"Thread.sleep(3000);"+
"System.err.println(\"[AFTER Thread Id=\"+Thread.currentThread().getId()+\"] \"+dataMap.get(\"count\"));";
try {
//MVEL.compileExpression(expression);
MVELHelper.compileAndExecute(expression, varsMap);
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
for(int k=0;k<10;k++){
ExecThread3 execThread=new ExecThread3();
new Thread(execThread).start();
}
}
}
I´ve been reading that the static fields are not serialized but, after testing it, I saw that´s not true.
The static modifier even overrides the transient modifier and makes the field serializable.
I write one example from a book that shows that a static transient field is serialized.
import java.io.*;
class USPresident implements Serializable {
private static final long serialVersionUID = 1L;
#Override
public String toString() {
return "US President [name=" + name
+ ", period=" + period + ", term=" + term + "]";
}
public USPresident(String name, String period, String term) {
this.name = name;
this.period = period;
this.term = term;
}
private String name;
private String period;
private static transient String term;
}
class TransientSerialization {
public static void main(String[] args) {
USPresident usPresident = new USPresident("Barack Obama", "2009 to --", "56th term");
System.out.println(usPresident);
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("USPresident.data"))) {
oos.writeObject(usPresident);
} catch (IOException ioe) {
// ignore
}
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("USPresident.data"))) {
Object obj = ois.readObject();
if (obj != null && obj instanceof USPresident) {
USPresident presidentOfUS = (USPresident) obj;
System.out.println(presidentOfUS);
}
} catch (IOException ioe) {
// ignore
} catch (ClassNotFoundException e) {
// ignore
}
}
}
Is wrong the general concept that static fields are not serialized? Is it just a recommendation?
Why the transient modifier doen't take effect with static ?
note: I understand that initialize a static field in a constructor is an odd code, but the compiler let me do it and it's just in order to understand static fields serialization.
This has nothing to do with serialization but due to the fact that you are setting the static field when you create your usPresident variable. This sets the field for the class of that JVM. Try reading in the serialized president in a different program and see that the transient field is not serialized.
As an aside: consider not ignoring your exceptions.
For example, refactored, your code could look like this:
class USPresident implements Serializable {
private static final long serialVersionUID = 1L;
#Override
public String toString() {
return "US President [name=" + name + ", period=" + period + ", term="
+ term + "]";
}
public USPresident(String name, String period, String term) {
this.name = name;
this.period = period;
this.term = term;
}
private String name;
private String period;
private static transient String term;
}
class TransientSerialization {
public static void main(String[] args) {
serializePresident();
deserializePresident();
}
private static void deserializePresident() {
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream(
"USPresident.data"));
Object obj = ois.readObject();
if (obj != null && obj instanceof USPresident) {
USPresident presidentOfUS = (USPresident) obj;
System.out.println(presidentOfUS);
}
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private static void serializePresident() {
USPresident usPresident = new USPresident("Barack Obama", "2009 to --",
"56th term");
System.out.println(usPresident);
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("USPresident.data"));
oos.writeObject(usPresident);
oos.close();
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
The second time your run it, change the main method to:
public static void main(String[] args) {
// serializePresident();
deserializePresident();
}
And see what comes up.
For me, the first run returns:
US President [name=Barack Obama, period=2009 to --, term=56th term]
US President [name=Barack Obama, period=2009 to --, term=56th term]
and the second run returns:
US President [name=Barack Obama, period=2009 to --, term=null]