I have an Object ArrayList and I need to use the toString() method of the Motor object, which is a parameter of the Vehicle object. My vehicle objects are in an ArrayList which is iterated through with a for-loop (I know a foreach loop would be easier, but this is part of the assignment)
Here is the code for the loop:
for (int i = 0; i < VehicleList.size(); i++) {
System.out.println();
String info = VehicleList.get(i).toString();
Motor m = VehicleList.get(i).motor;
String motorInfo = m.toString();
System.out.println(info);
System.out.println(m);
}
There is an error that says "motor cannot be resolved or is not a field".
All of the classes should allow this to work, unless of course there is a simple mistake I am missing.
Here is the Motor class:
public class Motor {
protected String name;
protected int cylinders;
protected int bhp;
protected double displacement;
public Motor(String name, int cylinders, int bhp, double displacement) {
this.name = name;
this.cylinders = cylinders;
this.bhp = bhp;
this.displacement = displacement;
}
public String toString() {
return "Motor name= " + name + ", cylinders= " + cylinders + ", bhp=
" + bhp + ", displacement= " + displacement;
}
}
Motors and Vehicles are intitialized here (In the TestVehicle class):
//Motors
Motor EcoBoost = new Motor("EcoBoost", 6, 310, 2.3);
Motor Hemi = new Motor("Hemi", 8, 707, 5.7);
Motor P90D = new Motor("P90D", 0, 762, 0.0);
//Vehicles
Vehicle v0 = new PassCar("Ford", "Mustang", 2016, 44500.0, 5, true, EcoBoost);
Vehicle v1 = new PassCar("Tesla", "Model S", 2016, 121000.0, 2, true, P90D);
Vehicle v2= new Truck("Dodge", "Ram", 2016, 46000.0, "pickup", 1500, Hemi);
PassCar and Truck are inherited classes of Vehicle with a few more attributes. I can post the PassCar or Truck class if needed but I do not think that is where the problem is arising from. I believe it is coming from the For-Loop, specifically the line Motor m = VehicleList.get(i).motor; but I am not sure of how to fix it.
Vehicle Class:
public class Vehicle {
protected String make;
protected String model;
protected int year;
protected double price;
public Vehicle(String make, String model, int year, double price) {
this.make = make;
this.model = model;
this.year = year;
this.price = price;
}
public void description() {
System.out.println("Description");
}
public String toString() {
return "make= " + make + ", model= " + model + ", year= " + year +
", price= " + price;
}
}
EDIT: There cannot be any Getters or Setters as per the assignment requirements, and it must be an ArrayList, not a regular List. When I switch to I get the error "Type mismatch: cannot convert from ArrayList to ArrayList
Here is an image of the classes:
ArrayList<Object> VehicleList = new ArrayList<>(Arrays.asList(vehicles));
VehicleList is declared to contain instances of Object, so the compiler will only let you access methods and fields it knows exist on all instances of Object.
Change it to ArrayList<Vehicle>.
First, mind the naming convention. Variables should be named in camcelCase e.g. vehicleListinstead ofVehicleList`
I have an Object ArrayList
I believe you mean declaration of vehicleList looks like ArrayList<Object> vehicleList
Then behavior is expected because compiler only knows that VehicleList.get(i) is going to return you an Object reference. It can be a Vehicle, but it can also be anything else. So it won't allow you to access the motor field, as there is simply no such field in Object.
Change your declaration to something like List<Vehicle> vehicleList
However, as mentioned in other answer, it is not a good idea to access the field directly because of various reason. A slightly less evil way is to have getter of motor. (A better way is to provide meaningful behaviors instead of providing access to internal data)
Create an interface IMotor which is used by Vehicle class and Implemented in PassCar and other implementation of vehicle.
IMotor.java
public interface IMotor {
public Motor getMotor();
}
Motor.java
public class Motor {
protected String name;
protected int cylinders;
protected int bhp;
protected double displacement;
public Motor(String name, int cylinders, int bhp, double displacement) {
this.name = name;
this.cylinders = cylinders;
this.bhp = bhp;
this.displacement = displacement;
}
public String toString() {
return "Motor name= " + name + ", cylinders= " + cylinders + ", bhp=" + bhp + ", displacement= " + displacement;
}
}
Vehicle.java
public abstract class Vehicle implements IMotor{
protected String make;
protected String model;
protected int year;
protected double price;
public Vehicle(String make, String model, int year, double price) {
this.make = make;
this.model = model;
this.year = year;
this.price = price;
}
public String toString() {
return "make= " + make + ", model= " + model + ", year= " + year +
", price= " + price;
}
}
PassCar
public class PassCar extends Vehicle{
protected Motor motor;
public PassCar(String make, String model, int year, double price, Motor motor) {
super(make, model, year, price);
this.motor = motor;
}
public Motor getMotor() {
return motor;
}
}
Test.java
import java.util.Arrays;
import java.util.List;
public class Test {
public static void main(String[] args) {
Motor EcoBoost = new Motor("EcoBoost", 6, 310, 2.3);
Vehicle v0 = new PassCar("Ford", "Mustang", 2016, 44500.0, EcoBoost);
List<Vehicle> vehicles = Arrays.asList(v0);
System.out.println(vehicles.get(0).getMotor());
}
}
Your problem is that motor is not a member of the Vehicle class, but you are trying to access it through an expression of type Vehicle - namely vehicleList.get(i). This is forbidden, because the compiler has no way of knowing that every possible kind of Vehicle has a motor. After all, what would happen if you added a Bicycle class?
To make this work, you should remove motor from the Truck and PassCar classes, and add it to the Vehicle class. That way, vehicleList.get(i).motor would actually make sense, since the Vehicle expression would be guaranteed to refer to a Vehicle with a Motor.
It would also be recommended to use a getter for the motor field - that is, have motor as a private field of the Vehicle class, and write a method getMotor() to return it. You could then write vehicleList.get(i).getMotor() to get the Motor object associated with one Vehicle in the list.
Thanks to the help of all of your comments and my Java textbook, I managed to piece it together. Here is how I got it to work:
for (int i = 0; i < vehicleList.size(); i++) {
String motorInfo = "";
String info = "";
System.out.println();
if (vehicleList.get(i) instanceof PassCar) {
info = ((PassCar)vehicleList.get(i)).toString();
**motorInfo = ((PassCar)vehicleList.get(i)).motor.toString();**
}
else if(vehicleList.get(i) instanceof Truck) {
info = ((Truck)vehicleList.get(i)).toString();
**motorInfo = ((Truck)vehicleList.get(i)).motor.toString();**
}
Basically I had to use a polymorphic call and check if it was an instance of a PassCar or Truck.
And as for the Array and ArrayList used during the Class, I edited them like this:
Vehicle [] vehicles = new Vehicle [3];
vehicles[0] = v0;
vehicles[1] = v1;
vehicles[2] = v2;
showVehicle(vehicles);
ArrayList<Vehicle> vehicleList = new ArrayList<Vehicle>(Arrays.asList(vehicles));
System.out.println();
System.out.println("Output from ArrayList in main: ");
Thank you for the help everyone!
I'm creating a shopping cart simulation with a list of products that i want to add together and display the total of as they are being added to the cart basket (implemented as a jlist).
In my main class I have a button with an action listener to take items from my stocklist and add them to the basket.
scanBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
checkoutBasket.addElement(productList.getSelectedValuesList());
}
});
In addition I have a JTextField set up below the basket which I want to dynamically update with the total cost as I add items to the cart. My question is how could I go about doing this ? Thank you.
cartTotalField = new JTextField();
getContentPane().add(cartTotalField);
cartTotalField.setBounds(581, 441, 233, 28);
Cart Item Class :
import java.io.*;
public class CartItem implements Serializable {
private String barcodeNo;
private String itemName;
private String price;
public CheckoutItem() {
}
public CheckoutItem (String barno, String in, String cost) {
barcodeNo = barno;
itemName = in;
price = cost;
}
public String getBarcodeNo(){
return barcodeNo;
}
public String getItemName(){
return itemName;
}
public void setitemName(String itemName){
this.itemName = itemName;
}
public String getPrice(){
return price;
}
public String toString(){
return barcodeNo + ": " + itemName + ", " + price;
}
public Object getID() {
// TODO Auto-generated method stub
return null;
}
}
In your actionPerformed, you could do something like this (of course, this is a very naive approach to get it, you could possibly think of something better on this):
#Override
public void actionPerformed(ActionEvent evt) {
//Get the newly added list values.
JList list = productList.getSelectedValuesList();
double totalAddedValue = 0.0;
double oldCartValue = 0.0;
//Iterate to get the price of the new items.
for (int i = 0; i < list.getModel().getSize(); i++) {
CartItem item = (CartItem) list.getModel().getElementAt(i);
totalAddedValue += Double.ParseDouble(item.getPrice());
}
//Set total price value as an addition to cart total field.
//cartTotalField must be accessible here.
string cartFieldText = cartTotalField.getText();
//Check that cartTextField already contains a value.
if(cartTextField != null && !cartTextField.isEmpty())
{
oldCartValue = Double.parseDouble(cartFieldText);
}
cartTotalField.setText(String.valueOf(oldCartValue + totalAddedValue));
checkoutBasket.addElement(list);
}
UPDATE: In general, you should consider adding checks and/or exception handling for numeric conversions. A good idea would also be to change the price property to double (or int, modifying the above code accordingly) in your CartItem class.
I'm currently in the process of creating a shopping cart simulation program. The main GUI contains two lists, one is a list of products or the inventory. (products stored within a .dat file which is automatically loaded upon launch) The other is blank and is to model my shopping basket. The idea is to be able to scan items from my inventory into the checkout basket. As this is happening i want a text field i created to dynamically update with the cost of all the items in the basket.
Below is the method for my scan button, which is supposed to perform the above :
public void actionPerformed(ActionEvent evt) {
//Get the newly added list values.
JList list = productList.getSelectedValuesList();
double totalAddedValue = 0.0;
double oldCartValue = 0.0;
//Iterate to get the price of the new items.
for (int i = 0; i < list.getModel().getSize(); i++) {
CartItem item = (CartItem) list.getModel().getElementAt(i);
totalAddedValue += Double.ParseDouble(item.getPrice());
}
//Set total price value as an addition to cart total field.
//cartTotalField must be accessible here.
string cartFieldText = cartTotalField.getText();
//Check that cartTextField already contains a value.
if(cartTextField != null && !cartTextField.isEmpty())
{
oldCartValue = Double.parseDouble(cartFieldText);
}
cartTotalField.setText(String.valueOf(oldCartValue + totalAddedValue));
checkoutBasket.addElement(list);
}
Currently however scanning the item will add it to the list but print strange results in the total. (Adds 5.5 for each item regardless of their actual value**). It will also print a line under the item name as such javax.swing.JList[,0,0,344x326,layout=java.awt.BorderLa... .
Below are the classes for my CartItem and ItemList if they may help. Thank you.
-Cart Item
import java.io.*;
public class CartItem implements Serializable {
private String barcodeNo;
private String itemName;
private String price;
public CartItem() {
}
public CartItem (String barno, String in, String cost) {
barcodeNo = barno;
itemName = in;
price = cost;
}
public String getBarcodeNo(){
return barcodeNo;
}
public String getItemName(){
return itemName;
}
public void setitemName(String itemName){
this.itemName = itemName;
}
public String getPrice(){
return price;
}
public String toString(){
return barcodeNo + ": " + itemName + ", " + price;
}
public Object getID() {
// TODO Auto-generated method stub
return null;
}
}
-ItemList
import javax.swing.DefaultListModel;
public class ItemList extends DefaultListModel {
public ItemList(){
super();
}
public void addCartItem(String barcodeNo, String itemName, String price){
super.addElement(new CartItem(barcodeNo, itemName, price));
}
public CartItem findItemByName(String name){
CartItem temp;
int indexLocation = -1;
for (int i = 0; i < super.size(); i++) {
temp = (CartItem)super.elementAt(i);
if (temp.getItemName().equals(name)){
indexLocation = i;
break;
}
}
if (indexLocation == -1) {
return null;
} else {
return (CartItem)super.elementAt(indexLocation);
}
}
public CartItem findItemByBarcode(String id){
CartItem temp;
int indexLocation = -1;
for (int i = 0; i < super.size(); i++) {
temp = (CartItem)super.elementAt(i);
if (temp.getBarcodeNo().equals(id)){
indexLocation = i;
break;
}
}
if (indexLocation == -1) {
return null;
} else {
return (CartItem)super.elementAt(indexLocation);
}
}
public void removeItem(String id){
CartItem empToGo = this.findItemByBarcode(id);
super.removeElement(empToGo);
}
}
You're adding the JList itself to the check out basket, and that doesn't make sense:
checkoutBasket.addElement(list);
This, javax.swing.JList[,0,0,344x326,layout=java.awt.BorderLa... . shows that something is displaying the toString() representation of the JList, likely your checkout basket.
Regarding,
Adds 5.5 for each item regardless of their actual value
I don't think your current code shows why this is happening, and you might want to create and post an mcve.
Other thoughts:
Don't use String to represent price, but rather consider a numeric field, perhaps BigDecimal if you want to be accurate for money.
You look to be mixing your view with your model too much. Try to keep them separate as possible, meaning, you should likely have some more non-GUI classes including one to represent the shopping basket, and any other nouns.
so I need some advice, I have been working on some code for quite a while and I can never seem to find out why my code is screwing up terribly. It seems as if one of the toString lines in my Product class is not working properly. Here is the code:
import java.util.ArrayList;
public class lab24ArrayList
{
public static void main(String[]args)
{
ShoppingCart cart = new ShoppingCart();
Product hat = new Product ("Hat", 10);
Product scarf = new Product ("Scarf", 8);
Product legos = new Product ("Legos", 19);
Product dvd = new Product ("DVD", 12);
System.out.println("Removing DVD: "+cart.remove(dvd));
cart.add(hat);
cart.add(scarf);
cart.remove(scarf);
System.out.println("Removing Scarf: " +cart.remove(scarf));
cart.add(legos);
cart.add(dvd);
cart.add(legos);
System.out.println(cart);
}
}
class ShoppingCart
{
ArrayList <Product> cart;
public ShoppingCart()
{
cart = new ArrayList<Product>();
}
public int size()
{
int k = cart.size();
return k;
}
public void add(Product p)
{
cart.add(p);
}
public Product remove(Product p)
{
if(cart.contains(p))
{
cart.remove(p);
return p;
}
else
return null;
}
}
class Product
{
private String name;
private double price;
public Product(String _name, double _price)
{
name = _name;
price = _price;
}
public String getName() {return name;}
public double getPrice() {return price;}
public String toString() {return name + ": $"+price;}
}
When I put it in the compiler, all I get is this:
Removing DVD: null
Removing Scarf: null
ShoppingCart#c2f0bd7
When I need to get this:
Removing DVD: null
Removing Scarf: Scarf: $8
Items: 6
Total: $60.00
Hat: $10
Legos: $19
DVD: $12
Legos: $19
You're missing a toString() method on your ShoppingCart, that's why you get ShoppingCart#c2f0bd7. Override toString() in the ShoppingCartclass to build a string from the items within it.
You're also removing the Scarf twice, once here cart.remove(scarf) then also in System.out.println("Removing Scarf: " +cart.remove(scarf)).
To clarify how to print out the cart, you'll want to create a toString method in ShoppingCart similar to what you've done in Product:
public static String toString() {
StringBuilder stringBuilder = new StringBuilder();
for(Product product : cart) {
stringBuilder.append(product);
}
return stringBuilder.toString();
}
That creates a StringBuilder, loops through each product in the cart and appends it to the StringBuilder. You then return that string.
I have a class Components:
public class Components {
int numberOfNets;
String nameOfComp;
String nameOfCompPart;
int numOfPin;
public components(int i, String compName, String partName, int pin) {
this.numberOfNets = i;
this.nameOfComp = compName;
this.nameOfCompPart = partName;
this.numOfPin = pin;
}
}
Inside another class I created an arraylist of Components class:
List<Components> compList = new ArrayList<Components>();
Later in the code, I am adding the elements in List in this way:
compList.add(new Components(0,compName,partName,0));
See, here numberOfNets and numOfPin variables in Components class are initiated with 0 values. But these values are getting calculated/incremented in a later part of code and hence I need to update the new values of only these two variables in each list element. Now from ArrayList doc I get the idea of updating a list element using its index by set operation. But I am confused how to set/update a particular variable of a class in an ArrayList of a class. I need to update only these two mentioned variables, not all of the four variables in Components class. Is there any way to do that?
You should add getter/setter to your component class so that outer class can update component's members
public class Components {
private int numberOfNets;
private String nameOfComp;
private String nameOfCompPart;
private int numOfPin;
public components(int i, String compName, String partName, int pin) {
setNumberOfNets(i);
setNameOfComp(compName);
setNameOfCompPart(partName);
setNumOfPin(pin);
}
public void setNumberOfNets(int numberOfNets) {
this.numberOfNets = numberOfNets;
}
// Similarly other getter and setters
}
You can now modify any data by using following code because get() will return reference to original object so modifying this object will update in ArrayList
compList.get(0).setNumberOfNets(newNumberOfNets);
Example code.
public class Main {
public static void main(String[] args) {
List<Components> compList = new ArrayList<Components>();
compList.add(new Components(0, "compName", "partName", 0));
System.out.println(compList.get(0).toString());
compList.get(0).numberOfNets = 3;
compList.get(0).numOfPin = 3;
System.out.println(compList.get(0).toString());
}
}
Your class.
public class Components {
int numberOfNets;
String nameOfComp;
String nameOfCompPart;
int numOfPin;
public Components(int i, String compName, String partName, int pin) {
this.numberOfNets = i;
this.nameOfComp = compName;
this.nameOfCompPart = partName;
this.numOfPin = pin;
}
public String toString() {
return this.numberOfNets + " " + nameOfComp + " " + nameOfCompPart
+ " " + numOfPin;
}
}
The output:
0 compName partName 0
3 compName partName 3