i have an exercise which i must write a programm in which i manage the timetable of trains.I write all the programm put i can not write the main class, because i must make an Arraylist with 3 passengers and i dont know what i must put in the blank
Code:
public class Route {
private int id;
private int aeroplane;
private String departure;
private String arrival;
private ArrayList<Ticket> Tickets = new ArrayList<>() ;
public Route(){
id = 0 ;
aeroplane = 0 ;
departure = " ";
arrival = " ";
Tickets = new ArrayList<>();
}
public Route(int ID, int aerop, String depar,String arriv,ArrayList<Ticket> tick ){
id=ID;
aeroplane=aerop;
departure=depar;
arrival=arriv;
Tickets=tick;
}
public static void main(String[] args) {
ArrayList <Train> train=new ArrayList<>();
Route d1= new Route(0051,50,"Greece","Italy",);// what i have to write in the last blank?
}}
I suppose you have those three classes:
Train
Ticket - which is valid for multiple trains
Route - which could contain multiple Tickets
Then you should model your Route like that:
public class Route {
private final int id;
private final int aeroplane;
private final String departure;
private final String arrival;
private final List<Ticket> tickets;
public Route(int id, int aeroplane, String departure, String arrival, List<Ticket> tickets) {
this.id = id;
this.aeroplane = aeroplane;
this.departure = departure;
this.arrival = arrival;
this.tickets = tickets;
}
}
Your route class does not have, and should not have a list of lists of trains. It is perfectly fine, that you have it has a list of tickets.
To the question of how to add the list of Trains to the Route instantiation, you should create a ticket first, or multiple if you like.
public static void main(String[] args) {
// create trains
Train train1 = new Train(1202, "Piraeus", "Athens");
Train train2 = new Train(1302, "Athens", "Thessaloniki");
Train train3 = new Train(1502, "Thessaloniki", "Rome");
// create ticket(s)
Ticket ticket = new Ticket(95, List.of(train1, train2, train3));
// create route and pass tickets
Route myRoute = new Route(0051, 50, "Greece", "Italy", List.of(ticket));
}
To create the lists here I used the factory method java.util.List.of (available since Java 9). Your route class is also a good candidate for a record (since Java 18). As an record it would look like:
public record RouteRecord(int id, int aeroplane, String departure, String arrival, List<Ticket> tickets) {}
Also, think about the concept of immutability.
In your main method ( it's not a class ) :
List<Ticket> tickets = new ArrayList<>();
tickets.add( new Ticket());
Route d1 = new Route(0051,50,"Greece","Italy",tickets);
and as it was mentined before you need to define a constructor :
public Route(int id, int aeroplane, String departure, String arrival, List<Ticket> tickets ){
this.id = id;
this.aeroplane = aeroplane;
this.departure = departure;
this.arrival = arrival;
this.Tickets = tickets;
}
Related
First of all, I'd like to say this is for a university project.
I have 3 classes. Order abstract class and Delivery and DineIn classes which inherits from Order.
I am using Gson to serialize/deserialize the child classes but I have run into a bit of a problem. The Order class has a field orderType which gson uses to determine type of order it is, DineIn or Delivery.
Serialization is working just fine. The problem is that whenever I try to deserialize, the type field value is not read and is always set as null even though it is present in the JSON file.
This happens when there are a lot of fields in Order because when I tried testing this program on a smaller scale with the Order class just having 2 fields (orderType and orderNo) everything worked just fine. I don't what I am doing wrong. I have tried searching on this site and am almost always coming across suggestions to make custom type adapters and serializers but we haven't studied about them in university and I don't want to use them (the instructor deducts marks for using anything he hasn't taught, I almost failed a course I took from him last time because I used things he hadn't taught. He doesn't seem to have a problem with third-party libraries though).
The code:
public class Main {
public static final List<Order> ordersList = read();
public static void main(String[] args) {
System.out.println(ordersList.get(0).getOrderType());
System.out.println(ordersList.get(0) instanceof DineIn ? "DineIn": "Delivery");
}
private static List<Order> read(){
List<Order> ordersList = new ArrayList<>();
Type type = new TypeToken<ArrayList<Order>>() {
}.getType();
RuntimeTypeAdapterFactory<Order> adapter = RuntimeTypeAdapterFactory.of(Order.class, "orderType")
.registerSubtype(DineIn.class)
.registerSubtype(Delivery.class);
Gson gson = new GsonBuilder().registerTypeAdapterFactory(adapter).create();
JsonReader ordersJsonReader;
try {
ordersJsonReader = new JsonReader(new FileReader("orders.json"));
List<Order> tempOrdersList = gson.fromJson(ordersJsonReader, type);
if (tempOrdersList != null) ordersList = tempOrdersList;
ordersJsonReader.close();
} catch (IOException e) {
e.printStackTrace();
}
return ordersList;
}
}
abstract class Order {
private final int orderNumber;
private final String date, customerName;
private final int discountRate;
private final String paymentMethod;
private String orderStatus;
private int grossTotal = 0;
private double netTotal = 0;
private int totalItems = 0;
protected final String orderType;
public abstract String getOrderType();
public abstract double getExtraCharges();
public Order(int orderNumber, String date, String customerName, int discountRate, String paymentMethod, String orderStatus, int grossTotal, double netTotal, int totalItems, String orderType) {
this.orderNumber = orderNumber;
this.date = date;
this.customerName = customerName;
this.discountRate = discountRate;
this.paymentMethod = paymentMethod;
this.orderStatus = orderStatus;
this.grossTotal = grossTotal;
this.netTotal = netTotal;
this.totalItems = totalItems;
this.orderType = orderType;
}
}
class DineIn extends Order {
private double serviceCharges = 150;
public DineIn(int orderNumber, String date, String customerName, int discountRate, String paymentMethod, String orderStatus, int grossTotal, double netTotal, int totalItems) {
super(orderNumber, date, customerName, discountRate, paymentMethod, orderStatus, grossTotal, netTotal, totalItems, "DineIn");
}
#Override
public String getOrderType() {
return orderType;
}
#Override
public double getExtraCharges() {
return serviceCharges;
}
}
class Delivery extends Order {
private double deliveryCharges = 100;
public Delivery(int orderNumber, String date, String customerName, int discountRate, String paymentMethod, String orderStatus, int grossTotal, double netTotal, int totalItems) {
super(orderNumber, date, customerName, discountRate, paymentMethod, orderStatus, grossTotal, netTotal, totalItems, "Delivery");
}
#Override
public String getOrderType() {
return orderType;
}
#Override
public double getExtraCharges() {
return deliveryCharges;
}
}
The JSON:
[
{
"serviceCharges": 150.0,
"orderNumber": 1,
"date": "12/12/2021",
"customerName": "Ali",
"discountRate": 15,
"paymentMethod": "Card",
"orderStatus": "Preparing",
"grossTotal": 5000,
"netTotal": 4500.0,
"totalItems": 14,
"orderType": "DineIn"
}
]
In your code you have a hierarchy where DineIn and Delivery extend from Order. The way the orderType field is set is through an explicit String argument in the super() constructor.
However, Gson does not use the constructor to instantiate the objects. It uses a special no-argument constructor and populates the values via reflection: https://stackoverflow.com/a/40442037/9698467
In this specific case the problem comes from the RuntimeTypeAdapterFactory, which removes the orderType field from the JSON that it reads. The source code here confirms that: https://github.com/google/gson/blob/86d88c32cf6a6b7a6e0bbc855d76e4ccf6f120bb/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java#L202
As #fluffy suggested newer versions of the library include the maintain flag, which should allow for the field to be preserved: https://github.com/google/gson/blob/c1e7e2d2808b042cbe47ca31869ee6ccc62c5417/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java#L214
I am doing a program to sell games. Now in my code it will show only the last review the customer writes, but instead I would like it to contain a list of all reviews the game got. I was thinking if it would be possible to have an ArrayList as a variable instead of the String review. Here is an example of how it looks like now.
public class Game {
private String gameName;
private int gamePrice;
private String gameReviews;
public Game(String gameName, int gamePrice, String gameReviews) {
this.gameName = gameName;
this.gamePrice = gamePrice;
this.gameReviews = gameReviews;
}
}
and then if I want to create an object how it would look like to replace the old one I had?
public class Games {
public static void main(String[] args) {
String gameN = "Name";
int gameP = 10;
String gameR = "Review";
Game game = new Game(gameN, gameP,gameR);
}
}
It is possible to use ArrayList instead of String.
import java.util.ArrayList;
class Game {
private String gameName;
private int gamePrice;
private ArrayList<String> gameReviews;
public Game(String gameName, int gamePrice, ArrayList<String> gameReviews) {
this.gameName = gameName;
this.gamePrice = gamePrice;
this.gameReviews = gameReviews;
}
public static void main(String[] args) {
String gameN = "Name";
int gameP = 10;
ArrayList<String> gameReviews = new ArrayList<String>();
gameReviews.add("Review 1");
gameReviews.add("Review 2");
gameReviews.add("Review 3");
gameReviews.add("Review 4");
Game game = new Game(gameN, gameP,gameReviews);
}
}
If the relationship between your game and the reviews is one-to-many, the data type of your reviews can be List<String>
public class Game {
private String gameName;
private int gamePrice;
private List<String> gameReviews;
public Game(String gameName, int gamePrice, List<String> gameReviews) {
this.gameName = gameName;
this.gamePrice = gamePrice;
this.gameReviews = gameReviews;
}
public Game(String gameName, int gamePrice) {
this.gameName = gameName;
this.gamePrice = gamePrice;
this.gameReviews = new ArrayList<>();
}
public void addGameReview (String gameReview) {
this.gameReviews.add(gameReview);
}
}
Then if you have the list of reviews at initialization you'd just pass it into the constructor:
List<String> reviews = new ArrayList<>();
Game game = new Game(gameN, gameP, reviews);
Otherwise, you could have a constructor that initializes gameReviews to an empty ArrayList, and add the review after the initialization
Game game = new Game(gameN, gameP);
game.addGameReview("This is a review of Game ...");
Related to my previous thread, i want to print an output like this:
bookId = "1234" (String)
bookName = "Machine Learning" (String)
price = $20 (int)
ratings = (array of object)
rater = a, score = 5
rater = b, score = 3
But this time, i tried to use an OOP manner.
So first, i made a POJO class called ProductView, the class will be look like this:
public class ProductView {
// field
private String bookId;
private String bookName;
private int price;
private List<Ratings> ratings;
// a constructor i tried to make
public ProductView(String bookId, String bookName, int price, List<Ratings> ratings) {
this.bookId = bookId;
this.bookName = bookName;
this.price = price;
this.ratings = ratings;
}
public String getBookId() {
return bookId;
}
public void setBookId(String bookId) {
this.itemId = itemId;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public Ratings getRatings() {
return ratings;
}
public void setRatings(Ratings ratings) {
this.ratings = ratings;
}
}
After that, i made a class called Ratings with the following field:
public class Ratings {
private String rater;
private int score;
public Ratings(String rater, int score) {
this.rater = rater;
this.score = score;
}
}
And finally, i made a Main Class called Main:
public class Main {
public static void main(String[] args) {
}
}
In the Main Class, i want to create an instance of the ProductView class and give it some value.
But i don't know how to do it with a list object param in my constructor.
Anyone can give me some insight?
first:
List is an interface, you should pass an implementation of list such as ArrayList or similar
second:
you have a compilation error in ProductView -> SetBookId, in this.itemId you don't have itemId as member or constructor parameter
furthermore, in get/set rating you need to pass and return list of Ratings.
nameing:
Ratings is actually just a Rating, you can make a new class of List or just use the Rating as is but change the name
now for your Question:
you can initialize first the list with objects and then send it to the constructor
such as:
List<Ratings> ratings = new ArrayList<>();
ratings.add(new Ratings("rater",5));
ratings.add(new Ratings("rater2",6));
ProductView productView = new ProductView("bookId","bookName",1,ratings);
Or, just initialize the ArrayList in the Constructor, the first way is preferable:
ProductView productView1 = new ProductView("bookId","bookName",1,
new ArrayList<Ratings>(Arrays.asList(new Ratings("rater",5), new Ratings("rater2",6))
));
hopefully, this answers your question
same as DodgyCodeException mentioned in the comments.
It could be a very simple solution but I just started learning Java. I would like to add every instantiated Product to the productList. Is there any way to solve this problem without modifying the access modifiers?
public class Product {
private int id;
private String name;
private float defaultPrice;
private Currency defaultCurrency;
private Supplier supplier;
private static List<Product> productList;
private ProductCategory productCategory;
public Product(float defaultPrice, Currency defaultCurrency, String name) {
this.id = IdGenerator.createID();
this.defaultPrice = defaultPrice;
this.defaultCurrency = defaultCurrency;
this.name = name;
}
}
You can just add a newly created Product to the list in its constructor:
public class Product {
private int id;
private String name;
private float defaultPrice;
private Currency defaultCurrency;
private Supplier supplier;
private static List<Product> productList = new LinkedList<>();
private ProductCategory productCategory;
public Product(float defaultPrice, Currency defaultCurrency, String name){
this.id = IdGenerator.createID();
this.defaultPrice = defaultPrice;
this.defaultCurrency = defaultCurrency;
this.name = name;
productList.add(this);
}
}
Change the initialisation line
private static List<Product> productList;
to
private static List<Product> productList = new LinkedList<>();
Add productList.add(this) as the last line of the constructor.
So each time you call the Product constructor, it will add this instance to the static list.
Like Peter Lawrey mentionned it in the comment section of Mureinik's answer, having a static collection in the POJO is not the best solution.
I would suggest to use a simple facade. This limit the list existence to the facade life and don't include the logic of a collection in a POJO.
public class FacadeProduct {
private List<Product> cacheProduct = new ArrayList<>();
public Product createProduct(float defaultPrice, Currency defaultCurrency, String name){
Product p = new Product(defaultPrice, defaultCurrency, name);
cacheProduct.add(p);
return p;
}
}
This would be quite simple to use.
public static void main(String ars[]){
{
FacadeProduct f = new FacadeProduct();
{
Product p1 = f.createProduct(1f, null, "test1");
Product p2 = f.createProduct(1f, null, "test2");
Product p3 = f.createProduct(1f, null, "test3");
// Here, the list have 3 instances in it
}
// We lose the p1, p2, p3 reference, but the list is still holding them with f.
}
//Here, we lose the f reference, the instances are all susceptible to be collected by the GC. Cleaning the memory
}
Initialize productList with null, and then modify the constructor as follows:
public Product(float defaultPrice, Currency defaultCurrency, String name) {
this.id = IdGenerator.createID();
this.defaultPrice = defaultPrice;
this.defaultCurrency = defaultCurrency;
this.name = name;
if (productList == null) productList = new ArrayList<>();
productList.add(this);
}
I am still pretty new with Java so don't hesitate if you think I am wildly off here...
I have a Java program with multiple object blueprint classes, a menu class, and a driver class. The driver class calls menu. In the menu class, I create a customer object while instantiating only 1 of it's 4 fields. The field is unique ID field. I want to get the other 3 fields from an ArrayList located in the driver class. How can I choose a customer object from an ArrayList in a separate class?
The first Object I am trying to create.
public class Customer {
private int id;
private String name;
private String address;
private String phone;
public static int count = 100;
public Customer(String name, String address, String phone) {
this.id = count;
this.name = name;
this.address = address;
this.phone = phone;
count++;
}
}
Reservation has a Customer
public class Reservation {
static Scanner scan = new Scanner(System.in);
private Customer customer;
private Flight flight;
private int partySize;
private double reservationCost;
final private double FIRST_CLASS_COST = 850.00;
final private double ECONOMY_COST = 450.00;
public Reservation(Customer customer, Flight flight, int partySize, double reservationCost) {
this.customer = customer;
this.flight = flight;
this.partySize = partySize;
this.reservationCost = reservationCost;
}
In the driver class, called AirlineDriver, there is an ArrayList of Customers. In the code below, how would I create a Customer object to then create a Reservation if I need to get one of the Customers in the ArrayList in the driver?
public class Menu {
static Scanner scan = new Scanner(System.in);
public Reservation createReservation() {
Customer cust = new Customer();
Flight flight;
Reservation reservation;
System.out.println("Are you a returning customer? (Y or N)");
String w = scan.nextLine();
while (!"Y".equals(w) || !"y".equals(w) || !"N".equals(w) || !"n".equals(w)) {
System.out.println("Incorrect key, please enter Y for Yes, and N for No.");
w = scan.nextLine();
}
if (w.equalsIgnoreCase("Y") || w.equalsIgnoreCase("y")) {
System.out.println("Welcome back and thank you for flying with us.");
System.out.println("What is your Customer ID?");
int custID = scan.nextInt();
}
If the customer already exists, they are already in this ArrayList.
public class AirlineDriver {
private static Scanner files;
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
ArrayList<Customer> cust = new ArrayList<Customer>();
Make sure, you have declared all getter method in Customer class. Because, I didn't declared. You need to iterate through the ArrayList<Customer>
for(Customer custom : cust)
{
// call all your getter method from Customer class.
String customerName = custom.getName();
}