这段 Java 代码为什么没有产生我期望的结果?

huangapple go评论66阅读模式
英文:

Why is this java code not producing the result I am expecting?

问题

程序需要根据顾客的年龄性别来发出正确的票价。

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        Person p1 = new Person();

        System.out.println("输入乘客姓名:");
        String name = sc.next();
        p1.setName(name);

        System.out.println("输入性别:");
        char gen = sc.next().charAt(0);
        p1.setGender(gen);

        System.out.println("输入年龄:");
        int age = sc.nextInt();
        p1.setAge(age);

        BusTicket b1 = getTicketDetails();
        b1.setPerson(p1);

        b1.calculateTotal();

        System.out.println("票号:" + b1.getTicketno());
        System.out.println("乘客姓名:" + p1.getName());
        System.out.println("票价:" + b1.getTicketprice());
        System.out.println("总金额:" + b1.getTotalamt());
    }

    public static BusTicket getTicketDetails() {
        Scanner sc=new Scanner(System.in);

        System.out.println("输入票号:");
        int no=sc.nextInt();

        BusTicket t1=new BusTicket();
        t1.setTicketno(no);

        System.out.println("输入票价:");
        float cost=sc.nextFloat();
        t1.setTicketprice(cost);

        return t1;
    }
}
public class Person {
    private String name;
    private char gender;
    private int age;

    public void setName(String name){
        this.name=name;
    }

    public String getName() {
        return this.name;
    }

    public void setGender(char gender){
        this.gender = gender;
    }

    public char getGender() {
        return this.gender;
    }

    public void setAge(int age){
        this.age = age;
    }

    public int getAge() {
        return this.age;
    }
}
public class BusTicket {
    private int ticketNo;
    private float ticketPrice;
    private float totalAmount;
    private Person person;

    public void setTicketno(int no) {
        ticketNo = no;
    }

    public int getTicketno() {
        return this.ticketNo;
    }

    public void setTicketprice(float price){
        ticketPrice = price;
    }

    public float getTicketprice(){
        return this.ticketPrice;
    }

    public void setTotalamt(float amt) {
        totalAmount=amt;
    }

    public float getTotalamt() {
        return this.totalAmount;
    }

    public void setPerson(Person p) {
        person=p;
    }

    public Person getPerson() {
        return this.person;
    }

    public void calculateTotal() {
        if(16 > person.getAge())
            this.totalAmount = ticketPrice - (float) (ticketPrice * 0.50);
        else if(person.getAge() < 60)
            this.totalAmount = ticketPrice - (float) (ticketPrice * 0.25);
        else if (person.getGender() == 'f' || person.getGender() == 'F')
            this.totalAmount = ticketPrice - (float) (ticketPrice * 0.10);
        else
            this.totalAmount = ticketPrice;
    }
}

calculateTotal 方法没有给出正确的输出。对于每张票价,输出的金额是其一半。在 calculateAmount 函数的 if-else 条件中没有正确执行。

为了获得我期望的结果,我需要做出什么改变?

测试用例

其中姓名不相关,基础票价为 $100.00

+-----|--------|-------------------|-----------------------------+
| 年龄 | 性别   | 预期折扣          | 预期总票价                  |
|-----|--------|-------------------|-----------------------------|
| 15  |   男   |       0.50        |             $50.00          |
| 15  |   女   |       0.50        |             $50.00          |
|  4  |   男   |       0.50        |             $50.00          |
| 12  |   女   |       0.50        |             $50.00          |
|-----|--------|-------------------|-----------------------------|
| 61  |   男   |       0.25        |             $75.00          |
| 61  |   女   |       0.25        |             $75.00          |
| 99  |   男   |       0.25        |             $75.00          |
| 75  |   女   |       0.25        |             $75.00          |
|-----|--------|-------------------|-----------------------------|
| 16  |   女   |       0.10        |             $90.00          |
| 27  |   女   |       0.10        |             $90.00          |
| 48  |   女   |       0.10        |             $90.00          |
| 60  |   女   |       0.10        |             $90.00          |
|-----|--------|-------------------|-----------------------------|
| 16  |   男   |       0.00        |             $100.00         |
| 27  |   男   |       0.00        |             $100.00         |
| 48  |   男   |       0.00        |             $100.00         |
| 60  |   男   |       0.00        |             $100.00         |
+-----|--------|-------------------|-----------------------------+
英文:

The program needs to issue the correct ticket price based on the age and gender of the customer.

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        Person p1 = new Person();

        System.out.println(&quot;Enter the passenger name:&quot;);
        String name = sc.next();
        p1.setName(name);

        System.out.println(&quot;Enter the gender:&quot;);
        char gen = sc.next().charAt(0);
        p1.setGender(gen);

        System.out.println(&quot;Enter the age:&quot;);
        int age = sc.nextInt();
        p1.setAge(age);

        BusTicket b1 = getTicketDetails();
        b1.setPerson(p1);

        b1.calculateTotal();

        System.out.println(&quot;Ticket no:&quot;+b1.getTicketno());
        System.out.println(&quot;Passenger Name:&quot;+p1.getName());
        System.out.println(&quot;Price of a ticket:&quot;+b1.getTicketprice());
        System.out.println(&quot;Total Amount:&quot;+b1.getTotalamt());
    }

    public static BusTicket getTicketDetails() {
        Scanner sc=new Scanner(System.in);

        System.out.println(&quot;Enter the ticket no:&quot;);
        int no=sc.nextInt();

        BusTicket t1=new BusTicket();
        t1.setTicketno(no);

        System.out.println(&quot;Enter the ticket price:&quot;);`enter code here`
        float cost=sc.nextFloat();
        t1.setTicketprice(cost);

        return t1;
    }
}
public class Person {
    private String name;
    private char gender;
    private int age;

    public void setName(String name){
        this.name=name;
    }

    public String getName() {
        return this.name;
    }

    public void setGender(char gender){
        this.gender = gender;
    }

    public char getGender() {
        return this.gender;
    }

    public void setAge(int age){
        this.age = age;
    }

    public int getAge() {
        return this.age;
    }
}
public class BusTicket {
private int ticketNo;
    private float ticketPrice;
    private float totalAmount;
    private Person person;

    public void setTicketno(int no) {
        ticketNo = no;
    }

    public int getTicketno() {
        return this.ticketNo;
    }

    public void setTicketprice(float price){
        ticketPrice = price;
    }

    public float getTicketprice(){
        return this.ticketPrice;
      }

    public void setTotalamt(float amt) {
        totalAmount=amt;
    }

    public float getTotalamt() {
        return this.totalAmount;
    }

    public void setPerson(Person p) {
        p=new Person();
        person=p;
    }

    public Person getPerson() {
        return this.person;
    }

    public void calculateTotal() {
        if(16 &gt; person.getAge())
            this.totalAmount = ticketPrice - (float) (ticketPrice * 0.50);
        else if(person.getAge() &lt; 60)
            this.totalAmount = ticketPrice - (float) (ticketPrice * 0.25);
        else if (person.getGender() == &#39;f&#39; || person.getGender() == &#39;F&#39;)
            this.totalAmount = ticketPrice - (float) (ticketPrice * 0.10);
        else
            this.totalAmount = ticketPrice;
    }
}

The calculateTotal method is not giving the correct output. For every ticket price, the output is giving the amount as half of it. The if-else condition in the calculateAmount function is not being properly executed.

What do I need to change it to in order to give me the results I expect?

Test Cases

Where Name is irrelevant and base ticket price is $100.00.

+-----|--------|-------------------|-----------------------------+
| Age | Gender | Expected Discount | Expected total ticket price |
|-----|--------|-------------------|-----------------------------|
| 15  |   M    |       0.50        |             $50.00          |
| 15  |   F    |       0.50        |             $50.00          |
|  4  |   M    |       0.50        |             $50.00          |
| 12  |   F    |       0.50        |             $50.00          |
|-----|--------|-------------------|-----------------------------|
| 61  |   M    |       0.25        |             $75.00          |
| 61  |   F    |       0.25        |             $75.00          |
| 99  |   M    |       0.25        |             $75.00          |
| 75  |   F    |       0.25        |             $75.00          |
|-----|--------|-------------------|-----------------------------|
| 16  |   F    |       0.10        |             $90.00          |
| 27  |   F    |       0.10        |             $90.00          |
| 48  |   F    |       0.10        |             $90.00          |
| 60  |   F    |       0.10        |             $90.00          |
|-----|--------|-------------------|-----------------------------|
| 16  |   M    |       0.00        |             $100.00         |
| 27  |   M    |       0.00        |             $100.00         |
| 48  |   M    |       0.00        |             $100.00         |
| 60  |   M    |       0.00        |             $100.00         |
+-----|--------|-------------------|-----------------------------+

答案1

得分: 3

问题是你在做以下操作时覆盖了 person:

public void setPerson(Person p){
      p = new Person();
      person = p;
}

用以下的 setter 替换它:

public void setPerson(Person p){
    this.person = p;
}
英文:

The problem is you are overwritting person when you doing :

public void setPerson(Person p){
p =new Person();
person=p;
}

Replace this setter with:

public void setPerson(Person p){
this.person=p;
}

答案2

得分: 2

Here, something like immutability will be your friend.

@Ner is correct by pointing out that the setPerson() method is what breaks your code since you instantiate a new Person object instead of using the one that is passed to the setter method, setPerson, in the BusTicket class.

This causes you to lose the data within the passed‑in Person object that is essential to the calculation.

The Person's name defaults to null, the gender character will default to 'u0000', and the age will default to 0.
That age value is what catches the first if‑statement in the calculation method of the BusTicket class every time, since 0 is less than 16.

One change to make could be to take:

public void setPerson(Person p) {
    p=new Person();
    person=p;
}

and transform it to:

public void setPerson(final Person person) {
    this.person = person;
}

Notice the usage of the final keyword here. This is a great way to protect incoming method arguments from having their reference altered in the scope of the method.

英文:

Here, something like immutability will be your friend.

@Ner is correct by pointing out that the setPerson() method is what breaks your code since you instantiate a new Person object instead of using the one that is passed to the setter method, setPerson, in the BusTicket class.

This causes you to lose the data within the passed‑in Person object that is essential to the calculation.

The Person's name defaults to null, the gender character will default to &#39;u0000&#39;, and the age will default to 0.
That age value is what catches the first if‑statement in the calculation method of the BusTicket class every time, since 0 is less than 16.

One change to make could be to take:

public void setPerson(Person p) {
    p=new Person();
    person=p;
}

and transform it to:

public void setPerson(final Person person) {
    this.person = person;
}

Notice the usage of the final keyword here. This is a great way to protect incoming method arguments from having their reference altered in the scope of the method.

Alternative Code Structure

I would propose the following alternatives to your classes, as they exemplify better practices that would prevent something like this bug from ever occurring.

import java.util.Scanner;
import java.util.function.Function;

public class Main {
    public static void main(final String[] args) {
        try(final Scanner scanner = new Scanner(System.in)) {
            final Person person = getPersonUsing(scanner);
            final BusTicket busTicket = getBusTicketForPersonUsing(scanner).apply(person);
            System.out.printf(&quot;%n%s&quot;, busTicket);
        }
    }

    private static Person getPersonUsing(final Scanner scanner) {
        System.out.print(&quot;Enter the passenger name: &quot;);
        final String name = scanner.nextLine();

        System.out.print(&quot;Enter the gender: &quot;);
        final Person.Gender gender = Person.Gender.valueOf(scanner.next().charAt(0));

        System.out.print(&quot;Enter the age: &quot;);
        final int age = scanner.nextInt();

        return new Person(name, gender, age);
    }

    private static Function&lt;Person, BusTicket&gt; getBusTicketForPersonUsing(final Scanner scanner) {
        return person -&gt; {
            System.out.print(&quot;Enter the ticket number: &quot;);
            final int ticketNumber = scanner.nextInt();

            System.out.print(&quot;Enter the base ticket price: &quot;);
            final float baseTicketPrice = scanner.nextFloat();

            return new BusTicket(ticketNumber, baseTicketPrice, person);
        };
    }
}
public class Person {
    private final String name;
    private final Person.Gender gender;
    private final int age;

    public Person(
            final String name,
            final Person.Gender gender,
            final int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }

    public String getName() {
        return this.name;
    }

    public Person.Gender getGender() {
        return this.gender;
    }

    public int getAge() {
        return this.age;
    }

    @Override
    public String toString() {
        return String.format(
                &quot;%s (%02d %s)&quot;,
            getName(),
            getAge(),
            getGender().asSingleLetter());
    }

    public enum Gender {
        FEMALE,
        MALE;

        public String asSingleLetter() {
            return String.valueOf(name().charAt(0));
        }

        public static Gender valueOf(final char gender) {
            switch (Character.toUpperCase(gender)) {
            case &#39;F&#39;: return FEMALE;
            case &#39;M&#39;: return MALE;
            default:
                throw new IllegalArgumentException(String.format(&quot;Gender [%s] could not be determined.&quot;, gender));
            }
        }
    }
}
import java.util.function.Function;

public class BusTicket {
    private final int ticketNumber;
    private final float baseTicketPrice;
    private final float totalAmount;
    private final Person person;

    public BusTicket(
            final int ticketNumber,
            final float baseTicketPrice,
            final Person person) {
        this.ticketNumber = ticketNumber;
        this.baseTicketPrice = baseTicketPrice;
        this.totalAmount = calculateTotal(person).apply(baseTicketPrice);
        this.person = person;
    }

    public int getTicketNumber() {
        return this.ticketNumber;
    }

    public float getBaseTicketPrice() {
        return this.baseTicketPrice;
    }

    public float getTotalAmount() {
        return this.totalAmount;
    }

    public Person getPerson() {
        return person;
    }

    @Override
    public String toString() {
        return String.format(
                &quot;%nTicket no: %d%n&quot; + 
                &quot;Passenger: %s%n&quot; +
                &quot;Base price of a ticket: $%.2f%n&quot; +
                &quot;Total Amount: $%.2f%n&quot;,
            getTicketNumber(),
            getPerson(),
            getBaseTicketPrice(),
            getTotalAmount());
    }

    private static float calculateDiscountForPerson(final Person person) {
        // 50% discount for age of 16
        if(person.getAge() &lt; 16) {
            return 0.50f;
        // 25% discount for age over 60
        } else if(person.getAge() &gt; 60) {
            return 0.25f;
        // 10% discount for females
        } else if (person.getGender() ==  Person.Gender.FEMALE) {
            return 0.10f;
        // 0% discount for men between 16 and 60
        } else {
            return 0.00f;
        }
    }

    private static Function&lt;Float, Float&gt; calculateTotal(final Person person) {
        return baseTicketPrice -&gt;
            baseTicketPrice * (1.0f - calculateDiscountForPerson(person));
    }
}
import org.junit.jupiter.api.Test;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

import static com.shaba.Person.Gender.FEMALE;
import static com.shaba.Person.Gender.MALE;

import static org.junit.jupiter.api.Assertions.assertEquals;

class BusTicketTest {
    private static final int   TICKET_NUMBER     = 42;
    private static final float BASE_TICKET_PRICE = 100.0f;

    @Test
    void shouldReturnExpectedTicketPrice() {
        // Map of Person and Expected Discounted Ticket Price
        final Map&lt;Person, Float&gt; cases = new HashMap&lt;&gt; ();

        cases.put(new Person(&quot;Tom&quot;, MALE,   15), 50.0f);
        cases.put(new Person(&quot;Jen&quot;, FEMALE, 15), 50.0f);
        cases.put(new Person(&quot;Tom&quot;, MALE,    4), 50.0f);
        cases.put(new Person(&quot;Jen&quot;, FEMALE, 12), 50.0f);

        cases.put(new Person(&quot;Tom&quot;, MALE,   61), 75.0f);
        cases.put(new Person(&quot;Jen&quot;, FEMALE, 61), 75.0f);
        cases.put(new Person(&quot;Tom&quot;, MALE,   99), 75.0f);
        cases.put(new Person(&quot;Jen&quot;, FEMALE, 75), 75.0f);

        cases.put(new Person(&quot;Jen&quot;, FEMALE, 16), 90.0f);
        cases.put(new Person(&quot;Jen&quot;, FEMALE, 27), 90.0f);
        cases.put(new Person(&quot;Jen&quot;, FEMALE, 48), 90.0f);
        cases.put(new Person(&quot;Jen&quot;, FEMALE, 60), 90.0f);

        cases.put(new Person(&quot;Tom&quot;, MALE,   16), 100.0f);
        cases.put(new Person(&quot;Tom&quot;, MALE,   27), 100.0f);
        cases.put(new Person(&quot;Tom&quot;, MALE,   48), 100.0f);
        cases.put(new Person(&quot;Tom&quot;, MALE,   60), 100.0f);

        cases.forEach(this::assertExpectedTotalTicketPrice);
    }

    private void assertExpectedTotalTicketPrice(
            final Person person,
            final float expectedTotal) {
        assertEquals(expectedTotal, makeTestBusTicket().apply(person).getTotalAmount());
    }

    private Function&lt;Person, BusTicket&gt; makeTestBusTicket() {
        return person -&gt; new BusTicket(TICKET_NUMBER, BASE_TICKET_PRICE, person);
    }
 }

Test Cases

These tests cases now occur as expected.

+-----|--------|-------------------|-----------------------------+
| Age | Gender | Expected Discount | Expected total ticket price |
|-----|--------|-------------------|-----------------------------|
| 15  |   M    |       0.50        |             $50.00          |
| 15  |   F    |       0.50        |             $50.00          |
|  4  |   M    |       0.50        |             $50.00          |
| 12  |   F    |       0.50        |             $50.00          |
|-----|--------|-------------------|-----------------------------|
| 61  |   M    |       0.25        |             $75.00          |
| 61  |   F    |       0.25        |             $75.00          |
| 99  |   M    |       0.25        |             $75.00          |
| 75  |   F    |       0.25        |             $75.00          |
|-----|--------|-------------------|-----------------------------|
| 16  |   F    |       0.10        |             $90.00          |
| 27  |   F    |       0.10        |             $90.00          |
| 48  |   F    |       0.10        |             $90.00          |
| 60  |   F    |       0.10        |             $90.00          |
|-----|--------|-------------------|-----------------------------|
| 16  |   M    |       0.00        |             $100.00         |
| 27  |   M    |       0.00        |             $100.00         |
| 48  |   M    |       0.00        |             $100.00         |
| 60  |   M    |       0.00        |             $100.00         |
+-----|--------|-------------------|-----------------------------+

Sample Output

Enter the passenger name: Tom
Enter the gender: M
Enter the age: 98
Enter the ticket number: 2346
Enter the base ticket price: 100
Ticket no: 2346
Passenger: Tom (98 M)
Base price of a ticket: $100.00
Total Amount: $75.00

huangapple
  • 本文由 发表于 2020年4月8日 22:52:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/61103635.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定