I have seen someone's code and unable to understand how it works.
As the code save List of object in list of Interfaces and can read it back.
Please explain how it works. And can we save Object in interface (where Object implements it). AFAIK interface doesn't have members. How this code save and retrieve please explain.
ContactBO implementing BusinessObject
public class ContactBO implements BusinessObject {
private String id, fullName, department, ;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
#Override
public boolean isSection() {
// TODO Auto-generated method stub
return false;
}
}
Where BussinessObject
public interface BusinessObject {
boolean isSection();
}
Saving list of Contact code
List<ContactBO> contactList = new Gson().fromJson(jsonArray.toString(),
new TypeToken<List<ContactBO>>() {}.getType());
List<BusinessObject> list = new ArrayList<BusinessObject>();
list.addAll(contactList);
read List of ContactBO using List of Interface
List<ContactBO> contactListItems = (List<ContactBO>) (List<?>) result.list;//where list is public List<BusinessObject> list;
Here is what I can understand from the source.
List<ContactBO> contactList = new Gson().fromJson(jsonArray.toString(),
new TypeToken<List<ContactBO>>() {}.getType());
This does not mean
As the code save List of object in list of Interfaces and can read it
back
The above line converts response using GSON to a List object of type ContactBO.
By implementing BusinessObject interface, ContactBO is still a class and not an interface.
Now the next line
List<BusinessObject> list = new ArrayList<BusinessObject>();
This again creates a List of type BusinessObject
Now the following line. list.addAll(contactList); Adds object of type ContactList to super object which is of type BusinessObject
"Polymorphism is the ability of an object to take on many forms. The most common use of polymorphism in OOP occurs when a parent class reference is used to refer to a child class object."
List<BusinessObject> list = new ArrayList<BusinessObject>();
This line basically show Polymorphsim concept, Parent class reference can hold the Child class object.
When you cast an object of a class into an interface, which that class implements you can only access implemented method(s) that the interface has.
Related
I have this code to create a class User
public class User {
private String name;
private ArrayList<User> owners = new ArrayList<>();
public User(String name, ArrayList<User> owners) {
this.name = name;
this.owners = owners;
}
public String getName() {
return name;
}
public void addOwner(User owner) {
owners.add(owner);
}
If i create an instance of this class with
User jhil = new User(name, new ArrayList<>());
What do i do to add a string element to the arraylist
I've tried with the addOwner method with
jhil.addOwner(jhilsara);
but i get a the method addOwner(String) is undefined for the type User error
I've also tried with the ArrayList add method
jhil.add(jhilsara);
But that doesn't work either.
So my question is what do i need to do in order to add something to the arraylist of an instanced of my class User
You have your ArrayList set to contain objects of the User class, not Strings. Change the declaration of it to:
private ArrayList<String> owners = new ArrayList<>();
Then, you also have to change addOwner to:
public void addOwner(String owner) {
owners.add(owner);
}
public static final Parcelable.Creator<MyParcelable> CREATOR
= new Parcelable.Creator<MyParcelable>() {
public MyParcelable createFromParcel(Parcel in) {
return new MyParcelable(in);
}
public MyParcelable[] newArray(int size) {
return new MyParcelable[size];
}
};
private MyParcelable(Parcel in) {
mData = in.readInt();
}
}
During my Android course, the instructor used this block of code and they didn't quite explained this. How can I interpret this code? I tried reading the documentation but I failed to interpret.
This concept is called Parcelable
A Parcelable is the Android implementation of the Java Serializable. It assumes a certain structure and way of processing it. This way a Parcelable can be processed relatively fast, compared to the standard Java serialization.
To allow your custom object to be parsed to another component they need to implement the android.os.Parcelable interface. It must also provide a static final method called CREATOR which must implement the Parcelable.Creator interface.
The code you have written will be your model class.
You can use Parcelable in Activity like :
intent.putExtra("student", new Student("1")); //size which you are storing
And to get this object :
Bundle data = getIntent().getExtras();
Student student = (Student) data.getParcelable("student");
Here Student is a model class name. replace this with yours.
In simple terms Parcelable is used to send a whole object of a model class to another page.
In your code this is in the model and it is storing int value size to Parcelable object to send and retrieve in other activity.
Reference :
Tutorial 1
Tutorial 2
Tutorial 3
--> Parcelable in Android
The Bundle object which is used to pass data to Android components is a key/value store for specialized objects. It is similar to a Map but can only contain these specialized objects
You can place the following objects types into a Bundle:
String
primitives
Serializable
Parcelable
If you need to pass your customer objects via a Bundle, you should implement the Parcelable interface.
--> Implementing Parcelable
You can create a POJO class for this, but you need to add some extra code to make it Parcelable. Have a look at the implementation.
public class Student implements Parcelable{
private String id;
private String name;
private String grade;
// Constructor
public Student(String id, String name, String grade){
this.id = id;
this.name = name;
this.grade = grade;
}
// Getter and setter methods
.........
.........
// Parcelling part
public Student(Parcel in){
String[] data = new String[3];
in.readStringArray(data);
this.id = data[0];
this.name = data[1];
this.grade = data[2];
}
#override
public int describeContents(){
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeStringArray(new String[] {this.id,
this.name,
this.grade});
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public Student createFromParcel(Parcel in) {
return new Student(in);
}
public Student[] newArray(int size) {
return new Student[size];
}
};
}
Once you have created this class, you can easily pass objects of this class through the Intent like this, and recover this object in the target activity.
intent.putExtra("student", new Student("1","Mike","6"));
Here, the student is the key which you would require to unparcel the data from the bundle.
Bundle data = getIntent().getExtras();
Student student = data.getParcelable("student");
This example shows only String types. But, you can parcel any kind of data you want. Try it out.
I would like to make a generic method to get a List from the parameter object.
The problem is because I have a declared object with a instance of the other class that extends the declared class.
I don't want to use the instanceof solution because the number of classes that extends LimitedValue can be big.
I thought to use reflection for a solution, but I don't know how to use that with an instance of object, in this part of the code:
Class cls = Class.forName(limitedValue.getClass().getName());
Object obj = cls.newInstance();
//This is wrong, I don't want a new instance.
Method[] methods = cls.getDeclaredMethods();
for(int x= 0; x < methods.length; x++) {
Method method = methods[x];
if ("java.util.List".equals(method.getReturnType().getName())) {
//How to get the value of this method from limitedValue instance ?
}
}
This is my full code:
public class CalculatorLimitedValue {
public static void main(String[] args) throws Exception {
StoreItem storeItem = new StoreItem(1L, "Name of StoreItem", 50L);
List listOfStoreItems = new ArrayList();
listOfStoreItems.add(storeItem);
LimitedValue limitedValue0 = new Store(listOfStoreItems);
List firstList = calculator(limitedValue0);
//do something with the list
SupermarketItem supermarketItem = new SupermarketItem(1L, "Name of SupermarketItem", 21L);
List listOfSupermarketItems = new ArrayList();
listOfSupermarketItems.add(supermarketItem);
LimitedValue limitedValue1 = new Supermarket(listOfSupermarketItems);
List secondList = calculator(limitedValue1);
//do something with the list
}
/** This is the method that I'd like to make generic to return a List */
private static List calculator(LimitedValue limitedValue) throws Exception{
Class cls = Class.forName(limitedValue.getClass().getName());
Object obj = cls.newInstance();
//This is wrong, I don't want a new instance.
Method[] methods = cls.getDeclaredMethods();
for(int x= 0; x < methods.length; x++) {
Method method = methods[x];
if ("java.util.List".equals(method.getReturnType().getName())) {
//How to get the value of this method from limitedValue instance ?
}
}
/* I don't want to use this one way, because my classes that extends LimitedValue
can be big. I would like to made a generic way to get de list of classes. */
if (limitedValue instanceof Store) {
System.out.println("This is a store");
return ((Store) limitedValue).getStoreItems();
} else if (limitedValue instanceof Supermarket) {
System.out.println("This is a supermarket");
return ((Supermarket) limitedValue).getSupermarketItems();
}
return null;
}
}
If it help, these are my other classes:
LimitedValue.class
public class LimitedValue { }
StoreItem.class
public class StoreItem {
private Long id;
private String nameOfStoreItem;
private Long valueOfStoreItem;
public StoreItem(Long id, String nameOfStoreItem, Long valueOfStoreItem){
this.id = id;
this.nameOfStoreItem = nameOfStoreItem;
this.valueOfStoreItem = valueOfStoreItem;
}
//getters and setters...
}
SupermarketItem.class
public class SupermarketItem {
private Long id;
private String nameOfSupermarketItem;
private Long valueOfSupermarketItem;
public SupermarketItem() {
}
public SupermarketItem(Long id, String nameOfSupermarketItem, Long valueOfSupermarketItem) {
this.id = id;
this.nameOfSupermarketItem = nameOfSupermarketItem;
this.valueOfSupermarketItem = valueOfSupermarketItem;
}
//getters and setters...
}
Store.class
public class Store extends LimitedValue {
private List<StoreItem> storeItems;
public Store(List<StoreItem> storeItems) {
this.storeItems = storeItems;
}
//getters and setters
}
Supermarket.class
public class Supermarket extends LimitedValue {
private List<SupermarketItem> supermarketItems;
public Supermarket(List<SupermarketItem> supermarketItems) {
this.supermarketItems = supermarketItems;
}
//getters and setters
}
You could try to use reflection here to try to achieve what you want, but it would be better to reconsider your overall design and try to use a better object oriented design that solves the problem at hand.
In particular, lets say we consider adding a method called getItems to the LimitedValue class that returns a List of items, which may be SupermarketItems or may be StoreItems. If it is structured correctly, you won't need to know the actual type because the code will be abstracted over it polymorphically.
public abstract class LimitedValue {
List<? extends Item> getItems();
}
We've now defined a new method on LimitedValue, but we also have to consider that we've introduced this new Item thing. I note that the SupermarketItem and StoreItem all share similiar attributes, name, id and value, so it seems that it might be possible to use a single class to represent them all.
public abstract class Item {
final Long id;
final String name;
final Long value;
public Item(final Long id, final Long name, final Long value) {
this.id = id;
this.name = name;
this.value = value;
}
String getName() {
return name;
}
// other getters and setters
}
public class SupermarketItem extends Item {
public SupermarketItem(final Long id, final Long name, final Long value) {
super(id, name, value);
}
}
public class StoreItem extends Item {
public StoreItem(final Long id, final Long name, final Long value) {
super(id, name, value);
}
}
Now we've completely abstracted away the need for any reflection when accessing these objects - you can simply call item.getValue() as you will know that every item in the list is of type Item.
Of course, you'll also need to refactor the Store and SuperMarket classes, for example:
public class Supermarket extends LimitedValue {
private List<SupermarketItem> supermarketItems;
public Supermarket(List<SupermarketItem> supermarketItems) {
this.supermarketItems = supermarketItems;
}
public List<? extends Item> getItems() {
return supermarketItems;
}
}
and because you are only returning a List<Item> you always know what is in it, and you can change your main code to work with this.
This is a much cleaner long term solution.
To get the List value, use Method#invoke:
List list = method.invoke(limitedValue);
You don't need Object obj = cls.newInstance(); - you're not using it at all in the method.
In any case, you're making it very difficult for yourself. You could also define an interface
public interface HasList<E> {
List<E> getList();
}
and have all classes implement this.
I have to implement the following class diagram to the java code. This diagram is very complicated and some parts creates confusion. This question definitely going to help me a lot as well as any reader because it contains several important aspects of UML diagram.
class Book{
String isbn;
String publisher;
String publishDate;
int pages;
}
class BookItem extends Book{
String barcode;
boolean isReferenceOnly;
}
class Author{
String name;
String biography;
Collection<Book> book;
}
class Account{
String number;
List<History> history;
String openDate;
AccountState state;
public Account(AccountState state){
this.state = state;
}
}
enum AccountState{
Active,
Frozen,
Closed
}
class Catalog implements Search, Manage{
List<BookItem> bookItem;
/* Implement the methods of Manage interface */
void add(BookItem item){ }
void remove(BookItem item){ }
/* Implement the methods of Search interface */
int search(BookItem item){ }
}
class Account{
String number;
List<History> history;
Student student = new Student();
void setStudent(Student student){
this.student = student;
}
}
interface Search{
int search(BookItem item);
}
interface Manage{
void add(BookItem item);
void remove(BookItem item);
}
class Student{
String name;
String address;
Search searchBook = new Catalog();
}
class Librarian{
String name;
String address;
String position;
Search searchBook = new Catalog();
Manage manage = new Catalog();
Account account = new Account();
void setAccount(Account account){
this.account = account;
}
class Library{
String name;
String Address;
List<BookItem> bookItem = new ArrayList<BookItem>();
Catalog catalog = new catalog();
List<Account> accounts = new ArrayList<Account>();
Library(Catalog catalog){
this.catalog = catalog;
}
void setBookItem(List<BookItem> bookItem){
this.bookItem = bookItem;
}
void setAccounts(List<Account> accounts){
this.accounts = accounts;
}
}
I implemented in the following way but confusion arise in various cases:
How to implement Class Student use the interface Search.
How to implement Class Librarian use the interfaces Search and Manage.
Why we are not use association instead of usage dependency.
How to implement that Enumeration data type in this case with usage dependency [I have just considered AccountState as a class, i the it is a wrong implementation].
How to use AccountState in the Account [I have just created a object of AccountState].
After read many blogs still unable to implement Aggregation and Composition confidently. Note: In this diagram 3 Aggregations and 1 Composition Exist. Those are:
(a) Library consists of many Account. {Aggregation}
(b) Many Book Item is the part of Library. {Aggregation}
(c) An Account is the part of a Student. {Aggregation}
(d) Library must have a Catalog. {Composition}
Please give your valuable advice so i can learn it well. Thanking you.
Since this question is homework for learning purposes, I will post only examples of how to implement the things you need to review and won't give a direct answer about how to apply them to your current design.
Enumeration in Java is implemented by using enum.
enum WeekDays {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY;
}
Aggregation/Composition means to have a field of the other class. If it's a weak association (aggregation), it should be initialized by the setter or another method. If it's a strong association, it should be initialized in the class constructor since it is needed for the class to live/work.
class WeakAssociation { }
class StrongAssociation { }
class NeedWeekAndStrongAssociation {
private WeakAssociation weakAssociation;
private StrongAssociation strongAssociation;
public NeedWeekAndStrongAssociation(StrongAssociation strongAssociation) {
this.strongAssociation = strongAssociation;
}
public void setWeakAssociation(WeakAssociation weakAssociation) {
this.weakAssociation = weakAssociation;
}
}
Usage dependency means that the class/interface will use the other class/interface within one or more of its methods:
class WantToBeUsed {
public void methodToBeUsed(String data) {
//fancy implementation
}
}
class CannotDoThisAlone {
public void cannotDoItAlone(String data) {
WantToBeUsed wantToBeUsed = new WantToBeUsed();
wantToBeUsed.methodToBeUsed(data);
}
}
Well, i was trying to pass arraylist of objects from one activity to another. I have 2 constructors in the class Student.
If, i use, Serializable than the code is like below:
#SuppressWarnings("serial")
public class Student implements Serializable
{
private int studentdID;
private String studentName;
private String studentDept;
public Student(){}
public Student(String name, String dpt)
{ this.studentName = name;
this.studentDept = dpt;}
public Student(int id, String name, String dpt)
{ this.studentdID = id;
this.studentName = name;
this.studentDept = dpt; }
public int getstudentdID() { return studentdID; }
public void setstudentdID(int studentdID) {this.studentdID = studentdID;}
public String getstudentName() { return studentName;}
public void setstudentName(String studentName) {this.studentName = studentName;}
public String getstudentDept() { return studentDept; }
public void setstudentDept(String studentDept) { this.studentDept = studentDept;}
}
But the problem i am facing is that how am i going to do this with parcelable? How am i going to set the values of the variables in class-like i did with Serializable? I mean separately using 2 constructors-one without ID another without the ID?
Did you read how Parcelable works?
You need only one constrcutor for parcelable to read what you pass to it, and Parcelable interface will add a method writeToParcel where you put the data to save.
It's not an automatic process like Serializable, everything is up to you.
The constructor which Parcelable will use will accept only one argument Parcel where you will find some methods like read*(KEY) to read back values.
And in writeToParcel you will write in the Parcel (the argument of the method) the values you want pass to pass with write*(KEY, VALUE).
Parcelable don't care about your constructors or fields.
P.S You will need a CREATOR too. Read some tutorial online to know more about it if you need.
Marco's answer explains why Parcelable doesn't automatically decide what constructor to use - it can't.
However, there is a way around this. Use Parcel.dataAvail(), which
Returns the amount of data remaining to be read from the parcel. That
is, dataSize()-dataPosition().
For example,
public Student(){}
public Student(String name, String dpt)
{
this.studentName = name;
this.studentDept = dpt;}
public Student(int id, String name, String dpt)
{ this.studentdID = id;
this.studentName = name;
this.studentDept = dpt;
}
public Student(Parcel in) {
name = in.readString();
dpt = in.readString();
if(in.dataAvail() > 0) // is there data left to read?
id = in.readInt();
}
^ The above constructor will allow for the necessary variables to be instantiated correctly. Also, you define writeToParcel() something like:
public void writeToParcel(Parcel out) {
out.writeString(name);
out.writeString(dpt);
//0 is the default value of id if you didn't initialize it like
// in the first constructor. If it isn't 0, that means it was initialized.
if(id != 0)
out.writeInt(id);
}
Of course, you'll need to define your CREATOR like so:
public static final Parcelable.Creator<Student> CREATOR = new Parcelable.Creator<Student>() {
public Student createFromParcel(Parcel in) {
return new Student(in);
}
public Student[] newArray(int size) {
return new Student[size];
}
};
#u3l solution is not required..how many constructors are there it doesn't matter.
simple it works go as normal implementation.
I mean no special care is required when multiple constructors present in parcelable.