Writing/reading an ArrayList of Parcelable objects - java

I have a class called ClassA which contains a List of ClassB objects. Both classes implement Parcelable.
I am trying to create the read/write methods for this list in ClassA and am having trouble. For example I tried:
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeList(mClassBList);
}
but then
private ClassA(Parcel in) {
mClassBList = in.readList();
}
throws an error because it needs all these extra arguments.
How do I correctly read/write this List?

The links suggested by both George and buczek can be really helpful in your case.
Perhaps more directly, you need to do something like this:
//Supposing you declared mClassBList as:
List<ClassB> mClassBList = new ArrayList<ClassB>();
in.readTypedList(mClassBList, ClassB.CREATOR);
I still recommend you check out the answer, especially (as suggested by Buczek) How to pass a parcelable object that contains a list of objects?

Related

Accessing attributes, methods of different class objects stored inside an object type Arraylist

I have different weapon classes with various attributes and functions (some of which are similar). I am trying to iterate through objects of classes and trying to access those attributes based on certain conditions. Below are some of the objects I created and am storing inside an ArrayList of type Object.
Ak117 ak117 = new Ak117();
Ak47 ak47 = new Ak47();
Bk57 bk57 = new Bk57();
ArrayList <Object> weaponObjects = new ArrayList<>(Arrays.asList(ak117, ak47, bk57);
int damage = weaponObjects.get(0).damageStats;
//damage stats is an integer inside AK117 class that returns its damage
When I do this Eclipse can't identify .damageStats; and throws an error.
Is there any way wherein I can access all attributes or methods of these objects?
You can use Interface or Abtract class
Example
Create an interface that contains all the common methods of the classes:
public interface Weapon{
int getDamageStats();
void shoot();
// more method
}
Creat class implements this interface
class Ak47 implements Weapon{
#Override
public int getDamageStats() {
return 100;
}
#Override
public void shoot() {
System.out.println("Ak shoot");
}
}
class Bk47 implements Weapon{
#Override
public int getDamageStats() {
return 500;
}
#Override
public void shoot() {
System.out.println("Bk shoot");
}
}
Call List by Weapon:
Ak47 = new Ak47();
Bk47 = new Bk47();
ArrayList <Weapon> weaponsList = Arrays.asList(ak47, bk47);
int damage = weaponsList .get(0).getDamageStats();
you need something like the below:
ArrayList <Weapon> weaponsList = Arrays.asList(ak117, ak47, bk47);
If you only store the Objects you can only call the Object's methods for each array list entry. If you use Weapon (an interface for all weapons that defines getDamageStats()) all subclasses can then have this method called.
You need to write a getter in every weapon class.
public class Ak47 {
int damageStats;
public int getDamageStats() {
return damageStats;
}
}
You can access damageStats in another class by creating an instance of Ak47 and calling the getDamgeStats on it.
public class Example {
Ak47 ak47 = new Ak47();
int example = ak47.getDamageStats();
}
I think you should rethink adding inheritance, I am not a gun expert but maybe by country idk. Another option is with abstract class and just throw the methods that are common and modify the others. Then just like Rob Evans said iterate over a list, but my advise is to use new ArrayList<>(new Ak47(), ...etc) and not Arrays.asList.
Yep, this is a casual problem with the Object class. If you initiate your ArrayList as an Object, as someone already said, you'll only be able to reach Object Class's methods. By what you sent, we can think that your other classes share communs attributes. So the best idea would be to pass by a SuperClass, which will be extended by every others classes and have a getter on it (in this case, a getDamageStats()). Then you initiate your ArrayList as the SuperClass instead of Object and you'll be able to reach what you seem to want

Proper way to create an new parcelable object

I have a class model called "Car".
If I want to create a new object of "Car" I can do something like this:
Car car = new Car();
But now, I made this class implements Parcelable. What is the best way of creating a new object of the class "Car"?
Right now I am doing this way:
Car car = new Car("blue");
And I am adding a new constructor to my model Class:
public class Car implements Parcelable {
public String color;
#Override
public int describeContents() { return 0; }
#Override
public void writeToParcel(Parcel dest, int flags) { dest.writeString(color); }
public static final Creator<Car> CREATOR = new Creator<Car>() {
public Car createFromParcel(Parcel in) { return new Car(in); }
public Car[] newArray(int size) { return new Car[size]; }
};
private Car(Parcel in) { color = in.readString(); }
public Car(String myColor) { color = myColor; }
}
Since I am new to this class Parcelable I'm not sure if this is the best aproach. Is anything bad having two constructors in my class? Is there any other more efficient way to do this?
I am afraid that adding this second constructor my application should lose some performance in creating new objects of this class.
Since I am new to this class Parcelable I'm not sure if this is the best aproach. Is anything bad having two constructors in my class? Is there any other more efficient way to do this?
It depends what you need, but your implementation of parcelable patters seems to be okey.
If u need to pass efficiently your object throught intent or arguments bundle, it is best approach. Parcelable is android more efficient implementation of class serialization.
If you want little less optimal (but easier) you could use serializable, this is default java approch, it's a bit slower, and has its own drawbacks ^^.
And if more important for you is readability of generated state (parcelable and serializable will make a byte stream from your object), you might want to use Json convertion (and for that i would suggest gson.
I am afraid that adding this second constructor my application should lose some performance in creating new objects of this class.
There is nothing wrong with multiple constructors. They are simply, a way to initialize your object state. Nothing more nothing less.
PS: For your old method of creating a car to work:
Car car = new Car();
Simply add empty constructor:
public Car() { }
Cheers.

How can I use multiple objects in the same fashion?

I am looking for help with having multiple different types of system accessed within java as if they are the same.
For example, I have the classes
private class SystemA{
public void in(boolean input){
//do x;
}
public boolean out(){
//return x;
}
}
Say I want to have an ArrayList of different systems. These systems all implement the functions in and out like SystemA does, but they will be different objects all with different internal architectures.
I would like to for example iterate through the aformentioned arraylist, calling out() on all of the objects - how can I:
Store multiple different object types.
Ensure that I can call the in and out functions on the object in the arraylist, not needing to worry that the object is one specific type or another.
Let your system classes implement a new MySystem interface:
public interface MySystem {
void in(boolean input);
boolean out();
}
E.g.:
private class SystemA implements MySystem {
#Override
public void in(boolean input) { ... }
#Override
public boolean out() { ... }
}
Your ArrayList will then look like any of these:
List<MySystem> list = new ArrayList<MySystem>();
List<? extends MySystem> list = someFactoryMethod();
I suggest reading the Java tutorial "What Is an Interface?" for more details. Also, read up on "subtype polymorphism" in general.
That's a broad question. What you need is polymorphism. Read about Java polymorphism here: http://home.cogeco.ca/~ve3ll/jatutor5.htm

Extending a non-generic class to a generic class

The Java class CircularFifoBuffer in the package org.apache.commons.collections.buffer is non-generic, and can store objects of any class.
I would like to create a generified version of this, that can only hold objects of class T. My first thought was to extend CircularFifoBuffer and simply write a new 'add' method:
public class CircularFifoQueue<T> extends CircularFifoBuffer {
public boolean add(T data) {
return super.add(data);
}
}
However, this leaves the old 'add' method in place, allowing for objects of arbitrary class to be added. Is there a way around this that uses inheritance rather than composition (so that I don't have to re-implement all of CircularFifoBuffer's methods) but prevents users of the class from adding non-T objects?
One idea is t implement your own buffer that just wraps the original one:
public class CircularFifoQueue<T> {
private CircularFifoBuffer buffer = new CircularFifoBuffer();
public boolean add(T data) {
return buffer.add(data);
}
// implement all other methods that are needed
}
So the internal buffer takes everything but the wrapper makes sure that only T type objects can be added. Problem: right now the buffer does not implement any interface. So it's usage is a bit limited right now (you can't use it if you need to send a Buffer for example)
No, you can't.
The simple reason why this isn't possible is polymorphism. If you could remove the add(Object) method, you would break polymorphism for the CircularFifoBuffer class.
Here is a simple example. For this to work correctly, your CircularFifoQueue class needs to have a add(Object) method.
CircularFifoBuffer buffer = new CircularFifoQueue<String>();
buffer.add(new Object());
#Vivien's answer already explains why it doesn't really make sense to do this (for more information, read about the Liskov substitution principle).
However, you could hack around this by defining a custom override of add(Object) that simply throws an exception at run-time. It's not a very elegant solution, but if you want a quick fix, then this might be it.
You can try the following approach. It is not very elegant, but it should do the job:
public class CircularFifoQueue<T> extends CircularFifoBuffer {
private Class<T> klass;
public CircularFifoQueue(Class<T> klass) {
this.klass = klass;
}
#Override
public boolean add(Object data) {
T typedData = klass.cast(data);
return super.add(typedData);
}
public boolean add(T data) {
return super.add(data);
}
}
...
CircularFifoQueue<String> queue = new CircularFifoQueue<String>(String.class);
queue.add("hello"); // should work
queue.add(123L); // should throw ClassCastException
Anyway, implementing a class that delegates its method calls is not very hard. Any decent IDE will autogenerate that for you.

Java Decorating The Easy Way

Say you have an API that is not accessible to change:
List<LegacyObject> getImportantThingFromDatabase(Criteria c);
Imaging Legacy Object has a ton of fields and you want to extend it to make getting at certain information easier:
class ImprovedLegacyObject extends LegacyObject {
String getSomeFieldThatUsuallyRequiresIteratorsAndAllSortsOfCrap() {
//cool code that makes things easier goes here
}
}
However, you can't just cast to your ImprovedLegacyObject, even though the fields are all the same and you haven't changed any of the underlying code, you've only added to it so that code that uses LegacyObject still works, but new code is easier to write.
Is it possible to have some easy way to convert LegacyObject to ImprovedLegacyObject without recreating all of the fields, or accessors? It should be a fast opperation too, I konw you could perform something by using reflections to copy all properties, but I don't think that would be fast enough when doing so to masses of LegacyObjects
EDIT: Is there anything you could do with static methods? To decorate an existing object?
You would have to perform the copying yourself. You can either have a constructor that does this (called a copy constructor):
public ImprovedLegacyObject(LegacyObject legacyObject) {
...
//copy stuff over
this.someField = legacyObject.getSomeField();
this.anotherField = legacyObject.getAnotherField();
...
}
or you can have a static factory method that returns an ImprovedLegacyObject
public static ImprovedLegacyObject create(LegacyObject legacyObject) {
...
//copy stuff over
...
return improvedLegacyObject;
}
If you're planning on extending this behavior to other legacy objects, then you should create an interface
public interface CoolNewCodeInterface {
public String getSomeFieldThatUsuallyRequiresIteratorsAndAllSortsOfCrap() {
}
public String getSomeFieldInAReallyCoolWay() {
}
}
Then your ImprovedLegacyObject would look like this:
public ImprovedLegacyObject extends LegacyObject implements CoolNewCodeInterface {
//implement methods from interface
}
How about making a copy constructor for your Improved Legacy Object that takes a Legacy Object as an argument. Then just create new objects from the old ones.

Categories

Resources