为什么这个Java代码不会产生我期望的结果?

问题描述 投票:0回答:2

程序需要根据客户的agegender发行正确的机票价格。

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("Enter the passenger name:");
        String name = sc.next();
        p1.setName(name);

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

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

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

        b1.calculateTotal();

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

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

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

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

        System.out.println("Enter the ticket price:");`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 > 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

+-----|--------|-------------------|-----------------------------+
| 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         |
+-----|--------|-------------------|-----------------------------+
java immutability setter side-effects mutability
2个回答
2
投票

问题是您在做某事时太写人了:

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

将此设置器替换为:

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

1
投票

[这里,类似immutability的人将成为您的朋友。

@Ner是正确的by pointing out,因为您实例化了一个新的setPerson()对象,而不是在[中使用传递给setter方法的对象Person,所以setPerson方法会破坏您的代码。 C0]类。

这将导致丢失对计算必不可少的传入BusTicket对象中的数据。

人物的Person默认为namenull字符默认为gender'u0000'默认为age。由于0小于age,所以BusTicket值每次都是[[catches 0类的计算方法中的第一个if语句的值。要做的一项更改是:

16

并将其转换为:

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

此处注意public void setPerson(final Person person) {
    this.person = person;
}
关键字的用法。这是一种保护传入的方法参数以免在方法范围内更改其引用的好方法。

替代代码结构

我将为您的课程提出以下替代方案,因为它们例举了可以避免此类错误发生的更好做法。

final

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("%n%s", busTicket);
        }
    }

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

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

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

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

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

            System.out.print("Enter the base ticket price: ");
            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(
                "%s (%02d %s)",
            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 'F': return FEMALE;
            case 'M': return MALE;
            default:
                throw new IllegalArgumentException(String.format("Gender [%s] could not be determined.", 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(
                "%nTicket no: %d%n" + 
                "Passenger: %s%n" +
                "Base price of a ticket: $%.2f%n" +
                "Total Amount: $%.2f%n",
            getTicketNumber(),
            getPerson(),
            getBaseTicketPrice(),
            getTotalAmount());
    }

    private static float calculateDiscountForPerson(final Person person) {
        // 50% discount for age of 16
        if(person.getAge() < 16) {
            return 0.50f;
        // 25% discount for age over 60
        } else if(person.getAge() > 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<Float, Float> calculateTotal(final Person person) {
        return baseTicketPrice ->
            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<Person, Float> cases = new HashMap<> (); cases.put(new Person("Tom", MALE, 15), 50.0f); cases.put(new Person("Jen", FEMALE, 15), 50.0f); cases.put(new Person("Tom", MALE, 4), 50.0f); cases.put(new Person("Jen", FEMALE, 12), 50.0f); cases.put(new Person("Tom", MALE, 61), 75.0f); cases.put(new Person("Jen", FEMALE, 61), 75.0f); cases.put(new Person("Tom", MALE, 99), 75.0f); cases.put(new Person("Jen", FEMALE, 75), 75.0f); cases.put(new Person("Jen", FEMALE, 16), 90.0f); cases.put(new Person("Jen", FEMALE, 27), 90.0f); cases.put(new Person("Jen", FEMALE, 48), 90.0f); cases.put(new Person("Jen", FEMALE, 60), 90.0f); cases.put(new Person("Tom", MALE, 16), 100.0f); cases.put(new Person("Tom", MALE, 27), 100.0f); cases.put(new Person("Tom", MALE, 48), 100.0f); cases.put(new Person("Tom", 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<Person, BusTicket> makeTestBusTicket() { return person -> new BusTicket(TICKET_NUMBER, BASE_TICKET_PRICE, person); } }

样本输出

+-----|--------|-------------------|-----------------------------+ | 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 | +-----|--------|-------------------|-----------------------------+

© www.soinside.com 2019 - 2024. All rights reserved.