Is it safe to assign default values to class members in Java? - java

Here's are two classes, Passenger and Car. Instead of initializing all private members of the Car class in all constructors, I thought of setting default values for them and overwriting specific members' values if provided by the instance creator.
import java.util.ArrayList;
class Passenger {
private String name;
Passenger(String name) {
this.name = name;
}
}
class Car {
private String color = "red";
private int numberOfWheels = 4;
private ArrayList<Passenger> passengers = new ArrayList<Passenger>();
Car() {}
Car(String color) {
this.color = color;
}
Car(int numberOfWheels) {
this.numberOfWheels = numberOfWheels;
}
public void addPassenger(Passenger p) {
this.passengers.add(p);
}
}
Is it safe to set default values to class members like this? Any pitfalls to avoid for any particular data types (even other than the ones I have used)?

Yes, it is safe.
Personally I prefer initialize where is declaration if is a common value for all constructors. If I have more constructor is not very pleasure to write that thing multiple times. And for me is more clear what value have.

Related

Java Multiple Objects return same info [duplicate]

This question already has answers here:
What does the 'static' keyword do in a class?
(22 answers)
Closed 3 years ago.
I'm trying to code a system to determine the type of a weapon and the damage of the weapon for a video game. I'm trying to instantiate two weapons with different stats, but when I use the method getType();, they return the same thing.
I tried using an ArrayList, but grabbing the type of the weapon from something such as (arraylist name here).get(0).getType(); and (arraylist name here).get(1).getType(); still return "AK-47".
ArrayList<Weapon> weapons = new ArrayList<Weapon>();
Weapon weapon = new Weapon("Desert Eagle", 5);
Weapon weapon2 = new Weapon("AK-47", 3);
weapons.add(weapon);
weapons.add(weapon2);
System.out.println(weapon.getType());
System.out.println(weapon2.getType());
Methods:
public class Weapon {
static String type;
static int damage;
public Weapon(String type, int damage) {
Weapon.type = type;
Weapon.damage = damage;
}
public static String getType() {
return type;
}
}
I want weapon.getType(); to return "Desert Eagle" and weapon2.getType(); to return "AK-47".
I know it should be a simple answer, but I'm probably just over-complicating this for myself haha. Any help is appreciated, thanks!
It is because your type is static
Change it to private String type;
Remove static keywoard as it makes fields shared across every instance of that class
static String type;
static int damage;
Remove static from type and damage in Weapon. static means one value for the class globally, not one value per class instance (which is what you want). Also, this.type = type; and this.damage = damage; in the constructor.
public class Weapon {
private String type;
private int damage;
public Weapon(String type, int damage) {
this.type = type;
this.damage = damage;
}
public String getType() {
return type;
}
}
Also, you aren't currently using any values from your List (you kept the references you created, and are calling through those references). And prefer programming to the List interface over the ArrayList type (and you could use the diamond operator <>). Like,
List<Weapon> weapons = new ArrayList<>();
weapons.add(new Weapon("Desert Eagle", 5));
weapons.add(new Weapon("AK-47", 3));
for (Weapon w : weapons) {
System.out.println(w.getType());
}
Outputs
Desert Eagle
AK-47

Chaining multiple constructors

I understand that when chaining constructors this must be done on the first line of the main constructor, can someone explain how you would go about the below code.
I want to chain to all constructors so that they can all be private other than the main constructor.
public class Flight {
int passengers = 0;
int seats = 150;
double maxKgPerPassenger;
private Flight(int passengers) {
this.passengers = passengers;
}
private Flight(int seats) {
this.seats = seats;
}
private Flight(double maxKgPerPassenger) {
this.maxKgPerPassenger = maxKgPerPassenger;
}
public Flight(int passengers, int seats, double maxKgPerPassenger) {
this(passengers);
this(seats);
this(maxKgPerPassenger);
}
}
A constructor is up to set as many fields as possible or construct an instance completely.
You pick a constructor which has a greater number of arguments and use it within constructors with a smaller amount. For example,
public Flight(double maxKgPerPassenger) {
this(0, 0, maxKgPerPassenger); // default, default, maxKgPerPassenger
}
private Flight(int passengers, int seats, double maxKgPerPassenger) {
this.passengers = passengers;
this.seats = seats;
this.maxKgPerPassenger = maxKgPerPassenger;
}
I want to chain to all constructors so that they can all be private other than the main constructor.
I suggest the opposite way. Make all constructors you are going to use public, but an all-arguments constructor private if you won't be using that.
The approach you tried to adopt is similar to the builder pattern where each method sets a single field. You definitely need to have a look at it if a number of arguments are going to grow up.
Why do you want to chain constructors ?
As you chain constructors, you have to specify some default values from the constructor with less argument to the invoked constructor with more arguments.
You do the reverse here :
public Flight(int passengers, int seats, double maxKgPerPassenger){
this(passengers);
this(seats);
this(maxKgPerPassenger);
}
You indeed want to invoke from the constructor with the most argument all other constructors.
It makes no sense and it is not valid either as a constructor can invoke a single other constructor of the same class.
I want to chain to all constructors so that they can all be private
other than the main constructor.
Things work in the reverse order.
The actual code doesn't seem to need constructor chaining.
This one is enough :
public Flight(int passengers, int seats, double maxKgPerPassenger){
this.passengers = passengers;
this.seats = seats;
this.maxKgPerPassenger = maxKgPerPassenger;
}
Suppose that class clients could create Flight instances with two flavors :
by passing all parameters
by passing only the seats parameter (remains being valued with default values)
You could so write :
public Flight(int passengers, int seats, double maxKgPerPassenger){
this.passengers = passengers;
this.seats = seats;
this.maxKgPerPassenger = maxKgPerPassenger;
}
public Flight(int seats){
super(50, seats, 10); // you pass some default values for passengers and maxKgPerPassenger
}
make the default constructor private to prevent constructor instantiation and instantiate objects using a public static method. This way you can work around the constructor restriction. To add a little confusion I converted your constructors to normal methods using the class name by adding void return type. Also consider if want you really want isn't the Builder pattern.
public class Flight {
private int passengers = 0;
private int seats = 150;
private double maxKgPerPassenger;
private Flight() {}
private void Flight(int passengers)
{
this.passengers = passengers;
}
private void Flight(int seats)
{
this.seats = seats;
}
private void Flight(double maxKgPerPassenger)
{
this.maxKgPerPassenger = maxKgPerPassenger;
}
public static Flight create(int passengers, int seats, double maxKgPerPassenger)
{
Flight flight = new Flight();
flight.Flight(passengers);
flight.Flight(seats);
flight.Flight(maxKgPerPassenger);
return flight;
}
}

How can we create immutable class object using setter instead constructor.As I want to use its setter method .Does it Possible to make immutable?

Creating immutable class using setter method from outside class.As i have a POJO Class Object creation may be done using setter method.How come it possible to make immutable using setter
Setters are mutators.
https://en.wikipedia.org/wiki/Mutator_method
I think you might be referring to a factory method?
https://www.tutorialspoint.com/design_pattern/factory_pattern.htm
Or maybe you have some hybrid thingo going on.
People more experienced then me would have better answers.
You can use the Builder Pattern. There you have a separate builder class with a kind of setter for each field. The final build() eventually creates the immutable object.
public final class Person {
private final String forename;
private final String surename;
private final int age;
private Person(String forename, String surename, int age) {
this.forename = forename;
this.surename = surename;
this.age = age;
}
public String getForename() {
return forename;
}
public String getSurename() {
return surename;
}
public int getAge() {
return age;
}
public static PersonBuilder createBuilder() {
return new PersonBuilder();
}
public static class PersonBuilder {
private String forename;
private String surename;
private int age;
private PersonBuilder() {
}
public PersonBuilder withForename(String forename) {
this.forename = forename;
return this;
}
public PersonBuilder withSurename(String surename) {
this.surename = surename;
return this;
}
public PersonBuilder withAge(int age) {
this.age = age;
return this;
}
public Person build() {
return new Person(forename, surename, age);
}
}
You can then create a Person instance like so:
Person person = Person.createBuilder().withSurename("Krueger")
.withForename("Freddy").withAge(47).build();
With a builder you have the best of both worlds. The flexibility of setters (including fluent API) and immutable objects at the end.
Edit:
Joshua Bloch stated in Item 15: "Minimize Mutability" in his book "Effective Java":
To make a class immutable, follow these five rules:
Don’t provide any methods that modify the object’s state (known as mutators).
Ensure that the class can’t be extended. [...]
Make all fields final. [...]
Make all fields private. [...]
Ensure exclusive access to any mutable components. [...]
To fulfill point 2 I added the final keyword to the above Person class.
According to this widely accepted definition of immutability a class with setters is per se not immutable because it violates point 1.
If think the intention to ask this question in an interview is to see wether the candidate is able to recognize the discrepancy in the question itself and how far goes the knowledge about immutability and the various alternatives to create instances of immutable classes (per constructor, per static factory methods, per factory classes, per builder pattern, ...).

Java association problems

Finding Java an overly complicated language. I can't figure out this association thing if my life depended on it. I'm specifically stuck on the Cab object +pickup(rider:Passenger): String. I know it will return a String and here's the code I have so far.
UML Diagram
package cabsimulation;
public class Cab {
private double companyTotalFare;
private double rate;
private double taxiTotalFare;
private int tripCounter;
private int cabID;
public Cab(int cabID){}
public double dropOff(int minutes){
return minutes*rate;
}
public double endOfShift(){
double sumOfFares = taxiTotalFare + companyTotalFare;
return sumOfFares;
}
//public String report();
public double getRate(){
return rate;
}
public void setRate(double cabRate){
this.rate = cabRate;
}
}
and
public class Passenger {
private final double weight;
private final boolean inFrontSeat;
public Passenger (double weight, boolean front){
this.weight = weight;
this.inFrontSeat = front;
}
public double getWeight(){
return weight;
}
public boolean isInFrontSeat(){
return inFrontSeat;
}
}
How do I write (program) an association between these two objects?
As written in your instructions: define a typed attribute
private Passenger passenger;
or the like (I'm no Java guy).
When you want to have an association between two classes, you will normally use an instance variable. In this case, a Cab can contain a Passenger. So you want to have an instance variable in the Cab class which is able to hold a Passenger. This can be done like that:
public class Cab {
Passenger passenger;
//...
}
In the pickUp method shown in the UML, you want to fill this variable, e. g. like that (unfortunately, there is no specification what String the method should return):
public class Cab {
Passenger passenger;
//...
public String pickUp(Passenger rider) {
this.passenger = rider;
return "something";
}
}
After you called the method pickUp, you can access the passenger in the cab via its instance variable.
I hope I could help you!
usually, if you have an attribute, you have the getter/setter which are dedicated to set and to get the attribute.
If you have a method (other than a setter) with a parameter of the type of an attribute, it does not mean that the parameter will set the attribute.
So for me, it could be easier to remove the method pickup and to define a getter and setter on passenger.

How to extend or implement classes? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Picture to show task:
First I am sorry, for my bad to for expressing my mind.
I have such a task, I don't need that you do it for me.
Vehicle is parent class for Sedan (Cause Sedan class is String type).
How to extend or implement Vehicle class with universal class?
I forgot to ask my teacher, but maybe you will know, what means striped pointer to Owner class, and what is that: has a?
P.S. If you need code that I have written already, I will show you.
So this is my parent Vehicle class:
public class Vehicle {
private int vehicleNumber;
protected int fuelTankSize;
protected int maxSpeed;
protected Owner owner;
//1
public Vehicle(int vehicleNumber){
this.vehicleNumber = vehicleNumber;
}
//2
public Vehicle(int vehicleNumber, int fuelTankSize) {
this.vehicleNumber = vehicleNumber;
this.fuelTankSize = fuelTankSize;
}
//3
public Vehicle(int vehicleNumber, int fuelTankSize, int maxSpeed) {
this.vehicleNumber = vehicleNumber;
this.fuelTankSize = fuelTankSize;
this.maxSpeed = maxSpeed;
}
//4
public Vehicle(int vehicleNumber, int fuelTankSize, int maxSpeed, Owner owner) {
this.vehicleNumber = vehicleNumber;
this.fuelTankSize = fuelTankSize;
this.maxSpeed = maxSpeed;
this.owner = owner;
}
//1
public int getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed (int maxSpeed){
this.maxSpeed = maxSpeed;
}
//2
protected int getFuelTankSize(){
return fuelTankSize;
}
protected void setFuelTankSize (int fuelTankSize){
this.fuelTankSize = fuelTankSize;
}
//3
public Owner getOwner(){
return owner;
}
public void setOwner (Owner owner){
this.owner = owner;
}
}
child Sedan with:
public class Sedan extends Vehicle {
private String registrationIndex;{
}
public Sedan (int vehicleNumber, int fuelTankSize, int maxSpeed, String registrationIndex, Owner owner) {
super(vehicleNumber, fuelTankSize, maxSpeed, owner);
this.setRegistrationIndex (registrationIndex);
}
public String getRegistrationIndex (){
return registrationIndex;
}
public void setRegistrationIndex (String registrationIndex) {
this.registrationIndex = registrationIndex;
}
}
second Universal child without an error:
public class Universal extends Vehicle {
private int trunkSize;
public Universal (int vehicleNumber, int fuelTankSize, int maxSpeed, int trunkSize, Owner owner) {
super(vehicleNumber, fuelTankSize, maxSpeed, owner);
this.setTrunkSize (trunkSize);
}
public int getTrunkSize() {
return trunkSize;
}
public void setTrunkSize(int trunkSize) {
this.trunkSize = trunkSize;
}
public void printDescription() {
super.printDescription();
System.out.println("Universalo bagažinės tūris: " + getTrunkSize() + "l.");
}
}
and some misterious (to me) Owner class:
public class Owner {
public String firstName;
public String lastName;
public Owner (String firstName){
this.firstName = firstName;
}
public Owner (String firstName, String lastName){
this.firstName = firstName;
this.lastName = lastName;
}
}
added VechileTest for testing:
public class VehicleTest {
public static void main(String[] args) {
Vehicle vehicleInf = new Vehicle (1, 45, 260);
Universal universalInf = new Universal(2, 50, 220, 70);
Sedan sedanInf = new Sedan (3, 40, 180, "AVA 123");
vehicleInf.printDescription();
universalInf.printDescription();
sedanInf.printDescription();
}
}
Well, 1st of all I recommend you read a good tutorial / explanation of UML class diagrams, like this here for example.
After you know the basics, it should be easy to translate that into Java code.
I'll give you the code for the Universal class and a start for your Vehicle. The rest you'll have to do on your own.
The class Universal:
public class Universal extends Vehicle {
private int trunkSize;
public int getTrunkSize() {
return this.trunkSize;
}
public void setTrunkSize(int trunkSize) {
this.trunkSize = trunkSize;
}
}
As you can see the first block inside a class box refers to the variables. The - and + indicates the visibility (private for -, public for +).
The next block is about the methods, specifying visibility, return type, method name and parameters (type and name).
The arrow between Universal and Vehicle indicates a inheritance relationship (see in code that Universal extends Vehicle).
So all in all the diagram is a construction plan for your classes; at least for the static part, meaning the relationships and state they can have.
The start of class Vehicle:
public class Vehicle {
private int vehicleNumber;
// the rest here ...
}
Edit:
Well, now that I see your code, you seem to have a few misconceptions:
The Sedan type is not from type String, it is from type Sedan (which extends Vehicle). Just the new member variable in the Sedan type is of type String, does not matter.
To your 1st question: The Vehicle class is the base (parent) class of Sedan. You do not to do anything with it, inheritance is expressed from the child towards the parent, not the other way around. Vehicle should usually be declared abstract (as you cannot create an instance of a generic Vehicle), but this is not in the diagram.
To your 2nd question: The has a relationship is just this. It expressed that one class has another class as it's member (which is redundantely expressed inside the class diagram already), so nothing to do for that.
Additionally your code has a few issues:
I do not see any constructors declared in Vehicle class, those 4 can go.
Your Sedan has a superflous pair of {} after declaration of your registrationIndex variable.
Since your Vehicle has no default constructor, you must call this constructor from your Sedan class (or remove the constructors from Vehicle.
Your Universal class calls the Vehicle constructor with the trunkSize while the Vehicle constructor expects the vehicleNumber there.
Your Vehicle class doesn't have a parameterless constructor, which means that Universal and Sedan must explicitly call one of them (super(...);). You're doing this in Universal (albeit incorrectly as you're passing the trunk size instead of the vehicle number expected by Vehicle's constructor) but not in Sedan.
As for the second question: The two major relations in OOP are is a and has a. The difference can be easily explained like this:
A Sedan is a vehicle
A vehicle has an owner
is a means it inherits some properties of something else, has a means that it has a reference to something else.

Categories