I have used a static variable in a Class and I want that the value of this variable is kept unchanged after restart of the jvm.
The idea is to store this value.
Can someone help me ?
If you want a variable whose value can change during the execution of the code, to be restored to whatever it was when you stopped the JVM, the next time you start the JVM, then you need to persist the value to an external medium. This is typically done by storing the value in a file or database, and retrieving it the next time the program starts. A key question when solving this problem is how to represent the value outside the executing program. For simple types like numbers and strings, this is not much of an issue. For values that are objects of non-trivial classes, the problem becomes more interesting. This is known as object serialization.
With the disclaimer that there are many different ways to persist data, here is a minimal example using Java Serialization to make the point more concrete.
class MyClassData implements Serializable {
private String myString = "A string";
private int myNumber = 5;
// To make the point that the state of the object stored in the
// variable can change at run-time.
public void changeThings( String myString, int myNumber) {
this.myString = myString;
this.myNumber = myNumber;
}
}
public class MyClass {
private static MyClassData data = restore();
// Call before exiting the program
private static void store() {
try( ObjectOutputStream out =
new ObjectOutputStream(new FileOutputStream("data.dat"))) {
out.writeObject(data);
}
catch( IOException e ) {
// Deal with this
}
}
private static MyClassData restore() {
try( ObjectInputStream in =
new ObjectInputStream(new FileInputStream("data.dat"))) {
return (MyClassData) in.readObject();
}
catch( IOException | ClassNotFoundException e ) {
return new MyClassData();
}
}
}
You restart the jvm every thing will be clear.So you can't get the values from static variables. If you use database then only you get the values without failing.
Related
I'm still pretty new to Java and right now I'm trying to make a copy of Menu. I think I've done a little bit of it where I created a new Menu object with new MenuItems in it. MenuItems is another class with two string variables and a double variable, the itemName and itemDescription and the itemPrice. So I'm trying to copy the contents, the three variables of the original MenuItems into the MenuItems copy, but I don't know how. I got stuck on trying to set the clone copy's name to the original's name.
public class Menu
{
Menu()
{
}
final int maxItems = 50;
MenuItem[] food = new MenuItem[maxItems + 1];
public Object clone()
{
Menu menuClone = new Menu();
MenuItem[] foodClone = new MenuItem[maxItems + 1];
for(int i = 1; i <= maxItems + 1; i++)
{
foodClone[i] = new MenuItem();
foodClone[i] = food[i].setItemName();
}
}
This is the MenuItem class:
public class MenuItem
{
private String name;
private String descrip;
private double price;
MenuItem()
{
}
public String getItemName()
{
return name;
}
public String getItemDescrip()
{
return descrip;
}
public double getPrice()
{
return price;
}
public void setItemName(String itemName)
{
name = itemName;
}
public void setItemDescrip(String itemDescrip)
{
descrip = itemDescrip;
}
public void setPrice(double itemPrice) throws IllegalArgumentException
{
if(itemPrice >= 0.0)
price = itemPrice;
else
throw new IllegalArgumentException("Enter only positive values");
}
public String toString(){
return "Name: " + name + ", Desc: " + descrip;
}
}
You are almost there, where you have:
foodClone[i] = food[i].setItemName();
You probably want (in addition to the other variables of MenuItem)
foodClone[i].setItemName(food[i].getItemName())`
However, it's best to use the clone method or a copy constructor (well, copy constructor arguably might be best).
I do prefer using a copy constructor, such an example would be:
MenuItem(MenuItem menuItemToClone)
{
this.name = menuItemToClone.name;
this.descrip = menuItemToClone.descrip;
this.price = menuItemToClone.price;
}
Then you would just do:
foodClone[i] = new MenuItem(food[i]);
Cloning only provides a shallow copy, despite some of the previous recommendations.
A common solution to the deep copy problem is to use Java Object Serialization (JOS). The idea is simple: Write the object to an array using JOS’s ObjectOutputStream and then use ObjectInputStream to reconstitute a copy of the object. The result will be a completely distinct object, with completely distinct referenced objects. JOS takes care of all of the details: superclass fields, following object graphs, and handling repeated references to the same object within the graph. Figure 3 shows a first draft of a utility class that uses JOS for making deep copies.
import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
/**
* Utility for making deep copies (vs. clone()'s shallow copies) of
* objects. Objects are first serialized and then deserialized. Error
* checking is fairly minimal in this implementation. If an object is
* encountered that cannot be serialized (or that references an object
* that cannot be serialized) an error is printed to System.err and
* null is returned. Depending on your specific application, it might
* make more sense to have copy(...) re-throw the exception.
*
* A later version of this class includes some minor optimizations.
*/
public class UnoptimizedDeepCopy {
/**
* Returns a copy of the object, or null if the object cannot
* be serialized.
*/
public static Object copy(Object orig) {
Object obj = null;
try {
// Write the object out to a byte array
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos);
out.writeObject(orig);
out.flush();
out.close();
// Make an input stream from the byte array and read
// a copy of the object back in.
ObjectInputStream in = new ObjectInputStream(
new ByteArrayInputStream(bos.toByteArray()));
obj = in.readObject();
}
catch(IOException e) {
e.printStackTrace();
}
catch(ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
return obj;
}
}
Unfortunately, this approach has some problems:
It will only work when the object being copied, as well as all of the other objects references directly or indirectly by the object, are serializable. (In other words, they must implement java.io.Serializable.) Fortunately it is often sufficient to simply declare that a given class implements java.io.Serializable and let Java’s default serialization mechanisms do their thing.
Java Object Serialization is slow, and using it to make a deep copy requires both serializing and deserializing. There are ways to speed it up (e.g., by pre-computing serial version ids and defining custom readObject() and writeObject() methods), but this will usually be the primary bottleneck.
The byte array stream implementations included in the java.io package are designed to be general enough to perform reasonable well for data of different sizes and to be safe to use in a multi-threaded environment. These characteristics, however, slow down ByteArrayOutputStream and (to a lesser extent) ByteArrayInputStream.
Source: http://javatechniques.com/blog/faster-deep-copies-of-java-objects/
In this book, there is this example of how to use static variables and methods. I dont understand what is going on. explain why there has to be static in front of the methods and variables. There are two seperate classes called Virus and VirusLab. The VirusLab.java takes in a command line argument and makes the amount of Virus objects, then spits out the number of Virus objects. Thanks
Virus:
public class Virus {
static int virusCount = 0;
public Virus() {
virusCount++;
}
public static int getVirusCount() {
return virusCount;
}
}
VirusLab:
public class VirusLab {
public static void main(String[] args) {
int numViruses = Integer.parseInt(args[0]);
if (numViruses > 0) {
Virus[] virii = new Virus[numViruses];
for (int i = 0; i < numViruses; i++) {
virii[i] = new Virus();
}
System.out.println("There are " + Virus.getVirusCount()
+ " viruses.");
}
}
}
A web search would have given you hundreds of links to explain 'static' keyword in Java.
Please refer to the following documentation: http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html
Also, please refer a text book for your further learning, that will help a lot.
I will keep it pretty short
You need static variables if you want that variable to be shared
across all the objects of your class,so that if one of the object
changes its value it would be reflected in other objects as well,which
is what is exactly done in above example.
A static variable is one which is not associated with an instance of a class.
This means you don't have to create a new instance of the class to access the variable from another class. Consider this:
public class Login {
public static String loggedInUser
public void setLoggedInUser(String name){
this.loggedInUser = name;
}
}
To access the String loggedInUser in another class, you wouldn't have to say
Login login = new Login();
String username = login.loggedInUser;
You'd just have to say
String username = Login.loggedInUser;
This can be useful in accessing variables outside of the class they were set in.
Hope that helps.
try reading this answer I gave in a previous question:
Accessing Static variables
and make google and wikipedia ur friend they'll save u time coming on here posting questions ,waiting and refreshing ur page to check if any answers were given.
I'm serialising and deserialising a large two dimensional array of objects. Each object contains instructions to creating a BufferedImage - this is done to get around BufferedImage not being directly serializable itself.
The class being serialised is:
public final class MapTile extends TransientImage
{
private static final long serialVersionUID = 0;
private transient BufferedImage f;
transient BufferedImage b;
int along;
int down;
boolean flip = false;
int rot = 0;
public MapTile(World w, int a, int d)
{
// f = w.getMapTiles();
along = a;
down = d;
assignImage();
}
public MapTile(World w, int a, int d, int r, boolean fl)
{
// f = w.getMapTiles();
along = a;
down = d;
rot = r;
flip = fl;
assignImage();
}
public int getA()
{
return along;
}
public int getD()
{
return down;
}
#Override
public void assignImage()
{
if (f == null)
{
f = World.mapTiles;
}
b = f.getSubimage(along, down, World.squareSize, World.squareSize);
if (rot != 0)
{
b = SmallMap.rotateImage(b, rot);
}
if (flip)
{
b = SmallMap.flipImage(b);
}
super.setImage(b);
f.flush();
b.flush();
f = null;
b = null;
}
}
which extends:
public abstract class TransientImage implements Serializable
{
private transient BufferedImage image;
public BufferedImage getImage()
{
return image;
}
public void setImage(BufferedImage i)
{
image = i;
}
public abstract void assignImage();
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
{
in.defaultReadObject();
assignImage();
}
}
This will ultimately be part of a map - usually it is created randomly but certain areas must be the same each time, hence serialising them and reading the array back in. As I will never need to save the image during normal usage I am putting in the write code:
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("verticalroad.necro")))
{
//out.writeObject(mapArray);
//}
//catch (IOException e) {
//}
in the class that creates the map, the read code:
try{
FileInputStream door = new FileInputStream(new File(f.getPath()+ "//verticalroad.necro"));
ObjectInputStream reader = new ObjectInputStream(door);
homeTiles = (MapTile[][]) reader.readObject();
}
catch (IOException | ClassNotFoundException e)
{
System.out.println("Thrown an error" + e.getMessage());
}
in the initialising class and commenting in and out as needed.
However. Each time I run the program the contents of the two dimensional array (mapArray in write, homeTiles in read) is different. Not only different from the one I (thought) I wrote, but also different each time the program is opened.
As can be seen, I'm printing out the toString to System.out which reveals further oddities. As its just a standard array, the toString isn't 100% helpful but it seems to cycle between several distinct values. However, even when the toStringg gives the same value, the contents of the array as displayed are not the same.
An example of a toString is hometiles:[[Lriseofthenecromancer.MapTile;#7681720a Looking at the documentation for Array.toString (here) it seems to be badly formed, lacking a trailing ]. I'm not sure if this is a clue to the issue or if its simply that the array is very large (several thousand objects) and its an issue of display space (I'm using NetBeans).
Any insight as to why this is changing would be appreciated. My working assumption is that its serializing the array but not the contents. But I have no idea a) if that's the case and b)if it is, what to do about it.
EDIT: Looking into this a bit further, it seems that instance variables aren't being set immediately. Printing them out directly after the call to setImage() has them all at zero, printing them from the calling class has them where they should be.
The underlying problem was that I'm an idiot. The specific expression of this in this particular case was that I forgot that subclasses couldn't inherit private methods. As such, the assignImage call wasn't being made and the image wasn't being set up.
Sorry for wasting the time of anyone who looked at this. I feel quite embarrassed.
I have the following class, which performs some calculations to fill its static arrays.
public class Amount implements Serializable{
private static final long serialVersionUID = 8141477444408242243L;
public static Amount values1[][] = new Amount[10][30];
public static Amount values2[][] = new Amount[10][30];
public static Amount values3[][] = new Amount[10][30];
double highestValue;
double highestAmount;
double lowestAmount;
double lowestValue;
...
}
As the calculations take 20 minutes or so, I am looking to store the arrays on file and load the values when the program starts. I am attempting to use the java serialization method and have the following functions
public static void loadFile(Amount[][] arr, String filename){
try {
FileInputStream fis = new FileInputStream(filename);
ObjectInputStream in = new ObjectInputStream(fis);
arr = (Amount[][])in.readObject();
in.close();
}
catch (Exception e) {
System.out.println(e);
}
}
public static void saveFile(Amount[][] arr, String filename){
try {
FileOutputStream fos = new FileOutputStream(filename);
ObjectOutputStream out = new ObjectOutputStream(fos);
out.writeObject(arr);
out.flush();
out.close();
}
catch (IOException e) {
System.out.println(e);
}
}
which I call like this saveFile(values1, "valueOneSaveFile"); and loadFile(values1, "valueOneSaveFile");
I have run the program once, saving all the arrays to various files. The files have been created and look to be around the correct size. When I change my program to call the loadFile functions, the arrays do not appear to initialize correctly. I am getting null pointer exceptions when trying to read a value from the array (which appears to be empty after the load)
The problem is in your LoadFile method.
Java passes parameters by value. In the case of objects a copy of the "pointer" is passed.
When you update the array:
arr = (Amount[][])in.readObject();
You are not updating Amount.values1 array, instead the local arr variable points to a new array.
You should change the method signature to:
public static Amount[][] loadFile(String filename)
And use it accordingly.
It might be an issue with the readObject and writeObject methods that you are implementing in your Amount class. A comprehensive example can be found here.
You might also consider using XStream to save/load your data. It is very easy to use, as shown here.
I hope in a good manner :-)
I wrote this piece of code.
What I wished to do, is to build something like "cache".
I assumed that I had to watch for different threads, as might many calls get to that class, so I tried the ThreadLocal functionality.
Base pattern is
have "MANY SETS of VECTOR"
The vector holds something like:
VECTOR.FieldName = "X"
VECTOR.FieldValue= "Y"
So many Vector objects in a set. Different set for different calls from different machines, users, objects.
private static CacheVector instance = null;
private static SortedSet<SplittingVector> s = null;
private static TreeSet<SplittingVector> t = null;
private static ThreadLocal<SortedSet<SplittingVector>> setOfVectors = new ThreadLocal<SortedSet<SplittingVector>>();
private static class MyComparator implements Comparator<SplittingVector> {
public int compare(SplittingVector a, SplittingVector b) {
return 1;
}
// No need to override equals.
}
private CacheVector() {
}
public static SortedSet<SplittingVector> getInstance(SplittingVector vector) {
if (instance == null) {
instance = new CacheVector();
//TreeSet<SplittingVector>
t = new TreeSet<SplittingVector>(new MyComparator());
t.add(vector);
s = Collections.synchronizedSortedSet(t);//Sort the set of vectors
CacheVector.assign(s);
} else {
//TreeSet<SplittingVector> t = new TreeSet<SplittingVector>();
t.add(vector);
s = Collections.synchronizedSortedSet(t);//Sort the set of vectors
CacheVector.assign(s);
}
return CacheVector.setOfVectors.get();
}
public SortedSet<SplittingVector> retrieve() throws Exception {
SortedSet<SplittingVector> set = setOfVectors.get();
if (set == null) {
throw new Exception("SET IS EMPTY");
}
return set;
}
private static void assign(SortedSet<SplittingVector> nSet) {
CacheVector.setOfVectors.set(nSet);
}
So... I have it in the attach and I use it like this:
CachedVector cache = CachedVector.getInstance(bufferedline);
The nice part: Bufferedline is a splitted line based on some delimiter from data files. Files can be of any size.
So how do you see this code? Should I be worry ?
I apologise for the size of this message!
Writing correct multi-threaded code is not that easy (i.e. your singleton fails to be), so try to rely on existing solutions if posssible. If you're searching for a thread-safe Cache implementation in Java, check out this LinkedHashMap. You can use it to implement a LRU cache. And collections.synchronizedMap(). can make this thread-safe.