In my project, I manipulate instances of the following class :
public class MyClass implements Serializable{
private MyEnum model;
private Object something; //NOT TRANSIENT
public MyClass(MyEnum model){
this.model = model;
//something = ...
}
}
Every instance of MyClass is created by passing it a model
public enum MyEnum{
A,
B,
C,
//A lot more of these...
;
}
I often have to serialize/deserialize instances of MyClass, this is why I marked its field something as NOT transient.
The behavior is such that :
During serialization, something and the "identifier" of model will be serialized.
During deserialization, something will be deserialized and model will be equal to what it was before, without having to deserialize it since it's an enum.
But I have so many of these models that I'm getting for my enum :
"The code for the static initializer is exceeding the 65535 bytes limit"
What is the proper way to fix this problem? How to write this enum as a class to work around this limitation?
Having such large enums does not make sense. Don't you think that you have too much data in there?
You are using enums as a way to map between unique object instances and string names. So replace your enums with another type, for example, String.
TL;DR
You cannot use enum for what you require. It does not work. You could use an ArrayList or array with Strings which is filled through a file or db .
Related
I have:
class MyClass extends MyClass2 implements Serializable {
//...
}
In MyClass2 is a property that is not serializable. How can I serialize (and de-serialize) this object?
Correction: MyClass2 is, of course, not an interface but a class.
As someone else noted, chapter 11 of Josh Bloch's Effective Java is an indispensible resource on Java Serialization.
A couple points from that chapter pertinent to your question:
assuming you want to serialize the state of the non-serializable field in MyClass2, that field must be accessible to MyClass, either directly or through getters and setters. MyClass will have to implement custom serialization by providing readObject and writeObject methods.
the non-serializable field's Class must have an API to allow getting it's state (for writing to the object stream) and then instantiating a new instance with that state (when later reading from the object stream.)
per Item 74 of Effective Java, MyClass2 must have a no-arg constructor accessible to MyClass, otherwise it is impossible for MyClass to extend MyClass2 and implement Serializable.
I've written a quick example below illustrating this.
class MyClass extends MyClass2 implements Serializable{
public MyClass(int quantity) {
setNonSerializableProperty(new NonSerializableClass(quantity));
}
private void writeObject(java.io.ObjectOutputStream out)
throws IOException{
// note, here we don't need out.defaultWriteObject(); because
// MyClass has no other state to serialize
out.writeInt(super.getNonSerializableProperty().getQuantity());
}
private void readObject(java.io.ObjectInputStream in)
throws IOException {
// note, here we don't need in.defaultReadObject();
// because MyClass has no other state to deserialize
super.setNonSerializableProperty(new NonSerializableClass(in.readInt()));
}
}
/* this class must have no-arg constructor accessible to MyClass */
class MyClass2 {
/* this property must be gettable/settable by MyClass. It cannot be final, therefore. */
private NonSerializableClass nonSerializableProperty;
public void setNonSerializableProperty(NonSerializableClass nonSerializableProperty) {
this.nonSerializableProperty = nonSerializableProperty;
}
public NonSerializableClass getNonSerializableProperty() {
return nonSerializableProperty;
}
}
class NonSerializableClass{
private final int quantity;
public NonSerializableClass(int quantity){
this.quantity = quantity;
}
public int getQuantity() {
return quantity;
}
}
MyClass2 is just an interface so techinicaly it has no properties, only methods. That being said if you have instance variables that are themselves not serializeable the only way I know of to get around it is to declare those fields transient.
ex:
private transient Foo foo;
When you declare a field transient it will be ignored during the serialization and deserialization process. Keep in mind that when you deserialize an object with a transient field that field's value will always be it's default (usually null.)
Note you can also override the readResolve() method of your class in order to initialize transient fields based on other system state.
If possible, the non-serialiable parts can be set as transient
private transient SomeClass myClz;
Otherwise you can use Kryo. Kryo is a fast and efficient object graph serialization framework for Java (e.g. JAVA serialization of java.awt.Color requires 170 bytes, Kryo only 4 bytes), which can serialize also non serializable objects. Kryo can also perform automatic deep and shallow copying/cloning. This is direct copying from object to object, not object->bytes->object.
Here is an example how to use kryo
Kryo kryo = new Kryo();
// #### Store to disk...
Output output = new Output(new FileOutputStream("file.bin"));
SomeClass someObject = ...
kryo.writeObject(output, someObject);
output.close();
// ### Restore from disk...
Input input = new Input(new FileInputStream("file.bin"));
SomeClass someObject = kryo.readObject(input, SomeClass.class);
input.close();
Serialized objects can be also compressed by registering exact serializer:
kryo.register(SomeObject.class, new DeflateCompressor(new FieldSerializer(kryo, SomeObject.class)));
If you can modify MyClass2, the easiest way to address this is declare the property transient.
Depends why that member of MyClass2 isn't serializable.
If there's some good reason why MyClass2 can't be represented in a serialized form, then chances are good the same reason applies to MyClass, since it's a subclass.
It may be possible to write a custom serialized form for MyClass by implementing readObject and writeObject, in such a way that the state of the MyClass2 instance data in MyClass can be suitably recreated from the serialized data. This would be the way to go if MyClass2's API is fixed and you can't add Serializable.
But first you should figure out why MyClass2 isn't serializable, and maybe change it.
You will need to implement writeObject() and readObject() and do manual serialization/deserialization of those fields. See the javadoc page for java.io.Serializable for details. Josh Bloch's Effective Java also has some good chapters on implementing robust and secure serialization.
You can start by looking into the transient keyword, which marks fields as not part of the persistent state of an object.
Several possibilities poped out and i resume them here:
Implement writeObject() and readObject() as sk suggested
declare the property transient and it won't be serialized as first stated by hank
use XStream as stated by boris-terzic
use a Serial Proxy as stated by tom-hawtin-tackline
XStream is a great library for doing fast Java to XML serialization for any object no matter if it is Serializable or not. Even if the XML target format doesn't suit you, you can use the source code to learn how to do it.
A useful approach for serialising instances of non-serializable classes (or at least subclasses of) is known a Serial Proxy. Essentially you implement writeReplace to return an instance of a completely different serializable class which implements readResolve to return a copy of the original object. I wrote an example of serialising java.awt.BasicStroke on Usenet
I've got some problem that i can't figure out for a loong time.
I'm building web app in core-plugin architecture.
Plugins provides some functionality by methods. For example:
public void doSomething(Input input){
// Some functionality
}
The Input class can be basically anything. For example:
public class Input{
private String text;
private List<String> textList;
private InnerField inner;
private List<InnerField> innerList;
}
public class InnerField{
private String text;
pirvate Integer number;
}
The core module is collecting all methods of plugins and provides them to webpage user so the user can pick a method and set input data.
I know how to use java reflection api and get into metadata of methods and classes. The problem is with figuring out the structure of Class that would describe the Input and in same time store the data of Object.
In other words. I want to create a Class let's say InputData that i can pass to frontend which will:
build form based on fields declaration
fill form based on data
This InputData on submit would be serialized to json and saved in DB and, of course, should be mapped to original Input class so we can pass it to the plugin method.
I was thinking about something like this:
public class InputField{
private String className; //java.lang.String, some.package.CustomClass
private boolean variable; // if true, the strVal is a reference to other object (stored in map)
private String strVal; //value parsed to String if it's basic type like String, Integer, Boolean
private List<InputField> fields; //list of inner fields if it's complex type
}
And this would be good enough but only if the Input class would not have List types in it.
The one last kicker is that each field (even Input object itself) can be a referece to some variable.
So for example the user provided some values for Input class and want to reuse that so in form he just provides a name of the variable that it refers to. At the runtime when we invoke the plugin method the processor istead of parsing this json to data would search for data referenced by the variable name.
I know.. probably none of you know what i'm talking about but i'm in so awfull mindset that i can't even explain it well.
I am hoping that somone will kind of understand me and put me on the right tracks. Maybe someone had similar issue?
Edit: As requested below is short describtion what i really wanr to achive:
Basically i need a generic class in core module that will describe objects that are not known at compile time. From objects of this generic class i should be able to:
get metadata for building dynamic form in frontend and fill this form with data
map this object to original object (the one that is described by the generic class
generic class should be serializable (for example to json)
I "only" need help in generic class structure.
As i realized, thanks to Stephen, answers for "question" i asked would not be any help for anyone as i doubt someone would face exact same issue.
However, i figured out the right way to go for me. Frankly asking a question here was helpfull because trying to explain what i want achive made me think outside of the box.
Anyway. Earlier i was trying to keep Class definition along side with Object data in one Meta-Class. I separated those so i have class which holds definition about input class:
#Data
public class ObjectDefinition{
private String name;
private String path; // for example $root.myField.text, $root.listField[$idx].number
private Class type;
private boolean collection;
private boolean basicType;
private List<ObjectDefinition> fields; //only if this object is not basic
}
The values will be stored in a list of objects of class:
#Data
public class Field {
private String type;
private String path;
private String value;
private String var;
private boolean isCollection;
private int collectionSize;
}
Ugly? Maybe. Not efficent? Probably. Most important it will work and meets my requirements.
I want to validate all properties in an object A (say a). Class A has composite object B which has its own properties.
Class A
public Class A {
private String name;
private B b;
private Set<SomeObject> fields = new HashSet<SomeObject>();
//getter and setters for name and b
}
Class B
public Class B {
private String address;
private String dob;
//getter and setters for address and dob
}
-----EDIT -----
Class SomeObject
public Class SomeObject{
private Double amount;
//getter and setters for amount
}
Logic to get value name and object b using reflection
Field[] fields = a.getClass().getDeclaredFields();
for (Field field : fields) {
String fieldName = field.getName();
System.out.println(" *** Field Name *** " + fieldName);
field.setAccessible(true);
Object obj1 = field.get(a);
System.out.println(" *** Object 1 *** " + obj1);
}
--EDIT ---
I use reflection to get value of name dynamically. But how do I know there is property B which is a composite object or a Set of another object and I should apply reflection on B to get values of address and dob. Again how can I get values from Set and apply reflection on iteration. Is there a better solution without iteration.
Other way round, I should determine if a class is Wrapper class (String, Integer etc) or User defined class(User Defined Bean). If wrapper class/primitive then no getter invocation. Again If it is collection or something I should iterate and apply reflection on each Object to get amount
Is there any java API available which can do this level of data extraction from a complex object. eg EquiBuilder, BeanUtils etc
Can someone help.
You can use Field.getType().isPrimitive() to find out if a field is of a primitive type (int, bool, &c.). If it's not, you have some object type, and if the field's value is not null you should recursively traverse the referenced object's fields.
It seems there's no built-in way of discriminating between primitive wrappers and other Java classes. https://stackoverflow.com/a/1704658/1015327 has a suggestion for a work-around, manually gathering the primitive wrapper classes.
There is no simple or straightforward way to do what you want. There is a large number of possible field types. The field can be primitive, Collection, costume type, Date, UUID, JLabel, etc.
If you know the set of possible built-in types that you'll encounter, you might be able to hack your way through it. First get the type of the field, and then run the type through a series of checks against the possible types. If a match is found, cast and retrieve the value(s). If no match is found, then you can assume that this is a custom type with its own fields.
You still have to worry about custom types that extends built-in types (e.g. custom Map). Honestly, I don't think reflection is the way to go here.
I want to add new fields(variables) and encapsulating methods for a given class. For example: A class name Student has no any fields like below:
public class Student implements Serializable{
}
then in my application an instance is created;
Student s=new Student();
I want to add new methods which do not exist for student class at the run time.for example: I want to add a field called studentName, and getStudentName() and setStudentName() methods.
Then at the run time the student object will be like this;
public class Student implements Serializable{
private String studentName;
public void setStudentName(..){}
public String getStudentName(){return ...;}
}
In my application objects are written to a text file and all objects of same type do not have all variables. Therefore, I want to add only the required fields to save memory.
Any way is there a way to do this? Any sample code or link?
EDIT: or else can we create a class either and create instances which does not exists ?
EDIT 2: Thanks all of you answered and got many info and ideas. And changed the way to a better path from your suggestions as well
Why not just create a HashMap of values? Much more efficient, and has all the flexibility you're looking for.
public class Student
{
private HashMap<String, String> values;
public Student()
{
this.values = new HashMap<String, String>();
}
public void addValue(String name, String value)
{
values.put(name, value);
}
public String getValue(String name)
{
return values.get(name);
}
}
Why a HashMap?
You said that all objects may have differing values, and you'll be defining those new methods and attributes by a String. Well.. this will achieve that functionality without any horrible bytecode manipulation. For example:
String attrName = "name";
String attrValue = "jim";
Student stu = new Student();
stu.addValue(attrName, attrValue);
At the moment, you've only got the one value in your HashMap. The only overheard you have to face is the HashMap object itself, and two methods, which frankly is a fair trade off for a far tidier solution.
You can use bytecode instrumentation libraries like Javassist or ASM for this purpose. Here is an example of adding a field or method by using Javassist.
While it is possible with bytecode manipulation and such it wouldn't be wise, especially if you intend to do this to "save memory". It's unlikely that you would have so much data that it would make a difference, and if you did, you would store them in a database anyways.
Instead of writing your own HashMap based solution you can use DynaBean and DynaClass: support not only simple properties but also indexed (Array) and mapped (Map).
DynaBean can be introspected to get properties and values so you can dump to file BUT
with this solution you are only "simulating" a bean, your Student class doesn't really contains fields and accessors (you you call Student.getClass().getDeclaredField() you will get an empty array).
If you need to compose a "real" java java.lang.Class Javassist (my preferred choice, I used to resolve a solution similar to your question) or ASM (or CGLIB) are the best choiches.
I dont believe if this is possible in java but I'm sure it will only add to the memory because if you add them dynamically they must be set up beforehand + the code to add them dynamically.
Practically speaking, not in Java. In other languages like Javascript, this is possible.
Java is not a dynamic programming language and so I would not advice to follow that route even if some advance approaches may allow you to do so.
The Java idiom for that scenario would be to store the field values in a (hash) map instead. So you would have a couple of common accessors to set or get all attribute values and in the accessor you would need to indicate the name of the attribute you want to change.
However this solution won't save memory unless the maximum number of attributes is rather large and most object just have values for a small number of such attributes.
public class Entity {
// 5 is an estimate for the number attrs.
private Map<String,Object> attrs = new HashMap<>(5);
public Object getAttribute(String name) { return attrs.get(name); }
public void setAttribute(String name, Object obj) { attrs.put(name,obj); }
}
You could implement some runtime type-checking if you manage meta-data about possible attributes and their value types.
I have an abstract class that implements an interface. I then have several classes that extends that abstract class that are in turn composed of a hierarchy of some objects plus one or more Lists of objects extending the same abstract class, repeated for some levels. In essence,
public interface Bar
public abstract class BarImpl implements Bar
public class Foo extends BarImpl {
private String value1;
private String value2;
private List<Foo2> fooSubs;
public List<Foo2> getFooSubs() {
return fooSubs;
}
}
public class Foo2 extends BarImpl {
private String value3;
private String value4;
private List<Foo3> fooSubs;
public List<Foo3> getFooSubs() {
return fooSubs;
}
}
...etc...
The data in question is actually X12 healthcare claim data for those who are familiar. I've defined a Loop interface to correspond to the various loops that compose the X12 file.
My issues is this - I need to also be able to describe a single transaction, in theory using the same object or some wrapper on that object, where for some specified depth the size of each list of objects is 1.
My first though is/was to add a boolean singleTransaction to the BarImpl abstract class. Each class extending that would then have a check on the addFoo methods to make sure that the object did not grow beyond the single entry. Before converting to FooSingle I would check as well.
public void addFoo(Foo foo) throws FooException {
if (singleTransaction && fooSubs.size() >= 1)
throw new FooException();
else
fooSubs.add(foo);
}
I would also have to remove the setFoo method, so as to prevent an already-populated List from being assigned. Perhaps just make it final...
Does this seem like a reasonable way to go about this? I could then have a SingleBarImpl class that would verify it had a single path down the hierarchy, filter the boolean down, and could then safely assume that there was only one object-per-list for the specified classes. This could then simplify the access to the hierarchy since I no longer needed to worry about multiple list entires.
This feels very ugly is why I raise the question, and I wasn't quite sure what I should search on for an alternative. So I decided to stop lurking, create an account, and throw this out there. So...any ideas? Am I missing some design pattern that makes this much more elegant?
I am not familiar with X12 healthcare claim data and hence can't properly model the domain, but it sounds like you want to use the GOF composite pattern . A "Leaf" implementation class could easily replace your "singleTransaction" flag