Object array with known data type - java

I am currently working on a project and I have an array of Objects. I know that the array will store the following types: Product, Food, Clothes (food and clothes are both subclasses of Product). The thing is that I am trying to access an attribute of an object from the array (barCode), but when I try to do that it gives me an error and says that "barCode is undefined for type Object".
How can I solve this problem?
I cannot create an separates array for every type because it won't be scalable when I would add more classes and types.
Thanks!
yes. the future classes will also be sublcasses of Product
this is one instance of the code. the only problem is on the lines with getBarCode() (which is a method for the Product class)
private Object arr[] = super.getArray();
public void sort(int c)
{
Object aux;
int min = 999, poz;
for(int i = 0; i < super.getIndex() - 1; i ++)
{
for(int j = i; j < super.getIndex(); j ++)
{
if( arr[j].getBarCode() < min)
{
min = arr[j].getBarCode();
poz = j;
}
}
aux = arr[i];
arr[i] = arr[poz];
arr[poz] = aux;
}
}

If you could guarantee that the method barCode exists on Product and its children, then you could just use an array of Product instead.
You would have to deal with any sort of fiddly casting you would want to do if you want to use specific child class methods, but that would at least let you call the same method on all elements without too much worrying.
So long as getArray can be changed to return Product, then you can write this:
private Product[] arr = super.getArray();
You'd change aux to a type of Product, too.

When accessing the object from the array, what you can do is compare the object type.
Like this:
Object o = array[0];
if(o.getClass().equals(Product.class)) {
Product p = (Product)o;
p.getBarcode();
}
Alternatively, if all of your objects you are putting into this array are subclasses of Product, just make an arrayList to use Products, like new ArrayList(), and then call the barcode method for there.

Related

How to work with arrays with an unknown number of dimensions in Java? [duplicate]

I need to be able to have an n-dimensional field where n is based on an input to the constructor. But I'm not even sure if that's possible. Is it?
Quick solution: you could approximate it with a non-generic ArrayList of ArrayList of ... going as deep as you need to. However, this may get awkward to use pretty fast.
An alternative requiring more work could be to implement your own type using an underlying flat array representation where you calculate the indexing internally, and providing accessor methods with vararg parameters. I am not sure if it is fully workable, but may be worth a try...
Rough example (not tested, no overflow checking, error handling etc. but hopefully communicates the basic idea):
class NDimensionalArray {
private Object[] array; // internal representation of the N-dimensional array
private int[] dimensions; // dimensions of the array
private int[] multipliers; // used to calculate the index in the internal array
NDimensionalArray(int... dimensions) {
int arraySize = 1;
multipliers = new int[dimensions.length];
for (int idx = dimensions.length - 1; idx >= 0; idx--) {
multipliers[idx] = arraySize;
arraySize *= dimensions[idx];
}
array = new Object[arraySize];
this.dimensions = dimensions;
}
...
public Object get(int... indices) {
assert indices.length == dimensions.length;
int internalIndex = 0;
for (int idx = 0; idx < indices.length; idx++) {
internalIndex += indices[idx] * multipliers[idx];
}
return array[internalIndex];
}
...
}
Here's a nice article that explains how to use reflection to create arrays at run-time: Java Reflection: Arrays. That article explains how to create a one-dimensional array, but java.lang.reflect.Array also contains another newInstance method to create multi-dimensional arrays. For example:
int[] dimensions = { 10, 10, 10 }; // 3-dimensional array, 10 elements per dimension
Object myArray = Array.newInstance(String.class, dimensions); // 3D array of strings
Since the number of dimensions is not known until runtime, you can only handle the array as an Object and you must use the get and set methods of the Array class to manipulate the elements of the array.
Try this:
https://github.com/adamierymenko/hyperdrive

2D array of multiple different objects

For my project, I need a 2D array that can hold multiple different object types. The problem with java is that it doesn't let you do that. You can only have an array of a particular object type.
Now don't get me wrong, but I did some research, and one proposed solution is to use an Object array, since every class in java extends the object class by default. For example:
Object[][] someArray = new Object[5][5];
someArray[1][2] = new Cat();
someArray[3][4] = new Dog();
The problem with this is that the object class, being a superclass, cannot access the methods and fields of the subclasses that extend it. So if I have a public eat() method in my cat or dog class, the elements in someArray wont be able to access that method.
So I'm at a dead-end here. Any help is appreciated. Thanks in advance.
[ please don't judge me for answering my own question ]
One possible solution is using 2D ArrayLists. The way a 2D Array works is by literally having a 1D array consisting of 1D arrays.
Maybe the same concept can be applied to ArrayLists, which can in fact store any object types without having accessibility issues. A 5x5 ArrayList can be created as follows:
ArrayList<ArrayList> someArray = new ArrayList<ArrayList>();
for(int x=0 ; x<5 ; x++)
{
someArray.add(new ArrayList());
for(int y=0 ; y<5 ; y++)
someArray.get(x).add(null);
}
and to set row 1 col 2 to a cat object:
someArray.get(1).set(2, new Cat());
someArray.get(3).set(4, new Dog());
So 2D ArrayLists, though a bit confusing might solve this issue pretty efficiently.
to call the eat() method of the Dog class and `Cat`` class, You can cast the array reference to a subclass reference.((Dog)someArray[x][y]).eat();
public class Dog{
public Dog(){
super();
}
public String eat(){
String str = "yum";
return str;
}
public static void main (String[]args){
Object [][] arr = new Object [2] [2];
for(int i = 0; i < arr.length; i++){
for(int j = 0; j < arr[i].length; j++){
arr[i][j] = new Dog();
}
}
System.out.println(((Dog)arr[1][1]).eat());
}
}
The ideal use in your case is to create a superclass called Animal that is extended by dog and cat. Your ArrayList or array will be of Animal type.
How different do these objects need to be? If they're your own classes, then just create some sort of superclass that they all extend and use that as the array type. If you don't want to do that, I guess you could set something up like this:
private Object[][] array = new Object[5][5];
public void setValue(int x, int y, Object val) {
if(x > 0 && x < array.length && y > 0 && y < array[0].length) {
array[x][y] = val;
}
}
public Object getValue(int x, int y) {
if(x > 0 && x < array.length && y > 0 && y < array[0].length) {
return array[x][y];
}
return null;
}
Using it would be a little tedious, but you could cast each call to getValue() to the type you needed it to be. With Object Oriented programming, having a simple solution to this can be kind of difficult. I could write some more advanced code that would return the object casted to a certain class, but it's a little bit of work. Let me know if you'd like that.

Sorting and printing only certain objects in an array with multiple class types, java

My apologies for being horrible with the terminology...
My program's parent class is Vehicle. Vehicle contains 4 variables, make model date and serial. That class has two children, Car and Boat. Car has children Truck and Van, Boat has children Powerboat and Sailboat. Each of the children has its own specific set of variables. I have an array of type Vehicle which contains objects of type Truck, Van, Sailboat and Powerboat.
My problem comes when I want to print only Boat objects. They need to be sorted by boatLength. I get error
cannot find symbol
in my sorting algorithm:
//regulates the first value
for (int i = 0; i < input.length-1; i++)
{
int min = i;
//checks remaining values for min
for (int j = i+1; j < input.length; j++)
{
if (input[j].getBoatLength().compareToIgnoreCase(input[min].getBoatLength())<0)
{
min = j;
}
}
//swaps values
Vehicle temp = input[i];
input[i] = input[min];
input[min] = temp;
}
Is there a way I can sort and print only the boat objects without creating an array for the Boat objects?
here is the error message:
VehicleClient.java:276: error: cannot find symbol
if (vehicles[i] instanceof Boat)
^
symbol: variable vehicles
location: class VehicleClient
VehicleClient.java:310: error: cannot find symbol
if (input[j].getBoatLength().compareToIgnoreCase(input[min].getBoatLength())<0)
^
symbol: method getBoatLength()
location: class Vehicle
VehicleClient.java:310: error: cannot find symbol
if (input[j].getBoatLength().compareToIgnoreCase(input[min].getBoatLength())<0)
^
symbol: method getBoatLength()
location: class Vehicle
3 errors
Your error is caused by you trying to call a method that is defined in Boat on a reference of type Vehicle. The compiler is searching for getBoatLength in the Vehicle class and can't find it (as it is not there). You can solve it by casting the variable reference into a Boat type reference (if you are sure the object is of type Boat).
There are several approaches you can take to tackle what you are asking for. Here are my thoughts:
I don't know how you created the array input, but I assume you can create two separate arrays instead of one - one for Boat objects and one for Car objects. Then you can use only the Boat array.
I'm guessing you need the array as it is, with Car and Boat object together - so the previous approach isn't relevant. As you mentioned - you could create an additional array from the first one for the Boat objects and use the new array. For that you can just create it when you create the original array and add every Boat object to both arrays, or alternatively go over the input array and use the very un-oop method instanceof:
List<Boat> boats = new ArrayList();
for (Vehicle object : input){
if (object instanceof Boat){
boats.add((Boat)object);
}
}
return boats.toArray();
You could also use the instanceof to just sort the Boat object in-place in the array you already have and print them:
//regulates the first value
for (int i = 0; i < input.length-1; i++)
{
int min = i;
//checks remaining values for min
for (int j = i+1; j < input.length; j++)
{
if (!(input[j] instance Boat)){ //check to use only Boat objects
continue;
} //now that you are sure it's a Boat object - cast the reference to use it as a Boat object reference
if (((Boat)input[j]).getBoatLength().compareToIgnoreCase(((Boat)input[min]).getBoatLength())<0)
{
min = j;
}
}
//swaps values
Vehicle temp = input[i];
input[i] = input[min];
input[min] = temp;
}
The last approach (approach 3) is probably what you are after, but note that the fact that you need to use the instanceof method normally tells you that your design is not really oop. Although you are using polymorphism to call the boatLength on objects of different subclasses of Boat, the fact that you need to check which subclass of Vehicle is each object in run-time (going over the input array) means you are going un-polymorphic there and therefore un-oop-ic. That's why I included approach 1 as well, which is the correct one in my opinion. If you need the Boats as Boats - keep them separated and when you need all the objects refer to the two arrays (the Car objects one and the Boat objects one) one after the other. You could even have them in another array (currently of size 2) of Vehicle arrays, and have a constant that "remembers" which position is the Boat objects array:
public static final int BOATS_ARR_INDEX = 0;
public static final int CARS_ARR_INDEX = 1;
Vehicle[][] vehicleArrs = new Vehicle[2][];
vehicleArrs[BOATS_ARR_INDEX] = boatsArrayGeneratingMethod();
vehicleArrs[CARS_ARR_INDEX] = carsArrayGeneratingMethod();
for (Vehicle[] vehicleArr : vehicleArrs){
// do whatever you want to do for all Vehicle objects here, iterating through vehicleArr
}
Boat[] boats = vehicleArrs[BOATS_ARR_INDEX];
//do you original code from the question here

Java ArrayList get() as Integer rather than Object

new to Java. Trying to understand the point of declaring my ArrayList as an <Integer>. I still have to cast my .get() result as an int in my methods for it to work, else it still returns an Object. eg: (int) deliv.get(j) int the Sort method's for loop. Is there a way to avoid this or is my code the correct approach?
Problem: Assume the array can change size, hence not just using primitive array. All numbers should be pairs, looking for the unique one missing it's pair value. I sort the array, then cycle through the pairs to look for a mismatch. Thanks.
import java.util.*;
class StolenDrone{
public static void main(String[] args){
ArrayList<Integer> deliv_id = new ArrayList<>();
deliv_id.add(99);
deliv_id.add(13);
deliv_id.add(4);
deliv_id.add(5);
deliv_id.add(8);
deliv_id.add(99);
deliv_id.add(8);
deliv_id.add(5);
deliv_id.add(4);
System.out.println("Array is: " + deliv_id);
sort(deliv_id);
System.out.println("Array is: " + deliv_id);
int unique = findUnique(deliv_id);
System.out.println("Unique ID is: " + unique);
}
//Sort ArrayList into increasing order
static void sort(ArrayList deliv){
int temp;
for(int i = 0; i<deliv.size();i++){
for (int j=0; j<deliv.size()-1;j++){
if((int) deliv.get(j)> (int) deliv.get(j+1)){
temp = (int) deliv.get(j+1);
deliv.set(j+1, deliv.get(j));
deliv.set(j, temp);
}
}
}
}
//check pairs in ArrayList to find unique entry
static int findUnique(ArrayList deliv){
for(int i = 0; i<deliv.size()-1;i+=2){
if(deliv.get(i) == null){
return -1; //no unique
}
if((int) deliv.get(i) != (int) deliv.get(i+1)){
return (int) deliv.get(i);
}
}
return -1;
}
}
When you type parameterize ArrayList<Integer> the compiler knows that everything inside the ArrayList is of type Integer and will only allow you to add Integers to the list, and thus get() returns Integer. Without parameterizing the compiler will allow you to add any Object to the ArrayList, and thus calling get() will return an Object and requiring the cast to int.
To remove the need for casts you need to change parameters with type ArrayList to ArrayList<Integer> in the function declaration.
static void sort(ArrayList deliv)
Your method signature requests an untyped ArrayList.
The compiler cannot know what will be inside the ArrayList so it requires you to cast the result.
Change it to this:
static void sort(ArrayList<Integer> deliv)
Now the compiler knows it is an ArrayList of Integers.
So you wont need to add the cast to get()
In Java Integet is wrapper-class of int. You cannot set int as a type of ArrayList to work, but you can put there int type and it will be automatticly casted to Integer. To meke work it good you should do like this :
static void sort(ArrayList deliv){
int temp;
for(int i = 0; i<deliv.size();i++){
for (int j=0; j<deliv.size()-1;j++){
if(deliv.get(j)> deliv.get(j+1)){ // You should not cast, Integer is Comparable
temp = deliv.get(j+1).intValue();//Changes here
deliv.set(j+1, deliv.get(j).intValue());//And here
deliv.set(j, temp);
}
}
}
}
Good luck

Java N-Dimensional Arrays

I need to be able to have an n-dimensional field where n is based on an input to the constructor. But I'm not even sure if that's possible. Is it?
Quick solution: you could approximate it with a non-generic ArrayList of ArrayList of ... going as deep as you need to. However, this may get awkward to use pretty fast.
An alternative requiring more work could be to implement your own type using an underlying flat array representation where you calculate the indexing internally, and providing accessor methods with vararg parameters. I am not sure if it is fully workable, but may be worth a try...
Rough example (not tested, no overflow checking, error handling etc. but hopefully communicates the basic idea):
class NDimensionalArray {
private Object[] array; // internal representation of the N-dimensional array
private int[] dimensions; // dimensions of the array
private int[] multipliers; // used to calculate the index in the internal array
NDimensionalArray(int... dimensions) {
int arraySize = 1;
multipliers = new int[dimensions.length];
for (int idx = dimensions.length - 1; idx >= 0; idx--) {
multipliers[idx] = arraySize;
arraySize *= dimensions[idx];
}
array = new Object[arraySize];
this.dimensions = dimensions;
}
...
public Object get(int... indices) {
assert indices.length == dimensions.length;
int internalIndex = 0;
for (int idx = 0; idx < indices.length; idx++) {
internalIndex += indices[idx] * multipliers[idx];
}
return array[internalIndex];
}
...
}
Here's a nice article that explains how to use reflection to create arrays at run-time: Java Reflection: Arrays. That article explains how to create a one-dimensional array, but java.lang.reflect.Array also contains another newInstance method to create multi-dimensional arrays. For example:
int[] dimensions = { 10, 10, 10 }; // 3-dimensional array, 10 elements per dimension
Object myArray = Array.newInstance(String.class, dimensions); // 3D array of strings
Since the number of dimensions is not known until runtime, you can only handle the array as an Object and you must use the get and set methods of the Array class to manipulate the elements of the array.
Try this:
https://github.com/adamierymenko/hyperdrive

Categories