Accessing properties of Generic class in Java - java

Hi I am new to Java Generics and I am trying to access properties inside generic class. So far I have found C# related answers, it would be of great help if someone could please guide as to how I should do it in java.
Say I have Class Car and it has properties integer type wheels and String type model.
Now I have a method say vehiclehelper(List<T> vehicles) which takes a generic type list.
At place of invocation of vehiclehelper, it will be like :
List<Car> cars = new ArrayList<>();
cars.add(new Car(4, "Honda"));
vehiclehelper(cars);
Now coming to vehiclehelpermethod, in its body I want to loop over the list<T>vehicles and fetch the wheels property from it..something like:
for(T vehicle: vehicles)
count+ = vehicle.getWheels();
Now here at this point I am getting error, saying property isn't defined. What should I do to fetch the wheel property from my list of generic type?

create an interface ICar or an abstract class that represents a car, and has the methods that you expect a car to have, (e.g getWheels()).
then send a list of the objects that implements/extend this class as a parameter carHelper(List<ICar> cars)

Your class Car is not generalized. It's common class. You just manipulate Car objects via generalized List collection. It should not any issues with access to Car fields through getters or setters if that fields are private. Code below works perfectly.
public class App {
public static void main(String[] args) {
List<Car> carList = new ArrayList<>();
carList.add(new Car(4, "Honda"));
carList.add(new Car(3, "Polaris Slingshot"));
System.out.println(carHelper(carList)); // the result is 7
}
static int carHelper(List<Car> cars) {
int count = 0;
for (Car car : cars) {
count += car.getWheel();
}
return count;
}
}
class Car {
private int wheels;
private String name;
public Car(int wheels, String name) {
this.wheels = wheels;
this.name = name;
}
public int getWheels() {
return wheels;
}
public void setWheels(int wheels) {
this.wheels = wheels;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
If you want to have universal method carHelper for any object type, then you have to make it generalized:
static <T> int carHelper(List<T> elements) {
int count = 0;
for (T element : elements) {
count += element.getWheel();
}
return count;
}
But in the case you will get compile-time error at element.getWheel() because T type is some unknown type. Compiler does not know about his methods. To find some generic solution we have to define boundary for method parameters. Let's say input parameters will be Vehicle or it's children. In Vehicle class, let's say, we will introduce needed fields and his descendants will inherit them. In the case below listed method will work. Read about wildcards in generics.
static int carHelper(List<? extends Car> elements) {
int count = 0;
for (Car element : elements) {
count += element.getWheels();
}
return count;
}

Related

Reach parent class methods from arraylist of subclasses

I am trying to reach my parent class Car() variables and methods, from my ArrayList in main() of Objects Automobile(), Bus() which all inherit Car(). It gives me the opportunity to get the .Class and I know I can then compare if the class is Automobile or Bus and then do some operations, but I am actually trying to sort allInOne() ArrayList by getModel() Strings.
public class Car {
private String brand;
private String model;
public String getBrand(){
return brand;
}
public String getModel(){
return model;
}
}
public class Automobile extends Car {
int x;
Automobile(String brand, String model, int x){
super(brand, model);
this.x = x;
}
}
public class Bus extends Car {
int x;
Bus(String brand, String model, int x){
super(brand, model);
this.x = x;
}
main(){
Car first = new Automobile("brand1", "model1", 2);
Car second = new Bus("brand2", "model2", 3);
ArrayList<Object> allInOne = new ArrayList<Object>();
allInOne.add(first);
allInOne.add(second);
//here is the question part
allInOne.get(0).getBrand;
}
Instead of having Object List use ArrayList<Car>
ArrayList<Car> allInOne = new ArrayList<>();
then you can access all these methods:
allInOne.get(0).getBrand();
OR
If you want to stick to List of Object for some reason, then you can do this:
((Car) allInOne.get(0)).getBrand();
When instantiating the List, change Car as reference type instead of Object so that you might use the methods/attributes inherited from Parent Class.
ArrayList<Car> allInOne = new ArrayList<Car>(); // Java 7
ArrayList<Car> allInOne = new ArrayList<>(); // Java 8 it is not longer necessary to put reference type when instance an object.

Java Superclass get parameter value from subclass

The Question is:
1) How can i get subclass parameter values to superclass?
2) i want to take the name(From subclass) for collection.sort , like this.model.compareTo(other.model). However, I don't know how to get the "Name" Value from subclass and do the collection.sort.
** Is it correct to write public int compareTo(Car other, Taxi other2)??? **
Here is the code:
public class Car implement comparable <Car>()
{
private string model;
private int price;
public car(String model , int price)
{
this.model=model;
this.price=price;
}
............some getmethod here..........
public int compareTo (Car other)
{
** Want to sort by name , like this.model.compareTo(other.model)**
}
}
Taxi.java:
public class taxi extends Car ()
{
private string name;
public taxi (String model , int price, String name)
{
super(model, price);
this.name = name;
}
......some getmethod here..........
}
you can use subclass values by creating object of sub class in superclass.
It is also known as delegation.

Using reflection to get a specific attribute from a extended instance

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.

Temporary extending existing object in Java - is this a good idea?

I'm implementing an algorithm during which we must temporary order existing objects (we will compare them according to this order during execution of the algorithm). I'm thinking of the best way of doing that, while being consistent with OOP paradigm.
So let's think about the following example. We have objects of class Car, and now we want to use the algorithm on such objects. So I thought of making a subclass OrderedCar, which will have a unique int in its fields. This class would have a function - ArrayList<OrderedCar> defineOrder(ArrayList<Car> order), which would output OrderedCar list with numbers corresponding to the indices of a given car in order table. We would then be able to compare OrderedCars using numbers with which they were initialized. We could then execute the algorithm on OrderedCars and convert them to Cars after the algorithm terminates.
During the algorithm I need all of the methods from Car class, that's why I thought of making OrderedCar a subclass. Is this a good idea though? Also, how to create a constructor in Java, which will "copy" the Car and assign a number to it (I'm thinking of something like public OrderedCar(Car c, int order), but what to do with the car c in order to "copy" it? I don't want to copy all of the fields individually, is there some kind of shortcut in Java?)
You could favor composition over inheritance and just create a class that contains a Car and its order:
public class OrderedCar{
private int order;
private Car car;
public OrderedCar(int order, Car car){
this.order = order;
this.car = car;
}
public int getOrder(){
return order;
}
public Car getCar(){
return car;
}
}
Then you can sort this class by its order, and whenever you needed to operate on its car, you would just call the getCar() function.
If it is enough for you to compute the order basing on public methods of your Car class I think the simplest solution would be to just implement a comparator.
Here is a small example. I'm using the age property to do the sorting.
public class Car {
protected int age;
protected String manufacturer;
Car(int age, String manufacturer) {
this.age = age;
this.manufacturer = manufacturer;
}
public int getAge() {
return age;
}
public String toString() {
return this.manufacturer + " age: " + this.age;
}
}
import java.util.Comparator;
public class CarComparator implements Comparator<Car> {
public int compare(Car c1, Car c2) {
// do some complicated comparison using
// Car public methods, we simple use to
// age property here
return c1.getAge() - c2.getAge();
}
}
import java.util.ArrayList;
public class CarComparingApp {
public static void main(String[] args) {
Car ferrari = new Car(1, "Ferrari");
Car maserati = new Car(4, "Maserati");
Car subaru = new Car(3, "Subaru");
ArrayList<Car> cars = new ArrayList<Car>();
cars.add(ferrari);
cars.add(maserati);
cars.add(subaru);
cars.sort(new CarComparator());
for(Car c: cars) {
System.out.println(c);
}
}
}

How to look up objects with multiple attributes within an Arraylist?

I have a class that has a constructor as the following:
public Stock(String symbol, String name, int value) {
this.symbol = symbol;
this.name = name;
this.value = value;
}
Now, I have another class that is an abstract data type:
public class Holding {
private Stock stock;
private int amount;
public Holding() {
this.stock = null;
this.amount = 0;
}
public Holding(Stock stock, int amount) {
this.stock = stock;
this.amount = amount;
}
}
Now, I am writing a method in another class.
I have created an arraylist using the Holding class above.
in this class
private ArrayList<Holding> holdings;
Now, I know that my objects in the Holding class contains a stock object, and an int amount.
How can I access only the symbol in my stock object in the Holding ArrayList?
Not sure what you mean.
for (Holding h : holdings) {
out.println(h.getStock().getSymbol());
}
That's assuming you have appropriate getters.
You would want to use Java's foreach to loop through the ArrayList:
for (Holding currentHolding : holdings) {
System.out.println(currentHolding.stock.symbol); // prints out all the symbols
}
You need to change the attribute Stock from private to public, or create a getStock method to return it. Otherwise, since it is private, you can't access it.
How can I access only the symbol in my stock object in the Holding ArrayList?
With the code as given, you can't do this.
You need to add a public getter method for the stock field of the Holding class.
You (may) need to add a public getter method for the symbol field of the Stock class.
When you have done that you can do something like this:
public Holding getHoldingForSymbol(List<Holding> holdings, String symbol) {
for (Holding h : holdings) {
if (h.getStock().getSymbol().equals(symbol)) {
return h;
}
}
return null; // or throw an exception
}

Categories

Resources