Serialization problems: objects that depend on each other and ArrayLists - java

I have to serialize a project and it's the first time I use serialization. After getting informed about it, I thought of two possible problems: my classes have atributes which type is another different class that has atributes which type is the first class (explained poorly, but can see in the code) and the fact that I use ArrayLists (which I've read can't be serialized). So I decided to try with a very simplified version of the project:
A group, this containts an ArrayList of Person:
public class Group implements Serializable {
private static final long serialVersionUID = 1L;
private Person leader;
private List<Person> members;
private int number;
public Group(Person leader, int number) {
this.leader = leader;
this.number = number;
this.members = new ArrayList<Person>();
this.members.add(leader);
}
public void addMember(Person p) {
this.members.add(p);
}
public int getNumber() {
return number;
}
}
A person, this contains an ArrayList of Groups:
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private List<Group> groups;
private String name;
public Person(String name) {
this.name = name;
this.groups = new ArrayList<Group>();
}
public Group createGroup(int number) {
Group g = new Group(this, number);
this.groups.add(g);
return g;
}
public void joinGroup(Group g) {
this.groups.add(g);
g.addMember(this);
}
}
And a main method which creates a few groups and people and uses writeObject() to write them into a file, plus another main that uses readObject() to get the objects back (it only uses readObject() and prints them).
I didn't expect this to work for the reasons mentioned above, but it worked perfectly, so I tried to serialize my main project (way more complex) but it didn't work (huge stack trace, simply saying "User", which is the equivalent to person, is not serializable).
Is there any reason for this or any major flaw that I should take into account?
I apologize for not including the two main methods I use, as well as none of the stacktrace or the main project, but I didn't want to make this question extremely long.

my classes have atributes which type is another different class that has atributes which type is the first class (explained poorly, but can see in the code)
Incomprehensible. Both Java and Serialization handle circular dependencies, if that's what you're talking about.
and the fact that I use ArrayLists (which I've read can't be serialized)
Wrong.
simply saying "User", which is the equivalent to person, is not serializable
So User doesn't implement Serializable.
Is there any reason for this or any major flaw that I should take into account?
Make User implement Serializable.Same for any other class that gives you the same message.
You need to read the Object Serialization Specification and the relevant Javadoc, and stop relying on arbitrary Internet rubbish.

Related

Find object created inside a method in other class

For example, 2 class: Ticket and Customer
public class Ticket{
private String cstName;
public Ticket(String name){
this.cstName = name;
}
}
public class Customer{
private String name;
public void book(){
Ticket t = new Ticket(t);
}
}
How can I find and use t object elsewhere ???
What you ask for is completely impossible. An object is made, the object is assigned to a local variable, and the method ends.
As the method ends, all local variables (and t is a local variable), immediately go into the bin and there is nothing in java that lets you 'plug into' this process or that lets you stop this process. The variable is just gone.
The object is still on the heap somewhere, but no longer accessible. Eventually it will be garbage collected. There's nothing you can do about that, either. Java does not have a 'list all objects in the heap' method and never will.
You can mess with reference queues which is an extremely advanced topic that in no way is suitable given the way this question is stated, and wouldn't work for arbitrary methods like this.
If you control the code of Ticket itself you can save the reference as part of the constructor, which would be extremely bad design, and would have nothing at all to do with the notion of t, or that the book method made it.
What you presumably want, is a field:
public class Customer {
private String name;
private Ticket ticket;
public void book() {
this.ticket = new Ticket(t);
}
public Ticket getTicket() {
return this.ticket;
}
}
and now you could do:
Customer c = new Customer();
c.book();
Ticket t = c.getTicket();
or perhaps do:
public class Customer {
private String name;
private Ticket ticket;
public Ticket book() {
this.ticket = new Ticket(t);
return this.ticket;
}
}
and now you could do:
Customer c = new Customer();
Ticket t = c.book();

Java - Possible use of Strategy Design Pattern?

public class ClassA_V01 {
private String name;
private int age;
// getter and setter
}
public class ClassA_V02 {
private String name;
private int age;
private int gender;
// getter and setter
}
public static void main(String[] args) {
SomeClass classA = new ClassA_V01();
classA.setName("myName);
classA.setAge(99);
performLogic(classA);
// OR
SomeClass classA = new ClassA_V02();
classA.setName("myName);
classA.setAge(99);
classA.setAge(1);
performLogic(classA);
}
public void performLogic(SomeClass classA) {
// do something
}
For strategy pattern to work, both classes must implement the same methods defined in the interface. But what if the classes need to have different fields and methods?
In my example, ClassA_V01 and ClassA_V02 are the same class except that one has more attribute "gender"
How does one implement the above such that classA can be equals to either ClassA_V01() or ClassA_V02?
"...For strategy pattern to work, both classes must implement the same methods defined in the interface. But what if the classes need to have different fields and methods?..." really this is not a criteria for strategy pattern.
Strategy pattern's intent is to identify and make family of algorithms interchangeable. If you read the pattern's documentation carefully, Strategy can be used when many related classes differ only in their behavior.
Appropriate decomposition is the key for better (extendable) design. A typical (but primitive) solution to Employee assignment, sub-classing tempEmp and permanentEmp types will put us in trouble and will not allow temp employee to become permanent in its life time (which has no meaning in real terms). This happens because we miss an important point- each employees employeeness is not different, they are all same type of employees with different pay policies. (same logic can be extended for Leave policy and so on)
This becomes simple if all types of employees have Salary computation based on same components (same state). But your question is what if TempEmployee gets only basicPay whereas PermanentEmployee gets basicPay as well as travelAllowance (additional attribute which is not present for TempEmp). This can be modeled by a combination of simple inheritance hierarchy along with strategy taking care of computation algorithm dependent upon Employee's (aka. Context) attribute (age)
public class Employee {
//name and id
private PayPackage payPackage;
private int age;
PayPackage strategy;
public double computeSalary() {
return payPackage.computePay(age);
}
//get/setPayPackage(...)
}
public abstract class PayPackage {
private double basicPay;
abstract public double computePay(int age);
protected double getBasicPay(){
return basicPay;
}
}
public class TempPayPackage extends PayPackage{
#Override
public double computePay(int age) {
double veteranAllowance = 0;
if (age > 40) {
veteranAllowance = 2000.00;
}
return getBasicPay() + veteranAllowance;
}
}
public class PermanentPayPackage extends PayPackage{
private double travelAllowance;
#Override
public double computePay(int age) {
double veteranAllowance = 0;
if (age > 40) {
veteranAllowance = 5000.00;
}
return getBasicPay() + travelAllowance + veteranAllowance;
}
}
Important thing to remember is Design patterns never work alone or as an alternative, they work hand in hand with Object oriented code and other patterns.

java nested builder pattern duplicate fields

The nested builder patterns that I've come across online usually have something like this:
class Person{
private int id;
private String name;
private int age;
... so on
private Person(Builder builder){
this.id = builder.id;
this.name = builder.name;
this.age = builder.age;
}
public static class Builder{
private int id;
private String name;
private int age;
... so on
public Builder id(int id){
this.id = id;
return this;
}
public Builder name(String name){
this.name = name;
return this;
}
.... so on
public Person build(){
return new Person(this);
}
}
}
My question is, is it necessary to duplicate fields in Person and Builder? It seems like a lot of redundant code. And my second question is, would the following code be a viable replacement, why or why not?
class Person{
private int id;
private String name;
private int age;
... so on
private Person(){}
public static class Builder{
private Person person = new Person();
public Builder id(int id){
this.person.id = id;
return this;
}
public Builder name(String name){
this.person.name = name;
return this;
}
.... so on
public Person build(){
return person;
}
// UPDATED -- another build method
public Person build(){
Person built = this.person;
this.person = new Person();
return built;
}
}
}
Note: I understand this topic may be opinionated and there may not be a "right" answer, but I just want to hear different ideas and opinions. I'm not looking for the ultimate truth.
Your code would be fine as long as:
you keep your Person member variables private (you are doing so)
you don't provide methods that allow modification of those member variables (the code you show does not do, but you have omitted parts of it)
those member variables are immutable or you ensure getters provide copies of them. usually better that the members are already immutable (hint: even java collections). otherwise you will be creating instances on each getX call.
once Builder.build is called, noone must be able to modify Person instance state, not even Builder itself. this is not happening in the code you posted
builder does not expose "temporal instance" being built (if any at all). No instance must be exposed aside the return of build method.
there are opinions about which is the preferred way or not, matter of taste most of the time. But in terms of being right or not, that approach would be fine with some modifications. At the end, what happens before the build is called is purely internal to the Builder. It's an implementation matter. The important thing is that the previous rules are met.
To fix rule 4: your Builder.build method should return a deep clone of the temp instance being used (there are ways to achcieve that without needing to specify each field). Or, you should have a flag in builder that forbids calling any other method on Builder instance, once build has been called.
Side note: i usually prefer that Builder class also uses private constructor. I would have this on Person class:
public static Builder builder() {
return new Builder();
}
This can give you more flexibility on the way to initialize the Builder, or even you can have several builder methods doing not exactly the same stuff in terms of "preconfiguring" the builder (and since they are methods, you have more flexibility on naming than on constructors :) )

Is this an example of anti-pattern?

Me and one of my colleague were trying to solve the following problem:
Lets take an example of class A
One of my colleagues was facing problem of extracting one particular property from A.
Fetching one property from One particular class (in this case A) is easy. but lets
assume that you have multiple classes (A1, A2...) and you want to fetch one
particular property from the collection of these classes with more and more reusability of code.
for example
public class A {
private String name;
.
.
.
}
List<String> listOfNames = createNameList(listOfAInstances);
createNameList() method would be like following:
List<String> tempList = new ArrayList<>();
for(A a : listOfAInstances) {
tempList.add(a.getName());
}
return tempList;
now if there are multiple classes I have to do this for each class and different properties.
I suggested two approaches:
Reflection based approach.
Create an interface called "PropertyExtractable" and put a method in it called "extractProperty" in it.
As shown below:
interface PropertyExtractable {
Object extractProperty();
}
public class A implements PropertyExtractable {
private String name;
.
.
.
public Object extractProperty() {
return this.name;
}
}
For this I can write some utility method which then can be used everywhere i.e.
public Object getPropertiesOfPropertyExtractable(PropertyExtractable prExtractable) {
return prExtractable.extractProperty();
}
This was the background, one other colleague of mine had different opinion about 2nd approach, he told me it seems like anti-pattern. He tried to explain to me but I didn't get it entirely so and hence I am asking here.
I am trying to compare this example with the Comparator interface in Java. Like java allows us to use Comparator on any of the custom object class and allows us to define the logic for comparison then why can't I define the logic for extraction
Further more interfaces can be used in this way, then why shouldn't we use it
I want to know is this approach an anti-pattern? why?
You can place extracting code in separate method and reuse it:
class A {
private String name;
public String getName() {
return name;
}
}
class B {
private String surname;
public String getSurname() {
return surname;
}
}
public class SomeClass {
private <T> List<String> extractFields(List<T> list, Function<T, String> extractorFunction) {
return list.stream().map(extractorFunction).collect(Collectors.toList());
}
public void someMethod() {
List<A> listOfInstancesA = new ArrayList<>();
List<B> listOfInstancesB = new ArrayList<>();
// fill lists
List<String> fieldsA = extractFields(listOfInstancesA, A::getName);
List<String> fieldsB = extractFields(listOfInstancesB, B::getSurname);
}
}
The situation you describe is working with a legacy system which you don't want to change.
Since if you weren't you'd introduce an interface for the common properties (like your example for the Comparator interface). You introduced an interface without a meaning which may be an anti-pattern since you actually need a functional interface: PropertyExtractable vs. NamedObject=> has a method: String getName()).
If you want to implement Reflection, then your interface may be correct but I don't see it (e.g. in your case you already have Reflection built in into Java).
Usually you use the Adapter pattern to get a property/method from an object which doesn't implement the requested interface.

Different methods need different attributes in one object

I have a given web service. (This is only an example, the real one is more complex, but it has the same problem.) The service has three methods and all three methods have a person as parameter and need other things from it. (I can't change the entity or methods.)
Entity (Person) (It has only a default constructor):
private String name;
private int age;
private Address address;
private List<String> hobbies;
private List<Person> friends;
Method1 needs name and age.
Method2 needs address name and age.
Method3 needs all.
I need to fill the object from my own objects. I need to write a "converter". What is the best practice for it?
My solutions:
Builder Pattern with builds for three methods.
Set all attributes and send unhandled overhead (bad solution in my eyes).
Creating a builder that sets only required fields sounds good.
You can inherit from this class for each of your needs and implement your own constructors
public class Target {
// fields
}
public class Purpose1 extends Target {
public Purpose1(String name, int age) {
// set fields or do whatever you wish
}
}
public class Purpose2 extends Target {
public Purpose2(String address, String name, int age) {
// set fields or do whatever you wish
}
}
public class Purpose3 extends Target {
public Purpose3(...) {
// set fields or do whatever you wish
}
}
And then you may use instances of subclasses where class Target is required.
I think you can get what you want with a suitable usage of decorator pattern:
https://en.wikipedia.org/wiki/Decorator_pattern

Categories

Resources